Example: Establish a secure client with Global Secure ToolKit (GSKit) APIs

This code sample provides an example of a client that uses the GSKit APIs.

The following graphic shows the function calls on a secure client using the GSKit APIs:



Socket flow of events: GSKit client

This flow describes the socket calls in the following sample application. Use this client example with the GSKit server example and the Example: GSKit secure server with asynchronous handshake.

  1. The gsk_environment_open() function obtains a handle to an SSL environment.
  2. One or more calls to gsk_attribute_set_xxxxx() to set attributes of the SSL environment. At a minimum, either a call to gsk_attribute_set_buffer() to set the GSK_OS400_APPLICATION_ID value or to set the GSK_KEYRING_FILE value. Only one of these should be set. It is preferred that you use the GSK_OS400_APPLICATION_ID value. Also ensure you set the type of application (client or server), GSK_SESSION_TYPE, using gsk_attribute_set_enum().
  3. A call to gsk_environment_init() to initialize this environment for SSL processing and to establish the SSL security information for all SSL sessions that run using this environment.
  4. The socket() function creates a socket descriptor. The client then issues the connect() to connect to the server application.
  5. The gsk_secure_soc_open() function obtains storage for a secure session, sets default values for attributes, and returns a handle that must be saved and used on secure session-related function calls.
  6. The gsk_attribute_set_numeric_value() function associates a specific socket with this secure session.
  7. The gsk_secure_soc_init() function starts an asynchronous negotiation of a secure session, using the attributes set for the SSL environment and the secure session.
  8. The gsk_secure_soc_write() function writes data on a secure session to the worker thread.
    Note: For the GSKit server example, this function writes data to the worker thread where the gsk_secure_soc_startRecv() function is completed. In the asynchronous example, it writes to the completed gsk_secure_soc_startInit() .
  9. The gsk_secure_soc_read() function receives a message from the worker thread using the secure session.
  10. The gsk_secure_soc_close() function ends the secure session.
  11. The gsk_environment_close() function closes the SSL environment.
  12. The close() function ends the connection.
Note: By using the code examples, you agree to the terms of the Code license and disclaimer information.
/* GSK Client Program using Application Id            */

/* This program assumes that the application id is    */
/* already registered and a certificate has been      */
/* associated with the application id                */
/*                                                    */
/* No parameters, some comments and many hardcoded    */
/* values to keep it short and simple                 */

/* use following command to create bound program:     */
/* CRTBNDC PGM(MYLIB/GSKCLIENT)                       */
/*         SRCFILE(MYLIB/CSRC)                        */
/*         SRCMBR(GSKCLIENT)                          */

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <gskssl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#define TRUE 1
#define FALSE 0

void main(void)
{
  gsk_handle my_env_handle=NULL;    /* secure environment handle */
  gsk_handle my_session_handle=NULL;    /* secure session handle */

  struct sockaddr_in address;
  int buf_len, rc = 0, sd = -1;
  int amtWritten, amtRead;
  char buff1[1024];
  char buff2[1024];

  /*  hardcoded IP address (change to make address were server program runs */
  char addr[16] = "1.1.1.1";

  /*********************************************/
  /* Issue all of the command in a do/while    */
  /* loop so that clean up can happen at end   */
  /*********************************************/
  do
  {
    /* open a gsk environment */
    rc = errno = 0;
    rc = gsk_environment_open(&my_env_handle);
    if (rc != GSK_OK)
    {
      printf("gsk_environment_open() failed with rc = %d and errno = %d.\n",
             rc,errno);
      printf("rc of %d means %s\n", rc, gsk_strerror(rc));
      break;
    }

    /* set the Application ID to use */
    rc = errno = 0;
    rc = gsk_attribute_set_buffer(my_env_handle,
                                  GSK_OS400_APPLICATION_ID,
                                  "MY_CLIENT_APP",
                                  13);
  if (rc != GSK_OK)
    {
      printf("gsk_attribute_set_buffer() failed with rc = %d and errno = %d.\n",
             rc,errno);
      printf("rc of %d means %s\n", rc, gsk_strerror(rc));
      break;
    }

    /* set this side as the client (this is the default */
    rc = errno = 0;
    rc = gsk_attribute_set_enum(my_env_handle,
                                GSK_SESSION_TYPE,
                                GSK_CLIENT_SESSION);
    if (rc != GSK_OK)
    {
      printf("gsk_attribute_set_enum() failed with rc = %d and errno = %d.\n",
             rc,errno);
      printf("rc of %d means %s\n", rc, gsk_strerror(rc));
      break;
    }

    /* by default SSL_V2, SSL_V3, and TLS_V1 are enabled  */
    /* We will disable SSL_V2 for this example.           */
    rc = errno = 0;
    rc = gsk_attribute_set_enum(my_env_handle,
                                GSK_PROTOCOL_SSLV2,
                                GSK_PROTOCOL_SSLV2_OFF);
    if (rc != GSK_OK)
    {
      printf("gsk_attribute_set_enum() failed with rc = %d and errno = %d.\n",
             rc,errno);
      printf("rc of %d means %s\n", rc, gsk_strerror(rc));
      break;
    }

    /* set the cipher suite to use.  By default our default list     */
    /* of ciphers is enabled.  For this example we will just use one */
    rc = errno = 0;
    rc = gsk_attribute_set_buffer(my_env_handle,
                                  GSK_V3_CIPHER_SPECS,
                                  "05", /* SSL_RSA_WITH_RC4_128_SHA */
                                  2);
    if (rc != GSK_OK)
    {
      printf("gsk_attribute_set_buffer() failed with rc = %d and errno = %d.\n",
             rc,errno);
      printf("rc of %d means %s\n", rc, gsk_strerror(rc));
      break;
    }

    /* Initialize the secure environment */
    rc = errno = 0;
    rc = gsk_environment_init(my_env_handle);
    if (rc != GSK_OK)
    {
      printf("gsk_environment_init() failed with rc = %d and errno = %d.\n",
             rc,errno);
      printf("rc of %d means %s\n", rc, gsk_strerror(rc));
      break;
    }

    /* initialize a socket to be used for listening */
    sd = socket(AF_INET, SOCK_STREAM, 0);
    if (sd < 0)
    {
      perror("socket() failed");
      break;
    }

    /* connect to the server using a set port number */
    memset((char *) &address, 0, sizeof(address));
    address.sin_family = AF_INET;
    address.sin_port = 13333;
    address.sin_addr.s_addr = inet_addr(addr);
    rc = connect(sd, (struct sockaddr *) &address, sizeof(address));
    if (rc < 0)
    {
      perror("connect() failed");
      break;
    }

    /* open a secure session */
    rc = errno = 0;
    rc = gsk_secure_soc_open(my_env_handle, &my_session_handle);
    if (rc != GSK_OK)
    {
      printf("gsk_secure_soc_open() failed with rc = %d and errno = %d.\n",
             rc,errno);
      printf("rc of %d means %s\n", rc, gsk_strerror(rc));
      break;
    }

    /* associate our socket with the secure session */
    rc=errno=0;
    rc = gsk_attribute_set_numeric_value(my_session_handle,
                                         GSK_FD,
                                         sd);
    if (rc != GSK_OK)
    {
      printf("gsk_attribute_set_numeric_value() failed with rc = %d ", rc);
      printf("and errno = %d.\n", errno);
      printf("rc of %d means %s\n", rc, gsk_strerror(rc));
      break;
    }

    /* initiate the SSL handshake */
    rc = errno = 0;
    rc = gsk_secure_soc_init(my_session_handle);
    if (rc != GSK_OK)
    {
      printf("gsk_secure_soc_init() failed with rc = %d and errno = %d.\n",
             rc,errno);
      printf("rc of %d means %s\n", rc, gsk_strerror(rc));
      break;
    }

    /* memset buffer to hex zeros */
    memset((char *) buff1, 0, sizeof(buff1));

    /* send a message to the server using the secure session */
    strcpy(buff1,"Test of gsk_secure_soc_write \n\n");

    /* send the message to the client using the secure session */
    buf_len = strlen(buff1);
    amtWritten = 0;
    rc = gsk_secure_soc_write(my_session_handle, buff1, buf_len, &amtWritten);
    if (amtWritten != buf_len)
    {
      if (rc != GSK_OK)
      {
        printf("gsk_secure_soc_write() rc = %d and errno = %d.\n",rc,errno);
        printf("rc of %d means %s\n", rc, gsk_strerror(rc));
        break;
      }
      else
      {
        printf("gsk_secure_soc_write() did not write all data.\n");
        break;
      }
    }

    /* write results to screen */
    printf("gsk_secure_soc_write() wrote %d bytes...\n", amtWritten);
    printf("%s\n",buff1);

  /* memset buffer to hex zeros */
    memset((char *) buff2, 0x00, sizeof(buff2));

    /* receive a message from the client using the secure session */
    amtRead = 0;
    rc = gsk_secure_soc_read(my_session_handle, buff2, sizeof(buff2), &amtRead);

    if (rc != GSK_OK)
    {
      printf("gsk_secure_soc_read() rc = %d and errno = %d.\n",rc,errno);
      printf("rc of %d means %s\n", rc, gsk_strerror(rc));
      break;
    }

    /* write results to screen */
    printf("gsk_secure_soc_read() received %d bytes, here they are ...\n",
           amtRead);
    printf("%s\n",buff2);


  } while(FALSE);

  /* disable SSL support for the socket */
  if (my_session_handle != NULL)
    gsk_secure_soc_close(&my_session_handle);

  /* disable the SSL environment */
  if (my_env_handle != NULL)
    gsk_environment_close(&my_env_handle);

  /* close the connection */
  if (sd > -1)
    close(sd);

  return;
}
Related concepts
Global Secure ToolKit (GSKit) APIs
Related reference
Example: GSKit secure server with asynchronous data receive
Example: GSKit secure server with asynchronous handshake
Related information
socket()
close()
connect()
gsk_environment_open()
gsk_attribute_set_buffer
gsk_attribute_set_enum()
gsk_environment_init()
gsk_secure_soc_open()
gsk_attribute_set_numeric_value()
gsk_secure_soc_init()
gsk_secure_soc_close()
gsk_environment_close()
gsk_secure_soc_write()
gsk_secure_soc_startInit()
gsk_secure_soc_startRecv()
gsk_secure_soc_read()