Trying to use the RACF callable services was like trying to find treasure with an incomplete map. I found it hard to create a C program to query a repository for ID information. This post is mainly about using the RACF callable services.
I was trying to understand the mapping of a digital certificate to a z/OS userid, but with little success. I found a RACF callable service which appeared to do what I wanted – but it did not give the answers – because, like many treasure maps, I was looking in the wrong place.
RACF has two repositories for mapping identities to userid.
- RACDCERT MAP which was the original way of mapping names. As far as I can tell, the only way of getting the certificate to userid mapping programmatically, is to use the certificate to logon, and then find the userid! This is used by Liberty Web Server.
- RACMAP MAP which is part of Enterprise wide identification. It maps identity strings, as you may get from LDAP, to a userid. You can use the r_usermap callable service to get this information.
It took me some time to realise that these are different entities, and explains why there was no documentation on getting Liberty to work with RACMAP to handle certificates. I found out RACMAP does not map certificate, after I got my program working.
The r_usermap service documentation is accurate – but incomplete, so I’ll document some of the things I learned in getting this to work.
The callable service to extract the userid from identity information is documented here. In essence you call the assembler routine r_usermap or IRRSIM00.
Building it
When you compile it, you need to provide the stub IRRSIM00 at bind time. I used JCL
//S1 JCLLIB ORDER=CBC.SCCNPRC //DOCLG EXEC PROC=EDCCBG,INFILE='ADCD.C.SOURCE(C)', // CPARM='OPTF(DD:COPTS)' //COMPILE.COPTS DD * LIST,SSCOMM,SOURCE,LANGLVL(EXTENDED) TEST /* //COMPILE.SYSIN DD * Source program goes here //BIND.CSS DD DISP=SHR,DSN=SYS1.CSSLIB //BIND.SYSIN DD * INCLUDE CSS(IRRSIM00) /*
You need code like
#pragma linkage(IRRSIM00, OS) int main(){... ... char * workarea ; workarea = (char *) malloc(1024) ; long ALET1= 0; ... long SAF_RC,RACF_RC,RACF_RS; ... rc= IRRSIM00(workarea, // WORKAREA &ALET1 , // ALET &SAF_RC, // SAF RC ...
Some fields are in UTF-8.
To covert from EBCDIC to UTF-8, (it looks like ASCII ) I used
cd = iconv_open("UTF-8", "IBM-1047"); ... struct { short length ; // length of string following or 0 if ommitted char value[248]; } DN; char * sDN= "CN=COLIN.C=GB"; size_t llinput= strlen(sDN); size_t lloutput= sizeof(DN.value); char * pOutValue= &DN.value[0]; rc = iconv(cd, // from iconv_open &sDN, // input string &llinput, // length of input &pOutValue,// output &lloutput);// length of output if (rc == -1) // problem { perror("iconv"); exit(99); } DN.length =sizeof(DN.value) - ll2; // calculate true length
What access do I need?
You need
permit IRR.RUSERMAP class(FACILITY) access(READ) ID(....) SETROPTS RACLIST(facility ) REFRESH
Output
Once I had got the program to compile and bind, and got the authorisation it worked great.
It only works with the RACFMAP … command, not the RACFDCERT command, obvious now I know! To get the information from the RACDCERT MAP, you need to use initACEE.
Hello Colin,
I’m looking to make racroute call from a C program that will be called by a cobol cics program, do you sample that you can provide. thanks
LikeLike
Hi,
I do not have a sample as such. You should be able to write a C program (get it working in batch first). Then convert it to CICS, and then exec cics link to it passing a commarea.
regards
Colin
LikeLike