Mercurial > hg > nginx
comparison src/event/ngx_event_openssl.c @ 6548:8a34e92d8ab5
SSL: made it possible to iterate though all certificates.
A pointer to a previously configured certificate now stored in a certificate.
This makes it possible to iterate though all certificates configured in
the SSL context. This is now used to configure OCSP stapling for all
certificates, and in ngx_ssl_session_id_context().
As SSL_CTX_use_certificate() frees previously loaded certificate of the same
type, and we have no way to find out if it's the case, X509_free() calls
are now posponed till ngx_ssl_cleanup_ctx().
Note that in OpenSSL 1.0.2+ this can be done without storing things in exdata
using the SSL_CTX_set_current_cert() and SSL_CTX_get0_certificate() functions.
These are not yet available in all supported versions though, so it's easier
to continue to use exdata for now.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 19 May 2016 14:46:32 +0300 |
parents | a873b4d9cd80 |
children | d3302eb87a0c |
comparison
equal
deleted
inserted
replaced
6547:e222a97d46c1 | 6548:8a34e92d8ab5 |
---|---|
103 int ngx_ssl_connection_index; | 103 int ngx_ssl_connection_index; |
104 int ngx_ssl_server_conf_index; | 104 int ngx_ssl_server_conf_index; |
105 int ngx_ssl_session_cache_index; | 105 int ngx_ssl_session_cache_index; |
106 int ngx_ssl_session_ticket_keys_index; | 106 int ngx_ssl_session_ticket_keys_index; |
107 int ngx_ssl_certificate_index; | 107 int ngx_ssl_certificate_index; |
108 int ngx_ssl_next_certificate_index; | |
108 int ngx_ssl_stapling_index; | 109 int ngx_ssl_stapling_index; |
109 | 110 |
110 | 111 |
111 ngx_int_t | 112 ngx_int_t |
112 ngx_ssl_init(ngx_log_t *log) | 113 ngx_ssl_init(ngx_log_t *log) |
185 ngx_ssl_error(NGX_LOG_ALERT, log, 0, | 186 ngx_ssl_error(NGX_LOG_ALERT, log, 0, |
186 "SSL_CTX_get_ex_new_index() failed"); | 187 "SSL_CTX_get_ex_new_index() failed"); |
187 return NGX_ERROR; | 188 return NGX_ERROR; |
188 } | 189 } |
189 | 190 |
191 ngx_ssl_next_certificate_index = X509_get_ex_new_index(0, NULL, NULL, NULL, | |
192 NULL); | |
193 if (ngx_ssl_next_certificate_index == -1) { | |
194 ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed"); | |
195 return NGX_ERROR; | |
196 } | |
197 | |
190 ngx_ssl_stapling_index = X509_get_ex_new_index(0, NULL, NULL, NULL, NULL); | 198 ngx_ssl_stapling_index = X509_get_ex_new_index(0, NULL, NULL, NULL, NULL); |
191 | 199 |
192 if (ngx_ssl_stapling_index == -1) { | 200 if (ngx_ssl_stapling_index == -1) { |
193 ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed"); | 201 ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed"); |
194 return NGX_ERROR; | 202 return NGX_ERROR; |
207 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_new() failed"); | 215 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_new() failed"); |
208 return NGX_ERROR; | 216 return NGX_ERROR; |
209 } | 217 } |
210 | 218 |
211 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) { | 219 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) { |
220 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | |
221 "SSL_CTX_set_ex_data() failed"); | |
222 return NGX_ERROR; | |
223 } | |
224 | |
225 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, NULL) == 0) { | |
212 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | 226 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, |
213 "SSL_CTX_set_ex_data() failed"); | 227 "SSL_CTX_set_ex_data() failed"); |
214 return NGX_ERROR; | 228 return NGX_ERROR; |
215 } | 229 } |
216 | 230 |
343 } | 357 } |
344 | 358 |
345 if (SSL_CTX_use_certificate(ssl->ctx, x509) == 0) { | 359 if (SSL_CTX_use_certificate(ssl->ctx, x509) == 0) { |
346 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | 360 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, |
347 "SSL_CTX_use_certificate(\"%s\") failed", cert->data); | 361 "SSL_CTX_use_certificate(\"%s\") failed", cert->data); |
362 X509_free(x509); | |
363 BIO_free(bio); | |
364 return NGX_ERROR; | |
365 } | |
366 | |
367 if (X509_set_ex_data(x509, ngx_ssl_next_certificate_index, | |
368 SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index)) | |
369 == 0) | |
370 { | |
371 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); | |
348 X509_free(x509); | 372 X509_free(x509); |
349 BIO_free(bio); | 373 BIO_free(bio); |
350 return NGX_ERROR; | 374 return NGX_ERROR; |
351 } | 375 } |
352 | 376 |
357 "SSL_CTX_set_ex_data() failed"); | 381 "SSL_CTX_set_ex_data() failed"); |
358 X509_free(x509); | 382 X509_free(x509); |
359 BIO_free(bio); | 383 BIO_free(bio); |
360 return NGX_ERROR; | 384 return NGX_ERROR; |
361 } | 385 } |
362 | |
363 X509_free(x509); | |
364 | 386 |
365 /* read rest of the chain */ | 387 /* read rest of the chain */ |
366 | 388 |
367 for ( ;; ) { | 389 for ( ;; ) { |
368 | 390 |
2161 STACK_OF(X509_NAME) *list; | 2183 STACK_OF(X509_NAME) *list; |
2162 u_char buf[EVP_MAX_MD_SIZE]; | 2184 u_char buf[EVP_MAX_MD_SIZE]; |
2163 | 2185 |
2164 /* | 2186 /* |
2165 * Session ID context is set based on the string provided, | 2187 * Session ID context is set based on the string provided, |
2166 * the server certificate, and the client CA list. | 2188 * the server certificates, and the client CA list. |
2167 */ | 2189 */ |
2168 | 2190 |
2169 md = EVP_MD_CTX_create(); | 2191 md = EVP_MD_CTX_create(); |
2170 if (md == NULL) { | 2192 if (md == NULL) { |
2171 return NGX_ERROR; | 2193 return NGX_ERROR; |
2181 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | 2203 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, |
2182 "EVP_DigestUpdate() failed"); | 2204 "EVP_DigestUpdate() failed"); |
2183 goto failed; | 2205 goto failed; |
2184 } | 2206 } |
2185 | 2207 |
2186 cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); | 2208 for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); |
2187 | 2209 cert; |
2188 if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) { | 2210 cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index)) |
2189 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | 2211 { |
2190 "X509_digest() failed"); | 2212 if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) { |
2191 goto failed; | 2213 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, |
2192 } | 2214 "X509_digest() failed"); |
2193 | 2215 goto failed; |
2194 if (EVP_DigestUpdate(md, buf, len) == 0) { | 2216 } |
2195 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | 2217 |
2196 "EVP_DigestUpdate() failed"); | 2218 if (EVP_DigestUpdate(md, buf, len) == 0) { |
2197 goto failed; | 2219 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, |
2220 "EVP_DigestUpdate() failed"); | |
2221 goto failed; | |
2222 } | |
2198 } | 2223 } |
2199 | 2224 |
2200 list = SSL_CTX_get_client_CA_list(ssl->ctx); | 2225 list = SSL_CTX_get_client_CA_list(ssl->ctx); |
2201 | 2226 |
2202 if (list != NULL) { | 2227 if (list != NULL) { |
2948 void | 2973 void |
2949 ngx_ssl_cleanup_ctx(void *data) | 2974 ngx_ssl_cleanup_ctx(void *data) |
2950 { | 2975 { |
2951 ngx_ssl_t *ssl = data; | 2976 ngx_ssl_t *ssl = data; |
2952 | 2977 |
2978 X509 *cert, *next; | |
2979 | |
2980 cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); | |
2981 | |
2982 while (cert) { | |
2983 next = X509_get_ex_data(cert, ngx_ssl_next_certificate_index); | |
2984 X509_free(cert); | |
2985 cert = next; | |
2986 } | |
2987 | |
2953 SSL_CTX_free(ssl->ctx); | 2988 SSL_CTX_free(ssl->ctx); |
2954 } | 2989 } |
2955 | 2990 |
2956 | 2991 |
2957 ngx_int_t | 2992 ngx_int_t |