/* * Copyright (C) Maxim Dounin * Copyright (C) Nginx, Inc. */ #include #include #include #ifdef SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data); ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) { BIO *bio; int len; u_char *p, *buf; ngx_str_t *staple; OCSP_RESPONSE *response; if (file->len == 0) { return NGX_OK; } 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_pnalloc(cf->pool, len); 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); goto failed; } OCSP_RESPONSE_free(response); BIO_free(bio); staple = ngx_palloc(cf->pool, sizeof(ngx_str_t)); if (staple == NULL) { return NGX_ERROR; } staple->data = buf; staple->len = len; 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; failed: OCSP_RESPONSE_free(response); BIO_free(bio); return NGX_ERROR; } static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data) { u_char *p; ngx_str_t *staple; ngx_connection_t *c; c = ngx_ssl_get_connection(ssl_conn); ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL certificate status callback"); staple = data; /* we have to copy the staple as OpenSSL will free it by itself */ p = OPENSSL_malloc(staple->len); if (p == NULL) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "OPENSSL_malloc() failed"); return SSL_TLSEXT_ERR_ALERT_FATAL; } ngx_memcpy(p, staple->data, staple->len); SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, staple->len); return SSL_TLSEXT_ERR_OK; } #else ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, "\"ssl_stapling\" ignored, not supported"); return NGX_OK; } #endif