手机
当前位置:查字典教程网 >编程开发 >C语言 >使用pthread库实现openssl多线程ssl服务端和客户端
使用pthread库实现openssl多线程ssl服务端和客户端
摘要:服务端代码如下:复制代码代码如下:#include#include#include#include#ifndef_WIN32#include...

服务端代码如下:

复制代码 代码如下:

#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("nulln"); }

#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 errn");

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 accerrn");

return ;

}

printf ("SSL connection using %sn", 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: %sn", str);

OPENSSL_free (str);

str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0);

CHK_NULL(str);

printf ("t issuer: %sn", 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 errn");

closesocket(s);

return;

}

printf("get : %sn",buf);

#if 0

buf[err] = '';

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("errn");

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 keyn");

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("errn");

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;

}

客户端代码如下:

复制代码 代码如下:

#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_callbackn");

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 errn");

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 errn");

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 errn");

return ;

}

SSL_set_fd(ssl,sock);

err = SSL_connect (ssl);

if(err<0)

{

printf("SSL_connect errn");

return;

}

printf ("SSL connection using %sn", 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: %sn", str);

OPENSSL_free (str);

str = X509_NAME_oneline (X509_get_issuer_name (server_cert),0,0);

printf ("t issuer: %sn", str);

OPENSSL_free (str);

X509_free (server_cert);

err = SSL_write (ssl, "Hello World!", strlen("Hello World!"));

if(err<0)

{

printf("ssl write errn");

return ;

}

#if 0

memset(buf,0,ONE_BUF_SIZE);

err = SSL_read (ssl, buf, sizeof(buf) - 1);

if(err<0)

{

printf("ssl read errn");

return ;

}

buf[err] = '';

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 eern");

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 errn");

continue;

}

}

for (i=0; i<MAX_T; i++)

{

pthread_join(pid[i],NULL);

}

SSL_CTX_free (ctx);

printf("test okn");

return 0;

}

上述程序在windows下运行成功,采用了windows下的开源pthread库。

需要注意的是,如果多线程用openssl,需要设置两个回调函数

复制代码 代码如下:

CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id);

CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback);

【使用pthread库实现openssl多线程ssl服务端和客户端】相关文章:

使用OpenGL实现3D立体显示的程序代码

C++用指针变量作为函数的参数接受数组的值的问题详细总结

深入解析C++ Data Member内存布局

深入第K大数问题以及算法概要的详解

使用map实现单词转换的实例分析

C++中的friend友元函数详细解析

基于getline()函数的深入理解

用C++实现队列的程序代码

C++实现数组的排序/插入重新排序/以及逆置操作详解

C语言typedef与复杂函数声明问题的深入解析

精品推荐
分类导航