How do I format an encoded name from a digital certificate?

I had a string CN=myserver,O=test,C=us in a certificate, which has been encoded

Offset   :                                       EBCDIC          ASCII 
00000000 : 302F310B 30090603 55040613 02757331  ................ 0/1.0...U....us1  
00000010 : 0D300B06 0355040A 13047465 73743111  ................ .0...U....test1.  
00000020 : 300F0603 55040313 086D7973 65727665  ........._`..... 0...U....myserve  
00000030 : 72                                  .                r                 
    

where you can see the encoded string in ASCII on the right. How do I extract the string CN=myserver,O=test,C=us from this?

This format is used for Subjects and Issuers (and other types).

The hex string has an ASN.1 encoding. It usually starts with a 0x30. See here for a good introduction to ASN.1 encoding.

  • 30 means this is a sequence
  • 2f is the length of the data following
  • etc

On z/OS you can use system ssl to decode this back to a printable string. You need two steps.

  1. Convert to internal format,
  2. Create the printable EBCDIC string from the internal format.

Step1 create internal format of the data

#pragma runopts(POSIX(ON)) 
#include <gskcms.h> 
#include <gskssl.h>  
void x509_to_string(char * pData, // pointer to the data
                     int lData)    // length of the data
{ 
   x509_name    X509;   // internal format.
   int rc; 
   gsk_buffer cert;     // intermediate format
   if (lData == 0) 
   { 
      printf("no data"); 
      return; 
   } 
   cert.length=   lData; 
   cert.data  =   pData ; 
   // convert from 0x302F310B 30090603 to internal 
   rc = gsk_decode_name( 
       & cert, 
       & X509); 
   if ( rc != 0) 
   { 
     //use gsk_strerror(rc) to return a string.
     printf("\nInternal error:gsk_decode_name %s\n", 
                  gsk_strerror(rc)); 
     return; 
   } 

Convert from internal format to an EBCDIC string.

   char * pName ;       // output value   
   // convert from internal to CN=COLIN,C=GB 
   rc = gsk_name_to_dn( 
              &X509, 
              &pName); 
   // free the intermediate value regardless of rc
   gsk_free_name(&X509); 
   if ( rc != 0) 
     { 
       printf("\nInternal error:gsk_name_dn %s\n", 
                    gsk_strerror(rc)); 
       return; 
     } 
   printf("%s.",pName); 

   //free the string 
   gsk_free_string(pName); 
} 

Convert from EBCDIC string to intermediate or certificate format.

There are the reverse functions.

  • gsk_dn_to_name( pName, &X509);
  • rc = gsk_encode_name( &X509, & cert);

Both C=GB,CN=colin and c=GB,cn=colin produce

00000000 : 301D310E 300C0603 55040313 05636F6C …………..?% 0.1.0…U….col
00000010 : 696E310B 30090603 55040613 024742 .>…………. in1.0…U….GB

JCL

I needed binder input options.

INCLUDE GSK(GSKCMS31) 
INCLUDE GSK(GSKSSL) 

and JCL

//COMPILE  EXEC PROC=EDCCB, 
//       LIBPRFX=&LIBPRFX, 
//       CPARM='OPTFILE(DD:SYSOPTF)', 
// BPARM='SIZE=(900K,124K),RENT,LIST,RMODE=ANY,AMODE=31,AC=1' 
//COMPILE.SYSLIB DD DISP=SHR,DSN=&LIBPRFX..SCEEH.SYS.H 
//               DD DISP=SHR,DSN=&LIBPRFX..SCEEH.H 
//               DD DISP=SHR,DSN=SYS1.SIEAHDR.H 
...
//COMPILE.SYSIN  DD DSN=&SOURCE(&PROG),DISP=SHR 
//COMPILE.SYS    DD DISP=SHR,DSN=&LIBPRFX..SCEEH.SYS.H 
//COMPILE.SYSOPTF DD DISP=SHR,DSN=&SOURCE(CCOPTS) 
//* 
//* Bind the module 
//* 
//BIND.SYSLMOD DD DISP=SHR,DSN=&LOADLIB(&PROG) 
//BIND.SYSLIB  DD DISP=SHR,DSN=&LIBPRFX..SCEELKED 
//             DD DISP=SHR,DSN=SYS1.SIEALNKE 
//BIND.GSK     DD DISP=SHR,DSN=SYS1.SIEALNKE 
...
//BIND.SYSIN DD DISP=SHR,DSN=&SOURCE(&BINDOPTS) 

Where the gskcms.h and gskssl.h are in DSN=SYS1.SIEAHDR.H or /usr/include/, and the binder stubs are in DSN=SYS1.SIEALNKE.

What WLM classification does z/OSMF need?

I was asked this question; I asked around and Ive summarized the responses below.

z/OSMF has two address spaces. The Angel task and the server task

The Angel task

Once the Angel task has started it uses very little CPU. It provides cross memory services for z/OSMF.

If your default service class for this is SYSSTC, then this will be fine.

The server

This is a more interesting challenge. This address space runs all of the work. It is written in Java. On my system it takes a lot of CPU to start up, but once it is up, it only uses CPU when there is work to do. This work tends to be as a result of a web browser or REST requests, and is not usually mission critical.

Running this as with a service class of Discretionary. May be OK, but as z/OSMF is used by systems programmers, they may give it a little extra boost.

If you are using z/OSMF to run and monitor your system, you may want to put it in a service class with non Discretionary, so that it continues to run even it your system is constrained for CPU.

Personally I would use TSO and ISPF in preference to z/OSMF, but new people to z/OS are familiar with Web Server based products rather than TSO.

I asked about this problem on the IBM Mainframe mailing list,and got some responses.

Kolusu Sri said

IZUSVR1 uses the setting from IZUPRMxx parmlib member, so you can add WLM_CLASSES in there.

On my system we have

WLM_CLASSES DEFAULT(IZUGHTTP)    

            LONG_WORK(IZUGWORK)  

you also need racf permissions

SEC_GROUPS USER(IZUUSER),ADMIN(IZUADMIN),SECADMIN(IZUSECAD)

SESSION_EXPIRE(495)

The IZUGHTTP service class is for foreground z/OSMF transactions (except asynchronous beans).

The IZUGWORK transaction class is for long running asynchronous beans and for unexpected z/OSMF work, not otherwise classified. Asynchronous beans are used in some scenarios of the Software Management plugin.

See z/OSMF V2.1 Resource Requirements section WLM Classification for z/OSMF on page 11. For more information.

                                        

Mike Shorkend said

Also keep in mind that a large proportion of IZUSVR1 CPU consumption is ZIIP eligible. I prefer to send ZIIP heavy workloads to a dedicated service class (mixing workloads might cause a ZIIP eligible workload to get denied ZIIP because the service class it is associated with is meeting its goals because of other non-ZIIP workloads). On a busy development LPAR I use a service class with importance 5 and execution velocity of 30 and it performs well. Also keep in mind the HONORPRIORITY setting for the service class which can cause/prevent  spill over of ZIIP eligible work to general usage processors.