ネットワーク

58. TCP/IP SSL通信クライアント

TCP/IP SSL クライアント・プログラムの例を紹介しよう。

SSLサーバーの例で既に説明したように SSLクライアントも Socketの代わりに

SSLハンドルを使用するだけのものである。

【 SSLCLT: SSL による TCP/IPクライアント ( C/400) 】
/********************************************************************** 
/*                                                                      
/*   SSLCLT:   TEST SSL CLIENT                                          
/*                                                                      
/********************************************************************** 
#include <stdio.h>                                                      
#include <stdlib.h>                                                     
#include <string.h>                                                     
#include <sys/socket.h>                                                 
#include <sys/types.h>                                                  
#include <netinet/in.h>                                                 
#include <netinet/tcp.h>                                                
#include <arpa/inet.h>                                                  
#include <ssl.h>                                                        
#include <errno.h>                                                      
                                                                        
#define TRUE         0                                                  
#define FALSE       -1                                                  
#define SSL_HANDSHAKE_AS_CLIENT 0                                       
typedef struct {                                                        
   int  BYTESPRO;                                                       
   int  BYTESAVL;                                                       
   char MSGID[7];                                                       
   char RESRVD;                                                         
   char EXCPDATA[100];                                                  
} ERRSTRUCTURE;     /* Define the error return structure            */  
ERRSTRUCTURE  errcode;/* Error Code Structure for RCVMSG      */        
char addr[11] = "192.168.1.3";                                          
SSLHandle*  sslh;                                                       
SSLInitApp  sslinit;                                                    
void * malloc_ptr = (void*)NULL;                                        
unsigned int malloc_size = 8192;                                        
unsigned short int cipher = SSL_RSA_WITH_RC4_128_SHA;                   
char ssl_msg[256];                                                      
int PORT = 443;                                                         
                                                                        
void  INZSR(void);                                                      
int   SSL_INZSR(void);                                                  
int   SSL_CREATE(int *sockfd);                                          
char* SSL_error(int rc);                                                
void  err_log(char* msg, int opt, char* function, int line);            
                                                                    
void main(void){                                                    
   int sockfd, len, rc;                                             
  struct sockaddr_in iaddr;                                         
   char buff[48];                                                   
                                                                    
   printf("** SSLCLT **n");                                        
   getchar();                                                       
   INZSR();                                                         
   if(SSL_INZSR() == FALSE){/*SSL_INZSR*/                           
     exit(0);                                                       
   }/*SSL_INZSR*/                                                   
  /*-------------------------------------------------------*/       
  /*         socket : Get a socket descriptor              */       
  /*-------------------------------------------------------*/       
  if((sockfd = socket(AF_INET, SOCK_STREAM, 0 )) < 0){              
     perror("SOCKET"); getchar(); exit(0);                          
  }                                                                 
  /*---------------------------------------------------------*/     
  /*   SSL_Create : enable SSL support                       */     
  /*---------------------------------------------------------*/     
  sslh = SSL_Create(sockfd, SSL_ENCRYPT);                            
  if(sslh == NULL){                                                  
     printf("SSL_CREATE failed with errno = %d・n", errno);           
     close(sockfd); getchar(); exit(0);                              
  }                                                                  
  /*-----------------------------------------------------------*/    
  /* connect: connect to the server using a set of port number */    
  /*-----------------------------------------------------------*/    
  memset(&iaddr, 0x00, sizeof(struct sockaddr_in));                  
  iaddr.sin_family = AF_INET;                                        
  iaddr.sin_port  = htons(PORT); /* PORT no set*/                    
  iaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* any address OK */    
  rc = connect(sockfd, (struct sockaddr *)&iaddr, sizeof(iaddr));    
  if(rc < 0){                                                        
     perror("CONNECT"); getchar(); exit(0);                          
  }                                                                  
                                                                     
  /*-----------------------------------------------------------*/    
  /*  setup to call handshake , setting cipher                 */    
  /*-----------------------------------------------------------*/    
   sslh->protocol = 0;                                               
   sslh->timeout = 0;                                                
   sslh->cipherSuiteList = &cipher;                                  
   sslh->cipherSuiteListLen = 1;                                     
  /*-----------------------------------------------------------*/    
  /*   initiate the SSL handshake as a CLIENT                  */    
  /*-----------------------------------------------------------*/    
   rc = SSL_Handshake(sslh, SSL_HANDSHAKE_AS_CLIENT);                
   if(rc != 0){                                                      
     perror("SSL_HANDSHAKE");                                        
     close(sockfd);                                                  
     getchar();                                                      
     exit(0);                                                        
   }                                                                 
  /*-----------------------------------------------------------*/    
  /*   send a message to the server using secure session       */    
  /*-----------------------------------------------------------*/    
  memset(buff, 0, sizeof(buff));                                     
  strcpy(buff, "* CLIENT 1ST MESSAGE USING SSL");                    
  len = strlen(buff);                                                
  rc = SSL_Write(sslh, buff, len);                                   
  if(rc != len){                                                     
     if(rc < 0){                                                    
       perror("SSL_WRITE"); getchar(); exit(0);                     
     }                                                              
     else{                                                          
       printf("SSL_WRITE did not all data・n");                      
       getchar(); exit(0);                                          
     }                                                              
  }                                                                 
  else{                                                             
     printf("SSL_WRITE OK = %s・n", buff);                           
  }                                                                 
  /*-----------------------------------------------------------*/   
  /*   receive the message from the server using SSL           */   
  /*-----------------------------------------------------------*/   
  memset(buff, 0, sizeof(buff));                                    
  rc = SSL_Read(sslh, buff, len);                                   
  if(rc < 0){                                                       
       perror("SSL_READ"); getchar(); exit(0);                      
  }                                                                 
     printf("SSL_READ  OK = %s・n", buff);                           
   SSL_Destroy(sslh);                                               
   close(sockfd);                                           
                                                            
    printf("**************************************・n");     
    printf("*   SSLCLT   SUCCESSFULLY COMPLETE ! *・n");     
    printf("**************************************・n");     
   getchar();                                               
}                                                           
/****************/                                          
void  INZSR(void)                                           
/****************/                                          
 {                                                          
                                                            
    errcode.BYTESPRO = errcode.BYTESAVL = 0;                
 }                                                          
/********************/                                      
int   SSL_INZSR(void)                                       
/********************/                                      
 {                                                          
    int rc = 0;                                             
    char errmsg[128];                                       
                                                            
    memset((char*)&sslinit, 0, sizeof(sslinit));                        
    sslinit.applicationID = "MY_CLIENT_APP";                            
    sslinit.applicationIDLen = 13;                                      
    sslinit.localCertificate = NULL;                                    
    sslinit.localCertificateLen = 0;                                    
    sslinit.cipherSuiteList = NULL;                                     
    sslinit.cipherSuiteListLen = 0;                                     
                                                                        
    malloc_ptr = (void*)malloc(malloc_size);                            
    sslinit.localCertificate = (unsigned char*)malloc_ptr;              
    sslinit.localCertificateLen = malloc_size;                          
                                                                        
    rc = SSL_Init_Application(&sslinit);                                
    if(rc != 0){/* init App err */                                      
      memset(errmsg, 0, sizeof(errmsg));                                
      sprintf(errmsg,                                                   
             "SSL_INZSR:SSL_Init_App ERROR = %s・n", SSL_error(rc))      
      err_log(errmsg, FALSE, "SSL_INZSR", __LINE__);                    
      return FALSE;                                                     
    }/* init App err */                                                 
                                                                        
    return TRUE;                                                      
}                                                                     
/****************************/                                        
int   SSL_CREATE(int *sockfd)                                         
/****************************/                                        
 {                                                                    
    sslh = SSL_Create(*sockfd, SSL_ENCRYPT);                          
    if(sslh == NULL){                                                 
       printf("SSL_Create  failed with errno = %d・n", errno);         
       close(*sockfd);                                                
       return FALSE;                                                  
    }                                                                 
    return TRUE;                                                      
}                                                                     
/**********************/                                              
char* SSL_error(int rc)                                               
/**********************/                                              
{                                                                     
                                                                      
   memset(ssl_msg, 0, sizeof(ssl_msg));                               
   switch(rc){/*switch*/                                              
   case  SSL_ERROR_NO_CIPHERS:                                          
            strcpy(ssl_msg,                                             
            "a cipher suite that is not valid was specified");          
            break;                                                      
   case  SSL_ERROR_CERT_EXPIRED:                                        
            strcpy(ssl_msg,                                             
            "the validity time period of certificate is expired.");     
            break;                                                      
   case  SSL_ERROR_KEYPASSWORD_EXPIRED:                                 
            strcpy(ssl_msg,                                             
            "the specified key ring pasword has expied.");              
            break;                                                      
   case  SSL_ERROR_NO_KEYRING:                                          
            strcpy(ssl_msg,                                             
            "No key ring filee was found.");                            
            break;                                                      
   case  SSL_ERROR_NOT_REGISTERED:                                      
            strcpy(ssl_msg,                                             
            "The applicatin identifier is not registored width certifi・ 
cate registry facility.");                                              
            break;                                                      
   case  SSL_ERROR_NOT_TRUSTED_ROOT:                                   
            strcpy(ssl_msg,                                            
            "The certificate is not signed by a tructed certificate ・  
authority.");                                                          
            break;                                                     
   case  SSL_ERROR_NO_CERTIFICATE:                                     
            strcpy(ssl_msg,                                            
            "No certificate is available for SSL processing.");        
            break;                                                     
   case  SSL_ERROR_IO:                                                 
            strcpy(ssl_msg,                                            
            "An error occurd in SSL processing; check the error value")
            break;                                                     
   case  SSL_ERROR_SSL_NOT_AVAILABLE:                                  
            strcpy(ssl_msg,                                            
            "SSL が使用可能ではありません。 ");                        
            break;                                                     
   case  SSL_ERROR_UNKNOWN:                                            
            strcpy(ssl_msg,                                            
            "An unknown oe unexpected error occued durering SSL ・      
processing");                                                          
            break;                                                
   default:                                                       
            sprintf(ssl_msg, "rc = %d", rc);                      
   }/*switch*/                                                    
   return ssl_msg;                                                
}                                                                 
/********************************************************/        
void  err_log(char* msg, int opt, char* err_at, int line)         
/********************************************************/        
{                                                                 
    fprintf(stderr, "%s・n", msg);                                 
    fprintf(stderr, " ->ERR AT = %s, LINE = %d・n", err_at, line); 
    if(opt == TRUE)                                               
      fprintf(stderr, "%s・n", strerror(errno));                   
}
【 解説 】

コンパイルは

CRTBNDC MYOBJLIB/SSLCLT SRCFILE(MYSRCLIB/QCSRC) AUT(*ALL)

クライアントの場合も

sslinit.applicationID = "MY_CLIENT_APP";

sslinit.applicationIDLen = 13;

によってアプリケーションが宣言されていることに注意されたい。