ngx_int_t ngx_ssl_create_session(ngx_ssl_ctx_t *ssl_ctx, ngx_connection_t *c, ngx_uint_t flags) { ngx_ssl_t *ssl; if (!(ssl = ngx_pcalloc(c->pool, sizeof(ngx_ssl_t)))) { return NGX_ERROR; } if (!(ssl->buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE))) { return NGX_ERROR; } if (flags & NGX_SSL_BUFFER) { ssl->buffer = 1; } ssl->ssl = SSL_new(ssl_ctx); if (ssl->ssl == NULL) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed"); return NGX_ERROR; } if (SSL_set_fd(ssl->ssl, c->fd) == 0) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_fd() failed"); return NGX_ERROR; } SSL_set_accept_state(ssl->ssl); c->ssl = ssl; return NGX_OK; }
static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_http_ssl_srv_conf_t *prev = parent; ngx_http_ssl_srv_conf_t *conf = child; ngx_conf_merge_value(conf->enable, prev->enable, 0); if (conf->enable == 0) { return NGX_CONF_OK; } ngx_conf_merge_str_value(conf->certificate, prev->certificate, NGX_DEFLAUT_CERTIFICATE); ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, NGX_DEFLAUT_CERTIFICATE_KEY); /* TODO: configure methods */ conf->ssl_ctx = SSL_CTX_new(SSLv23_server_method()); if (conf->ssl_ctx == NULL) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_new() failed"); return NGX_CONF_ERROR; } if (SSL_CTX_use_certificate_file(conf->ssl_ctx, (char *) conf->certificate.data, SSL_FILETYPE_PEM) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_use_certificate_file(\"%s\") failed", conf->certificate.data); return NGX_CONF_ERROR; } if (SSL_CTX_use_PrivateKey_file(conf->ssl_ctx, (char *) conf->certificate_key.data, SSL_FILETYPE_PEM) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_use_PrivateKey_file(\"%s\") failed", conf->certificate_key.data); return NGX_CONF_ERROR; } return NGX_CONF_OK; }
ngx_int_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size) { int n, sslerr; ngx_err_t err; char *handshake; n = SSL_read(c->ssl->ssl, buf, size); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n); if (n > 0) { return n; } sslerr = SSL_get_error(c->ssl->ssl, n); err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr); if (sslerr == SSL_ERROR_WANT_READ) { return NGX_AGAIN; } if (sslerr == SSL_ERROR_WANT_WRITE) { ngx_log_error(NGX_LOG_ALERT, c->log, err, "SSL wants to write%s", handshake); return NGX_ERROR; #if 0 return NGX_AGAIN; #endif } if (!SSL_is_init_finished(c->ssl->ssl)) { handshake = "in SSL handshake"; } else { handshake = ""; } c->ssl->no_rcv_shut = 1; if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) { ngx_log_error(NGX_LOG_INFO, c->log, err, "client closed connection%s", handshake); return NGX_ERROR; } ngx_ssl_error(NGX_LOG_ALERT, c->log, err, "SSL_read() failed%s", handshake); return NGX_ERROR; }
static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data) { int rc; X509 *cert; u_char *p; ngx_connection_t *c; ngx_ssl_stapling_t *staple; c = ngx_ssl_get_connection(ssl_conn); ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL certificate status callback"); rc = SSL_TLSEXT_ERR_NOACK; cert = SSL_get_certificate(ssl_conn); staple = X509_get_ex_data(cert, ngx_ssl_stapling_index); if (staple == NULL) { return rc; } if (staple->staple.len && staple->valid >= ngx_time()) { /* we have to copy ocsp response as OpenSSL will free it by itself */ p = OPENSSL_malloc(staple->staple.len); if (p == NULL) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "OPENSSL_malloc() failed"); return SSL_TLSEXT_ERR_NOACK; } ngx_memcpy(p, staple->staple.data, staple->staple.len); SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, staple->staple.len); rc = SSL_TLSEXT_ERR_OK; } ngx_ssl_stapling_update(staple); return rc; }
static ngx_int_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size) { int n, sslerr; ngx_err_t err; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size); n = SSL_write(c->ssl->ssl, data, size); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n); if (n > 0) { return n; } sslerr = SSL_get_error(c->ssl->ssl, n); err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr); if (sslerr == SSL_ERROR_WANT_WRITE) { c->write->ready = 0; return NGX_AGAIN; } if (sslerr == SSL_ERROR_WANT_READ) { ngx_log_error(NGX_LOG_ALERT, c->log, err, "SSL wants to read%s", handshake); return NGX_ERROR; #if 0 return NGX_AGAIN; } #endif c->ssl->no_rcv_shut = 1; ngx_ssl_error(NGX_LOG_ALERT, c->log, err, "SSL_write() failed"); return NGX_ERROR; }
static ngx_int_t ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) { BIO *bio; int len; u_char *p, *buf; OCSP_RESPONSE *response; ngx_ssl_stapling_t *staple; staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) { return NGX_ERROR; } bio = BIO_new_file((char *) file->data, "r"); if (bio == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "BIO_new_file(\"%s\") failed", file->data); return NGX_ERROR; } response = d2i_OCSP_RESPONSE_bio(bio, NULL); if (response == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "d2i_OCSP_RESPONSE_bio(\"%s\") failed", file->data); BIO_free(bio); return NGX_ERROR; } len = i2d_OCSP_RESPONSE(response, NULL); if (len <= 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "i2d_OCSP_RESPONSE(\"%s\") failed", file->data); goto failed; } buf = ngx_alloc(len, ssl->log); if (buf == NULL) { goto failed; } p = buf; len = i2d_OCSP_RESPONSE(response, &p); if (len <= 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "i2d_OCSP_RESPONSE(\"%s\") failed", file->data); ngx_free(buf); goto failed; } OCSP_RESPONSE_free(response); BIO_free(bio); staple->staple.data = buf; staple->staple.len = len; staple->valid = NGX_MAX_TIME_T_VALUE; return NGX_OK; failed: OCSP_RESPONSE_free(response); BIO_free(bio); return NGX_ERROR; }
ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify) { ngx_int_t rc; ngx_pool_cleanup_t *cln; ngx_ssl_stapling_t *staple; staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t)); if (staple == NULL) { return NGX_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_ssl_stapling_cleanup; cln->data = staple; if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_stapling_index, staple) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_set_ex_data() failed"); return NGX_ERROR; } staple->ssl_ctx = ssl->ctx; staple->timeout = 60000; staple->verify = verify; if (file->len) { /* use OCSP response from the file */ if (ngx_ssl_stapling_file(cf, ssl, file) != NGX_OK) { return NGX_ERROR; } goto done; } rc = ngx_ssl_stapling_issuer(cf, ssl); if (rc == NGX_DECLINED) { return NGX_OK; } if (rc != NGX_OK) { return NGX_ERROR; } rc = ngx_ssl_stapling_responder(cf, ssl, responder); if (rc == NGX_DECLINED) { return NGX_OK; } if (rc != NGX_OK) { return NGX_ERROR; } done: SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback); SSL_CTX_set_tlsext_status_arg(ssl->ctx, staple); return NGX_OK; }
static ngx_int_t ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx) { int len; u_char *p; uintptr_t escape; ngx_str_t binary, base64; ngx_buf_t *b; OCSP_CERTID *id; OCSP_REQUEST *ocsp; ocsp = OCSP_REQUEST_new(); if (ocsp == NULL) { ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0, "OCSP_REQUEST_new() failed"); return NGX_ERROR; } id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer); if (id == NULL) { ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0, "OCSP_cert_to_id() failed"); goto failed; } if (OCSP_request_add0_id(ocsp, id) == NULL) { ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0, "OCSP_request_add0_id() failed"); OCSP_CERTID_free(id); goto failed; } len = i2d_OCSP_REQUEST(ocsp, NULL); if (len <= 0) { ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0, "i2d_OCSP_REQUEST() failed"); goto failed; } binary.len = len; binary.data = ngx_palloc(ctx->pool, len); if (binary.data == NULL) { goto failed; } p = binary.data; len = i2d_OCSP_REQUEST(ocsp, &p); if (len <= 0) { ngx_ssl_error(NGX_LOG_EMERG, ctx->log, 0, "i2d_OCSP_REQUEST() failed"); goto failed; } base64.len = ngx_base64_encoded_length(binary.len); base64.data = ngx_palloc(ctx->pool, base64.len); if (base64.data == NULL) { goto failed; } ngx_encode_base64(&base64, &binary); escape = ngx_escape_uri(NULL, base64.data, base64.len, NGX_ESCAPE_URI_COMPONENT); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp request length %z, escape %d", base64.len, (int) escape); len = sizeof("GET ") - 1 + ctx->uri.len + sizeof("/") - 1 + base64.len + 2 * escape + sizeof(" HTTP/1.0" CRLF) - 1 + sizeof("Host: ") - 1 + ctx->host.len + sizeof(CRLF) - 1 + sizeof(CRLF) - 1; b = ngx_create_temp_buf(ctx->pool, len); if (b == NULL) { goto failed; } p = b->last; p = ngx_cpymem(p, "GET ", sizeof("GET ") - 1); p = ngx_cpymem(p, ctx->uri.data, ctx->uri.len); if (ctx->uri.data[ctx->uri.len - 1] != '/') { *p++ = '/'; } if (escape == 0) { p = ngx_cpymem(p, base64.data, base64.len); } else { p = (u_char *) ngx_escape_uri(p, base64.data, base64.len, NGX_ESCAPE_URI_COMPONENT); } p = ngx_cpymem(p, " HTTP/1.0" CRLF, sizeof(" HTTP/1.0" CRLF) - 1); p = ngx_cpymem(p, "Host: ", sizeof("Host: ") - 1); p = ngx_cpymem(p, ctx->host.data, ctx->host.len); *p++ = CR; *p++ = LF; /* add "\r\n" at the header end */ *p++ = CR; *p++ = LF; b->last = p; ctx->request = b; OCSP_REQUEST_free(ocsp); return NGX_OK; failed: OCSP_REQUEST_free(ocsp); return NGX_ERROR; }
static char * ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_stream_ssl_conf_t *prev = parent; ngx_stream_ssl_conf_t *conf = child; ngx_pool_cleanup_t *cln; ngx_conf_merge_msec_value(conf->handshake_timeout, prev->handshake_timeout, 60000); ngx_conf_merge_value(conf->session_timeout, prev->session_timeout, 300); ngx_conf_merge_value(conf->prefer_server_ciphers, prev->prefer_server_ciphers, 0); ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, NGX_DEFAULT_ECDH_CURVE); ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); conf->ssl.log = cf->log; if (conf->certificate.len == 0) { return NGX_CONF_OK; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", &conf->certificate); return NGX_CONF_ERROR; } if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) { return NGX_CONF_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_CONF_ERROR; } cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, &conf->certificate_key, conf->passwords) != NGX_OK) { return NGX_CONF_ERROR; } if (SSL_CTX_set_cipher_list(conf->ssl.ctx, (const char *) conf->ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_cipher_list(\"%V\") failed", &conf->ciphers); return NGX_CONF_ERROR; } if (conf->prefer_server_ciphers) { SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } #ifndef LIBRESSL_VERSION_NUMBER SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); #endif if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) { return NGX_CONF_ERROR; } ngx_conf_merge_value(conf->builtin_session_cache, prev->builtin_session_cache, NGX_SSL_NONE_SCACHE); if (conf->shm_zone == NULL) { conf->shm_zone = prev->shm_zone; } if (ngx_ssl_session_cache(&conf->ssl, &ngx_stream_ssl_sess_id_ctx, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { return NGX_CONF_ERROR; } ngx_conf_merge_value(conf->session_tickets, prev->session_tickets, 1); #ifdef SSL_OP_NO_TICKET if (!conf->session_tickets) { SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET); } #endif ngx_conf_merge_ptr_value(conf->session_ticket_keys, prev->session_ticket_keys, NULL); if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static char * ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_http_ssl_srv_conf_t *prev = parent; ngx_http_ssl_srv_conf_t *conf = child; ngx_pool_cleanup_t *cln; if (conf->enable == NGX_CONF_UNSET) { if (prev->enable == NGX_CONF_UNSET) { conf->enable = 0; } else { conf->enable = prev->enable; conf->file = prev->file; conf->line = prev->line; } } ngx_conf_merge_value(conf->session_timeout, prev->session_timeout, 300); ngx_conf_merge_value(conf->prefer_server_ciphers, prev->prefer_server_ciphers, 0); ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate, ""); ngx_conf_merge_str_value(conf->trusted_certificate, prev->trusted_certificate, ""); ngx_conf_merge_str_value(conf->crl, prev->crl, ""); ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, NGX_DEFAULT_ECDH_CURVE); ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); ngx_conf_merge_value(conf->stapling, prev->stapling, 0); ngx_conf_merge_value(conf->stapling_verify, prev->stapling_verify, 0); ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, ""); ngx_conf_merge_str_value(conf->stapling_responder, prev->stapling_responder, ""); conf->ssl.log = cf->log; if (conf->enable) { if (conf->certificate.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " "the \"ssl\" directive in %s:%ui", conf->file, conf->line); return NGX_CONF_ERROR; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined for " "the \"ssl\" directive in %s:%ui", conf->file, conf->line); return NGX_CONF_ERROR; } } else { if (conf->certificate.len == 0) { return NGX_CONF_OK; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", &conf->certificate); return NGX_CONF_ERROR; } } if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) { return NGX_CONF_ERROR; } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx, ngx_http_ssl_servername) == 0) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, "nginx was built with SNI support, however, now it is linked " "dynamically to an OpenSSL library which has no tlsext support, " "therefore SNI is not available"); } #endif #ifdef TLSEXT_TYPE_next_proto_neg SSL_CTX_set_next_protos_advertised_cb(conf->ssl.ctx, ngx_http_ssl_npn_advertised, NULL); #endif cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_CONF_ERROR; } cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, &conf->certificate_key) != NGX_OK) { return NGX_CONF_ERROR; } if (SSL_CTX_set_cipher_list(conf->ssl.ctx, (const char *) conf->ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_cipher_list(\"%V\") failed", &conf->ciphers); return NGX_CONF_ERROR; } if (conf->verify) { if (conf->client_certificate.len == 0 && conf->verify != 3) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no ssl_client_certificate for ssl_client_verify"); return NGX_CONF_ERROR; } if (ngx_ssl_client_certificate(cf, &conf->ssl, &conf->client_certificate, conf->verify_depth) != NGX_OK) { return NGX_CONF_ERROR; } } if (ngx_ssl_trusted_certificate(cf, &conf->ssl, &conf->trusted_certificate, conf->verify_depth) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) { return NGX_CONF_ERROR; } if (conf->prefer_server_ciphers) { SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } /* a temporary 512-bit RSA key is required for export versions of MSIE */ SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) { return NGX_CONF_ERROR; } ngx_conf_merge_value(conf->builtin_session_cache, prev->builtin_session_cache, NGX_SSL_NONE_SCACHE); if (conf->shm_zone == NULL) { conf->shm_zone = prev->shm_zone; } if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { return NGX_CONF_ERROR; } if (conf->stapling) { if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file, &conf->stapling_responder, conf->stapling_verify) != NGX_OK) { return NGX_CONF_ERROR; } } return NGX_CONF_OK; }
static ngx_int_t ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf) { ngx_pool_cleanup_t *cln; pscf->ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); if (pscf->ssl == NULL) { return NGX_ERROR; } pscf->ssl->log = cf->log; if (ngx_ssl_create(pscf->ssl, pscf->ssl_protocols, NULL) != NGX_OK) { return NGX_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_ssl_cleanup_ctx; cln->data = pscf->ssl; if (pscf->ssl_certificate.len) { if (pscf->ssl_certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"proxy_ssl_certificate_key\" is defined " "for certificate \"%V\"", &pscf->ssl_certificate); return NGX_ERROR; } if (ngx_ssl_certificate(cf, pscf->ssl, &pscf->ssl_certificate, &pscf->ssl_certificate_key, pscf->ssl_passwords) != NGX_OK) { return NGX_ERROR; } } if (SSL_CTX_set_cipher_list(pscf->ssl->ctx, (const char *) pscf->ssl_ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_cipher_list(\"%V\") failed", &pscf->ssl_ciphers); return NGX_ERROR; } if (pscf->ssl_verify) { if (pscf->ssl_trusted_certificate.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no proxy_ssl_trusted_certificate for proxy_ssl_verify"); return NGX_ERROR; } if (ngx_ssl_trusted_certificate(cf, pscf->ssl, &pscf->ssl_trusted_certificate, pscf->ssl_verify_depth) != NGX_OK) { return NGX_ERROR; } if (ngx_ssl_crl(cf, pscf->ssl, &pscf->ssl_crl) != NGX_OK) { return NGX_ERROR; } } return NGX_OK; }
static char * ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_mail_ssl_conf_t *prev = parent; ngx_mail_ssl_conf_t *conf = child; char *mode; ngx_pool_cleanup_t *cln; ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_uint_value(conf->starttls, prev->starttls, NGX_MAIL_STARTTLS_OFF); ngx_conf_merge_value(conf->session_timeout, prev->session_timeout, 300); ngx_conf_merge_value(conf->prefer_server_ciphers, prev->prefer_server_ciphers, 0); ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1)); ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); conf->ssl.log = cf->log; if (conf->enable) { mode = "ssl"; } else if (conf->starttls != NGX_MAIL_STARTTLS_OFF) { mode = "starttls"; } else { mode = ""; } if (*mode) { if (conf->certificate.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " "the \"%s\" directive in %s:%ui", mode, conf->file, conf->line); return NGX_CONF_ERROR; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined for " "the \"%s\" directive in %s:%ui", mode, conf->file, conf->line); return NGX_CONF_ERROR; } } else { if (conf->certificate.len == 0) { return NGX_CONF_OK; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", &conf->certificate); return NGX_CONF_ERROR; } } if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) { return NGX_CONF_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_CONF_ERROR; } cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, &conf->certificate_key) != NGX_OK) { return NGX_CONF_ERROR; } if (conf->ciphers.len) { if (SSL_CTX_set_cipher_list(conf->ssl.ctx, (const char *) conf->ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_cipher_list(\"%V\") failed", &conf->ciphers); } } if (conf->prefer_server_ciphers) { SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } if (ngx_ssl_generate_rsa512_key(&conf->ssl) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; } ngx_conf_merge_value(conf->builtin_session_cache, prev->builtin_session_cache, NGX_SSL_NONE_SCACHE); if (conf->shm_zone == NULL) { conf->shm_zone = prev->shm_zone; } if (ngx_ssl_session_cache(&conf->ssl, &ngx_mail_ssl_sess_id_ctx, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static char * ngx_rtmp_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_rtmp_ssl_srv_conf_t *prev = parent; ngx_rtmp_ssl_srv_conf_t *conf = child; ngx_pool_cleanup_t *cln; ngx_array_t *passwords = NULL; conf->ssl.log = cf->log; if (!conf->enable) { return NGX_CONF_OK; } ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); if (conf->certificate.len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Missing ssl_certificate"); return NGX_CONF_ERROR; } ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); if (conf->certificate_key.len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Missing ssl_certificate_key"); return NGX_CONF_ERROR; } ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, NGX_CONF_BITMASK_SET |NGX_RTMPS_DEFAULT_PROTOCOLS); ngx_conf_merge_str_value(conf->password_file, prev->password_file, ""); ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, NGX_RTMPS_DEFAULT_ECDH_CURVE); ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_RTMPS_DEFAULT_CIPHERS); ngx_conf_merge_value(conf->prefer_server_ciphers, prev->prefer_server_ciphers, 0); if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) { return NGX_CONF_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_CONF_ERROR; } cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; if (conf->password_file.len > 0) { passwords = ngx_ssl_read_password_file(cf, &conf->password_file); if (passwords == NULL) { return NGX_CONF_ERROR; } } if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, &conf->certificate_key, passwords) != NGX_OK) { return NGX_CONF_ERROR; } if (SSL_CTX_set_cipher_list(conf->ssl.ctx, (const char *) conf->ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_cipher_list(%V) failed", &conf->ciphers); return NGX_CONF_ERROR; } if (conf->prefer_server_ciphers) { SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) { return NGX_CONF_ERROR; } SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET); return NGX_CONF_OK; }
/* callback for new session caching, to be set with SSL_CTX_sess_set_new_cb */ int ngx_http_lua_ssl_sess_store_handler(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess) { lua_State *L; ngx_int_t rc; #if OPENSSL_VERSION_NUMBER >= 0x1010005fL unsigned int len; #endif ngx_connection_t *c, *fc = NULL; ngx_http_request_t *r = NULL; ngx_http_connection_t *hc; ngx_http_lua_ssl_ctx_t *cctx; ngx_http_lua_srv_conf_t *lscf; ngx_http_core_loc_conf_t *clcf; c = ngx_ssl_get_connection(ssl_conn); dd("c = %p", c); cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); dd("ssl sess_store handler, sess_store-ctx=%p", cctx); hc = c->data; fc = ngx_http_lua_create_fake_connection(NULL); if (fc == NULL) { goto failed; } fc->log->handler = ngx_http_lua_log_ssl_sess_store_error; fc->log->data = fc; fc->addr_text = c->addr_text; fc->listening = c->listening; r = ngx_http_lua_create_fake_request(fc); if (r == NULL) { goto failed; } r->main_conf = hc->conf_ctx->main_conf; r->srv_conf = hc->conf_ctx->srv_conf; r->loc_conf = hc->conf_ctx->loc_conf; fc->log->file = c->log->file; fc->log->log_level = c->log->log_level; fc->ssl = c->ssl; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); #if defined(nginx_version) && nginx_version >= 1003014 # if nginx_version >= 1009000 ngx_set_connection_log(fc, clcf->error_log); # else ngx_http_set_connection_log(fc, clcf->error_log); # endif #else fc->log->file = clcf->error_log->file; if (!(fc->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { fc->log->log_level = clcf->error_log->log_level; } #endif if (cctx == NULL) { cctx = ngx_pcalloc(c->pool, sizeof(ngx_http_lua_ssl_ctx_t)); if (cctx == NULL) { goto failed; /* error */ } } cctx->connection = c; cctx->request = r; cctx->session = sess; #if OPENSSL_VERSION_NUMBER < 0x1010005fL cctx->session_id.data = sess->session_id; cctx->session_id.len = sess->session_id_length; #else cctx->session_id.data = (u_char *)SSL_SESSION_get_id(sess, &len); cctx->session_id.len = len; #endif cctx->done = 0; dd("setting cctx"); if (SSL_set_ex_data(c->ssl->connection, ngx_http_lua_ssl_ctx_index, cctx) == 0) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed"); goto failed; } lscf = ngx_http_get_module_srv_conf(r, ngx_http_lua_module); /* TODO honor lua_code_cache off */ L = ngx_http_lua_get_lua_vm(r, NULL); c->log->action = "storing SSL session by lua"; rc = lscf->srv.ssl_sess_store_handler(r, lscf, L); if (rc >= NGX_OK || rc == NGX_ERROR) { cctx->done = 1; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "ssl_session_store_by_lua*: handler return value: %i, " "sess new cb exit code: %d", rc, cctx->exit_code); c->log->action = "SSL handshaking"; /* Return value is a flag indicating whether the passed-in session * has been freed by this callback; always return 0 so OpenSSL will * free the session. Nginx's own session caching logic has the same * practice. */ return 0; } /* impossible to reach here */ ngx_http_lua_assert(0); failed: if (r && r->pool) { ngx_http_lua_free_fake_request(r); } if (fc) { ngx_http_lua_close_fake_connection(fc); } return 0; }
static ngx_int_t ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, X509 *cert, ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify) { ngx_int_t rc; ngx_pool_cleanup_t *cln; ngx_ssl_stapling_t *staple; staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t)); if (staple == NULL) { return NGX_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_ssl_stapling_cleanup; cln->data = staple; if (X509_set_ex_data(cert, ngx_ssl_stapling_index, staple) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); return NGX_ERROR; } staple->ssl_ctx = ssl->ctx; staple->timeout = 60000; staple->verify = verify; staple->cert = cert; if (file->len) { /* use OCSP response from the file */ if (ngx_ssl_stapling_file(cf, ssl, staple, file) != NGX_OK) { return NGX_ERROR; } return NGX_OK; } rc = ngx_ssl_stapling_issuer(cf, ssl, staple); if (rc == NGX_DECLINED) { return NGX_OK; } if (rc != NGX_OK) { return NGX_ERROR; } rc = ngx_ssl_stapling_responder(cf, ssl, staple, responder); if (rc == NGX_DECLINED) { return NGX_OK; } if (rc != NGX_OK) { return NGX_ERROR; } return NGX_OK; }
/* cached session fetching callback to be set with SSL_CTX_sess_set_get_cb */ ngx_ssl_session_t * ngx_http_lua_ssl_sess_fetch_handler(ngx_ssl_conn_t *ssl_conn, u_char *id, int len, int *copy) { lua_State *L; ngx_int_t rc; ngx_connection_t *c, *fc = NULL; ngx_http_request_t *r = NULL; ngx_pool_cleanup_t *cln; ngx_http_connection_t *hc; ngx_http_lua_ssl_ctx_t *cctx; ngx_http_lua_srv_conf_t *lscf; ngx_http_core_loc_conf_t *clcf; /* set copy to 0 as we expect OpenSSL to handle * the memory of returned session */ *copy = 0; c = ngx_ssl_get_connection(ssl_conn); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "ssl session fetch: connection reusable: %ud", c->reusable); cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); dd("ssl sess_fetch handler, sess_fetch-ctx=%p", cctx); if (cctx && cctx->entered_sess_fetch_handler) { /* not the first time */ dd("here: %d", (int) cctx->entered_sess_fetch_handler); if (cctx->done) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "ssl_session_fetch_by_lua*: " "sess get cb exit code: %d", cctx->exit_code); dd("lua ssl sess_fetch done, finally"); return cctx->session; } #ifdef SSL_ERROR_PENDING_SESSION return SSL_magic_pending_session_ptr(); #else ngx_log_error(NGX_LOG_CRIT, c->log, 0, "lua: cannot yield in sess get cb: " "missing async sess get cb support in OpenSSL"); return NULL; #endif } dd("first time"); ngx_reusable_connection(c, 0); hc = c->data; fc = ngx_http_lua_create_fake_connection(NULL); if (fc == NULL) { goto failed; } fc->log->handler = ngx_http_lua_log_ssl_sess_fetch_error; fc->log->data = fc; fc->addr_text = c->addr_text; fc->listening = c->listening; r = ngx_http_lua_create_fake_request(fc); if (r == NULL) { goto failed; } r->main_conf = hc->conf_ctx->main_conf; r->srv_conf = hc->conf_ctx->srv_conf; r->loc_conf = hc->conf_ctx->loc_conf; fc->log->file = c->log->file; fc->log->log_level = c->log->log_level; fc->ssl = c->ssl; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); #if defined(nginx_version) && nginx_version >= 1003014 # if nginx_version >= 1009000 ngx_set_connection_log(fc, clcf->error_log); # else ngx_http_set_connection_log(fc, clcf->error_log); # endif #else fc->log->file = clcf->error_log->file; if (!(fc->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { fc->log->log_level = clcf->error_log->log_level; } #endif if (cctx == NULL) { cctx = ngx_pcalloc(c->pool, sizeof(ngx_http_lua_ssl_ctx_t)); if (cctx == NULL) { goto failed; /* error */ } } cctx->exit_code = 1; /* successful by default */ cctx->connection = c; cctx->request = r; cctx->session_id.data = id; cctx->session_id.len = len; cctx->entered_sess_fetch_handler = 1; cctx->done = 0; dd("setting cctx = %p", cctx); if (SSL_set_ex_data(c->ssl->connection, ngx_http_lua_ssl_ctx_index, cctx) == 0) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed"); goto failed; } lscf = ngx_http_get_module_srv_conf(r, ngx_http_lua_module); /* TODO honor lua_code_cache off */ L = ngx_http_lua_get_lua_vm(r, NULL); c->log->action = "fetching SSL session by lua"; rc = lscf->srv.ssl_sess_fetch_handler(r, lscf, L); if (rc >= NGX_OK || rc == NGX_ERROR) { cctx->done = 1; if (cctx->cleanup) { *cctx->cleanup = NULL; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "ssl_session_fetch_by_lua*: handler return value: %i, " "sess get cb exit code: %d", rc, cctx->exit_code); c->log->action = "SSL handshaking"; return cctx->session; } /* rc == NGX_DONE */ cln = ngx_pool_cleanup_add(fc->pool, 0); if (cln == NULL) { goto failed; } cln->handler = ngx_http_lua_ssl_sess_fetch_done; cln->data = cctx; if (cctx->cleanup == NULL) { /* we only want exactly one cleanup handler to be registered with the * connection to clean up cctx when connection is aborted */ cln = ngx_pool_cleanup_add(c->pool, 0); if (cln == NULL) { goto failed; } cln->data = cctx; cctx->cleanup = &cln->handler; } *cctx->cleanup = ngx_http_lua_ssl_sess_fetch_aborted; #ifdef SSL_ERROR_PENDING_SESSION return SSL_magic_pending_session_ptr(); #else ngx_log_error(NGX_LOG_CRIT, c->log, 0, "lua: cannot yield in sess get cb: " "missing async sess get cb support in OpenSSL"); /* fall through to the "failed" label below */ #endif failed: if (r && r->pool) { ngx_http_lua_free_fake_request(r); } if (fc) { ngx_http_lua_close_fake_connection(fc); } return NULL; }
static char * ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_mail_ssl_conf_t *prev = parent; ngx_mail_ssl_conf_t *conf = child; char *mode; ngx_pool_cleanup_t *cln; ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_uint_value(conf->starttls, prev->starttls, NGX_MAIL_STARTTLS_OFF); ngx_conf_merge_value(conf->session_timeout, prev->session_timeout, 300); ngx_conf_merge_value(conf->prefer_server_ciphers, prev->prefer_server_ciphers, 0); ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, NGX_DEFAULT_ECDH_CURVE); ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate, ""); ngx_conf_merge_str_value(conf->trusted_certificate, prev->trusted_certificate, ""); ngx_conf_merge_str_value(conf->crl, prev->crl, ""); ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); conf->ssl.log = cf->log; if (conf->enable) { mode = "ssl"; } else if (conf->starttls != NGX_MAIL_STARTTLS_OFF) { mode = "starttls"; } else { mode = ""; } if (conf->file == NULL) { conf->file = prev->file; conf->line = prev->line; } if (*mode) { if (conf->certificate.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " "the \"%s\" directive in %s:%ui", mode, conf->file, conf->line); return NGX_CONF_ERROR; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined for " "the \"%s\" directive in %s:%ui", mode, conf->file, conf->line); return NGX_CONF_ERROR; } } else { if (conf->certificate.len == 0) { return NGX_CONF_OK; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", &conf->certificate); return NGX_CONF_ERROR; } } if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) { return NGX_CONF_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_CONF_ERROR; } cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, &conf->certificate_key, conf->passwords) != NGX_OK) { return NGX_CONF_ERROR; } if (conf->verify) { if (conf->client_certificate.len == 0 && conf->verify != 3) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no ssl_client_certificate for ssl_client_verify"); return NGX_CONF_ERROR; } if (ngx_ssl_client_certificate(cf, &conf->ssl, &conf->client_certificate, conf->verify_depth) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_ssl_trusted_certificate(cf, &conf->ssl, &conf->trusted_certificate, conf->verify_depth) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) { return NGX_CONF_ERROR; } } if (SSL_CTX_set_cipher_list(conf->ssl.ctx, (const char *) conf->ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_cipher_list(\"%V\") failed", &conf->ciphers); return NGX_CONF_ERROR; } if (conf->prefer_server_ciphers) { SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } #ifndef LIBRESSL_VERSION_NUMBER SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); #endif if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) { return NGX_CONF_ERROR; } ngx_conf_merge_value(conf->builtin_session_cache, prev->builtin_session_cache, NGX_SSL_NONE_SCACHE); if (conf->shm_zone == NULL) { conf->shm_zone = prev->shm_zone; } if (ngx_ssl_session_cache(&conf->ssl, &ngx_mail_ssl_sess_id_ctx, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { return NGX_CONF_ERROR; } ngx_conf_merge_value(conf->session_tickets, prev->session_tickets, 1); #ifdef SSL_OP_NO_TICKET if (!conf->session_tickets) { SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET); } #endif ngx_conf_merge_ptr_value(conf->session_ticket_keys, prev->session_ticket_keys, NULL); if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl) { int i, n, rc; X509 *cert, *issuer; X509_STORE *store; X509_STORE_CTX *store_ctx; STACK_OF(X509) *chain; ngx_ssl_stapling_t *staple; staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); #if OPENSSL_VERSION_NUMBER >= 0x10001000L SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain); #else chain = ssl->ctx->extra_certs; #endif n = sk_X509_num(chain); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, "SSL get issuer: %d extra certs", n); for (i = 0; i < n; i++) { issuer = sk_X509_value(chain, i); if (X509_check_issued(issuer, cert) == X509_V_OK) { #if OPENSSL_VERSION_NUMBER >= 0x10100001L X509_up_ref(issuer); #else CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509); #endif ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, "SSL get issuer: found %p in extra certs", issuer); staple->cert = cert; staple->issuer = issuer; return NGX_OK; } } store = SSL_CTX_get_cert_store(ssl->ctx); if (store == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_get_cert_store() failed"); return NGX_ERROR; } store_ctx = X509_STORE_CTX_new(); if (store_ctx == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_STORE_CTX_new() failed"); return NGX_ERROR; } if (X509_STORE_CTX_init(store_ctx, store, NULL, NULL) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_STORE_CTX_init() failed"); X509_STORE_CTX_free(store_ctx); return NGX_ERROR; } rc = X509_STORE_CTX_get1_issuer(&issuer, store_ctx, cert); if (rc == -1) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_STORE_CTX_get1_issuer() failed"); X509_STORE_CTX_free(store_ctx); return NGX_ERROR; } if (rc == 0) { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, "\"ssl_stapling\" ignored, issuer certificate not found"); X509_STORE_CTX_free(store_ctx); return NGX_DECLINED; } X509_STORE_CTX_free(store_ctx); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, "SSL get issuer: found %p in cert store", issuer); staple->cert = cert; staple->issuer = issuer; return NGX_OK; }
static void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx) { #if OPENSSL_VERSION_NUMBER >= 0x0090707fL const #endif u_char *p; int n; size_t len; time_t now, valid; ngx_str_t response; X509_STORE *store; STACK_OF(X509) *chain; OCSP_CERTID *id; OCSP_RESPONSE *ocsp; OCSP_BASICRESP *basic; ngx_ssl_stapling_t *staple; ASN1_GENERALIZEDTIME *thisupdate, *nextupdate; staple = ctx->data; now = ngx_time(); ocsp = NULL; basic = NULL; id = NULL; if (ctx->code != 200) { goto error; } /* check the response */ len = ctx->response->last - ctx->response->pos; p = ctx->response->pos; ocsp = d2i_OCSP_RESPONSE(NULL, &p, len); if (ocsp == NULL) { ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0, "d2i_OCSP_RESPONSE() failed"); goto error; } n = OCSP_response_status(ocsp); if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) { ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "OCSP response not successful (%d: %s)", n, OCSP_response_status_str(n)); goto error; } basic = OCSP_response_get1_basic(ocsp); if (basic == NULL) { ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0, "OCSP_response_get1_basic() failed"); goto error; } store = SSL_CTX_get_cert_store(staple->ssl_ctx); if (store == NULL) { ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0, "SSL_CTX_get_cert_store() failed"); goto error; } #if OPENSSL_VERSION_NUMBER >= 0x10001000L SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain); #else chain = staple->ssl_ctx->extra_certs; #endif if (OCSP_basic_verify(basic, chain, store, staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY) != 1) { ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0, "OCSP_basic_verify() failed"); goto error; } id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer); if (id == NULL) { ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0, "OCSP_cert_to_id() failed"); goto error; } if (OCSP_resp_find_status(basic, id, &n, NULL, NULL, &thisupdate, &nextupdate) != 1) { ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "certificate status not found in the OCSP response"); goto error; } if (n != V_OCSP_CERTSTATUS_GOOD) { ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "certificate status \"%s\" in the OCSP response", OCSP_cert_status_str(n)); goto error; } if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) { ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0, "OCSP_check_validity() failed"); goto error; } if (nextupdate) { valid = ngx_ssl_stapling_time(nextupdate); if (valid == (time_t) NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "invalid nextUpdate time in certificate status"); goto error; } } else { valid = NGX_MAX_TIME_T_VALUE; } OCSP_CERTID_free(id); OCSP_BASICRESP_free(basic); OCSP_RESPONSE_free(ocsp); id = NULL; basic = NULL; ocsp = NULL; /* copy the response to memory not in ctx->pool */ response.len = len; response.data = ngx_alloc(response.len, ctx->log); if (response.data == NULL) { goto error; } ngx_memcpy(response.data, ctx->response->pos, response.len); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp response, %s, %uz", OCSP_cert_status_str(n), response.len); if (staple->staple.data) { ngx_free(staple->staple.data); } staple->staple = response; staple->valid = valid; /* * refresh before the response expires, * but not earlier than in 5 minutes, and at least in an hour */ staple->loading = 0; staple->refresh = ngx_max(ngx_min(valid - 300, now + 3600), now + 300); ngx_ssl_ocsp_done(ctx); return; error: staple->loading = 0; staple->refresh = now + 300; if (id) { OCSP_CERTID_free(id); } if (basic) { OCSP_BASICRESP_free(basic); } if (ocsp) { OCSP_RESPONSE_free(ocsp); } ngx_ssl_ocsp_done(ctx); }
static char * ngx_tcp_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_tcp_ssl_srv_conf_t *prev = parent; ngx_tcp_ssl_srv_conf_t *conf = child; ngx_pool_cleanup_t *cln; ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_value(conf->session_timeout, prev->session_timeout, 300); ngx_conf_merge_value(conf->prefer_server_ciphers, prev->prefer_server_ciphers, 0); ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1|NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); //ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, NGX_DEFAULT_ECDH_CURVE); ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate, ""); ngx_conf_merge_str_value(conf->crl, prev->crl, ""); ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); conf->ssl.log = cf->log; if (conf->enable) { if (conf->certificate.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " "the \"ssl\" directive in %s:%ui", conf->file, conf->line); return NGX_CONF_ERROR; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined for " "the \"ssl\" directive in %s:%ui", conf->file, conf->line); return NGX_CONF_ERROR; } } else { if (conf->certificate.len == 0) { return NGX_CONF_OK; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", &conf->certificate); return NGX_CONF_ERROR; } } if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) { return NGX_CONF_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_CONF_ERROR; } cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; //#if defined(tengine_version) // ngx_str_t pass_phrase_dialog = ngx_string("builtin"); // ngx_str_t ngx_tcp_ssl_unknown_server_name = ngx_string("unknown"); // // ngx_tcp_core_srv_conf_t *cscf; // ngx_http_ssl_pphrase_dialog_conf_t dialog; // // cscf = ngx_tcp_conf_get_module_srv_conf(cf, ngx_tcp_core_module); // dialog.ssl = &conf->ssl; // dialog.type = &pass_phrase_dialog; // if (cscf->server_name.len != 0) { // dialog.server_name = &cscf->server_name; // } else { // dialog.server_name = &ngx_tcp_ssl_unknown_server_name; // } // // if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, // &conf->certificate_key, &dialog) // != NGX_OK) // { // return NGX_CONF_ERROR; // } //#else //#if defined(nginx_version) && nginx_version >= 1007003 // if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, // &conf->certificate_key, conf->passwords) //#else if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, &conf->certificate_key) //#endif != NGX_OK) { return NGX_CONF_ERROR; } //#endif if (SSL_CTX_set_cipher_list(conf->ssl.ctx, (const char *) conf->ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_cipher_list(\"%V\") failed", &conf->ciphers); } if (conf->verify) { if (conf->client_certificate.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no ssl_client_certificate for ssl_client_verify"); return NGX_CONF_ERROR; } if (ngx_tcp_ssl_client_certificate(cf, &conf->ssl, &conf->client_certificate, conf->verify_depth, conf->verify == 2 ? 1 : 0) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) { return NGX_CONF_ERROR; } } if (conf->prefer_server_ciphers) { SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } /* a temporary 512-bit RSA key is required for export versions of MSIE */ //#if defined(nginx_version) && nginx_version >= 1000006 SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); //#else // if (ngx_ssl_generate_rsa512_key(&conf->ssl) != NGX_OK) { // return NGX_CONF_ERROR; // } //#endif if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; } ngx_conf_merge_value(conf->builtin_session_cache, prev->builtin_session_cache, NGX_SSL_NONE_SCACHE); if (conf->shm_zone == NULL) { conf->shm_zone = prev->shm_zone; } if (ngx_ssl_session_cache(&conf->ssl, &ngx_tcp_ssl_sess_id_ctx, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static ngx_int_t ngx_stream_proxy_ssl_name(ngx_stream_session_t *s) { u_char *p, *last; ngx_str_t name; ngx_stream_upstream_t *u; ngx_stream_proxy_srv_conf_t *pscf; pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); u = s->upstream; name = pscf->ssl_name; if (name.len == 0) { name = pscf->upstream->host; } if (name.len == 0) { goto done; } /* * ssl name here may contain port, strip it for compatibility * with the http module */ p = name.data; last = name.data + name.len; if (*p == '[') { p = ngx_strlchr(p, last, ']'); if (p == NULL) { p = name.data; } } p = ngx_strlchr(p, last, ':'); if (p != NULL) { name.len = p - name.data; } if (!pscf->ssl_server_name) { goto done; } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME /* as per RFC 6066, literal IPv4 and IPv6 addresses are not permitted */ if (name.len == 0 || *name.data == '[') { goto done; } if (ngx_inet_addr(name.data, name.len) != INADDR_NONE) { goto done; } /* * SSL_set_tlsext_host_name() needs a null-terminated string, * hence we explicitly null-terminate name here */ p = ngx_pnalloc(s->connection->pool, name.len + 1); if (p == NULL) { return NGX_ERROR; } (void) ngx_cpystrn(p, name.data, name.len + 1); name.data = p; ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, "upstream SSL server name: \"%s\"", name.data); if (SSL_set_tlsext_host_name(u->peer.connection->ssl->connection, name.data) == 0) { ngx_ssl_error(NGX_LOG_ERR, s->connection->log, 0, "SSL_set_tlsext_host_name(\"%s\") failed", name.data); return NGX_ERROR; } #endif done: u->ssl_name = name; return NGX_OK; }
// borrowed from original ngx_event_openssl.c v1.7.1 ngx_int_t ngx_tcp_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_int_t depth, ngx_int_t optional) { STACK_OF(X509_NAME) *list; /* @see https://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html * When proxying tcp connection, you expect handshake to fail if no * client certificate was send by client and ssl_verify_client=on. * But by default nginx allowed connection by any client. */ int ossl_verify_mode = optional ? SSL_VERIFY_PEER : SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; SSL_CTX_set_verify(ssl->ctx, ossl_verify_mode, ngx_tcp_ssl_verify_callback); SSL_CTX_set_verify_depth(ssl->ctx, depth); if (cert->len == 0) { return NGX_OK; } if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) { return NGX_ERROR; } if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_load_verify_locations(\"%s\") failed", cert->data); return NGX_ERROR; } /* * SSL_CTX_load_verify_locations() may leave errors in the error queue * while returning success */ ERR_clear_error(); list = SSL_load_client_CA_file((char *) cert->data); if (list == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_load_client_CA_file(\"%s\") failed", cert->data); return NGX_ERROR; } /* * before 0.9.7h and 0.9.8 SSL_load_client_CA_file() * always leaved an error in the error queue */ ERR_clear_error(); SSL_CTX_set_client_CA_list(ssl->ctx, list); return NGX_OK; }
static char * ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_mail_ssl_conf_t *prev = parent; ngx_mail_ssl_conf_t *conf = child; ngx_pool_cleanup_t *cln; ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_value(conf->starttls, prev->starttls, NGX_MAIL_STARTTLS_OFF); if (conf->enable == 0 && conf->starttls == NGX_MAIL_STARTTLS_OFF) { return NGX_CONF_OK; } ngx_conf_merge_value(conf->session_timeout, prev->session_timeout, 300); ngx_conf_merge_value(conf->prefer_server_ciphers, prev->prefer_server_ciphers, 0); ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, (NGX_CONF_BITMASK_SET |NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1)); ngx_conf_merge_str_value(conf->certificate, prev->certificate, NGX_DEFLAUT_CERTIFICATE); ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, NGX_DEFLAUT_CERTIFICATE_KEY); ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFLAUT_CIPHERS); conf->ssl.log = cf->log; if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) { return NGX_CONF_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_CONF_ERROR; } cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, &conf->certificate_key) != NGX_OK) { return NGX_CONF_ERROR; } if (conf->ciphers.len) { if (SSL_CTX_set_cipher_list(conf->ssl.ctx, (const char *) conf->ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_cipher_list(\"%V\") failed", &conf->ciphers); } } #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE if (conf->prefer_server_ciphers) { SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } #endif if (ngx_ssl_generate_rsa512_key(&conf->ssl) != NGX_OK) { return NGX_CONF_ERROR; } ngx_conf_merge_value(conf->builtin_session_cache, prev->builtin_session_cache, NGX_SSL_NONE_SCACHE); if (conf->shm_zone == NULL) { conf->shm_zone = prev->shm_zone; } if (ngx_ssl_session_cache(&conf->ssl, &ngx_mail_ssl_sess_id_ctx, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static char * ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_http_ssl_srv_conf_t *prev = parent; ngx_http_ssl_srv_conf_t *conf = child; ngx_pool_cleanup_t *cln; ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_value(conf->session_timeout, prev->session_timeout, 300); ngx_conf_merge_value(conf->prefer_server_ciphers, prev->prefer_server_ciphers, 0); ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, (NGX_CONF_BITMASK_SET |NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1)); ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate, ""); ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); conf->ssl.log = cf->log; if (conf->enable) { if (conf->certificate.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " "the \"ssl\" directive in %s:%ui", conf->file, conf->line); return NGX_CONF_ERROR; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined for " "the \"ssl\" directive in %s:%ui", conf->file, conf->line); return NGX_CONF_ERROR; } } else { if (conf->certificate.len == 0) { return NGX_CONF_OK; } if (conf->certificate_key.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", &conf->certificate); return NGX_CONF_ERROR; } } if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) { return NGX_CONF_ERROR; } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx, ngx_http_ssl_servername) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_tlsext_servername_callback() failed"); return NGX_CONF_ERROR; } #endif cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_CONF_ERROR; } cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, &conf->certificate_key) != NGX_OK) { return NGX_CONF_ERROR; } if (SSL_CTX_set_cipher_list(conf->ssl.ctx, (const char *) conf->ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_cipher_list(\"%V\") failed", &conf->ciphers); } if (conf->verify) { if (conf->client_certificate.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no ssl_client_certificate for ssl_client_verify"); return NGX_CONF_ERROR; } if (ngx_ssl_client_certificate(cf, &conf->ssl, &conf->client_certificate, conf->verify_depth) != NGX_OK) { return NGX_CONF_ERROR; } } #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE if (conf->prefer_server_ciphers) { SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } #endif /* a temporary 512-bit RSA key is required for export versions of MSIE */ if (ngx_ssl_generate_rsa512_key(&conf->ssl) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; } ngx_conf_merge_value(conf->builtin_session_cache, prev->builtin_session_cache, NGX_SSL_NONE_SCACHE); if (conf->shm_zone == NULL) { conf->shm_zone = prev->shm_zone; } if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static ngx_int_t ngx_http_lua_set_ssl(ngx_conf_t *cf, ngx_http_lua_loc_conf_t *llcf) { ngx_pool_cleanup_t *cln; llcf->ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); if (llcf->ssl == NULL) { return NGX_ERROR; } llcf->ssl->log = cf->log; if (ngx_ssl_create(llcf->ssl, llcf->ssl_protocols, NULL) != NGX_OK) { return NGX_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_ssl_cleanup_ctx; cln->data = llcf->ssl; if (SSL_CTX_set_cipher_list(llcf->ssl->ctx, (const char *) llcf->ssl_ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_cipher_list(\"%V\") failed", &llcf->ssl_ciphers); return NGX_ERROR; } if (llcf->ssl_trusted_certificate.len) { #if defined(nginx_version) && nginx_version >= 1003007 if (ngx_ssl_trusted_certificate(cf, llcf->ssl, &llcf->ssl_trusted_certificate, llcf->ssl_verify_depth) != NGX_OK) { return NGX_ERROR; } #else ngx_log_error(NGX_LOG_CRIT, cf->log, 0, "at least nginx 1.3.7 is " "required for the \"lua_ssl_trusted_certificate\" " "directive"); return NGX_ERROR; #endif } dd("ssl crl: %.*s", (int) llcf->ssl_crl.len, llcf->ssl_crl.data); if (ngx_ssl_crl(cf, llcf->ssl, &llcf->ssl_crl) != NGX_OK) { return NGX_ERROR; } return NGX_OK; }
ngx_int_t ngx_ssl_shutdown(ngx_connection_t *c) { int n, sslerr; ngx_uint_t again; if (c->timedout) { SSL_set_shutdown(c->ssl->ssl, SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN); } else { if (c->ssl->no_rcv_shut) { SSL_set_shutdown(c->ssl->ssl, SSL_RECEIVED_SHUTDOWN); } if (c->ssl->no_send_shut) { SSL_set_shutdown(c->ssl->ssl, SSL_SENT_SHUTDOWN); } } again = 0; for ( ;; ) { n = SSL_shutdown(c->ssl->ssl); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n); if (n == 0) { again = 1; break; } if (n == 1) { SSL_free(c->ssl->ssl); c->ssl = NULL; return NGX_OK; } break; } if (!again) { sslerr = SSL_get_error(c->ssl->ssl, n); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr); } if (again || sslerr == SSL_ERROR_WANT_READ) { ngx_add_timer(c->read, 10000); if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { return NGX_ERROR; } return NGX_AGAIN; } if (sslerr == SSL_ERROR_WANT_WRITE) { if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { return NGX_ERROR; } return NGX_AGAIN; } ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_shutdown() failed"); return NGX_ERROR; }