我正在使用openssl(作为客户端和服务器)的linux多进程平台上工作,我将需要使用EXTERNAL CACHE实现会话重用(具有会话ID)。
我成功地连接了#34;一些回调openssl以获得新的通知并获得SSL_SESSION,但仅当我使用相同的SSL_CTX对象时。
我的问题是当SSL_CTX对象永远不是同一个时,我如何重用会话对象。
Openssl似乎不是为此而构建的。 简而言之,我想为SSL会话实现一个外部缓存,它不依赖于SSL_CTX。
还有一件事:你知道也许是一个开源项目吗?我认为mod_ssl就是这样,但不确定(需要检查)。
非常感谢。
*编辑*
我写了一些代码作为示例:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
static SSL_SESSION* sess_session = 0;
static unsigned char* char_session;
static long char_session_length;
static int new_session_cb(struct ssl_st *ssl, SSL_SESSION *sessionX)
{
printf("!!! NEW SESSION CB !!!\n");
char_session_length = i2d_SSL_SESSION(sessionX, &char_session);
printf("Session length: %ld bytes.\n",char_session_length);
sess_session = sessionX;
return 0;
}
static void remove_session_cb(struct ssl_ctx_st *ctx, SSL_SESSION *sess)
{
printf("!!! REMOVE SESSION CB !!!\n");
return;
}
static SSL_SESSION *get_session_cb(struct ssl_st *ssl, const unsigned char *data, int len, int *copy)
{
printf("!!! GET SESSION CB !!!\n");
/* allow the session to be freed automatically by openssl */
*copy = 0;
SSL_SESSION* a;
const unsigned char* ptr = (const unsigned char *)malloc(char_session_length);
memcpy(ptr,char_session, char_session_length);
a = d2i_SSL_SESSION(NULL, &ptr, char_session_length);
free((void*)ptr);
return a;
}
int main(int argc, char **argv)
{
SSL *ssl = NULL;
SSL_CTX *ctx = NULL;
int servfd = -1;
int clntfd = -1;
struct sockaddr_in serv;
struct sockaddr_in clnt;
socklen_t socksize;
char buf[128];
int ret;
int clean_disconnect;
/* Initialize OpenSSL. */
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
/* Setup the socket to listen for incoming connections. */
memset(&serv, 0, sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = htonl(INADDR_ANY);
serv.sin_port = htons(4433);
servfd = socket(AF_INET, SOCK_STREAM, 0);
if (servfd == -1) {
printf("Failed to create socket\n");
return 0;
}
if (bind(servfd, (struct sockaddr *)&serv, sizeof(struct sockaddr)) != 0) {
printf("Failed to bind\n");
goto cleanup;
}
if (listen(servfd, 512) != 0) {
printf("Failed to listen\n");
goto cleanup;
}
/* Wait for and handle connections as they come in. */
while (1) {
printf("Loop..\n");
/* Generate an SSL server context. */
ctx = SSL_CTX_new(SSLv23_server_method());
if (ctx == NULL) {
printf("Failed to create SSL server context\n");
goto cleanup;
}
/* Set some options and the session id.
* SSL_OP_NO_SSLv2: SSLv2 is insecure, disable it.
* SSL_OP_NO_TICKET: We don't want TLS tickets used because this is an SSL server caching example.
* It should be fine to use tickets in addition to server side caching.
*/
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_TICKET);
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_AUTO_CLEAR|SSL_SESS_CACHE_NO_INTERNAL);
SSL_CTX_sess_set_new_cb(ctx, new_session_cb);
SSL_CTX_sess_set_remove_cb(ctx,remove_session_cb);
SSL_CTX_sess_set_get_cb(ctx, get_session_cb);
/* Load certificate. */
if (SSL_CTX_use_certificate_file(ctx, "/XXXX/certs/www.site1.com.crt", SSL_FILETYPE_PEM) != 1) {
printf("Failed to load cert.pem\n");
goto cleanup;
}
if (SSL_CTX_use_PrivateKey_file(ctx, "/XXXX/certs/www.site1.com.key.pem.insecure", SSL_FILETYPE_PEM) != 1) {
printf("Failed to load key.pem\n");
goto cleanup;
}
if (!SSL_CTX_check_private_key(ctx)) {
printf("Failed to validate cert\n");
goto cleanup;
}
socksize = sizeof(struct sockaddr_in);
clntfd = accept(servfd, (struct sockaddr *)&clnt, &socksize);
if (clntfd == -1) {
continue;
}
ssl = SSL_new(ctx);
SSL_set_fd(ssl, clntfd);
SSL_accept(ssl);
clean_disconnect = 1;
ret = SSL_read(ssl, buf, sizeof(buf));
if (ret <= 0) {
switch (SSL_get_error(ssl, ret)) {
case SSL_ERROR_NONE:
case SSL_ERROR_ZERO_RETURN:
break;
default:
clean_disconnect = 0;
break;
}
}
if (clean_disconnect) {
SSL_shutdown(ssl);
} else {
SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
}
SSL_free(ssl);
close(clntfd);
cleanup:
if (ctx != NULL)
SSL_CTX_free(ctx);
}
if (servfd != -1)
close(servfd);
return 0;
}
我遇到了这个崩溃:
Loop..
!!! NEW SESSION CB !!!
Session length: 115 bytes.
Clean Disconnect do shutdown...
Loop..
!!! GET SESSION CB !!!
Program received signal SIGSEGV, Segmentation fault.
malloc_consolidate (av=av@entry=0x7ffff79b1760 <main_arena>) at malloc.c:4151
4151 malloc.c: No such file or directory.
(gdb) bt
#0 malloc_consolidate (av=av@entry=0x7ffff79b1760 <main_arena>) at malloc.c:4151
#1 0x00007ffff7672ce8 in _int_malloc (av=0x7ffff79b1760 <main_arena>, bytes=1056) at malloc.c:3423
#2 0x00007ffff76756c0 in __GI___libc_malloc (bytes=1056) at malloc.c:2891
#3 0x00000000004afa36 in CRYPTO_malloc (num=1056, file=0x5f893a "crypto/kdf/tls1_prf.c", line=40) at crypto/mem.c:92
#4 0x00000000004afa69 in CRYPTO_zalloc (num=1056, file=0x5f893a "crypto/kdf/tls1_prf.c", line=40) at crypto/mem.c:100
#5 0x00000000004adefd in pkey_tls1_prf_init (ctx=0x8badf0) at crypto/kdf/tls1_prf.c:40
#6 0x00000000004a79be in int_ctx_new (pkey=0x0, e=0x0, id=1021) at crypto/evp/pmeth_lib.c:135
#7 0x00000000004a7cca in EVP_PKEY_CTX_new_id (id=1021, e=0x0) at crypto/evp/pmeth_lib.c:220
#8 0x000000000044d6e6 in tls1_PRF (s=0x8bb800, seed1=0x5f0c09, seed1_len=13, seed2=0x8baa10, seed2_len=32, seed3=0x8baa30, seed3_len=32, seed4=0x0, seed4_len=0,
seed5=0x0, seed5_len=0, sec=0x8cc0f8 "\324\f", <incomplete sequence \353>, slen=48, out=0x8bad90 "h\031\233\367\377\177", olen=88) at ssl/t1_enc.c:65
#9 0x000000000044d945 in tls1_generate_key_block (s=0x8bb800, km=0x8bad90 "h\031\233\367\377\177", num=88) at ssl/t1_enc.c:94
#10 0x000000000044e6de in tls1_setup_key_block (s=0x8bb800) at ssl/t1_enc.c:417
#11 0x0000000000431a37 in ossl_statem_server_pre_work (s=0x8bb800, wst=WORK_MORE_A) at ssl/statem/statem_srvr.c:477
#12 0x0000000000424d78 in write_state_machine (s=0x8bb800) at ssl/statem/statem.c:725
#13 0x0000000000424658 in state_machine (s=0x8bb800, server=1) at ssl/statem/statem.c:394
#14 0x0000000000424138 in ossl_statem_accept (s=0x8bb800) at ssl/statem/statem.c:175
#15 0x000000000041ca46 in SSL_do_handshake (s=0x8bb800) at ssl/ssl_lib.c:3025
#16 0x00000000004199ba in SSL_accept (s=0x8bb800) at ssl/ssl_lib.c:1457
#17 0x00000000004034ee in main (argc=1, argv=0x7fffffffdf28) at ../src/openssl_server2.c:195
(gdb)
答案 0 :(得分:0)
您想使用PEM_write_bio_SSL_SESSION
,PEM_read_bio_SSL_SESSION
,SSL_get1_session
和SSL_set_session
。但这是基本的东西。
以下是详细解释的link。这个对我有用。您也可以加密磁盘上的密码。
取决于在磁盘上保留秘密不是问题。