我使用TLS/SSL
api在c
中开发了openssl-1.0.2k
服务器。为了验证客户端,我提供了CAfile
并设置了以下选项。
SSL_CTX_load_verify_locations(ctx, "rootCAChain.chain", NULL );
SSL_CTX_set_client_CA_list( ctx, SSL_load_client_CA_file( "rootCAChain.chain" ) );
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL );
SSL_CTX_set_verify_depth(ctx, 2);
其中,rootCAChain.chain
是两个PEM
证书(根CA和中间CA)的列表。
我使用s_client
应用程序使用以下命令测试我的服务器;
openssl s_client -connect 127.0.0.1:8888 -cert client.crt -key client.key -CAfile rootCAChain.chain -msg -verify 2 -verify_return_error
问题:SSL_accept
来电期间的握手失败。我在错误队列中输入了错误,
err = SSL_accept(ssl);
if( err != 1 )
{
ERR_error_string_n( ERR_get_error(), buf, sizeof(buf) );
printf( buf );
exit( 1 );
}
输出:
error:14089086:SSL routines:ssl3_get_client_certificate:certificate verify failed
我在客户端和服务器上拥有相同的证书副本以及CA.这是个问题吗?
另一方面,证书是可以的,因为我使用s_server
进行了测试。完整代码如下。
#define _CRT_SECURE_NO_DEPRECATE
#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#pragma comment (lib,"uuid.lib")
#pragma comment (lib,"libeay32.lib")
#pragma comment (lib,"ssleay32.lib")
#pragma comment (lib,"Ws2_32.lib")
//Prototypen
int startWinsock(void);
int main()
{
long rc;
SOCKET acceptSocket;
SOCKET connectedSocket = NULL;
SOCKADDR_IN addr;
char buf[1024];
char buf2[1024];
SSL_CTX *ctx;
SSL *ssl;
int err;
rc = startWinsock();
if(rc != 0)
{
printf("Fehler: startWinsock, Error Code: %d\n", rc);
return 1;
}
else
{
printf("Winsock Started!\n");
}
acceptSocket = socket(AF_INET,SOCK_STREAM,0);
if(acceptSocket == INVALID_SOCKET)
{
printf("Socket cannot be created, Error Code: %d\n",WSAGetLastError());
return 1;
}
else
{
printf("Socket Created!\n");
}
memset(&addr,0,sizeof(SOCKADDR_IN));
addr.sin_family=AF_INET;
addr.sin_port=htons(8888);
addr.sin_addr.s_addr=INADDR_ANY;
rc=bind(acceptSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN));
if(rc==SOCKET_ERROR)
{
printf("Error: bind, Error code: %d\n",WSAGetLastError());
return 1;
}
else
{
printf("Bind successfull..\n");
}
rc = listen(acceptSocket,10);
if(rc == SOCKET_ERROR)
{
printf("Error: listen, error code: %d\n",WSAGetLastError());
return 1;
}
else
{
printf("acceptSocket is in listen Mode....\n");
}
connectedSocket = accept(acceptSocket,NULL,NULL);
if(connectedSocket==INVALID_SOCKET)
{
printf("Error: accept, error code: %d\n",WSAGetLastError());
return 1;
}
else
{
printf("New connection is accepted...!\n");
}
SSL_load_error_strings();
SSL_library_init();
ctx=SSL_CTX_new(SSLv23_server_method());
err = SSL_CTX_use_certificate_file(ctx, "serverCert.crt", SSL_FILETYPE_PEM);
if (err != 1)
printf("SSL_CTX_use_certificate_file failed\n");
else
printf("certificate file loaded ok\n");
/* Indicate the key file to be used */
err = SSL_CTX_use_PrivateKey_file(ctx, "serverKey.key", SSL_FILETYPE_PEM);
if (err != 1)
printf("SSL_CTX_use_PrivateKey_file failed\n");
else
printf("private-key file loaded ok\n");
/* Make sure the key and certificate file match. */
if (SSL_CTX_check_private_key(ctx) != 1)
printf("SSL_CTX_check_private_key failed\n");
else
printf("private key verified ok\n");
if (SSL_CTX_load_verify_locations(ctx, "rootCAChain.chain", NULL ) != 1)
printf("Error loading CA file and/or directory");
// if (SSL_CTX_set_default_verify_paths(ctx) != 1)
// printf("Error loading default CA file and/or directory");
SSL_CTX_set_client_CA_list( ctx, SSL_load_client_CA_file( "rootCAChain.chain" ) );
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT|SSL_VERIFY_CLIENT_ONCE, NULL );
SSL_CTX_set_verify_depth(ctx, 2);
// SSL_CTX_set_options(ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3);
ssl = SSL_new(ctx);
if(!ssl)
{
closesocket(connectedSocket);
fprintf(stderr, "SSL creation error\n");
return -1;
}
SSL_set_fd(ssl, connectedSocket);
err = SSL_accept(ssl);
if( err != 1 )
{
ERR_error_string_n( ERR_get_error(), buf, sizeof(buf) );
printf( buf );
exit( 1 );
}
printf("SSL accepted.. \n");
while(1)
{
int read_size = SSL_read(ssl, buf, sizeof(buf) );
if ( read_size > 0 )
{
buf[read_size]='\0';
printf("Getting %d Bytes of Data\nData: %s\n", read_size, buf);
}
sprintf( buf2,"Du mich auch %s\r\n", "x" );
err=SSL_write(ssl, buf2, strlen(buf2));
if(!err)
{
closesocket(connectedSocket);
fprintf(stderr, "SSL write error\n");
return -1;
}
Sleep(1000);
}
SSL_shutdown(ssl);
SSL_free(ssl);
SSL_CTX_free(ctx);
fflush(stdout);
closesocket(acceptSocket);
closesocket(connectedSocket);
WSACleanup();
return 0;
}
int startWinsock(void)
{
WSADATA wsa;
return WSAStartup(MAKEWORD(2,0),&wsa);
}