comparison src/event/ngx_event_openssl.c @ 688:f31b19fe7f48 NGINX_1_3_7

nginx 1.3.7 *) Feature: OCSP stapling support. Thanks to Comodo, DigiCert and GlobalSign for sponsoring this work. *) Feature: the "ssl_trusted_certificate" directive. *) Feature: resolver now randomly rotates addresses returned from cache. Thanks to Anton Jouline. *) Bugfix: OpenSSL 0.9.7 compatibility.
author Igor Sysoev <http://sysoev.ru>
date Tue, 02 Oct 2012 00:00:00 +0400
parents 981b4c44593b
children
comparison
equal deleted inserted replaced
687:a7305f494f1c 688:f31b19fe7f48
80 80
81 81
82 int ngx_ssl_connection_index; 82 int ngx_ssl_connection_index;
83 int ngx_ssl_server_conf_index; 83 int ngx_ssl_server_conf_index;
84 int ngx_ssl_session_cache_index; 84 int ngx_ssl_session_cache_index;
85 int ngx_ssl_certificate_index;
86 int ngx_ssl_stapling_index;
85 87
86 88
87 ngx_int_t 89 ngx_int_t
88 ngx_ssl_init(ngx_log_t *log) 90 ngx_ssl_init(ngx_log_t *log)
89 { 91 {
92 SSL_library_init(); 94 SSL_library_init();
93 SSL_load_error_strings(); 95 SSL_load_error_strings();
94 96
95 OpenSSL_add_all_algorithms(); 97 OpenSSL_add_all_algorithms();
96 98
99 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
97 #ifndef SSL_OP_NO_COMPRESSION 100 #ifndef SSL_OP_NO_COMPRESSION
98 { 101 {
99 /* 102 /*
100 * Disable gzip compression in OpenSSL prior to 1.0.0 version, 103 * Disable gzip compression in OpenSSL prior to 1.0.0 version,
101 * this saves about 522K per connection. 104 * this saves about 522K per connection.
102 */ 105 */
103 int i, n; 106 int n;
104 STACK_OF(SSL_COMP) *ssl_comp_methods; 107 STACK_OF(SSL_COMP) *ssl_comp_methods;
105 108
106 ssl_comp_methods = SSL_COMP_get_compression_methods(); 109 ssl_comp_methods = SSL_COMP_get_compression_methods();
107 n = sk_SSL_COMP_num(ssl_comp_methods); 110 n = sk_SSL_COMP_num(ssl_comp_methods);
108 111
109 for (i = 0; i < n; i++) { 112 while (n--) {
110 (void) sk_SSL_COMP_delete(ssl_comp_methods, i); 113 (void) sk_SSL_COMP_pop(ssl_comp_methods);
111 } 114 }
112 } 115 }
116 #endif
113 #endif 117 #endif
114 118
115 ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); 119 ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
116 120
117 if (ngx_ssl_connection_index == -1) { 121 if (ngx_ssl_connection_index == -1) {
133 ngx_ssl_error(NGX_LOG_ALERT, log, 0, 137 ngx_ssl_error(NGX_LOG_ALERT, log, 0,
134 "SSL_CTX_get_ex_new_index() failed"); 138 "SSL_CTX_get_ex_new_index() failed");
135 return NGX_ERROR; 139 return NGX_ERROR;
136 } 140 }
137 141
142 ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
143 NULL);
144 if (ngx_ssl_certificate_index == -1) {
145 ngx_ssl_error(NGX_LOG_ALERT, log, 0,
146 "SSL_CTX_get_ex_new_index() failed");
147 return NGX_ERROR;
148 }
149
150 ngx_ssl_stapling_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
151 NULL);
152 if (ngx_ssl_stapling_index == -1) {
153 ngx_ssl_error(NGX_LOG_ALERT, log, 0,
154 "SSL_CTX_get_ex_new_index() failed");
155 return NGX_ERROR;
156 }
157
138 return NGX_OK; 158 return NGX_OK;
139 } 159 }
140 160
141 161
142 ngx_int_t 162 ngx_int_t
214 234
215 ngx_int_t 235 ngx_int_t
216 ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, 236 ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
217 ngx_str_t *key) 237 ngx_str_t *key)
218 { 238 {
239 BIO *bio;
240 X509 *x509;
241 u_long n;
242
219 if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) { 243 if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
220 return NGX_ERROR; 244 return NGX_ERROR;
221 } 245 }
222 246
223 if (SSL_CTX_use_certificate_chain_file(ssl->ctx, (char *) cert->data) 247 /*
248 * we can't use SSL_CTX_use_certificate_chain_file() as it doesn't
249 * allow to access certificate later from SSL_CTX, so we reimplement
250 * it here
251 */
252
253 bio = BIO_new_file((char *) cert->data, "r");
254 if (bio == NULL) {
255 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
256 "BIO_new_file(\"%s\") failed", cert->data);
257 return NGX_ERROR;
258 }
259
260 x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
261 if (x509 == NULL) {
262 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
263 "PEM_read_bio_X509_AUX(\"%s\") failed", cert->data);
264 BIO_free(bio);
265 return NGX_ERROR;
266 }
267
268 if (SSL_CTX_use_certificate(ssl->ctx, x509) == 0) {
269 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
270 "SSL_CTX_use_certificate(\"%s\") failed", cert->data);
271 X509_free(x509);
272 BIO_free(bio);
273 return NGX_ERROR;
274 }
275
276 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509)
224 == 0) 277 == 0)
225 { 278 {
226 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, 279 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
227 "SSL_CTX_use_certificate_chain_file(\"%s\") failed", 280 "SSL_CTX_set_ex_data() failed");
228 cert->data); 281 return NGX_ERROR;
229 return NGX_ERROR; 282 }
230 } 283
284 X509_free(x509);
285
286 /* read rest of the chain */
287
288 for ( ;; ) {
289
290 x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
291 if (x509 == NULL) {
292 n = ERR_peek_last_error();
293
294 if (ERR_GET_LIB(n) == ERR_LIB_PEM
295 && ERR_GET_REASON(n) == PEM_R_NO_START_LINE)
296 {
297 /* end of file */
298 ERR_clear_error();
299 break;
300 }
301
302 /* some real error */
303
304 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
305 "PEM_read_bio_X509(\"%s\") failed", cert->data);
306 BIO_free(bio);
307 return NGX_ERROR;
308 }
309
310 if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) {
311 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
312 "SSL_CTX_add_extra_chain_cert(\"%s\") failed",
313 cert->data);
314 X509_free(x509);
315 BIO_free(bio);
316 return NGX_ERROR;
317 }
318 }
319
320 BIO_free(bio);
231 321
232 if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) { 322 if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) {
233 return NGX_ERROR; 323 return NGX_ERROR;
234 } 324 }
235 325
287 */ 377 */
288 378
289 ERR_clear_error(); 379 ERR_clear_error();
290 380
291 SSL_CTX_set_client_CA_list(ssl->ctx, list); 381 SSL_CTX_set_client_CA_list(ssl->ctx, list);
382
383 return NGX_OK;
384 }
385
386
387 ngx_int_t
388 ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
389 ngx_int_t depth)
390 {
391 SSL_CTX_set_verify_depth(ssl->ctx, depth);
392
393 if (cert->len == 0) {
394 return NGX_OK;
395 }
396
397 if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
398 return NGX_ERROR;
399 }
400
401 if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
402 == 0)
403 {
404 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
405 "SSL_CTX_load_verify_locations(\"%s\") failed",
406 cert->data);
407 return NGX_ERROR;
408 }
292 409
293 return NGX_OK; 410 return NGX_OK;
294 } 411 }
295 412
296 413
1471 1588
1472 1589
1473 void ngx_cdecl 1590 void ngx_cdecl
1474 ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...) 1591 ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
1475 { 1592 {
1476 u_long n; 1593 int flags;
1477 va_list args; 1594 u_long n;
1478 u_char *p, *last; 1595 va_list args;
1479 u_char errstr[NGX_MAX_CONF_ERRSTR]; 1596 u_char *p, *last;
1597 u_char errstr[NGX_MAX_CONF_ERRSTR];
1598 const char *data;
1480 1599
1481 last = errstr + NGX_MAX_CONF_ERRSTR; 1600 last = errstr + NGX_MAX_CONF_ERRSTR;
1482 1601
1483 va_start(args, fmt); 1602 va_start(args, fmt);
1484 p = ngx_vslprintf(errstr, last - 1, fmt, args); 1603 p = ngx_vslprintf(errstr, last - 1, fmt, args);
1486 1605
1487 p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p); 1606 p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p);
1488 1607
1489 for ( ;; ) { 1608 for ( ;; ) {
1490 1609
1491 n = ERR_get_error(); 1610 n = ERR_peek_error_line_data(NULL, NULL, &data, &flags);
1492 1611
1493 if (n == 0) { 1612 if (n == 0) {
1494 break; 1613 break;
1495 } 1614 }
1496 1615
1497 if (p >= last) { 1616 if (p >= last) {
1498 continue; 1617 goto next;
1499 } 1618 }
1500 1619
1501 *p++ = ' '; 1620 *p++ = ' ';
1502 1621
1503 ERR_error_string_n(n, (char *) p, last - p); 1622 ERR_error_string_n(n, (char *) p, last - p);
1504 1623
1505 while (p < last && *p) { 1624 while (p < last && *p) {
1506 p++; 1625 p++;
1507 } 1626 }
1627
1628 if (p < last && *data && (flags & ERR_TXT_STRING)) {
1629 *p++ = ':';
1630 p = ngx_cpystrn(p, (u_char *) data, last - p);
1631 }
1632
1633 next:
1634
1635 (void) ERR_get_error();
1508 } 1636 }
1509 1637
1510 ngx_log_error(level, log, err, "%s)", errstr); 1638 ngx_log_error(level, log, err, "%s)", errstr);
1511 } 1639 }
1512 1640