I was testing out certificate access to logon to z/OS using pthread_secure_applid() services . It took a little while to get my program working, but once it was working I tried to be “customer like” rather than a simple Unit Test. The documentation is not very clear, but it does work.
You can create a RACF definition for the simple case
- For a certificate where the Subject Distinguished Name(DN) matches the definition’s Subject DN, then use userid xyz.
- For a certificate where part of the Subject DN matches the definitions Subject DN, then use userid ijklm.
These both default to using an APPLID OMVSAPPL
I wanted to say
- for application id ZZZ, if a certificate with this subject DN, then use userid TESTZ
- for application id YYY if a certificate with the same subject DN, then use userid TESTY
Topics covered n this post:
- How to set up your enterprise certificate
- Define a certificate-to-user mapping (simple case)
- Define a certificate with mutliid mapping
- Creating definitions
- Controlling access to the applid
- Problem I experienced
How to set up your enterprise certificates
If you want to control certificate to userid mapping, at an individual level
You can use the following, where SDN is the Subject Distinguished Name from the certificate,
RACDCERT MAP ID(.... ) SDN(...)
for each individual.
To remove access you just delete the profile (and refresh RACLIST).
You can also specify the Issuers Distinguished Name (IDN) so you refer to the correct certificate.
If you want to control certificate to userid mapping, at the group level
You can use a Subject DN filter. This may mean you need to define your Subject DN with Organisation Units(OU), as
- CN=COLIN,OU=TEST,O=MYORG
- CN=MARY,OU=SALES,O=MYORG
You can then have a filter SDN(‘OU=TEST,O=MYORG’) to allow just those in the OU=TEST group to logon, and sales people will not get access.
If you then want to prevent individuals from getting access you need to define a specific profile, and point it to a userid which can do nothing.
You could also have your certificates issued by different CA’s For example, have a certificate with an Issuer Distinguished Name(IDN) including the department name.
- Subject DN(CN=COLIN,OU=TEST,O=MYORG) Issuer DN(OU=TEST,OU=CA,O=MYORG)
and specify IDN(OU=TEST,OU=CA,O=MYORG).
Note: with this, if someone changes department, and moved from Sales to Test, they will need a new certificate.
Some people may require more than one certificate. For example someone who has normal access for their day to day job, and super powers for emergencies.
Note: In addition to getting access with a certificate you may still want to use a password.
Define a certificate to user mapping (simple case)
Use a fully qualified Subject DN filter
For example, a certificate has SDN CN=docec256.O=Doc.C=GB .
//COLRACF JOB 1,MSGCLASS=H //S1 EXEC PGM=IKJEFT01,REGION=0M //STEPLIB DD DISP=SHR,DSN=SYS1.MIGLIB //SYSPRINT DD SYSOUT=* //SYSTSPRT DD SYSOUT=* //SYSTSIN DD * RACDCERT DELMAP(LABEL('CP')) ID(COLIN) RACDCERT MAP ID(COLIN ) - SDNFILTER('CN=docec256.O=Doc.C=GB') - IDNFILTER('CN=SSCA256.OU=CA.O=DOC.C=GB') - WITHLABEL('CP') RACDCERT LISTMAP ID(COLIN) SETROPTS RACLIST(DIGTNMAP, DIGTCRIT) REFRESH /*
This uses both Subject Distinguished Name, and Issuer Distinguished Name. You can use either or both filters.
With this definition when I used openssl s_client to talk to my server application running on z/OS. When I specified the client certificate with the specified Subject DN and signer, I could use:
- AT-TLS, use BPX1IOC() and retrieve the userid. Internally this uses applid=OMVSAPPL
- do it myself
- retrieve the certificate with the BPX1IOC() TTLS_QUERY_ONLY call;
- use rc = pthread_security_applid_np( __CREATE_SECURITY_ENV,…. “OMVSAPPL”) passing the certificate and the applid OMVSAPPL
The code checks my the extracted userid (COLIN) has read access to the profile OMVSAPPL in class(APPL)) and, if it has access, it returns the userid to the application.
See below if you do not want to use applid OMVSAPPL
Use a partially qualified Subject DN filter
Instead of a fully qualified Subject DN, CN=docec256.O=Doc.C=GB. You can use a partially qualified DN, for example CN=docec256.O=Doc.C=GB. Any certificate which has a DN including O=Doc.C=GB will be accepted
RACDCERT DELMAP(LABEL('CPGEN')) ID(ADCDF) RACDCERT MAP ID(ADCDF ) - SDNFILTER('O=Doc.C=GB') - WITHLABEL('CPGEN') RACDCERT LISTMAP ID(ADCDF) SETROPTS RACLIST(DIGTNMAP, DIGTCRIT) REFRESH
With this definition when I used openssl s_client to talk to my server application running on z/OS. When I specified the client certificate with the specified Issuer CN, it worked the same way as the simple case above.
The code checks my the user extracted userid (ADCDF) has read access to the profile OMVSAPPL in class(APPL)) and, if it has access, it returns the userid to the application.
Define a certificate with mutliid mapping
A specific Subject DN gets a different userid depending on the application id.
As above you can specify an Issuer Distinguished Name or a Subject Distinguished Name.
Use an Issuer Distinguished Name
Use an Issuer certificate, so any certificate issued by DN this will be covered.
I defined the profile for my Issuer CA certificate. The definition below says – any certificate issued by this CA.
RACDCERT DELMAP(LABEL('CPMULTI')) MULTIID RACDCERT MULTIID MAP WITHLABEL('CPMULTI') TRUST - IDNFILTER('CN=SSCA256.OU=CA.O=DOC.C=GB') - CRITERIA(ZZAPPLID=&APPLID)
Define which userid to use based on the CRITeria
RDEFINE DIGTCRIT ZZAPPLID=ZZZ APPLDATA('ADCDZ') RDEFINE DIGTCRIT ZZAPPLID=AAA APPLDATA('ADCDF')
In my program I had
struct __certificate ct; ct.__cert_type = __CERT_X509; char * pData = (char *) ioc.TTLSi_BufferPtr; ct.__cert_length = ... ct.__cert_ptr = ...; rc = pthread_security_applid_np(__CREATE_SECURITY_ENV, __CERTIFICATE_IDENTITY, sizeof(ct), &ct, "", 0, "AAA");
With this, the CRITERIA(ZZAPPLID=&APPLID) becomes CRITERIA(ZZAPPLID=AAA), which maps to CRITeria
RDEFINE DIGTCRIT ZZAPPLID=AAA APPLDATA('ADCDF'),
and so maps to userid ADCDF.
When applid ZZZ was used instead of AAA, then
RDEFINE DIGTCRIT ZZAPPLID=AAA APPLDATA('ADCDF')
AT-TLS only seems to be able to use the APPL OMVSAPPL (the default). I could not find a way of getting it to use an APPLID, so I had to use pthead_security_appl_np to be able to use an applid different from the default.
Use a subject DN
You can use an explicit Subject DN
RACDCERT MULTIID MAP WITHLABEL('CPMULTIU') TRUST - SDNFILTER('CN=docecgen.O=Doc2.C=GB') - CRITERIA(UAPPLID=&APPLID) RDEFINE DIGTCRIT UAPPLID=AAA APPLDATA('ADCDA') RDEFINE DIGTCRIT UAPPLID=BBB APPLDATA('ADCDB')
the userid used depending which APPLID was specified in my application.
I could use a subset of the the SDN
RACDCERT DELMAP(LABEL('CPMULTIU')) MULTIID RDELETE DIGTCRIT APPLID=OMVSAPPL RDELETE DIGTCRIT APPLID=ZZZ RACDCERT MULTIID MAP WITHLABEL('CPMULTIU') TRUST - SDNFILTER('O=Doc2.C=GB') - CRITERIA(UAPPLID=&APPLID) RDEFINE DIGTCRIT UAPPLID=AAA APPLDATA('ADCDD') RDEFINE DIGTCRIT UAPPLID=BBB APPLDATA('ADCDE')
Creating definitions
What the documentation does not say, is that you can have any keyword in the criteria, as long as the substitute value has a DIGTCRIT.
This means you can have
RACDCERT MULTIID MAP ... CRITERIA(ZORK=&APPLID)
and have statements like
RDEFINE DIGTCRIT ZORK=AAA APPLDATA('IBMUSER')
Controlling access to the applid
If there is a profile for the applid in CLASS(APPL) the userid will need read access to the profile.
If the profile is not defined, then anyone can use the profile.
Problem I experienced
ESRCH: errno 143 EDC5143I No such process. errno2 0be8044c
I got messages
ESRCH:The user ID provided as input is not defined to the security product or does not have an OMVS segment defined
pthread_s… rc = -1 errno 143 EDC5143I No such process. errno2 0be8044c
Where TSO BPXMTEXT 0be8044c gives
BPXPTSEC 01/05/18
JRNoCertforUser: There is no userid defined for this certificate. Action: Ensure the userid is known to the SAF service.
Cause 1:
I used an APPLID which did not have a criteria
I also got this when I used pthread_security_applid_np(…) with an an applid which did not have a matching RDEFINE DIGTCRIT
For example the following worked
- applid AAA and RDEFINE DIGTCRIT UAPPLID=AAA APPLDATA(‘ADCDA’)
when I used a different applid I got the “EDC5143I No such process. errno2 0be8044c” message, along with the following on the joblog.
ICH408I USER(COLIN ) GROUP(SYS1 ) NAME(COLIN PAICE )
DIGITAL CERTIFICATE IS NOT DEFINED. CERTIFICATE SERIAL NUMBER(027C)
SUBJECT(CN=docecgen.O=Doc2.C=GB) ISSUER(CN=SSCA256.OU=CA.O=DOC.C=GB).
Cause 2:
In the definitions I had the wrong case: c=GB and c=gb.
Cause 3:
NOTRUST was specified
RACDCERT MULTIID MAP WITHLABEL('CPMULTIU') noTRUST - SDNFILTER('CN=docecgen.O=Doc2.C=GB') - CRITERIA(UAPPLID=&APPLID)
This also had a message on the job log:
ICH408I USER(START1 ) GROUP(SYS1 ) NAME(####################)
DIGITAL CERTIFICATE DEFINED TO A RESERVED USER ID. CERTIFICATE SERIAL
NUMBER(027C) SUBJECT(CN=docecgen.O=Doc2.C=GB) ISSUER(CN=SSCA256.OU=C
A.O=DOC.C=GB).
Cause 4:
I had specified the certificate’s DN in Issuers DN. It should have been SDNFILTER(‘CN=rsarsa.O=cpwebuser.C=GB’)
EMVSSAFEXTRERR 163 EDC5163I SAF/RACF extract error. errno2 0be8081c
pthread_secuity_applid_np() rc = -1 errno 163 EDC5163I SAF/RACF extract error. errno2 0be8081c
TSO BPXMTEXT 0be8081c , just gives
BPXPTSEC 01/05/18
with no message description
Cause 1:
I got this when I used
RACDCERT MULTIID MAP WITHLABEL('CPMULTIU') TRUST - SDNFILTER('CN=docecgen.O=Doc2.C=GB') - CRITERIA(UAPPLID=&APPLID)
and the SDNFILTER value was in upper case. When I corrected it (to the above) it worked.
It looks like certificate filter not found.
Cause 2:
I had a lower case keyword such as SDNFILTER(‘CN=docecgen.O=Doc2.c=GB’)
EMVSSAFEXTRERR 163 EDC5163I SAF/RACF extract error. errno2 0be80820
TSO BPXMTEXT 0be8082 gave
BPXPTSEC 01/05/18
and no other information.
I had
RACDCERT MULTIID MAP WITHLABEL('CPMULTIU') TRUST - SDNFILTER('CN=docecgen.O=Doc2.C=GB') - CRITERIA(UAPPLID=&APPLID) RDEFINE DIGTCRIT UAPPLID=ZZZ APPLDATA('ADCDB')
and userid ADCDB had no access to the RACF resource class(APPL) ZZZ.
EMVSERR 157 EDC5157I An internal error has occurred. errno2 0be800fc.
TSO BPXMTEXT 0be800fc gave
BPXPTSEC 01/05/18
JRSAFNoUID: The user ID has no UIDAction: Create an OMVS segment with a UID.
Cause:
If I display the userid LU ADCDG OMVS it gave UID= NONE.
I had created this situation using ALU ADCDG OMVS(NOUID). I reset it back using tso ALU ADCDG OMVS(UID(990098)).