Внешний кеш для сеансов в платформе с несколькими процессами

Я работаю над многопроцессорной платформой Linux, которая использует openssl (в качестве клиента и сервера), и мне нужно будет реализовать повторное использование сеанса (с идентификатором сеанса) с ВНЕШНИМ КЭШОМ.

Мне удалось «подключить» некоторый обратный вызов к 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) 

person Mikael Elharrar    schedule 06.09.2016    source источник


Ответы (1)


Вы хотите использовать PEM_write_bio_SSL_SESSION, PEM_read_bio_SSL_SESSION, SSL_get1_session и SSL_set_session. Но это базовые вещи.

Вот ссылка, которая подробно объясняет. Меня устраивает. Вы также можете зашифровать дисковый секрет.

Зависит от того, не является ли для вас проблемой сохранение секретов на диске.

person Harendra Rawat    schedule 06.12.2016