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