Exemplo n.º 1
0
NOEXPORT int load_key_file(SERVICE_OPTIONS *section) {
    int i, reason;
    UI_DATA ui_data;

    s_log(LOG_INFO, "Loading private key from file: %s", section->key);
    if(file_permissions(section->key))
        return 1; /* FAILED */

    ui_data.section=section; /* setup current section for callbacks */
    SSL_CTX_set_default_passwd_cb(section->ctx, password_cb);

    for(i=0; i<=3; i++) {
        if(!i && !cache_initialized)
            continue; /* there is no cached value */
        SSL_CTX_set_default_passwd_cb_userdata(section->ctx,
            i ? &ui_data : NULL); /* try the cached password first */
        if(SSL_CTX_use_PrivateKey_file(section->ctx, section->key,
                SSL_FILETYPE_PEM))
            break;
        reason=ERR_GET_REASON(ERR_peek_error());
        if(i<=2 && reason==EVP_R_BAD_DECRYPT) {
            sslerror_queue(); /* dump the error queue */
            s_log(LOG_ERR, "Wrong pass phrase: retrying");
            continue;
        }
        sslerror("SSL_CTX_use_PrivateKey_file");
        return 1; /* FAILED */
    }
    s_log(LOG_INFO, "Private key loaded from file: %s", section->key);
    return 0; /* OK */
}
Exemplo n.º 2
0
NOEXPORT void sslerror_queue(void) { /* recursive dump of the error queue */
    unsigned long err;

    err=ERR_get_error();
    if(err) {
        sslerror_queue();
        sslerror_log(err, "error queue");
    }
}
Exemplo n.º 3
0
Arquivo: ctx.c Projeto: Jimdo/stunnel
void sslerror(char *txt) { /* OpenSSL error handler */
    unsigned long err;

    err=ERR_get_error();
    if(err) {
        sslerror_queue();
        sslerror_log(err, txt);
    } else {
        s_log(LOG_ERR, "%s: Peer suddenly disconnected", txt);
    }
}
Exemplo n.º 4
0
Arquivo: ctx.c Projeto: Jimdo/stunnel
NOEXPORT int load_key_file(SERVICE_OPTIONS *section) {
    int i, reason;
    UI_DATA ui_data;
#if !defined(USE_WIN32) && !defined(USE_OS2)
    struct stat st; /* buffer for stat */
#endif

    s_log(LOG_INFO, "Loading key from file: %s", section->key);

#if !defined(USE_WIN32) && !defined(USE_OS2)
    /* check permissions of the private key file */
    if(stat(section->key, &st)) {
        ioerror("Private key file not found");
        return 1; /* FAILED */
    }
    if(st.st_mode & 7)
        s_log(LOG_WARNING, "Insecure file permissions on %s",
            section->key);
#endif

    ui_data.section=section; /* setup current section for callbacks */
#if defined(USE_WIN32) || OPENSSL_VERSION_NUMBER>=0x0090700fL
    SSL_CTX_set_default_passwd_cb(section->ctx, password_cb);
#endif

    for(i=0; i<=3; i++) {
        if(!i && !cache_initialized)
            continue; /* there is no cached value */
        SSL_CTX_set_default_passwd_cb_userdata(section->ctx,
            i ? &ui_data : NULL); /* try the cached password first */
        if(SSL_CTX_use_PrivateKey_file(section->ctx, section->key,
                SSL_FILETYPE_PEM))
            break;
        reason=ERR_GET_REASON(ERR_peek_error());
        if(i<=2 && reason==EVP_R_BAD_DECRYPT) {
            sslerror_queue(); /* dump the error queue */
            s_log(LOG_ERR, "Wrong pass phrase: retrying");
            continue;
        }
        sslerror("SSL_CTX_use_PrivateKey_file");
        return 1; /* FAILED */
    }
    return 0; /* OK */
}
Exemplo n.º 5
0
Arquivo: ctx.c Projeto: Jimdo/stunnel
NOEXPORT int load_key_engine(SERVICE_OPTIONS *section) {
    int i, reason;
    UI_DATA ui_data;
    EVP_PKEY *pkey;
    UI_METHOD *ui_method;

    s_log(LOG_INFO, "Loading key from engine: %s", section->key);

    ui_data.section=section; /* setup current section for callbacks */
#if defined(USE_WIN32) || OPENSSL_VERSION_NUMBER>=0x0090700fL
    SSL_CTX_set_default_passwd_cb(section->ctx, password_cb);
#endif

#ifdef USE_WIN32
    ui_method=UI_create_method("stunnel WIN32 UI");
    UI_method_set_reader(ui_method, pin_cb);
#else /* USE_WIN32 */
    ui_method=UI_OpenSSL();
    /* workaround for broken engines */
    /* ui_data.section=NULL; */
#endif /* USE_WIN32 */
    for(i=1; i<=3; i++) {
        pkey=ENGINE_load_private_key(section->engine, section->key,
            ui_method, &ui_data);
        if(!pkey) {
            reason=ERR_GET_REASON(ERR_peek_error());
            if(i<=2 && (reason==7 || reason==160)) { /* wrong PIN */
                sslerror_queue(); /* dump the error queue */
                s_log(LOG_ERR, "Wrong PIN: retrying");
                continue;
            }
            sslerror("ENGINE_load_private_key");
            return 1; /* FAILED */
        }
        if(SSL_CTX_use_PrivateKey(section->ctx, pkey))
            break; /* success */
        sslerror("SSL_CTX_use_PrivateKey");
        return 1; /* FAILED */
    }
    return 0; /* OK */
}
Exemplo n.º 6
0
NOEXPORT void info_callback(const SSL *ssl, int where, int ret) {
    CLI *c;
    SSL_CTX *ctx;
    const char *state_string;

    c=SSL_get_ex_data((SSL *)ssl, index_cli);
    if(c) {
        int state=SSL_get_state((SSL *)ssl);

#if 0
        s_log(LOG_DEBUG, "state = %x", state);
#endif

        /* log the client certificate request (if received) */
#ifndef SSL3_ST_CR_CERT_REQ_A
        if(state==TLS_ST_CR_CERT_REQ)
#else
        if(state==SSL3_ST_CR_CERT_REQ_A)
#endif
            print_client_CA_list(SSL_get_client_CA_list(ssl));
#ifndef SSL3_ST_CR_SRVR_DONE_A
        if(state==TLS_ST_CR_SRVR_DONE)
#else
        if(state==SSL3_ST_CR_SRVR_DONE_A)
#endif
            if(!SSL_get_client_CA_list(ssl))
                s_log(LOG_INFO, "Client certificate not requested");

        /* prevent renegotiation DoS attack */
        if((where&SSL_CB_HANDSHAKE_DONE)
                && c->reneg_state==RENEG_INIT) {
            /* first (initial) handshake was completed, remember this,
             * so that further renegotiation attempts can be detected */
            c->reneg_state=RENEG_ESTABLISHED;
        } else if((where&SSL_CB_ACCEPT_LOOP)
                && c->reneg_state==RENEG_ESTABLISHED) {
#ifndef SSL3_ST_SR_CLNT_HELLO_A
            if(state==TLS_ST_SR_CLNT_HELLO
                    || state==TLS_ST_SR_CLNT_HELLO) {
#else
            if(state==SSL3_ST_SR_CLNT_HELLO_A
                    || state==SSL23_ST_SR_CLNT_HELLO_A) {
#endif
                /* client hello received after initial handshake,
                 * this means renegotiation -> mark it */
                c->reneg_state=RENEG_DETECTED;
            }
        }

        if(c->opt->log_level<LOG_DEBUG) /* performance optimization */
            return;
    }

    if(where & SSL_CB_LOOP) {
        state_string=SSL_state_string_long(ssl);
        if(strcmp(state_string, "unknown state"))
            s_log(LOG_DEBUG, "SSL state (%s): %s",
                where & SSL_ST_CONNECT ? "connect" :
                where & SSL_ST_ACCEPT ? "accept" :
                "undefined", state_string);
    } else if(where & SSL_CB_ALERT) {
        s_log(LOG_DEBUG, "SSL alert (%s): %s: %s",
            where & SSL_CB_READ ? "read" : "write",
            SSL_alert_type_string_long(ret),
            SSL_alert_desc_string_long(ret));
    } else if(where==SSL_CB_HANDSHAKE_DONE) {
        ctx=SSL_get_SSL_CTX((SSL *)ssl);
        if(c->opt->option.client) {
            s_log(LOG_DEBUG, "%6ld client connect(s) requested",
                SSL_CTX_sess_connect(ctx));
            s_log(LOG_DEBUG, "%6ld client connect(s) succeeded",
                SSL_CTX_sess_connect_good(ctx));
            s_log(LOG_DEBUG, "%6ld client renegotiation(s) requested",
                SSL_CTX_sess_connect_renegotiate(ctx));
        } else {
            s_log(LOG_DEBUG, "%6ld server accept(s) requested",
                SSL_CTX_sess_accept(ctx));
            s_log(LOG_DEBUG, "%6ld server accept(s) succeeded",
                SSL_CTX_sess_accept_good(ctx));
            s_log(LOG_DEBUG, "%6ld server renegotiation(s) requested",
                SSL_CTX_sess_accept_renegotiate(ctx));
        }
        /* according to the source it not only includes internal
           and external session caches, but also session tickets */
        s_log(LOG_DEBUG, "%6ld session reuse(s)",
            SSL_CTX_sess_hits(ctx));
        if(!c->opt->option.client) { /* server session cache stats */
            s_log(LOG_DEBUG, "%6ld internal session cache item(s)",
                SSL_CTX_sess_number(ctx));
            s_log(LOG_DEBUG, "%6ld internal session cache fill-up(s)",
                SSL_CTX_sess_cache_full(ctx));
            s_log(LOG_DEBUG, "%6ld internal session cache miss(es)",
                SSL_CTX_sess_misses(ctx));
            s_log(LOG_DEBUG, "%6ld external session cache hit(s)",
                SSL_CTX_sess_cb_hits(ctx));
            s_log(LOG_DEBUG, "%6ld expired session(s) retrieved",
                SSL_CTX_sess_timeouts(ctx));
        }
    }
}

/**************************************** SSL error reporting */

void sslerror(char *txt) { /* OpenSSL error handler */
    unsigned long err;

    err=ERR_get_error();
    if(err) {
        sslerror_queue();
        sslerror_log(err, txt);
    } else {
        s_log(LOG_ERR, "%s: Peer suddenly disconnected", txt);
    }
}