COBOL SSL Sockets

By | September 10, 2013

What good are regular sockets when, in today’s environment of complex compliance requirements, we need to encrypt data in flight?  Building on my early post on COBOL POSIX Sockets, let’s show how to convert it to use SSL.

Since we are acting as an SSL client and not a server (and no client certificates will be involved) we don’t have to delve into the morass of certificate request generation, signing, et al.

Basically, everything is the same as the earlier post up through the connect() call except you connect to a different port. Then you set up the SSL environment and use gsk_secure_socket_init() to initiate the SSL handshaking, gsk_secure_socket_write() to send data and gsk_secure_socket_read() to receive data.  It’s not as daunting as one might at first think.

My approach is:

  1. Look up the hostname with getaddrinfo() to get its IP address.
  2. Allocate a socket.
  3. Set the port number and connect to the server.
  4. Turn on the tracing provided by System SSL by setting the appropriate environment variables.  This is only for debugging during testing.
  5. Open the SSL environment to get an environment handle.
  6. Use the handle to set some environment options:
    • Set the keyring to use to be the RACF Virtual keyring “*AUTH*/*”.  This allows any certificate authority certificate “owned” by CERTAUTH that is marked TRUST to validate an SSL connection. z/OS ships with many CA certs in CERTAUTH, but they do need to be marked with “TRUST”, for example,
      RACDCERT ALTER(LABEL('Verisign Class 4 Primary CA - G3')) CERTAUTH TRUST

      We could, instead of using RACF, point to a keyring database file in the HFS, which would allow us to do what we want without being a RACF administrator, but we’d have to learn to use gskeyman to build the keyring.  See below, however.

    • We could enable or disable specific versions of the protocol (SSLV2, TLSV1.2, etc.) if we wanted to do so here.
  7. Initialize the SSL environment.
  8. Open a secure socket to get a socket handle.
  9. Use the socket handle to set some options specific to this connection:
    • Tell SSL which socket we want to use (the one we allocated above and used to connect to the server).
    • We could also specify specific encryption types we want to use (presumably to omit insecure ones) with gsk_attribute_set_enum().
  1. Initialize the secure socket.  gsk_sercure_socket_init() is where all of the SSL handshaking will occur and where there is most likely to be an error encountered.
  2. Build the HTTP request string and convert it from EBCDIC to ASCII.
  3. Send the request over the SSL connection.
  4. Receive the reply.
  5. Convert the reply from ASCII to EBCDIC.
  6. Close the connection and SSL environment and do some housekeeping.
  7. Print the reply.

I’ll be using an API and example provided for the Apple ITunes store, documented here.

If there was an error, we can look at the trace data we collected.  In this case we put it to /tmp/cobssl.gsk.trc.  We convert it to a readable format with gsktrace /tmp/cobssl.gsk.trc >/tmp/cobssl.gsk.trc.lst and use OBROWSE to browse /tmp/cobssl.gsk.trc.lst.  The trace is instructive even when everything works.  To disable the tracing for a production environment, simply skip the setenv() calls.

The System SSL API is delivered in DLL format, so we have to compile with the DLL option and linkedit with DYNAM(DLL) and CASE(MIXED), include the Systems SSL side decks and store the load module into a PDSE.

Source and JCL:  cobssl.cbl  cobssl.jcl

Footnote: Using a key ring database instead of a RACF keyring

To use a key database stored in the HFS instead of a RACF keyring is not insurmountable. If you build a new certificate database with gskkyman it will contain the current certificate authority certificates, so if the server you are connecting to has a server certificate provided by one of the major certificate authorities, such as VeriSign, you should be good to go.  Use gskkyman to create a certificate database:

$ gskkyman

       Database Menu                                               

   1 - Create new database                                         
   2 - Open database                                               
   3 - Change database password                                    
   4 - Change database record length                               
   5 - Delete database                                             
   6 - Create key parameter file                                   
   7 - Display certificate file (Binary or Base64 ASN.1 DER)       

  11 - Create new token                                            
  12 - Delete token                                                
  13 - Manage token                                                
  14 - Manage token from list of tokens                            

   0 - Exit program                                                

Enter option number: 1                                             
Enter key database name (press ENTER to return to menu): cakeys.kdb
Enter database password (press ENTER to return to menu):           
Re-enter database password:                                        
Enter password expiration in days (press ENTER for no expiration): 
Enter database record length (press ENTER to use 5000):            

Enter 1 for FIPS mode database or 0 to continue: 0                 

Key database /u/xxxxxxx/.tmp/cakeys.kdb created.                    

Press ENTER to continue.                                           

       Key Management Menu                                          

       Database: /u/xxxxxxx/.tmp/cakeys.kdb                          
       Expiration: None                                             

   1 - Manage keys and certificates                                 
   2 - Manage certificates                                          
   3 - Manage certificate requests                                  
   4 - Create new certificate request                               
   5 - Receive requested certificate or a renewal certificate       
   6 - Create a self-signed certificate                             
   7 - Import a certificate                                         
   8 - Import a certificate and a private key                       
   9 - Show the default key                                         
  10 - Store database password                                      
  11 - Show database record length                                  

   0 - Exit program                                                 

Enter option number (press ENTER to return to previous menu): 0 

Then specify the path to the new keyring database, /u/xxxxxxx/.tmp/cakeys.kdb, instead of *AUTH*/* as the keyring and also specify the password with another gsk_attribute_set_buffer call for GSK_KEYRING_PW.

* GSK_KEYRING_PW from gskssl.h
77  ws-gsk-keyring-pw         pic s9(8) binary value 202.

[...]

call 'gsk_attribute_set_buffer'                        
  using by value           ws-gsk-env-handle           
                           ws-gsk-keyring-file         
        by content         z'/u/xxxxxxx/.tmp/cakeys.kdb'
        by value           ws-zero                     
  returning                ws-rc                       

if ws-rc not = zero                                    
then                                                   
  move z'gsk_attribute_set_buffer'                     
                        to ws-gsk-function             
  go to gsk-error                                      
end-if                                                 

call 'gsk_attribute_set_buffer'                        
  using by value           ws-gsk-env-handle           
                           ws-gsk-keyring-pw           
        by content         z'password'                 
        by value           ws-zero                     
  returning                ws-rc                       

if ws-rc not = zero                                    
then                                                   
  move z'gsk_attribute_set_buffer'                     
                        to ws-gsk-function             
  go to gsk-error                                      
end-if

2 thoughts on “COBOL SSL Sockets

Leave a Reply

Your email address will not be published. Required fields are marked *