找到一种在内存中加载多个ssl证书(2 RSA)的方法(ssl上下文)?OpenSSL



试图在内存中加载多个ssl证书。我试着从文档中编写代码,但失败了,因为文档对我来说很难理解。向stackoverflow寻求帮助

我正在寻找一种方法,这两个证书可以同时工作。

我必须在内存中加载的证书是赛门铁克和Zuul(。pem格式)。赛门铁克。Pem和zuul。文件是密码保护的,它包含(一个证书和一个私钥)。

下面的代码只加载赛门铁克证书。Openssl版本:Openssl 1.1.1g FIPS 2020年4月21日

if(server_ctx==NULL)
{
/* Global system initialization*/
SSL_library_init();
SSL_load_error_strings();
}
meth=TLS_server_method();
if(status == true)
{
server_ctx=SSL_CTX_new(meth);
if(server_ctx != NULL)
{
if((strcmp(protocol_current_version,"Y") == 0) || (strcmp(protocol_current_version,"y") == 0))
{
SSL_CTX_set_min_proto_version(server_ctx, TLS1_VERSION);
}
else if((strcmp(protocol_current_version,"N") == 0) || (strcmp(protocol_current_version,"n") == 0))
{
SSL_CTX_set_min_proto_version(server_ctx, TLS1_2_VERSION);
}
}
}
/* Load our keys and certificates*/
if(!(SSL_CTX_use_certificate_file(server_ctx,keyfile,SSL_FILETYPE_PEM)))
{ 
status = false; 
LOG(LEVEL1,"Error!!! Couldn't read certificate file: %s",ERR_error_string(ERR_get_error(),NULL));    
}

if(status==true)
{SSL_CTX_set_default_passwd_cb(server_ctx,password_cb);}

if(status==true)
{
if(!(SSL_CTX_use_PrivateKey_file(server_ctx,keyfile,SSL_FILETYPE_PEM)))
{       
LOG(LEVEL1,"Error!!! Couldn't read key file: %s",ERR_error_string(ERR_get_error(),NULL));    
status = false;
}
}
/* Load the CAs we trust*/
if(status==true)
{
if(!(SSL_CTX_load_verify_locations(server_ctx,ca_list,0)))
{           
LOG(LEVEL1,"Error!!! Couldn't read CA_LIST: %s",ERR_error_string(ERR_get_error(),NULL));
status=false;
}
}
//Force Mutual authentication if verify_ssl_peer is set
if(verify_ssl_peer)
{
SSL_CTX_set_verify(server_ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,NULL);
}

SSL_CTX_set_verify_depth(server_ctx,1);
//Set AUTO MODE RETRY Flag, Will not bother application till data is completely read
SSL_CTX_set_mode(server_ctx,SSL_MODE_AUTO_RETRY);   
//Set the list of supported cipher suites. Typically used to force only AES128 or AES256 bit encryption:
if(status==true)
{
//Force the cipher is verify_ssl_cipher is set
if(verify_ssl_cipher)
{
if(cipher_list==NULL)
{
LOG(LEVEL1,"[%s]: Error!!! Cipher list is set to NULL, will not initialize",__FUNCTION__);
status = false;
}
else
{

if(!SSL_CTX_set_cipher_list(server_ctx,cipher_list))
{LOG(LEVEL1,"Error!!! Failed to set cipher_list for ctx: %s",ERR_error_string(ERR_get_error(),NULL));}
}
}
}   
if(status==true)
{

/* Load randomness */
if(!(RAND_load_file(random_file,1024*1024)))
{
LOG(LEVEL1,"Error!!! Load randomness failed:%s",ERR_error_string(ERR_get_error(),NULL));
status=false;
}
}
if(status==true)
{
long opts = SSL_CTX_get_options(server_ctx);
opts = SSL_CTX_set_options(server_ctx,SSL_OP_ALL|opts);

LOG(LEVEL1,"SSl Server CTX Options set:%04x",opts);                     
}

一个可能的解决方案是在TLS客户端Hello中使用服务器名称指示:Zuul和赛门铁克客户端可以设置不同的TLS SNI字段,以便您的服务器可以详细说明它以选择适当的证书链。

详细说明,您的服务器应首先为Zuul设置一个SSL上下文,为Symantec设置另一个具有正确私钥和证书链的SSL上下文,然后在每个上下文中设置服务器名回调。

例如,为您的赛门铁克上下文设置服务器名称回调:

SSL_CTX_set_tlsext_servername_callback(symantec_context, serverNameCallbackHandler);

您可以设置一个参数,将由serverNameCallbackHandler函数处理此SSL_CTX:

SSL_CTX_set_tlsext_servername_arg(symantec_context, &your_data);

然后你应该实现将在TLS握手期间调用的回调。例如:

static int serverNameCallbackHandler(SSL *ssl, int *ad, void *arg)
{
MyData *data = (MyData *) arg;
// ...
const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
if (servername)
{
//Select the proper context
//...

if (match_found)
{
SSL_CTX* ctx = symantec_context;
SSL_CTX* v = SSL_set_SSL_CTX(ssl, ctx);
if (v != ctx)
{
// Internal Error on ssl context switch!
return SSL_TLSEXT_ERR_NOACK;
}
}
}

// NOTE: On Server name mismatch use the default context
return SSL_TLSEXT_ERR_OK;
}

关于如何在客户端处理SNI的信息,我认为openssl命令的开源代码非常有帮助。注意,你可以用openssl命令测试你的服务器:openssl s_client -servername 'your sni name' -CAfile ./RootCA.pem -connect ip:port

最新更新