c语言一个完整可执行的多线程openssl实例服务端+客户端

来源:互联网 发布:python 高斯曲线拟合 编辑:程序博客网 时间:2024/06/06 06:42
//服务器端#include <stdio.h>#include <stdlib.h>#include <memory.h>#include <errno.h>#ifndef    _WIN32#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <unistd.h>#else#include <winsock2.h>#include <windows.h>#endif#include "pthread.h"#include <openssl/rsa.h>#include <openssl/crypto.h>#include <openssl/x509.h>#include <openssl/pem.h>#include <openssl/ssl.h>#include <openssl/err.h>//#define CERTF "certs/sslservercert.pem"#define CERTF "/etc/pki/tls/misc/sslservercert.pem"//#define KEYF  "certs/sslserverkey.pem"#define KEYF  "/etc/pki/tls/misc/sslserverkey.pem"//#define    CAFILE  "certs/cacert.pem"#define    CAFILE  "/etc/pki/CA/cacert.pem"#define SOCKET_ERROR -1#define SOCKET int pthread_mutex_t    mlock=PTHREAD_MUTEX_INITIALIZER;static pthread_mutex_t *lock_cs;static long *lock_count;#define CHK_NULL(x) if ((x)==NULL) { printf("null\n"); }#define CHK_ERR(err,s) if ((err)==-1) { printf(" -1 \n"); }#define CHK_SSL(err) if ((err)==-1) {  printf(" -1 \n");}//#define    CAFILE  "demoCA/cacert.pem"int  verify_callback_server(int ok, X509_STORE_CTX *ctx){              printf("verify_callback_server \n");        return ok;}int    SSL_CTX_use_PrivateKey_file_pass(SSL_CTX *ctx,char *filename,char *pass){       EVP_PKEY     *pkey=NULL;       BIO               *key=NULL;       //printf("line=%d\n",__LINE__);             key=BIO_new(BIO_s_file());       //printf("pass=%s\n",pass);       BIO_read_filename(key,filename);       pkey=PEM_read_bio_PrivateKey(key,NULL,NULL,pass);       if(pkey==NULL)       {       //printf("line=%d\n",__LINE__);                    printf("PEM_read_bio_PrivateKey err");              return -1;       }       //printf("line=%d\n",__LINE__);             if (SSL_CTX_use_PrivateKey(ctx,pkey) <= 0)       {              printf("SSL_CTX_use_PrivateKey err\n");              return -1;       }       //printf("line=%d\n",__LINE__);             BIO_free(key);       return 1;}static int s_server_verify=SSL_VERIFY_NONE;void * thread_main(void *arg){        SOCKET s;       SOCKET AcceptSocket;       //WORD wVersionRequested;       //WSADATA wsaData;       struct sockaddr_in  service;       int    err;      size_t             client_len;                                                                                           SSL_CTX             *ctx;      SSL        *ssl;      X509             *client_cert;      char        *str;      char    buf[1024];      SSL_METHOD     *meth;       ssl=(SSL *)arg;       s=SSL_get_fd(ssl);       err = SSL_accept (ssl);      if(err<0)      {             printf("ssl accerr\n");             //return;      }      printf("SSL connection using %s\n", SSL_get_cipher (ssl));      client_cert = SSL_get_peer_certificate (ssl);      if (client_cert != NULL)      {                   printf ("Client certificate:\n");                     str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);                   CHK_NULL(str);                   printf ("\t subject: %s\n", str);                   OPENSSL_free (str);                     str = X509_NAME_oneline (X509_get_issuer_name  (client_cert), 0, 0);                   CHK_NULL(str);                   printf ("\t issuer: %s\n", str);                   OPENSSL_free (str);                     X509_free (client_cert);      }      else                  printf ("Client does not have certificate.\n");while(1){       memset(buf,0,1024);       err = SSL_read (ssl, buf, sizeof(buf) - 1);       if(err<0)       {              printf("ssl read err\n");              //closesocket(s);              close(s);              //return;       }else if(err>0)       {         printf("get : %s\n",buf);       }       else       {         printf("有客户端退出!\n");         break;       }}#if 1      buf[err] = '\0';      buf[err] = '\0';      err = SSL_write (ssl, "I hear you.", strlen("I hear you."));  CHK_SSL(err);#endif      SSL_free (ssl);      //closesocket(s);      close(s);}pthread_t pthreads_thread_id(void){       pthread_t ret;       ret=pthread_self();       return(ret);}void pthreads_locking_callback(int mode, int type, char *file,            int line){       if (mode & CRYPTO_LOCK)              {              pthread_mutex_lock(&(lock_cs[type]));              lock_count[type]++;              }       else              {              pthread_mutex_unlock(&(lock_cs[type]));              }}int main (){/*FILE *fstream;fstream=fopen("/etc/pki/tls/misc/servercert.pem","at+");if(fstream==NULL){  printf("open file failed!\n");  exit(1);}else{  fclose(fstream);  printf("file exit!\n");}*/       int                  err;                       int                  i;       SOCKET        s;       SOCKET        AcceptSocket;       //int        s,AcceptSocket;       //WORD           wVersionRequested;       //WSADATA            wsaData;       struct sockaddr_in  service;       pthread_t pid;      size_t             client_len;      SSL_CTX             *ctx;      SSL               *ssl;      X509             *client_cert;       char        *str;      char    buf[1024];      SSL_METHOD     *meth;      SSL_load_error_strings();      SSLeay_add_ssl_algorithms();      meth = SSLv3_server_method();      ctx = SSL_CTX_new (meth);      if (!ctx)      {                  ERR_print_errors_fp(stderr);                  exit(2);      }      if ((!SSL_CTX_load_verify_locations(ctx,CAFILE,NULL))||(!SSL_CTX_set_default_verify_paths(ctx)))      {             printf("err\n");             exit(1);      }      if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0)      {           ERR_print_errors_fp(stderr);           exit(3);      }      //printf("line=%d\n",__LINE__);      if (SSL_CTX_use_PrivateKey_file_pass(ctx,KEYF,"phrase") <= 0)      //if (SSL_CTX_use_PrivateKey_file_pass(ctx, KEYF, "1428795366") <= 0)      {                  ERR_print_errors_fp(stderr);                  exit(4);      }      //printf("line=%d\n",__LINE__);      if (!SSL_CTX_check_private_key(ctx))      {                  fprintf(stderr,"Private key does not match the certificate public key\n");                  exit(5);      }      s_server_verify=SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT|                                SSL_VERIFY_CLIENT_ONCE;      SSL_CTX_set_verify(ctx,s_server_verify,verify_callback_server);      SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAFILE));      //wVersionRequested = MAKEWORD( 2, 2 );      //err = WSAStartup( wVersionRequested, &wsaData );      //if ( err != 0 )      /*{              printf("err\n");                   return -1;       }*/       s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);       if(s<0) return -1;       service.sin_family = AF_INET;       service.sin_addr.s_addr = inet_addr("127.0.0.1");       service.sin_port = htons(1111);       //if (bind( s, (SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR)       if (bind( s, (struct sockaddr *) &service, sizeof(service)) == SOCKET_ERROR)       {              printf("bind() failed.\n");             // closesocket(s);              close(s);              return -1;       }       if (listen( s, 1 ) == SOCKET_ERROR)              printf("Error listening on socket.\n");       printf("recv .....\n");       lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));       lock_count=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));       for (i=0; i<CRYPTO_num_locks(); i++)       {              lock_count[i]=0;              pthread_mutex_init(&(lock_cs[i]),NULL);       }       CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id);       CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback);       while(1)       {              struct timeval tv;              fd_set fdset;              tv.tv_sec = 1;              tv.tv_usec = 0;              FD_ZERO(&fdset);              FD_SET(s, &fdset);           select(s+1, &fdset, NULL, NULL, (struct timeval *)&tv);           if(FD_ISSET(s, &fdset))              {                     AcceptSocket=accept(s, NULL,NULL);                     ssl = SSL_new (ctx);                         CHK_NULL(ssl);                     err=SSL_set_fd (ssl, AcceptSocket);                     if(err>0)                     {                            err=pthread_create(&pid,NULL,&thread_main,(void *)ssl);                            pthread_detach(pid);                     }                     else                            continue;              }       }      SSL_CTX_free (ctx);      return 0;}//客户端#include <stdio.h>#include <memory.h>#include <errno.h>#ifndef    _WIN32#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <unistd.h>#else#include <windows.h>#endif#include "pthread.h"#include <openssl/crypto.h>#include <openssl/x509.h>#include <openssl/pem.h>#include <openssl/ssl.h>#include <openssl/err.h>#define    MAX_T 1       //set pthread num//#define    CLIENTCERT       "certs/sslclientcert.pem"#define    CLIENTCERT       "/etc/pki/tls/misc/sslclientcert.pem"//#define    CLIENTKEY "clientkey.pem"#define    CLIENTKEY   "/etc/pki/tls/misc/sslclientkey.pem"//#define    CAFILE         "certs/cacert.pem"#define    CAFILE         "/etc/pki/CA/cacert.pem"#define    SOCKET int #define    SOCKET_ERROR -1 static pthread_mutex_t *lock_cs;static long *lock_count;pthread_t pthreads_thread_id(void){       pthread_t ret;       ret=pthread_self();       return(ret);}void pthreads_locking_callback(int mode, int type, char *file,int line){       if (mode & CRYPTO_LOCK){              pthread_mutex_lock(&(lock_cs[type]));              lock_count[type]++;       }       else {              pthread_mutex_unlock(&(lock_cs[type]));       }}int    verify_callback(int ok, X509_STORE_CTX *ctx){       printf("verify_callback\n");       return ok;}int    SSL_CTX_use_PrivateKey_file_pass(SSL_CTX *ctx,char *filename,char *pass){       EVP_PKEY     *pkey=NULL;       BIO               *key=NULL;             key=BIO_new(BIO_s_file());       BIO_read_filename(key,filename);       pkey=PEM_read_bio_PrivateKey(key,NULL,NULL,pass);       if(pkey==NULL) {              printf("PEM_read_bio_PrivateKey err");              return -1;       }       if (SSL_CTX_use_PrivateKey(ctx,pkey) <= 0){              printf("SSL_CTX_use_PrivateKey err\n");              return -1;       }       BIO_free(key);       return 1;}void*thread_main(void *arg){       int          err,buflen,read;       int          sd;       SSL_CTX             *ctx=(SSL_CTX *)arg;       struct            sockaddr_in dest_sin;       SOCKET        sock;       /*PHOSTENT   phe;       WORD           wVersionRequested;       WSADATA            wsaData;*/      SSL               *ssl;      X509             *server_cert;      char     *str;      char        buf [1024];      SSL_METHOD     *meth;       FILE              *fp;      /* wVersionRequested = MAKEWORD( 2, 2 );       err = WSAStartup( wVersionRequested, &wsaData );       if ( err != 0 ){              printf("WSAStartup err\n");                    return -1;       }*/       sock = socket(AF_INET, SOCK_STREAM, 0);       dest_sin.sin_family = AF_INET;       dest_sin.sin_addr.s_addr = inet_addr( "127.0.0.1" );       dest_sin.sin_port = htons( 1111 );again:       //err=connect( sock,(PSOCKADDR) &dest_sin, sizeof( dest_sin));       err=connect( sock,(struct sockaddr *) &dest_sin, sizeof( dest_sin));       if(err<0){              //Sleep(1);              sleep(1);              goto again;       }           ssl = SSL_new (ctx);                               if(ssl==NULL){              printf("ss new err\n");              return ;       }            SSL_set_fd(ssl,sock);      err = SSL_connect (ssl);                          if(err<0) {              printf("SSL_connect err\n");              return;       }      printf ("SSL connection using %s\n", SSL_get_cipher (ssl));      server_cert = SSL_get_peer_certificate (ssl);            printf ("Server certificate:\n");      str = X509_NAME_oneline (X509_get_subject_name (server_cert),0,0);      printf ("\t subject: %s\n", str);      OPENSSL_free (str);      str = X509_NAME_oneline (X509_get_issuer_name (server_cert),0,0);      printf ("\t issuer: %s\n", str);      OPENSSL_free (str);      X509_free (server_cert);      //new add      while(1)      {      char ch_array[1024];      scanf("%s",ch_array);      err = SSL_write(ssl,ch_array,strlen(ch_array));      }      //new add      //err = SSL_write (ssl, "Hello World!", strlen("Hello World!"));      if(err<0) {             printf("ssl write err\n");             return ;      }#if 1       //memset(buf,0,ONE_BUF_SIZE);       memset(buf,0,1024);       err = SSL_read (ssl, buf, sizeof(buf) - 1);                         if(err<0){              printf("ssl read err\n");              return ;       }      buf[err] = '\0';      printf ("Got %d chars:'%s'\n", err, buf);#endif      SSL_shutdown (ssl); /* send SSL/TLS close_notify */      SSL_free (ssl);       //closesocket(sock);      close(sock);}int    main (){      int          err,buflen,read;      int          sd;      struct            sockaddr_in dest_sin;      SOCKET sock;      /*PHOSTENT phe;      WORD wVersionRequested;      WSADATA wsaData;*/      SSL_CTX             *ctx;      SSL        *ssl;      X509             *server_cert;      char     *str;      char        buf [1024];      SSL_METHOD     *meth;       int           i;       pthread_t pid[MAX_T];           SSLeay_add_ssl_algorithms();      meth = SSLv3_client_method();      SSL_load_error_strings();      ctx = SSL_CTX_new (meth);                             if(ctx==NULL){              printf("ssl ctx new eer\n");              return -1;       }      if (SSL_CTX_use_certificate_file(ctx, CLIENTCERT, SSL_FILETYPE_PEM) <= 0){        ERR_print_errors_fp(stderr);        exit(3);      }      //if (SSL_CTX_use_PrivateKey_file_pass(ctx, CLIENTKEY, "123456") <= 0){      if (SSL_CTX_use_PrivateKey_file_pass(ctx, CLIENTKEY, "phrase") <= 0){         ERR_print_errors_fp(stderr);         exit(4);       }       lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));       lock_count=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));       for (i=0; i<CRYPTO_num_locks(); i++)       {              lock_count[i]=0;              pthread_mutex_init(&(lock_cs[i]),NULL);       }       CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id);       CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback);       for(i=0;i<MAX_T;i++)       {                         err=pthread_create(&(pid[i]),NULL,&thread_main,(void *)ctx);              if(err!=0)              {                     printf("pthread_create err\n");                     continue;              }       }       for (i=0; i<MAX_T; i++)       {              pthread_join(pid[i],NULL);       }      SSL_CTX_free (ctx);      printf("test ok\n");       return 0;}编译:gcc -o ssl_server ssl_server.c -Wall -g -lsslgcc -o ssl_client ssl_client.c -Wall -g -lssl生产私钥和证书:openssl genrsa -out privkey.pem 1024openssl req -new -x509 -key privkey.pem -out CAcert.pem -days 1095运行:在一个终端./ssl_server在多个终端./ssl_client

0 0
原创粉丝点击