源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

使用pthread库实现openssl多线程ssl服务端和客户端

  • 时间:2022-10-20 15:42 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:使用pthread库实现openssl多线程ssl服务端和客户端
服务端代码如下:
[u]复制代码[/u] 代码如下:
#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 KEYF  "certs/sslserverkey.pem" #define    CAFILE  "certs/cacert.pem" 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  "certs/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;        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; } static int s_server_verify=SSL_VERIFY_NONE; void * thread_main(void *arg) {         SOCKET s,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");        memset(buf,0,1024);        err = SSL_read (ssl, buf, sizeof(buf) - 1);        if(err<0)        {               printf("ssl read err\n");               closesocket(s);               return;        }        printf("get : %s\n",buf); #if 0       buf[err] = '\0';       err = SSL_write (ssl, "I hear you.", strlen("I hear you."));  CHK_SSL(err); #endif       SSL_free (ssl);        closesocket(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 () {        int                  err;                        int                  i;        SOCKET        s,AcceptSocket;        WORD           wVersionRequested;        WSADATA            wsaData;        struct sockaddr_in  service;        pthread_tpid;       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);       }       if (SSL_CTX_use_PrivateKey_file_pass(ctx, KEYF, "123456") <= 0)       {                   ERR_print_errors_fp(stderr);                   exit(4);       }        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)        {               printf("bind() failed.\n");               closesocket(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; }
客户端代码如下:
[u]复制代码[/u] 代码如下:
#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 1000 #define    CLIENTCERT       "certs/sslclientcert.pem" #define    CLIENTKEY  "certs/sslclientkey.pem" #define    CAFILE         "certs/cacert.pem" 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));        if(err<0)        {               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);        err = SSL_write (ssl, "Hello World!", strlen("Hello World!"));        if(err<0)        {               printf("ssl write err\n");               return ;        } #if 0        memset(buf,0,ONE_BUF_SIZE);       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); } int    main () {        int          err,buflen,read;       int          sd;        struct            sockaddr_in dest_sin;        SOCKETsock;        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_tpid[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)     {          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; }
上述程序在windows下运行成功,采用了windows下的开源pthread库。 需要注意的是,如果多线程用openssl,需要设置两个回调函数
[u]复制代码[/u] 代码如下:
CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id); CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback);
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部