编译
SSL/TLS client server examples using openssl
## Build
$ mkdir build
$ cd build
$ cmake ..
$ make
$ cp -rf ../certs ./
测试运行
### Server side
$ ./server
Certificate Verify Success
Client Hello World
```
### Client Side
$ ./client
Socket successfully created..
connected to the server..
Certificate Verify Success
SSL server send Client Hello World Appended by SSL serve
```
证书
示例代码
//ssl_client_libssl.c
#define SSL_CLIENT_RSA_CERT "./certs/client.crt"
#define SSL_CLIENT_RSA_KEY "./certs/client.key"
#define SSL_CLIENT_RSA_CA_CERT "./certs/ca.crt"
#define SSL_SERVER_ADDR "/tmp/ssl_server"
#define OFF 0
#define ON 1
#define USE_AF_UNIX 0
#define MAX 80
#define IP "127.0.0.1"
#define PORT 10001
#define SA struct sockaddr
int main(void)
{
int verify_peer = ON;
SSL_METHOD *client_meth;
SSL_CTX *ssl_client_ctx;
int clientsocketfd;
int handshakestatus;
SSL *clientssl;
char buffer[1024] = "Client Hello World";
int ret;
SSL_library_init();
SSL_load_error_strings();
client_meth = TLSv1_2_client_method();
ssl_client_ctx = SSL_CTX_new(client_meth);
if(!ssl_client_ctx)
{
ERR_print_errors_fp(stderr);
return -1;
}
printf("[c]SSL init successfully\n");
if(verify_peer)
{
if(SSL_CTX_use_certificate_file(ssl_client_ctx, SSL_CLIENT_RSA_CERT, SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stderr);
return -1;
}
if(SSL_CTX_use_PrivateKey_file(ssl_client_ctx, SSL_CLIENT_RSA_KEY, SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stderr);
return -1;
}
if(SSL_CTX_check_private_key(ssl_client_ctx) != 1)
{
printf("[c]Private and certificate is not matching\n");
return -1;
}
printf("[c]Private and certificate successfully\n");
}
//See function man pages for instructions on generating CERT files
if(!SSL_CTX_load_verify_locations(ssl_client_ctx, SSL_CLIENT_RSA_CA_CERT, NULL))
{
ERR_print_errors_fp(stderr);
return -1;
}
SSL_CTX_set_verify(ssl_client_ctx, SSL_VERIFY_PEER, NULL);
SSL_CTX_set_verify_depth(ssl_client_ctx, 4);
#if USE_AF_UNIX
struct sockaddr_un serveraddr;
if((clientsocketfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
{
printf("[c]Error on socket creation\n");
return -1;
}
memset(&serveraddr, 0, sizeof(struct sockaddr_un));
serveraddr.sun_family = AF_UNIX;
serveraddr.sun_path[0] = 0;
strncpy(&(serveraddr.sun_path[1]), SSL_SERVER_ADDR, strlen(SSL_SERVER_ADDR) + 1);
connect(clientsocketfd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr_un));
#else
struct sockaddr_in serveraddr;
// socket create and varification
clientsocketfd = socket(AF_INET, SOCK_STREAM, 0);
if (clientsocketfd == -1) {
printf("[c]socket creation failed...\n");
exit(0);
}
else
printf("[c]Socket successfully created OK..\n");
bzero(&serveraddr, sizeof(serveraddr));
// assign IP, PORT
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(IP);
serveraddr.sin_port = htons(PORT);
// connect the client socket to server socket
if (connect(clientsocketfd, (SA*)&serveraddr, sizeof(serveraddr)) != 0) {
printf("[c]connection with the server failed...\n");
exit(0);
}
else
printf("[c]connected to the server OK..\n");
#endif
clientssl = SSL_new(ssl_client_ctx);
if(!clientssl)
{
printf("[c]Error SSL_new\n");
return -1;
}
SSL_set_fd(clientssl, clientsocketfd);
printf("[c]clientssl=%d,clientsocketfd=%d\n",clientssl,clientsocketfd);
if((ret = SSL_connect(clientssl)) != 1)
{
printf("[c]SSL_connect,Handshake Error %d\n", SSL_get_error(clientssl, ret));
return -1;
}
printf("[c]Handshake OK..\n");
X509 *ssl_client_cert = NULL;
ssl_client_cert = SSL_get_peer_certificate(clientssl);
if(ssl_client_cert)
{
long verifyresult;
verifyresult = SSL_get_verify_result(clientssl);
if(verifyresult == X509_V_OK)
printf("[c]Certificate Verify Success\n");
else
printf("[c]Certificate Verify Failed\n");
X509_free(ssl_client_cert);
}
else
printf("[c]There is no client certificate\n");
SSL_write(clientssl, buffer, strlen(buffer));
printf("[c]SSL client send: %s\n", buffer);
memset(buffer, 0, sizeof(buffer));
SSL_read(clientssl, buffer, sizeof(buffer));
printf("[c]SSL client recv: %s\n", buffer);
SSL_shutdown(clientssl);
close(clientsocketfd);
SSL_free(clientssl);
SSL_CTX_free(ssl_client_ctx);
return 0;
}
//ssl_server_libssl.c
int main(void)
{
int verify_peer = ON;
const SSL_METHOD *server_meth;
SSL_CTX *ssl_server_ctx;
int serversocketfd;
int clientsocketfd;
int handshakestatus;
SSL_library_init();
SSL_load_error_strings();
server_meth = TLSv1_2_server_method();
ssl_server_ctx = SSL_CTX_new(server_meth);
if(!ssl_server_ctx)
{
ERR_print_errors_fp(stderr);
return -1;
}
printf("[s]SSL init successfully\n");
if(SSL_CTX_use_certificate_file(ssl_server_ctx, SSL_SERVER_RSA_CERT, SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stderr);
return -1;
}
if(SSL_CTX_use_PrivateKey_file(ssl_server_ctx, SSL_SERVER_RSA_KEY, SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stderr);
return -1;
}
if(SSL_CTX_check_private_key(ssl_server_ctx) != 1)
{
printf("[s]Private and certificate is not matching\n");
return -1;
}
printf("[s]Private and certificate successfully\n");
if(verify_peer)
{
//See function man pages for instructions on generating CERT files
if(!SSL_CTX_load_verify_locations(ssl_server_ctx, SSL_SERVER_RSA_CA_CERT, NULL))
{
ERR_print_errors_fp(stderr);
return -1;
}
SSL_CTX_set_verify(ssl_server_ctx, SSL_VERIFY_PEER, NULL);
SSL_CTX_set_verify_depth(ssl_server_ctx, 1);
}
#if USE_AF_UNIX
struct sockaddr_un serveraddr;
if((serversocketfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
{
printf("[s]Error on socket creation\n");
return -1;
}
memset(&serveraddr, 0, sizeof(struct sockaddr_un));
serveraddr.sun_family = AF_UNIX;
serveraddr.sun_path[0] = 0;
strncpy(&(serveraddr.sun_path[1]), SSL_SERVER_ADDR, strlen(SSL_SERVER_ADDR) + 1);
if(bind(serversocketfd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr_un)))
{
printf("[s]server bind error\n");
return -1;
}
#else
struct sockaddr_in serveraddr;
if((serversocketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("[s]Error on socket creation\n");
return -1;
}
memset(&serveraddr, 0, sizeof(struct sockaddr_in));
// assign IP, PORT
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(PORT);
if ((bind(serversocketfd, (SA*)&serveraddr, sizeof(serveraddr))) != 0)
{
printf("[s]server bind error\n");
return -1;
}
printf("[s]server bind OK\n");
#endif
if(listen(serversocketfd, SOMAXCONN))
{
printf("[s]Error on listen\n");
return -1;
}
printf("[s]server listen OK\n");
while(1)
{
SSL *serverssl;
char buffer[1024] = {0};
int bytesread = 0;
int addedstrlen;
int ret;
clientsocketfd = accept(serversocketfd, NULL, 0);
serverssl = SSL_new(ssl_server_ctx);
if(!serverssl)
{
printf("[s]Error SSL_new\n");
return -1;
}
SSL_set_fd(serverssl, clientsocketfd);
printf("[s]serverssl=%d,clientsocketfd=%d\n",serverssl,clientsocketfd);
if((ret = SSL_accept(serverssl))!= 1)
{
printf("[s]SSL_accept,Handshake Error %d\n", SSL_get_error(serverssl, ret));
return -1;
}
printf("[s]Handshake OK..\n");
if(verify_peer)
{
X509 *ssl_client_cert = NULL;
ssl_client_cert = SSL_get_peer_certificate(serverssl);
if(ssl_client_cert)
{
long verifyresult;
verifyresult = SSL_get_verify_result(serverssl);
if(verifyresult == X509_V_OK)
printf("[s]Certificate Verify Success\n");
else
printf("[s]Certificate Verify Failed\n");
X509_free(ssl_client_cert);
}
else
printf("[s]There is no client certificate\n");
}
bytesread = SSL_read(serverssl, buffer, sizeof(buffer));
addedstrlen = strlen("Appended by SSL server");
printf("[s]SSL server recv:%s\n", buffer);
strncpy(&buffer[bytesread], " Appended by SSL server", addedstrlen);
SSL_write(serverssl, buffer, bytesread + addedstrlen);
printf("[s]SSL server send:%s\n", buffer);
SSL_shutdown(serverssl);
close(clientsocketfd);
clientsocketfd = -1;
SSL_free(serverssl);
serverssl = NULL;
}
close(serversocketfd);
SSL_CTX_free(ssl_server_ctx);
return 0;
}