~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/event/ngx_event_openssl.c

Version: ~ [ nginx-0.8.20 ] ~ [ nginx-0.7.62 ] ~ [ nginx-0.6.39 ] ~

  1 
  2 /*
  3  * Copyright (C) Igor Sysoev
  4  */
  5 
  6 
  7 #include <ngx_config.h>
  8 #include <ngx_core.h>
  9 #include <ngx_event.h>
 10 
 11 
 12 typedef struct {
 13     ngx_uint_t  engine;   /* unsigned  engine:1; */
 14 } ngx_openssl_conf_t;
 15 
 16 
 17 static int ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
 18 static void ngx_ssl_handshake_handler(ngx_event_t *ev);
 19 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
 20 static void ngx_ssl_write_handler(ngx_event_t *wev);
 21 static void ngx_ssl_read_handler(ngx_event_t *rev);
 22 static void ngx_ssl_shutdown_handler(ngx_event_t *ev);
 23 static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
 24     ngx_err_t err, char *text);
 25 static void ngx_ssl_clear_error(ngx_log_t *log);
 26 
 27 static ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone,
 28     void *data);
 29 static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn,
 30     ngx_ssl_session_t *sess);
 31 static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
 32     u_char *id, int len, int *copy);
 33 static void ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess);
 34 static void ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
 35     ngx_slab_pool_t *shpool, ngx_uint_t n);
 36 static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
 37     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
 38 
 39 static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
 40 static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 41 static void ngx_openssl_exit(ngx_cycle_t *cycle);
 42 
 43 
 44 static ngx_command_t  ngx_openssl_commands[] = {
 45 
 46     { ngx_string("ssl_engine"),
 47       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
 48       ngx_openssl_engine,
 49       0,
 50       0,
 51       NULL },
 52 
 53       ngx_null_command
 54 };
 55 
 56 
 57 static ngx_core_module_t  ngx_openssl_module_ctx = {
 58     ngx_string("openssl"),
 59     ngx_openssl_create_conf,
 60     NULL
 61 };
 62 
 63 
 64 ngx_module_t  ngx_openssl_module = {
 65     NGX_MODULE_V1,
 66     &ngx_openssl_module_ctx,               /* module context */
 67     ngx_openssl_commands,                  /* module directives */
 68     NGX_CORE_MODULE,                       /* module type */
 69     NULL,                                  /* init master */
 70     NULL,                                  /* init module */
 71     NULL,                                  /* init process */
 72     NULL,                                  /* init thread */
 73     NULL,                                  /* exit thread */
 74     NULL,                                  /* exit process */
 75     ngx_openssl_exit,                      /* exit master */
 76     NGX_MODULE_V1_PADDING
 77 };
 78 
 79 
 80 static long  ngx_ssl_protocols[] = {
 81     SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1,
 82     SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1,
 83     SSL_OP_NO_SSLv2|SSL_OP_NO_TLSv1,
 84     SSL_OP_NO_TLSv1,
 85     SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3,
 86     SSL_OP_NO_SSLv3,
 87     SSL_OP_NO_SSLv2,
 88     0,
 89 };
 90 
 91 
 92 int  ngx_ssl_connection_index;
 93 int  ngx_ssl_server_conf_index;
 94 int  ngx_ssl_session_cache_index;
 95 
 96 
 97 ngx_int_t
 98 ngx_ssl_init(ngx_log_t *log)
 99 {
100     OPENSSL_config(NULL);
101 
102     SSL_library_init();
103     SSL_load_error_strings();
104 
105     ENGINE_load_builtin_engines();
106 
107     ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
108 
109     if (ngx_ssl_connection_index == -1) {
110         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed");
111         return NGX_ERROR;
112     }
113 
114     ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
115                                                          NULL);
116     if (ngx_ssl_server_conf_index == -1) {
117         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
118                       "SSL_CTX_get_ex_new_index() failed");
119         return NGX_ERROR;
120     }
121 
122     ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
123                                                            NULL);
124     if (ngx_ssl_session_cache_index == -1) {
125         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
126                       "SSL_CTX_get_ex_new_index() failed");
127         return NGX_ERROR;
128     }
129 
130     return NGX_OK;
131 }
132 
133 
134 ngx_int_t
135 ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
136 {
137     ssl->ctx = SSL_CTX_new(SSLv23_method());
138 
139     if (ssl->ctx == NULL) {
140         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_new() failed");
141         return NGX_ERROR;
142     }
143 
144     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) {
145         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
146                       "SSL_CTX_set_ex_data() failed");
147         return NGX_ERROR;
148     }
149 
150     /* client side options */
151 
152     SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
153     SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
154     SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG);
155 
156     /* server side options */
157 
158     SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
159     SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
160 
161     /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
162     SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
163 
164     SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
165     SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG);
166     SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_BLOCK_PADDING_BUG);
167 
168     SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
169 
170     SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE);
171 
172     if (ngx_ssl_protocols[protocols >> 1] != 0) {
173         SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]);
174     }
175 
176     SSL_CTX_set_read_ahead(ssl->ctx, 1);
177 
178     return NGX_OK;
179 }
180 
181 
182 ngx_int_t
183 ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
184     ngx_str_t *key)
185 {
186     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
187         return NGX_ERROR;
188     }
189 
190     if (SSL_CTX_use_certificate_chain_file(ssl->ctx, (char *) cert->data)
191         == 0)
192     {
193         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
194                       "SSL_CTX_use_certificate_chain_file(\"%s\") failed",
195                       cert->data);
196         return NGX_ERROR;
197     }
198 
199     if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) {
200         return NGX_ERROR;
201     }
202 
203     if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data,
204                                     SSL_FILETYPE_PEM)
205         == 0)
206     {
207         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
208                       "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key->data);
209         return NGX_ERROR;
210     }
211 
212     return NGX_OK;
213 }
214 
215 
216 ngx_int_t
217 ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
218     ngx_int_t depth)
219 {
220     STACK_OF(X509_NAME)  *list;
221 
222     SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_http_ssl_verify_callback);
223 
224     SSL_CTX_set_verify_depth(ssl->ctx, depth);
225 
226     if (cert->len == 0) {
227         return NGX_OK;
228     }
229 
230     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
231         return NGX_ERROR;
232     }
233 
234     if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
235         == 0)
236     {
237         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
238                       "SSL_CTX_load_verify_locations(\"%s\") failed",
239                       cert->data);
240         return NGX_ERROR;
241     }
242 
243     list = SSL_load_client_CA_file((char *) cert->data);
244 
245     if (list == NULL) {
246         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
247                       "SSL_load_client_CA_file(\"%s\") failed", cert->data);
248         return NGX_ERROR;
249     }
250 
251     /*
252      * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
253      * always leaved an error in the error queue
254      */
255 
256     ERR_clear_error();
257 
258     SSL_CTX_set_client_CA_list(ssl->ctx, list);
259 
260     return NGX_OK;
261 }
262 
263 
264 ngx_int_t
265 ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl)
266 {
267     X509_STORE   *store;
268     X509_LOOKUP  *lookup;
269 
270     if (crl->len == 0) {
271         return NGX_OK;
272     }
273 
274     if (ngx_conf_full_name(cf->cycle, crl, 1) != NGX_OK) {
275         return NGX_ERROR;
276     }
277 
278     store = SSL_CTX_get_cert_store(ssl->ctx);
279 
280     if (store == NULL) {
281         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
282                       "SSL_CTX_get_cert_store() failed");
283         return NGX_ERROR;
284     }
285 
286     lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
287 
288     if (lookup == NULL) {
289         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
290                       "X509_STORE_add_lookup() failed");
291         return NGX_ERROR;
292     }
293 
294     if (X509_LOOKUP_load_file(lookup, (char *) crl->data, X509_FILETYPE_PEM)
295         == 0)
296     {
297         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
298                       "X509_LOOKUP_load_file(\"%s\") failed", crl->data);
299         return NGX_ERROR;
300     }
301 
302     X509_STORE_set_flags(store,
303                          X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
304 
305     return NGX_OK;
306 }
307 
308 
309 static int
310 ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
311 {
312 #if (NGX_DEBUG)
313     char              *subject, *issuer;
314     int                err, depth;
315     X509              *cert;
316     X509_NAME         *sname, *iname;
317     ngx_connection_t  *c;
318     ngx_ssl_conn_t    *ssl_conn;
319 
320     ssl_conn = X509_STORE_CTX_get_ex_data(x509_store,
321                                           SSL_get_ex_data_X509_STORE_CTX_idx());
322 
323     c = ngx_ssl_get_connection(ssl_conn);
324 
325     cert = X509_STORE_CTX_get_current_cert(x509_store);
326     err = X509_STORE_CTX_get_error(x509_store);
327     depth = X509_STORE_CTX_get_error_depth(x509_store);
328 
329     sname = X509_get_subject_name(cert);
330     subject = sname ? X509_NAME_oneline(sname, NULL, 0) : "(none)";
331 
332     iname = X509_get_issuer_name(cert);
333     issuer = iname ? X509_NAME_oneline(iname, NULL, 0) : "(none)";
334 
335     ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
336                    "verify:%d, error:%d, depth:%d, "
337                    "subject:\"%s\",issuer: \"%s\"",
338                    ok, err, depth, subject, issuer);
339 
340     if (sname) {
341         OPENSSL_free(subject);
342     }
343 
344     if (iname) {
345         OPENSSL_free(issuer);
346     }
347 #endif
348 
349     return 1;
350 }
351 
352 
353 ngx_int_t
354 ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl)
355 {
356     RSA  *key;
357 
358     if (SSL_CTX_need_tmp_RSA(ssl->ctx) == 0) {
359         return NGX_OK;
360     }
361 
362     key = RSA_generate_key(512, RSA_F4, NULL, NULL);
363 
364     if (key) {
365         SSL_CTX_set_tmp_rsa(ssl->ctx, key);
366 
367         RSA_free(key);
368 
369         return NGX_OK;
370     }
371 
372     ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "RSA_generate_key(512) failed");
373 
374     return NGX_ERROR;
375 }
376 
377 
378 ngx_int_t
379 ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
380 {
381     DH   *dh;
382     BIO  *bio;
383 
384     /*
385      * -----BEGIN DH PARAMETERS-----
386      * MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc
387      * y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl
388      * 7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC
389      * -----END DH PARAMETERS-----
390      */
391 
392     static unsigned char dh1024_p[] = {
393         0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46, 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5,
394         0x80, 0xE9, 0xCF, 0xDB, 0xD9, 0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B,
395         0x08, 0xEE, 0xD4, 0xEB, 0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76,
396         0xE7, 0x10, 0x80, 0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5,
397         0xBE, 0xEC, 0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04,
398         0x9B, 0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04,
399         0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5, 0xDF,
400         0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC, 0x9A, 0x50,
401         0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A, 0x63, 0xAB, 0x1E,
402         0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D, 0x14, 0x67, 0x57, 0xDA,
403         0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B, 0x9B
404     };
405 
406     static unsigned char dh1024_g[] = { 0x02 };
407 
408 
409     if (file->len == 0) {
410 
411         dh = DH_new();
412         if (dh == NULL) {
413             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "DH_new() failed");
414             return NGX_ERROR;
415         }
416 
417         dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
418         dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
419 
420         if (dh->p == NULL || dh->g == NULL) {
421             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "BN_bin2bn() failed");
422             DH_free(dh);
423             return NGX_ERROR;
424         }
425 
426         SSL_CTX_set_tmp_dh(ssl->ctx, dh);
427 
428         DH_free(dh);
429 
430         return NGX_OK;
431     }
432 
433     if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
434         return NGX_ERROR;
435     }
436 
437     bio = BIO_new_file((char *) file->data, "r");
438     if (bio == NULL) {
439         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
440                       "BIO_new_file(\"%s\") failed", file->data);
441         return NGX_ERROR;
442     }
443 
444     dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
445     if (dh == NULL) {
446         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
447                       "PEM_read_bio_DHparams(\"%s\") failed", file->data);
448         BIO_free(bio);
449         return NGX_ERROR;
450     }
451 
452     SSL_CTX_set_tmp_dh(ssl->ctx, dh);
453 
454     DH_free(dh);
455     BIO_free(bio);
456 
457     return NGX_OK;
458 }
459 
460 
461 ngx_int_t
462 ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
463 {
464     ngx_ssl_connection_t  *sc;
465 
466     sc = ngx_pcalloc(c->pool, sizeof(ngx_ssl_connection_t));
467     if (sc == NULL) {
468         return NGX_ERROR;
469     }
470 
471     sc->buffer = ((flags & NGX_SSL_BUFFER) != 0);
472 
473     sc->connection = SSL_new(ssl->ctx);
474 
475     if (sc->connection == NULL) {
476         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed");
477         return NGX_ERROR;
478     }
479 
480     if (SSL_set_fd(sc->connection, c->fd) == 0) {
481         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_fd() failed");
482         return NGX_ERROR;
483     }
484 
485     if (flags & NGX_SSL_CLIENT) {
486         SSL_set_connect_state(sc->connection);
487 
488     } else {
489         SSL_set_accept_state(sc->connection);
490     }
491 
492     if (SSL_set_ex_data(sc->connection, ngx_ssl_connection_index, c) == 0) {
493         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed");
494         return NGX_ERROR;
495     }
496 
497     c->ssl = sc;
498 
499     return NGX_OK;
500 }
501 
502 
503 ngx_int_t
504 ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session)
505 {
506     if (session) {
507         if (SSL_set_session(c->ssl->connection, session) == 0) {
508             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_session() failed");
509             return NGX_ERROR;
510         }
511     }
512 
513     return NGX_OK;
514 }
515 
516 
517 ngx_int_t
518 ngx_ssl_handshake(ngx_connection_t *c)
519 {
520     int        n, sslerr;
521     ngx_err_t  err;
522 
523     ngx_ssl_clear_error(c->log);
524 
525     n = SSL_do_handshake(c->ssl->connection);
526 
527     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
528 
529     if (n == 1) {
530 
531         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
532             return NGX_ERROR;
533         }
534 
535         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
536             return NGX_ERROR;
537         }
538 
539 #if (NGX_DEBUG)
540         {
541         char         buf[129], *s, *d;
542         SSL_CIPHER  *cipher;
543 
544         cipher = SSL_get_current_cipher(c->ssl->connection);
545 
546         if (cipher) {
547             SSL_CIPHER_description(cipher, &buf[1], 128);
548 
549             for (s = &buf[1], d = buf; *s; s++) {
550                 if (*s == ' ' && *d == ' ') {
551                     continue;
552                 }
553 
554                 if (*s == LF || *s == CR) {
555                     continue;
556                 }
557 
558                 *++d = *s;
559             }
560 
561             if (*d != ' ') {
562                 d++;
563             }
564 
565             *d = '\0';
566 
567             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
568                            "SSL: %s, cipher: \"%s\"",
569                            SSL_get_version(c->ssl->connection), &buf[1]);
570 
571             if (SSL_session_reused(c->ssl->connection)) {
572                 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
573                                "SSL reused session");
574             }
575 
576         } else {
577             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
578                            "SSL no shared ciphers");
579         }
580         }
581 #endif
582 
583         c->ssl->handshaked = 1;
584 
585         c->recv = ngx_ssl_recv;
586         c->send = ngx_ssl_write;
587         c->recv_chain = ngx_ssl_recv_chain;
588         c->send_chain = ngx_ssl_send_chain;
589 
590         return NGX_OK;
591     }
592 
593     sslerr = SSL_get_error(c->ssl->connection, n);
594 
595     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
596 
597     if (sslerr == SSL_ERROR_WANT_READ) {
598         c->read->ready = 0;
599         c->read->handler = ngx_ssl_handshake_handler;
600         c->write->handler = ngx_ssl_handshake_handler;
601 
602         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
603             return NGX_ERROR;
604         }
605 
606         return NGX_AGAIN;
607     }
608 
609     if (sslerr == SSL_ERROR_WANT_WRITE) {
610         c->write->ready = 0;
611         c->read->handler = ngx_ssl_handshake_handler;
612         c->write->handler = ngx_ssl_handshake_handler;
613 
614         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
615             return NGX_ERROR;
616         }
617 
618         return NGX_AGAIN;
619     }
620 
621     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
622 
623     c->ssl->no_wait_shutdown = 1;
624     c->ssl->no_send_shutdown = 1;
625     c->read->eof = 1;
626 
627     if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
628         ngx_log_error(NGX_LOG_INFO, c->log, err,
629                       "peer closed connection in SSL handshake");
630 
631         return NGX_ERROR;
632     }
633 
634     c->read->error = 1;
635 
636     ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed");
637 
638     return NGX_ERROR;
639 }
640 
641 
642 static void
643 ngx_ssl_handshake_handler(ngx_event_t *ev)
644 {
645     ngx_connection_t  *c;
646 
647     c = ev->data;
648 
649     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
650                    "SSL handshake handler: %d", ev->write);
651 
652     if (ev->timedout) {
653         c->ssl->handler(c);
654         return;
655     }
656 
657     if (ngx_ssl_handshake(c) == NGX_AGAIN) {
658         return;
659     }
660 
661     c->ssl->handler(c);
662 }
663 
664 
665 ssize_t
666 ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl)
667 {
668     u_char     *last;
669     ssize_t     n, bytes;
670     ngx_buf_t  *b;
671 
672     bytes = 0;
673 
674     b = cl->buf;
675     last = b->last;
676 
677     for ( ;; ) {
678 
679         n = ngx_ssl_recv(c, last, b->end - last);
680 
681         if (n > 0) {
682             last += n;
683             bytes += n;
684 
685             if (last == b->end) {
686                 cl = cl->next;
687 
688                 if (cl == NULL) {
689                     return bytes;
690                 }
691 
692                 b = cl->buf;
693                 last = b->last;
694             }
695 
696             continue;
697         }
698 
699         if (bytes) {
700 
701             if (n == 0 || n == NGX_ERROR) {
702                 c->read->ready = 1;
703             }
704 
705             return bytes;
706         }
707 
708         return n;
709     }
710 }
711 
712 
713 ssize_t
714 ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
715 {
716     int  n, bytes;
717 
718     if (c->ssl->last == NGX_ERROR) {
719         c->read->error = 1;
720         return NGX_ERROR;
721     }
722 
723     if (c->ssl->last == NGX_DONE) {
724         c->read->ready = 0;
725         c->read->eof = 1;
726         return 0;
727     }
728 
729     bytes = 0;
730 
731     ngx_ssl_clear_error(c->log);
732 
733     /*
734      * SSL_read() may return data in parts, so try to read
735      * until SSL_read() would return no data
736      */
737 
738     for ( ;; ) {
739 
740         n = SSL_read(c->ssl->connection, buf, size);
741 
742         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n);
743 
744         if (n > 0) {
745             bytes += n;
746         }
747 
748         c->ssl->last = ngx_ssl_handle_recv(c, n);
749 
750         if (c->ssl->last == NGX_OK) {
751 
752             size -= n;
753 
754             if (size == 0) {
755                 return bytes;
756             }
757 
758             buf += n;
759 
760             continue;
761         }
762 
763         if (bytes) {
764             return bytes;
765         }
766 
767         switch (c->ssl->last) {
768 
769         case NGX_DONE:
770             c->read->ready = 0;
771             c->read->eof = 1;
772             return 0;
773 
774         case NGX_ERROR:
775             c->read->error = 1;
776 
777             /* fall thruogh */
778 
779         case NGX_AGAIN:
780             return c->ssl->last;
781         }
782     }
783 }
784 
785 
786 static ngx_int_t
787 ngx_ssl_handle_recv(ngx_connection_t *c, int n)
788 {
789     int        sslerr;
790     ngx_err_t  err;
791 
792     if (n > 0) {
793 
794         if (c->ssl->saved_write_handler) {
795 
796             c->write->handler = c->ssl->saved_write_handler;
797             c->ssl->saved_write_handler = NULL;
798             c->write->ready = 1;
799 
800             if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
801                 return NGX_ERROR;
802             }
803 
804             ngx_post_event(c->write, &ngx_posted_events);
805         }
806 
807         return NGX_OK;
808     }
809 
810     sslerr = SSL_get_error(c->ssl->connection, n);
811 
812     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
813 
814     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
815 
816     if (sslerr == SSL_ERROR_WANT_READ) {
817         c->read->ready = 0;
818         return NGX_AGAIN;
819     }
820 
821     if (sslerr == SSL_ERROR_WANT_WRITE) {
822 
823         ngx_log_error(NGX_LOG_INFO, c->log, 0,
824                       "peer started SSL renegotiation");
825 
826         c->write->ready = 0;
827 
828         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
829             return NGX_ERROR;
830         }
831 
832         /*
833          * we do not set the timer because there is already the read event timer
834          */
835 
836         if (c->ssl->saved_write_handler == NULL) {
837             c->ssl->saved_write_handler = c->write->handler;
838             c->write->handler = ngx_ssl_write_handler;
839         }
840 
841         return NGX_AGAIN;
842     }
843 
844     c->ssl->no_wait_shutdown = 1;
845     c->ssl->no_send_shutdown = 1;
846 
847     if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
848         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
849                        "peer shutdown SSL cleanly");
850         return NGX_DONE;
851     }
852 
853     ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed");
854 
855     return NGX_ERROR;
856 }
857 
858 
859 static void
860 ngx_ssl_write_handler(ngx_event_t *wev)
861 {
862     ngx_connection_t  *c;
863 
864     c = wev->data;
865 
866     c->read->handler(c->read);
867 }
868 
869 
870 /*
871  * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer
872  * before the SSL_write() call to decrease a SSL overhead.
873  *
874  * Besides for protocols such as HTTP it is possible to always buffer
875  * the output to decrease a SSL overhead some more.
876  */
877 
878 ngx_chain_t *
879 ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
880 {
881     int          n;
882     ngx_uint_t   flush;
883     ssize_t      send, size;
884     ngx_buf_t   *buf;
885 
886     if (!c->ssl->buffer) {
887 
888         while (in) {
889             if (ngx_buf_special(in->buf)) {
890                 in = in->next;
891                 continue;
892             }
893 
894             n = ngx_ssl_write(c, in->buf->pos, in->buf->last - in->buf->pos);
895 
896             if (n == NGX_ERROR) {
897                 return NGX_CHAIN_ERROR;
898             }
899 
900             if (n == NGX_AGAIN) {
901                 c->buffered |= NGX_SSL_BUFFERED;
902                 return in;
903             }
904 
905             in->buf->pos += n;
906 
907             if (in->buf->pos == in->buf->last) {
908                 in = in->next;
909             }
910         }
911 
912         return in;
913     }
914 
915 
916     /* the maximum limit size is the maximum uint32_t value - the page size */
917 
918     if (limit == 0 || limit > (off_t) (NGX_MAX_UINT32_VALUE - ngx_pagesize)) {
919         limit = NGX_MAX_UINT32_VALUE - ngx_pagesize;
920     }
921 
922     buf = c->ssl->buf;
923 
924     if (buf == NULL) {
925         buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE);
926         if (buf == NULL) {
927             return NGX_CHAIN_ERROR;
928         }
929 
930         c->ssl->buf = buf;
931     }
932 
933     if (buf->start == NULL) {
934         buf->start = ngx_palloc(c->pool, NGX_SSL_BUFSIZE);
935         if (buf->start == NULL) {
936             return NGX_CHAIN_ERROR;
937         }
938 
939         buf->pos = buf->start;
940         buf->last = buf->start;
941         buf->end = buf->start + NGX_SSL_BUFSIZE;
942     }
943 
944     send = 0;
945     flush = (in == NULL) ? 1 : 0;
946 
947     for ( ;; ) {
948 
949         while (in && buf->last < buf->end) {
950             if (in->buf->last_buf || in->buf->flush) {
951                 flush = 1;
952             }
953 
954             if (ngx_buf_special(in->buf)) {
955                 in = in->next;
956                 continue;
957             }
958 
959             size = in->buf->last - in->buf->pos;
960 
961             if (size > buf->end - buf->last) {
962                 size = buf->end - buf->last;
963             }
964 
965             if (send + size > limit) {
966                 size = (ssize_t) (limit - send);
967                 flush = 1;
968             }
969 
970             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
971                            "SSL buf copy: %d", size);
972 
973             ngx_memcpy(buf->last, in->buf->pos, size);
974 
975             buf->last += size;
976 
977             in->buf->pos += size;
978 
979             if (in->buf->pos == in->buf->last) {
980                 in = in->next;
981             }
982         }
983 
984         size = buf->last - buf->pos;
985 
986         if (!flush && buf->last < buf->end && c->ssl->buffer) {
987             break;
988         }
989 
990         n = ngx_ssl_write(c, buf->pos, size);
991 
992         if (n == NGX_ERROR) {
993             return NGX_CHAIN_ERROR;
994         }
995 
996         if (n == NGX_AGAIN) {
997             c->buffered |= NGX_SSL_BUFFERED;
998             return in;
999         }
1000 
1001         buf->pos += n;
1002         send += n;
1003         c->sent += n;
1004 
1005         if (n < size) {
1006             break;
1007         }
1008 
1009         if (buf->pos == buf->last) {
1010             buf->pos = buf->start;
1011             buf->last = buf->start;
1012         }
1013 
1014         if (in == NULL || send == limit) {
1015             break;
1016         }
1017     }
1018 
1019     if (buf->pos < buf->last) {
1020         c->buffered |= NGX_SSL_BUFFERED;
1021 
1022     } else {
1023         c->buffered &= ~NGX_SSL_BUFFERED;
1024     }
1025 
1026     return in;
1027 }
1028 
1029 
1030 ssize_t
1031 ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
1032 {
1033     int        n, sslerr;
1034     ngx_err_t  err;
1035 
1036     ngx_ssl_clear_error(c->log);
1037 
1038     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size);
1039 
1040     n = SSL_write(c->ssl->connection, data, size);
1041 
1042     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n);
1043 
1044     if (n > 0) {
1045 
1046         if (c->ssl->saved_read_handler) {
1047 
1048             c->read->handler = c->ssl->saved_read_handler;
1049             c->ssl->saved_read_handler = NULL;
1050             c->read->ready = 1;
1051 
1052             if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1053                 return NGX_ERROR;
1054             }
1055 
1056             ngx_post_event(c->read, &ngx_posted_events);
1057         }
1058 
1059         return n;
1060     }
1061 
1062     sslerr = SSL_get_error(c->ssl->connection, n);
1063 
1064     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1065 
1066     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
1067 
1068     if (sslerr == SSL_ERROR_WANT_WRITE) {
1069         c->write->ready = 0;
1070         return NGX_AGAIN;
1071     }
1072 
1073     if (sslerr == SSL_ERROR_WANT_READ) {
1074 
1075         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1076                       "peer started SSL renegotiation");
1077 
1078         c->read->ready = 0;
1079 
1080         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1081             return NGX_ERROR;
1082         }
1083 
1084         /*
1085          * we do not set the timer because there is already
1086          * the write event timer
1087          */
1088 
1089         if (c->ssl->saved_read_handler == NULL) {
1090             c->ssl->saved_read_handler = c->read->handler;
1091             c->read->handler = ngx_ssl_read_handler;
1092         }
1093 
1094         return NGX_AGAIN;
1095     }
1096 
1097     c->ssl->no_wait_shutdown = 1;
1098     c->ssl->no_send_shutdown = 1;
1099     c->write->error = 1;
1100 
1101     ngx_ssl_connection_error(c, sslerr, err, "SSL_write() failed");
1102 
1103     return NGX_ERROR;
1104 }
1105 
1106 
1107 static void
1108 ngx_ssl_read_handler(ngx_event_t *rev)
1109 {
1110     ngx_connection_t  *c;
1111 
1112     c = rev->data;
1113 
1114     c->write->handler(c->write);
1115 }
1116 
1117 
1118 void
1119 ngx_ssl_free_buffer(ngx_connection_t *c)
1120 {
1121     if (c->ssl->buf && c->ssl->buf->start) {
1122         if (ngx_pfree(c->pool, c->ssl->buf->start) == NGX_OK) {
1123             c->ssl->buf->start = NULL;
1124         }
1125     }
1126 }
1127 
1128 
1129 ngx_int_t
1130 ngx_ssl_shutdown(ngx_connection_t *c)
1131 {
1132     int        n, sslerr, mode;
1133     ngx_err_t  err;
1134 
1135     if (c->timedout) {
1136         mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
1137 
1138     } else {
1139         mode = SSL_get_shutdown(c->ssl->connection);
1140 
1141         if (c->ssl->no_wait_shutdown) {
1142             mode |= SSL_RECEIVED_SHUTDOWN;
1143         }
1144 
1145         if (c->ssl->no_send_shutdown) {
1146             mode |= SSL_SENT_SHUTDOWN;
1147         }
1148     }
1149 
1150     SSL_set_shutdown(c->ssl->connection, mode);
1151 
1152     ngx_ssl_clear_error(c->log);
1153 
1154     n = SSL_shutdown(c->ssl->connection);
1155 
1156     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
1157 
1158     sslerr = 0;
1159 
1160     /* SSL_shutdown() never returns -1, on error it returns 0 */
1161 
1162     if (n != 1 && ERR_peek_error()) {
1163         sslerr = SSL_get_error(c->ssl->connection, n);
1164 
1165         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1166                        "SSL_get_error: %d", sslerr);
1167     }
1168 
1169     if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) {
1170         SSL_free(c->ssl->connection);
1171         c->ssl = NULL;
1172 
1173         return NGX_OK;
1174     }
1175 
1176     if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
1177         c->read->handler = ngx_ssl_shutdown_handler;
1178         c->write->handler = ngx_ssl_shutdown_handler;
1179 
1180         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1181             return NGX_ERROR;
1182         }
1183 
1184         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1185             return NGX_ERROR;
1186         }
1187 
1188         if (sslerr == SSL_ERROR_WANT_READ) {
1189             ngx_add_timer(c->read, 30000);
1190         }
1191 
1192         return NGX_AGAIN;
1193     }
1194 
1195     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1196 
1197     ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
1198 
1199     SSL_free(c->ssl->connection);
1200     c->ssl = NULL;
1201 
1202     return NGX_ERROR;
1203 }
1204 
1205 
1206 static void
1207 ngx_ssl_shutdown_handler(ngx_event_t *ev)
1208 {
1209     ngx_connection_t           *c;
1210     ngx_connection_handler_pt   handler;
1211 
1212     c = ev->data;
1213     handler = c->ssl->handler;
1214 
1215     if (ev->timedout) {
1216         c->timedout = 1;
1217     }
1218 
1219     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "SSL shutdown handler");
1220 
1221     if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
1222         return;
1223     }
1224 
1225     handler(c);
1226 }
1227 
1228 
1229 static void
1230 ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
1231     char *text)
1232 {
1233     int         n;
1234     ngx_uint_t  level;
1235 
1236     level = NGX_LOG_CRIT;
1237 
1238     if (sslerr == SSL_ERROR_SYSCALL) {
1239 
1240         if (err == NGX_ECONNRESET
1241             || err == NGX_EPIPE
1242             || err == NGX_ENOTCONN
1243             || err == NGX_ETIMEDOUT
1244             || err == NGX_ECONNREFUSED
1245             || err == NGX_ENETDOWN
1246             || err == NGX_ENETUNREACH
1247             || err == NGX_EHOSTDOWN
1248             || err == NGX_EHOSTUNREACH)
1249         {
1250             switch (c->log_error) {
1251 
1252             case NGX_ERROR_IGNORE_ECONNRESET:
1253             case NGX_ERROR_INFO:
1254                 level = NGX_LOG_INFO;
1255                 break;
1256 
1257             case NGX_ERROR_ERR:
1258                 level = NGX_LOG_ERR;
1259                 break;
1260 
1261             default:
1262                 break;
1263             }
1264         }
1265 
1266     } else if (sslerr == SSL_ERROR_SSL) {
1267 
1268         n = ERR_GET_REASON(ERR_peek_error());
1269 
1270             /* handshake failures */
1271         if (n == SSL_R_DIGEST_CHECK_FAILED                           /*  149 */
1272             || n == SSL_R_NO_CIPHERS_PASSED                          /*  182 */
1273             || n == SSL_R_NO_SHARED_CIPHER                           /*  193 */
1274             || n == SSL_R_UNEXPECTED_MESSAGE                         /*  244 */
1275             || n == SSL_R_UNEXPECTED_RECORD                          /*  245 */
1276             || n == SSL_R_WRONG_VERSION_NUMBER                       /*  267 */
1277             || n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC        /*  281 */
1278             || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
1279             || n == SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE             /* 1010 */
1280             || n == SSL_R_SSLV3_ALERT_BAD_RECORD_MAC                 /* 1020 */
1281             || n == SSL_R_TLSV1_ALERT_DECRYPTION_FAILED              /* 1021 */
1282             || n == SSL_R_TLSV1_ALERT_RECORD_OVERFLOW                /* 1022 */
1283             || n == SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE          /* 1030 */
1284             || n == SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE              /* 1040 */
1285             || n == SSL_R_SSLV3_ALERT_NO_CERTIFICATE                 /* 1041 */
1286             || n == SSL_R_SSLV3_ALERT_BAD_CERTIFICATE                /* 1042 */
1287             || n == SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE        /* 1043 */
1288             || n == SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED            /* 1044 */
1289             || n == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED            /* 1045 */
1290             || n == SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN            /* 1046 */
1291             || n == SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER              /* 1047 */
1292             || n == SSL_R_TLSV1_ALERT_UNKNOWN_CA                     /* 1048 */
1293             || n == SSL_R_TLSV1_ALERT_ACCESS_DENIED                  /* 1049 */
1294             || n == SSL_R_TLSV1_ALERT_DECODE_ERROR                   /* 1050 */
1295             || n == SSL_R_TLSV1_ALERT_DECRYPT_ERROR                  /* 1051 */
1296             || n == SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION             /* 1060 */
1297             || n == SSL_R_TLSV1_ALERT_PROTOCOL_VERSION               /* 1070 */
1298             || n == SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY          /* 1071 */
1299             || n == SSL_R_TLSV1_ALERT_INTERNAL_ERROR                 /* 1080 */
1300             || n == SSL_R_TLSV1_ALERT_USER_CANCELLED                 /* 1090 */
1301             || n == SSL_R_TLSV1_ALERT_NO_RENEGOTIATION)              /* 1100 */
1302         {
1303             switch (c->log_error) {
1304 
1305             case NGX_ERROR_IGNORE_ECONNRESET:
1306             case NGX_ERROR_INFO:
1307                 level = NGX_LOG_INFO;
1308                 break;
1309 
1310             case NGX_ERROR_ERR:
1311                 level = NGX_LOG_ERR;
1312                 break;
1313 
1314             default:
1315                 break;
1316             }
1317         }
1318     }
1319 
1320     ngx_ssl_error(level, c->log, err, text);
1321 }
1322 
1323 
1324 static void
1325 ngx_ssl_clear_error(ngx_log_t *log)
1326 {
1327     while (ERR_peek_error()) {
1328         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "ignoring stale global SSL error");
1329     }
1330 
1331     ERR_clear_error();
1332 }
1333 
1334 
1335 void ngx_cdecl
1336 ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
1337 {
1338     u_long    n;
1339     va_list   args;
1340     u_char   *p, *last;
1341     u_char    errstr[NGX_MAX_CONF_ERRSTR];
1342 
1343     last = errstr + NGX_MAX_CONF_ERRSTR;
1344 
1345     va_start(args, fmt);
1346     p = ngx_vslprintf(errstr, last - 1, fmt, args);
1347     va_end(args);
1348 
1349     p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p);
1350 
1351     for ( ;; ) {
1352 
1353         n = ERR_get_error();
1354 
1355         if (n == 0) {
1356             break;
1357         }
1358 
1359         if (p >= last) {
1360             continue;
1361         }
1362 
1363         *p++ = ' ';
1364 
1365         ERR_error_string_n(n, (char *) p, last - p);
1366 
1367         while (p < last && *p) {
1368             p++;
1369         }
1370     }
1371 
1372     ngx_log_error(level, log, err, "%s)", errstr);
1373 }
1374 
1375 
1376 ngx_int_t
1377 ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
1378     ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout)
1379 {
1380     long  cache_mode;
1381 
1382     if (builtin_session_cache == NGX_SSL_NO_SCACHE) {
1383         SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF);
1384         return NGX_OK;
1385     }
1386 
1387     if (builtin_session_cache == NGX_SSL_NONE_SCACHE) {
1388 
1389         /*
1390          * If the server explicitly says that it does not support
1391          * session reuse (see SSL_SESS_CACHE_OFF above), then
1392          * Outlook Express fails to upload a sent email to
1393          * the Sent Items folder on the IMAP server via a separate IMAP
1394          * connection in the background. Therefore we have a special
1395          * mode (SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL_STORE)
1396          * where the server pretends that it supports session reuse,
1397          * but it does not actually store any session.
1398          */
1399 
1400         SSL_CTX_set_session_cache_mode(ssl->ctx,
1401                                        SSL_SESS_CACHE_SERVER
1402                                        |SSL_SESS_CACHE_NO_AUTO_CLEAR
1403                                        |SSL_SESS_CACHE_NO_INTERNAL_STORE);
1404 
1405         SSL_CTX_sess_set_cache_size(ssl->ctx, 1);
1406 
1407         return NGX_OK;
1408     }
1409 
1410     cache_mode = SSL_SESS_CACHE_SERVER;
1411 
1412     if (shm_zone && builtin_session_cache == NGX_SSL_NO_BUILTIN_SCACHE) {
1413         cache_mode |= SSL_SESS_CACHE_NO_INTERNAL;
1414     }
1415 
1416     SSL_CTX_set_session_cache_mode(ssl->ctx, cache_mode);
1417 
1418     SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len);
1419 
1420     if (builtin_session_cache != NGX_SSL_NO_BUILTIN_SCACHE) {
1421 
1422         if (builtin_session_cache != NGX_SSL_DFLT_BUILTIN_SCACHE) {
1423             SSL_CTX_sess_set_cache_size(ssl->ctx, builtin_session_cache);
1424         }
1425     }
1426 
1427     SSL_CTX_set_timeout(ssl->ctx, (long) timeout);
1428 
1429     if (shm_zone) {
1430         shm_zone->init = ngx_ssl_session_cache_init;
1431 
1432         SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_session);
1433         SSL_CTX_sess_set_get_cb(ssl->ctx, ngx_ssl_get_cached_session);
1434         SSL_CTX_sess_set_remove_cb(ssl->ctx, ngx_ssl_remove_session);
1435 
1436         if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_cache_index, shm_zone)
1437             == 0)
1438         {
1439             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
1440                           "SSL_CTX_set_ex_data() failed");
1441             return NGX_ERROR;
1442         }
1443     }
1444 
1445     return NGX_OK;
1446 }
1447 
1448 
1449 static ngx_int_t
1450 ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data)
1451 {
1452     size_t                    len;
1453     ngx_slab_pool_t          *shpool;
1454     ngx_ssl_session_cache_t  *cache;
1455 
1456     if (data) {
1457         shm_zone->data = data;
1458         return NGX_OK;
1459     }
1460 
1461     if (shm_zone->shm.exists) {
1462         shm_zone->data = data;
1463         return NGX_OK;
1464     }
1465 
1466     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1467 
1468     cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_session_cache_t));
1469     if (cache == NULL) {
1470         return NGX_ERROR;
1471     }
1472 
1473     shpool->data = cache;
1474     shm_zone->data = cache;
1475 
1476     ngx_rbtree_init(&cache->session_rbtree, &cache->sentinel,
1477                     ngx_ssl_session_rbtree_insert_value);
1478 
1479     ngx_queue_init(&cache->expire_queue);
1480 
1481     len = sizeof(" in SSL session shared cache \"\"") + shm_zone->shm.name.len;
1482 
1483     shpool->log_ctx = ngx_slab_alloc(shpool, len);
1484     if (shpool->log_ctx == NULL) {
1485         return NGX_ERROR;
1486     }
1487 
1488     ngx_sprintf(shpool->log_ctx, " in SSL session shared cache \"%V\"%Z",
1489                 &shm_zone->shm.name);
1490 
1491     return NGX_OK;
1492 }
1493 
1494 
1495 /*
1496  * The length of the session id is 16 bytes for SSLv2 sessions and
1497  * between 1 and 32 bytes for SSLv3/TLSv1, typically 32 bytes.
1498  * It seems that the typical length of the external ASN1 representation
1499  * of a session is 118 or 119 bytes for SSLv3/TSLv1.
1500  *
1501  * Thus on 32-bit platforms we allocate separately an rbtree node,
1502  * a session id, and an ASN1 representation, they take accordingly
1503  * 64, 32, and 128 bytes.
1504  *
1505  * On 64-bit platforms we allocate separately an rbtree node + session_id,
1506  * and an ASN1 representation, they take accordingly 128 and 128 bytes.
1507  *
1508  * OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
1509  * so they are outside the code locked by shared pool mutex
1510  */
1511 
1512 static int
1513 ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
1514 {
1515     int                       len;
1516     u_char                   *p, *id, *cached_sess;
1517     uint32_t                  hash;
1518     SSL_CTX                  *ssl_ctx;
1519     ngx_shm_zone_t           *shm_zone;
1520     ngx_connection_t         *c;
1521     ngx_slab_pool_t          *shpool;
1522     ngx_ssl_sess_id_t        *sess_id;
1523     ngx_ssl_session_cache_t  *cache;
1524     u_char                    buf[NGX_SSL_MAX_SESSION_SIZE];
1525 
1526     len = i2d_SSL_SESSION(sess, NULL);
1527 
1528     /* do not cache too big session */
1529 
1530     if (len > (int) NGX_SSL_MAX_SESSION_SIZE) {
1531         return 0;
1532     }
1533 
1534     p = buf;
1535     i2d_SSL_SESSION(sess, &p);
1536 
1537     c = ngx_ssl_get_connection(ssl_conn);
1538 
1539     ssl_ctx = SSL_get_SSL_CTX(ssl_conn);
1540     shm_zone = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_cache_index);
1541 
1542     cache = shm_zone->data;
1543     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1544 
1545     ngx_shmtx_lock(&shpool->mutex);
1546 
1547     /* drop one or two expired sessions */
1548     ngx_ssl_expire_sessions(cache, shpool, 1);
1549 
1550     cached_sess = ngx_slab_alloc_locked(shpool, len);
1551 
1552     if (cached_sess == NULL) {
1553 
1554         /* drop the oldest non-expired session and try once more */
1555 
1556         ngx_ssl_expire_sessions(cache, shpool, 0);
1557 
1558         cached_sess = ngx_slab_alloc_locked(shpool, len);
1559 
1560         if (cached_sess == NULL) {
1561             sess_id = NULL;
1562             goto failed;
1563         }
1564     }
1565 
1566     sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
1567     if (sess_id == NULL) {
1568         goto failed;
1569     }
1570 
1571 #if (NGX_PTR_SIZE == 8)
1572 
1573     id = sess_id->sess_id;
1574 
1575 #else
1576 
1577     id = ngx_slab_alloc_locked(shpool, sess->session_id_length);
1578     if (id == NULL) {
1579         goto failed;
1580     }
1581 
1582 #endif
1583 
1584     ngx_memcpy(cached_sess, buf, len);
1585 
1586     ngx_memcpy(id, sess->session_id, sess->session_id_length);
1587 
1588     hash = ngx_crc32_short(sess->session_id, sess->session_id_length);
1589 
1590     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
1591                    "ssl new session: %08XD:%d:%d",
1592                    hash, sess->session_id_length, len);
1593 
1594     sess_id->node.key = hash;
1595     sess_id->node.data = (u_char) sess->session_id_length;
1596     sess_id->id = id;
1597     sess_id->len = len;
1598     sess_id->session = cached_sess;
1599 
1600     sess_id->expire = ngx_time() + SSL_CTX_get_timeout(ssl_ctx);
1601 
1602     ngx_queue_insert_head(&cache->expire_queue, &sess_id->queue);
1603 
1604     ngx_rbtree_insert(&cache->session_rbtree, &sess_id->node);
1605 
1606     ngx_shmtx_unlock(&shpool->mutex);
1607 
1608     return 0;
1609 
1610 failed:
1611 
1612     if (cached_sess) {
1613         ngx_slab_free_locked(shpool, cached_sess);
1614     }
1615 
1616     if (sess_id) {
1617         ngx_slab_free_locked(shpool, sess_id);
1618     }
1619 
1620     ngx_shmtx_unlock(&shpool->mutex);
1621 
1622     ngx_log_error(NGX_LOG_ALERT, c->log, 0,
1623                   "could not add new SSL session to the session cache");
1624 
1625     return 0;
1626 }
1627 
1628 
1629 static ngx_ssl_session_t *
1630 ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len,
1631     int *copy)
1632 {
1633 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
1634     const
1635 #endif
1636     u_char                   *p;
1637     uint32_t                  hash;
1638     ngx_int_t                 rc;
1639     ngx_shm_zone_t           *shm_zone;
1640     ngx_slab_pool_t          *shpool;
1641     ngx_connection_t         *c;
1642     ngx_rbtree_node_t        *node, *sentinel;
1643     ngx_ssl_session_t        *sess;
1644     ngx_ssl_sess_id_t        *sess_id;
1645     ngx_ssl_session_cache_t  *cache;
1646     u_char                    buf[NGX_SSL_MAX_SESSION_SIZE];
1647 
1648     c = ngx_ssl_get_connection(ssl_conn);
1649 
1650     hash = ngx_crc32_short(id, (size_t) len);
1651     *copy = 0;
1652 
1653     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1654                    "ssl get session: %08XD:%d", hash, len);
1655 
1656     shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn),
1657                                    ngx_ssl_session_cache_index);
1658 
1659     cache = shm_zone->data;
1660 
1661     sess = NULL;
1662 
1663     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1664 
1665     ngx_shmtx_lock(&shpool->mutex);
1666 
1667     node = cache->session_rbtree.root;
1668     sentinel = cache->session_rbtree.sentinel;
1669 
1670     while (node != sentinel) {
1671 
1672         if (hash < node->key) {
1673             node = node->left;
1674             continue;
1675         }
1676 
1677         if (hash > node->key) {
1678             node = node->right;
1679             continue;
1680         }
1681 
1682         /* hash == node->key */
1683 
1684         do {
1685             sess_id = (ngx_ssl_sess_id_t *) node;
1686 
1687             rc = ngx_memn2cmp(id, sess_id->id,
1688                               (size_t) len, (size_t) node->data);
1689             if (rc == 0) {
1690 
1691                 if (sess_id->expire > ngx_time()) {
1692                     ngx_memcpy(buf, sess_id->session, sess_id->len);
1693 
1694                     ngx_shmtx_unlock(&shpool->mutex);
1695 
1696                     p = buf;
1697                     sess = d2i_SSL_SESSION(NULL, &p, sess_id->len);
1698 
1699                     return sess;
1700                 }
1701 
1702                 ngx_queue_remove(&sess_id->queue);
1703 
1704                 ngx_rbtree_delete(&cache->session_rbtree, node);
1705 
1706                 ngx_slab_free_locked(shpool, sess_id->session);
1707 #if (NGX_PTR_SIZE == 4)
1708                 ngx_slab_free_locked(shpool, sess_id->id);
1709 #endif
1710                 ngx_slab_free_locked(shpool, sess_id);
1711 
1712                 sess = NULL;
1713 
1714                 goto done;
1715             }
1716 
1717             node = (rc < 0) ? node->left : node->right;
1718 
1719         } while (node != sentinel && hash == node->key);
1720 
1721         break;
1722     }
1723 
1724 done:
1725 
1726     ngx_shmtx_unlock(&shpool->mutex);
1727 
1728     return sess;
1729 }
1730 
1731 
1732 void
1733 ngx_ssl_remove_cached_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
1734 {
1735      SSL_CTX_remove_session(ssl, sess);
1736 
1737      ngx_ssl_remove_session(ssl, sess);
1738 }
1739 
1740 
1741 static void
1742 ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
1743 {
1744     size_t                    len;
1745     u_char                   *id;
1746     uint32_t                  hash;
1747     ngx_int_t                 rc;
1748     ngx_shm_zone_t           *shm_zone;
1749     ngx_slab_pool_t          *shpool;
1750     ngx_rbtree_node_t        *node, *sentinel;
1751     ngx_ssl_sess_id_t        *sess_id;
1752     ngx_ssl_session_cache_t  *cache;
1753 
1754     shm_zone = SSL_CTX_get_ex_data(ssl, ngx_ssl_session_cache_index);
1755 
1756     if (shm_zone == NULL) {
1757         return;
1758     }
1759 
1760     cache = shm_zone->data;
1761 
1762     id = sess->session_id;
1763     len = (size_t) sess->session_id_length;
1764 
1765     hash = ngx_crc32_short(id, len);
1766 
1767     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
1768                    "ssl remove session: %08XD:%uz", hash, len);
1769 
1770     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1771 
1772     ngx_shmtx_lock(&shpool->mutex);
1773 
1774     node = cache->session_rbtree.root;
1775     sentinel = cache->session_rbtree.sentinel;
1776 
1777     while (node != sentinel) {
1778 
1779         if (hash < node->key) {
1780             node = node->left;
1781             continue;
1782         }
1783 
1784         if (hash > node->key) {
1785             node = node->right;
1786             continue;
1787         }
1788 
1789         /* hash == node->key */
1790 
1791         do {
1792             sess_id = (ngx_ssl_sess_id_t *) node;
1793 
1794             rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data);
1795 
1796             if (rc == 0) {
1797 
1798                 ngx_queue_remove(&sess_id->queue);
1799 
1800                 ngx_rbtree_delete(&cache->session_rbtree, node);
1801 
1802                 ngx_slab_free_locked(shpool, sess_id->session);
1803 #if (NGX_PTR_SIZE == 4)
1804                 ngx_slab_free_locked(shpool, sess_id->id);
1805 #endif
1806                 ngx_slab_free_locked(shpool, sess_id);
1807 
1808                 goto done;
1809             }
1810 
1811             node = (rc < 0) ? node->left : node->right;
1812 
1813         } while (node != sentinel && hash == node->key);
1814 
1815         break;
1816     }
1817 
1818 done:
1819 
1820     ngx_shmtx_unlock(&shpool->mutex);
1821 }
1822 
1823 
1824 static void
1825 ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
1826     ngx_slab_pool_t *shpool, ngx_uint_t n)
1827 {
1828     time_t              now;
1829     ngx_queue_t        *q;
1830     ngx_ssl_sess_id_t  *sess_id;
1831 
1832     now = ngx_time();
1833 
1834     while (n < 3) {
1835 
1836         if (ngx_queue_empty(&cache->expire_queue)) {
1837             return;
1838         }
1839 
1840         q = ngx_queue_last(&cache->expire_queue);
1841 
1842         sess_id = ngx_queue_data(q, ngx_ssl_sess_id_t, queue);
1843 
1844         if (n++ != 0 && sess_id->expire > now) {
1845             return;
1846         }
1847 
1848         ngx_queue_remove(q);
1849 
1850         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
1851                        "expire session: %08Xi", sess_id->node.key);
1852 
1853         ngx_rbtree_delete(&cache->session_rbtree, &sess_id->node);
1854 
1855         ngx_slab_free_locked(shpool, sess_id->session);
1856 #if (NGX_PTR_SIZE == 4)
1857         ngx_slab_free_locked(shpool, sess_id->id);
1858 #endif
1859         ngx_slab_free_locked(shpool, sess_id);
1860     }
1861 }
1862 
1863 
1864 static void
1865 ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
1866     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
1867 {
1868     ngx_rbtree_node_t  **p;
1869     ngx_ssl_sess_id_t   *sess_id, *sess_id_temp;
1870 
1871     for ( ;; ) {
1872 
1873         if (node->key < temp->key) {
1874 
1875             p = &temp->left;
1876 
1877         } else if (node->key > temp->key) {
1878 
1879             p = &temp->right;
1880 
1881         } else { /* node->key == temp->key */
1882 
1883             sess_id = (ngx_ssl_sess_id_t *) node;
1884             sess_id_temp = (ngx_ssl_sess_id_t *) temp;
1885 
1886             p = (ngx_memn2cmp(sess_id->id, sess_id_temp->id,
1887                               (size_t) node->data, (size_t) temp->data)
1888                  < 0) ? &temp->left : &temp->right;
1889         }
1890 
1891         if (*p == sentinel) {
1892             break;
1893         }
1894 
1895         temp = *p;
1896     }
1897 
1898     *p = node;
1899     node->parent = temp;
1900     node->left = sentinel;
1901     node->right = sentinel;
1902     ngx_rbt_red(node);
1903 }
1904 
1905 
1906 void
1907 ngx_ssl_cleanup_ctx(void *data)
1908 {
1909     ngx_ssl_t  *ssl = data;
1910 
1911     SSL_CTX_free(ssl->ctx);
1912 }
1913 
1914 
1915 ngx_int_t
1916 ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
1917 {
1918     s->data = (u_char *) SSL_get_version(c->ssl->connection);
1919     return NGX_OK;
1920 }
1921 
1922 
1923 ngx_int_t
1924 ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
1925 {
1926     s->data = (u_char *) SSL_get_cipher_name(c->ssl->connection);
1927     return NGX_OK;
1928 }
1929 
1930 
1931 ngx_int_t
1932 ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
1933 {
1934     int           len;
1935     u_char       *p, *buf;
1936     SSL_SESSION  *sess;
1937 
1938     sess = SSL_get0_session(c->ssl->connection);
1939 
1940     len = i2d_SSL_SESSION(sess, NULL);
1941 
1942     buf = ngx_alloc(len, c->log);
1943     if (buf == NULL) {
1944         return NGX_ERROR;
1945     }
1946 
1947     s->len = 2 * len;
1948     s->data = ngx_pnalloc(pool, 2 * len);
1949     if (s->data == NULL) {
1950         ngx_free(buf);
1951         return NGX_ERROR;
1952     }
1953 
1954     p = buf;
1955     i2d_SSL_SESSION(sess, &p);
1956 
1957     ngx_hex_dump(s->data, buf, len);
1958 
1959     ngx_free(buf);
1960 
1961     return NGX_OK;
1962 }
1963 
1964 
1965 ngx_int_t
1966 ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
1967 {
1968     size_t   len;
1969     BIO     *bio;
1970     X509    *cert;
1971 
1972     s->len = 0;
1973 
1974     cert = SSL_get_peer_certificate(c->ssl->connection);
1975     if (cert == NULL) {
1976         return NGX_OK;
1977     }
1978 
1979     bio = BIO_new(BIO_s_mem());
1980     if (bio == NULL) {
1981         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
1982         X509_free(cert);
1983         return NGX_ERROR;
1984     }
1985 
1986     if (PEM_write_bio_X509(bio, cert) == 0) {
1987         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "PEM_write_bio_X509() failed");
1988         goto failed;
1989     }
1990 
1991     len = BIO_pending(bio);
1992     s->len = len;
1993 
1994     s->data = ngx_pnalloc(pool, len);
1995     if (s->data == NULL) {
1996         goto failed;
1997     }
1998 
1999     BIO_read(bio, s->data, len);
2000 
2001     BIO_free(bio);
2002     X509_free(cert);
2003 
2004     return NGX_OK;
2005 
2006 failed:
2007 
2008     BIO_free(bio);
2009     X509_free(cert);
2010 
2011     return NGX_ERROR;
2012 }
2013 
2014 
2015 ngx_int_t
2016 ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2017 {
2018     u_char      *p;
2019     size_t       len;
2020     ngx_uint_t   i;
2021     ngx_str_t    cert;
2022 
2023     if (ngx_ssl_get_raw_certificate(c, pool, &cert) != NGX_OK) {
2024         return NGX_ERROR;
2025     }
2026 
2027     if (cert.len == 0) {
2028         s->len = 0;
2029         return NGX_OK;
2030     }
2031 
2032     len = cert.len - 1;
2033 
2034     for (i = 0; i < cert.len - 1; i++) {
2035         if (cert.data[i] == LF) {
2036             len++;
2037         }
2038     }
2039 
2040     s->len = len;
2041     s->data = ngx_pnalloc(pool, len);
2042     if (s->data == NULL) {
2043         return NGX_ERROR;
2044     }
2045 
2046     p = s->data;
2047 
2048     for (i = 0; i < cert.len - 1; i++) {
2049         *p++ = cert.data[i];
2050         if (cert.data[i] == LF) {
2051             *p++ = '\t';
2052         }
2053     }
2054 
2055     return NGX_OK;
2056 }
2057 
2058 
2059 ngx_int_t
2060 ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2061 {
2062     char       *p;
2063     size_t      len;
2064     X509       *cert;
2065     X509_NAME  *name;
2066 
2067     s->len = 0;
2068 
2069     cert = SSL_get_peer_certificate(c->ssl->connection);
2070     if (cert == NULL) {
2071         return NGX_OK;
2072     }
2073 
2074     name = X509_get_subject_name(cert);
2075     if (name == NULL) {
2076         X509_free(cert);
2077         return NGX_ERROR;
2078     }
2079 
2080     p = X509_NAME_oneline(name, NULL, 0);
2081 
2082     for (len = 0; p[len]; len++) { /* void */ }
2083 
2084     s->len = len;
2085     s->data = ngx_pnalloc(pool, len);
2086     if (s->data == NULL) {
2087         OPENSSL_free(p);
2088         X509_free(cert);
2089         return NGX_ERROR;
2090     }
2091 
2092     ngx_memcpy(s->data, p, len);
2093 
2094     OPENSSL_free(p);
2095     X509_free(cert);
2096 
2097     return NGX_OK;
2098 }
2099 
2100 
2101 ngx_int_t
2102 ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2103 {
2104     char       *p;
2105     size_t      len;
2106     X509       *cert;
2107     X509_NAME  *name;
2108 
2109     s->len = 0;
2110 
2111     cert = SSL_get_peer_certificate(c->ssl->connection);
2112     if (cert == NULL) {
2113         return NGX_OK;
2114     }
2115 
2116     name = X509_get_issuer_name(cert);
2117     if (name == NULL) {
2118         X509_free(cert);
2119         return NGX_ERROR;
2120     }
2121 
2122     p = X509_NAME_oneline(name, NULL, 0);
2123 
2124     for (len = 0; p[len]; len++) { /* void */ }
2125 
2126     s->len = len;
2127     s->data = ngx_pnalloc(pool, len);
2128     if (s->data == NULL) {
2129         OPENSSL_free(p);
2130         X509_free(cert);
2131         return NGX_ERROR;
2132     }
2133 
2134     ngx_memcpy(s->data, p, len);
2135 
2136     OPENSSL_free(p);
2137     X509_free(cert);
2138 
2139     return NGX_OK;
2140 }
2141 
2142 
2143 ngx_int_t
2144 ngx_ssl_get_serial_number(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2145 {
2146     size_t   len;
2147     X509    *cert;
2148     BIO     *bio;
2149 
2150     s->len = 0;
2151 
2152     cert = SSL_get_peer_certificate(c->ssl->connection);
2153     if (cert == NULL) {
2154         return NGX_OK;
2155     }
2156 
2157     bio = BIO_new(BIO_s_mem());
2158     if (bio == NULL) {
2159         X509_free(cert);
2160         return NGX_ERROR;
2161     }
2162 
2163     i2a_ASN1_INTEGER(bio, X509_get_serialNumber(cert));
2164     len = BIO_pending(bio);
2165 
2166     s->len = len;
2167     s->data = ngx_pnalloc(pool, len);
2168     if (s->data == NULL) {
2169         BIO_free(bio);
2170         X509_free(cert);
2171         return NGX_ERROR;
2172     }
2173 
2174     BIO_read(bio, s->data, len);
2175     BIO_free(bio);
2176     X509_free(cert);
2177 
2178     return NGX_OK;
2179 }
2180 
2181 
2182 ngx_int_t
2183 ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2184 {
2185     X509  *cert;
2186 
2187     if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) {
2188         s->len = sizeof("FAILED") - 1;
2189         s->data = (u_char *) "FAILED";
2190 
2191         return NGX_OK;
2192     }
2193 
2194     cert = SSL_get_peer_certificate(c->ssl->connection);
2195 
2196     if (cert) {
2197         s->len = sizeof("SUCCESS") - 1;
2198         s->data = (u_char *) "SUCCESS";
2199 
2200     } else {
2201         s->len = sizeof("NONE") - 1;
2202         s->data = (u_char *) "NONE";
2203     }
2204 
2205     X509_free(cert);
2206 
2207     return NGX_OK;
2208 }
2209 
2210 
2211 static void *
2212 ngx_openssl_create_conf(ngx_cycle_t *cycle)
2213 {
2214     ngx_openssl_conf_t  *oscf;
2215 
2216     oscf = ngx_pcalloc(cycle->pool, sizeof(ngx_openssl_conf_t));
2217     if (oscf == NULL) {
2218         return NULL;
2219     }
2220 
2221     /*
2222      * set by ngx_pcalloc():
2223      *
2224      *     oscf->engine = 0;
2225      */
2226 
2227     return oscf;
2228 }
2229 
2230 
2231 static char *
2232 ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2233 {
2234     ngx_openssl_conf_t *oscf = conf;
2235 
2236     ENGINE     *engine;
2237     ngx_str_t  *value;
2238 
2239     if (oscf->engine) {
2240         return "is duplicate";
2241     }
2242 
2243     oscf->engine = 1;
2244 
2245     value = cf->args->elts;
2246 
2247     engine = ENGINE_by_id((const char *) value[1].data);
2248 
2249     if (engine == NULL) {
2250         ngx_ssl_error(NGX_LOG_WARN, cf->log, 0,
2251                       "ENGINE_by_id(\"%V\") failed", &value[1]);
2252         return NGX_CONF_ERROR;
2253     }
2254 
2255     if (ENGINE_set_default(engine, ENGINE_METHOD_ALL) == 0) {
2256         ngx_ssl_error(NGX_LOG_WARN, cf->log, 0,
2257                       "ENGINE_set_default(\"%V\", ENGINE_METHOD_ALL) failed",
2258                       &value[1]);
2259 
2260         ENGINE_free(engine);
2261 
2262         return NGX_CONF_ERROR;
2263     }
2264 
2265     ENGINE_free(engine);
2266 
2267     return NGX_CONF_OK;
2268 }
2269 
2270 
2271 static void
2272 ngx_openssl_exit(ngx_cycle_t *cycle)
2273 {
2274     ENGINE_cleanup();
2275 }
2276 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.