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;
によってアプリケーションが宣言されていることに注意されたい。