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

Linux Cross Reference
Nginx/event/ngx_event_openssl.c

Version: ~ [ nginx-0.6.26 ] ~ [ nginx-0.5.35 ] ~ [ nginx-0.5.20 ] ~ [ nginx-0.5.19 ] ~

  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_str_t  engine;
 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_init_conf(ngx_cycle_t *cycle, void *conf);
 41 static void ngx_openssl_exit(ngx_cycle_t *cycle);
 42 
 43 #if !(NGX_SSL_ENGINE)
 44 static char *ngx_openssl_noengine(ngx_conf_t *cf, ngx_command_t *cmd,
 45      void *conf);
 46 #endif
 47 
 48 
 49 static ngx_command_t  ngx_openssl_commands[] = {
 50 
 51     { ngx_string("ssl_engine"),
 52       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
 53 #if (NGX_SSL_ENGINE)
 54       ngx_conf_set_str_slot,
 55 #else
 56       ngx_openssl_noengine,
 57 #endif
 58       0,
 59       offsetof(ngx_openssl_conf_t, engine),
 60       NULL },
 61 
 62       ngx_null_command
 63 };
 64 
 65 
 66 static ngx_core_module_t  ngx_openssl_module_ctx = {
 67     ngx_string("openssl"),
 68     ngx_openssl_create_conf,
 69     ngx_openssl_init_conf
 70 };
 71 
 72 
 73 ngx_module_t  ngx_openssl_module = {
 74     NGX_MODULE_V1,
 75     &ngx_openssl_module_ctx,               /* module context */
 76     ngx_openssl_commands,                  /* module directives */
 77     NGX_CORE_MODULE,                       /* module type */
 78     NULL,                                  /* init master */
 79     NULL,                                  /* init module */
 80     NULL,                                  /* init process */
 81     NULL,                                  /* init thread */
 82     NULL,                                  /* exit thread */
 83     NULL,                                  /* exit process */
 84     ngx_openssl_exit,                      /* exit master */
 85     NGX_MODULE_V1_PADDING
 86 };
 87 
 88 
 89 static long  ngx_ssl_protocols[] = {
 90     SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1,
 91     SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1,
 92     SSL_OP_NO_SSLv2|SSL_OP_NO_TLSv1,
 93     SSL_OP_NO_TLSv1,
 94     SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3,
 95     SSL_OP_NO_SSLv3,
 96     SSL_OP_NO_SSLv2,
 97     0,
 98 };
 99 
100 
101 int  ngx_ssl_connection_index;
102 int  ngx_ssl_server_conf_index;
103 int  ngx_ssl_session_cache_index;
104 
105 
106 ngx_int_t
107 ngx_ssl_init(ngx_log_t *log)
108 {
109 #if OPENSSL_VERSION_NUMBER >= 0x00907000
110     OPENSSL_config(NULL);
111 #endif
112 
113     SSL_library_init();
114     SSL_load_error_strings();
115 
116 #if (NGX_SSL_ENGINE)
117     ENGINE_load_builtin_engines();
118 #endif
119 
120     ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
121 
122     if (ngx_ssl_connection_index == -1) {
123         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed");
124         return NGX_ERROR;
125     }
126 
127     ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
128                                                          NULL);
129     if (ngx_ssl_server_conf_index == -1) {
130         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
131                       "SSL_CTX_get_ex_new_index() failed");
132         return NGX_ERROR;
133     }
134 
135     ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
136                                                            NULL);
137     if (ngx_ssl_session_cache_index == -1) {
138         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
139                       "SSL_CTX_get_ex_new_index() failed");
140         return NGX_ERROR;
141     }
142 
143     return NGX_OK;
144 }
145 
146 
147 ngx_int_t
148 ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
149 {
150     ssl->ctx = SSL_CTX_new(SSLv23_method());
151 
152     if (ssl->ctx == NULL) {
153         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_new() failed");
154         return NGX_ERROR;
155     }
156 
157     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) {
158         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
159                       "SSL_CTX_set_ex_data() failed");
160         return NGX_ERROR;
161     }
162 
163     /* client side options */
164 
165     SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
166     SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
167     SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG);
168 
169     /* server side options */
170 
171     SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
172     SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
173 
174     /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
175     SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
176 
177     SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
178     SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG);
179     SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_BLOCK_PADDING_BUG);
180 
181 #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
182     SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
183 #endif
184 
185 
186     if (ngx_ssl_protocols[protocols >> 1] != 0) {
187         SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]);
188     }
189 
190     /*
191      * we need this option because in ngx_ssl_send_chain()
192      * we may switch to a buffered write and may copy leftover part of
193      * previously unbuffered data to our internal buffer
194      */
195     SSL_CTX_set_mode(ssl->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
196 
197     SSL_CTX_set_read_ahead(ssl->ctx, 1);
198 
199     return NGX_OK;
200 }
201 
202 
203 ngx_int_t
204 ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
205     ngx_str_t *key)
206 {
207     if (ngx_conf_full_name(cf->cycle, cert, 1) == NGX_ERROR) {
208         return NGX_ERROR;
209     }
210 
211     if (SSL_CTX_use_certificate_chain_file(ssl->ctx, (char *) cert->data)
212         == 0)
213     {
214         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
215                       "SSL_CTX_use_certificate_chain_file(\"%s\") failed",
216                       cert->data);
217         return NGX_ERROR;
218     }
219 
220     if (ngx_conf_full_name(cf->cycle, key, 1) == NGX_ERROR) {
221         return NGX_ERROR;
222     }
223 
224     if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data,
225                                     SSL_FILETYPE_PEM)
226         == 0)
227     {
228         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
229                       "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key->data);
230         return NGX_ERROR;
231     }
232 
233     return NGX_OK;
234 }
235 
236 
237 ngx_int_t
238 ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
239     ngx_int_t depth)
240 {
241     STACK_OF(X509_NAME)  *list;
242 
243     SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_http_ssl_verify_callback);
244 
245     SSL_CTX_set_verify_depth(ssl->ctx, depth);
246 
247     if (cert->len == 0) {
248         return NGX_OK;
249     }
250 
251     if (ngx_conf_full_name(cf->cycle, cert, 1) == NGX_ERROR) {
252         return NGX_ERROR;
253     }
254 
255     if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
256         == 0)
257     {
258         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
259                       "SSL_CTX_load_verify_locations(\"%s\") failed",
260                       cert->data);
261         return NGX_ERROR;
262     }
263 
264     list = SSL_load_client_CA_file((char *) cert->data);
265 
266     if (list == NULL) {
267         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
268                       "SSL_load_client_CA_file(\"%s\") failed", cert->data);
269         return NGX_ERROR;
270     }
271 
272     /*
273      * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
274      * always leaved an error in the error queue
275      */
276 
277     ERR_clear_error();
278 
279     SSL_CTX_set_client_CA_list(ssl->ctx, list);
280 
281     return NGX_OK;
282 }
283 
284 
285 static int
286 ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
287 {
288     char              *subject, *issuer;
289     int                err, depth;
290     X509              *cert;
291     X509_NAME         *name;
292     ngx_connection_t  *c;
293     ngx_ssl_conn_t    *ssl_conn;
294 
295     ssl_conn = X509_STORE_CTX_get_ex_data(x509_store,
296                                           SSL_get_ex_data_X509_STORE_CTX_idx());
297 
298     c = ngx_ssl_get_connection(ssl_conn);
299 
300     cert = X509_STORE_CTX_get_current_cert(x509_store);
301     err = X509_STORE_CTX_get_error(x509_store);
302     depth = X509_STORE_CTX_get_error_depth(x509_store);
303 
304     name = X509_get_subject_name(cert);
305     subject = name ? X509_NAME_oneline(name, NULL, 0) : "(none)";
306 
307     name = X509_get_issuer_name(cert);
308     issuer = name ? X509_NAME_oneline(name, NULL, 0) : "(none)";
309 
310     ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
311                    "verify:%d, error:%d, depth:%d, "
312                    "subject:\"%s\",issuer: \"%s\"",
313                    ok, err, depth, subject, issuer);
314 
315     return 1;
316 }
317 
318 
319 ngx_int_t
320 ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl)
321 {
322     RSA  *key;
323 
324     if (SSL_CTX_need_tmp_RSA(ssl->ctx) == 0) {
325         return NGX_OK;
326     }
327 
328     key = RSA_generate_key(512, RSA_F4, NULL, NULL);
329 
330     if (key) {
331         SSL_CTX_set_tmp_rsa(ssl->ctx, key);
332 
333         RSA_free(key);
334 
335         return NGX_OK;
336     }
337 
338     ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "RSA_generate_key(512) failed");
339 
340     return NGX_ERROR;
341 }
342 
343 
344 ngx_int_t
345 ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
346 {
347     ngx_ssl_connection_t  *sc;
348 
349     sc = ngx_pcalloc(c->pool, sizeof(ngx_ssl_connection_t));
350     if (sc == NULL) {
351         return NGX_ERROR;
352     }
353 
354     sc->buffer = ((flags & NGX_SSL_BUFFER) != 0);
355 
356     sc->connection = SSL_new(ssl->ctx);
357 
358     if (sc->connection == NULL) {
359         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed");
360         return NGX_ERROR;
361     }
362 
363     if (SSL_set_fd(sc->connection, c->fd) == 0) {
364         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_fd() failed");
365         return NGX_ERROR;
366     }
367 
368     if (flags & NGX_SSL_CLIENT) {
369         SSL_set_connect_state(sc->connection);
370 
371     } else {
372         SSL_set_accept_state(sc->connection);
373     }
374 
375     if (SSL_set_ex_data(sc->connection, ngx_ssl_connection_index, c) == 0) {
376         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed");
377         return NGX_ERROR;
378     }
379 
380     c->ssl = sc;
381 
382     return NGX_OK;
383 }
384 
385 
386 ngx_int_t
387 ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session)
388 {
389     if (session) {
390         if (SSL_set_session(c->ssl->connection, session) == 0) {
391             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_session() failed");
392             return NGX_ERROR;
393         }
394     }
395 
396     return NGX_OK;
397 }
398 
399 
400 ngx_int_t
401 ngx_ssl_handshake(ngx_connection_t *c)
402 {
403     int        n, sslerr;
404     ngx_err_t  err;
405 
406     ngx_ssl_clear_error(c->log);
407 
408     n = SSL_do_handshake(c->ssl->connection);
409 
410     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
411 
412     if (n == 1) {
413 
414         if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
415             return NGX_ERROR;
416         }
417 
418         if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
419             return NGX_ERROR;
420         }
421 
422 #if (NGX_DEBUG)
423         {
424         char         buf[129], *s, *d;
425         SSL_CIPHER  *cipher;
426 
427         cipher = SSL_get_current_cipher(c->ssl->connection);
428 
429         if (cipher) {
430             SSL_CIPHER_description(cipher, &buf[1], 128);
431 
432             for (s = &buf[1], d = buf; *s; s++) {
433                 if (*s == ' ' && *d == ' ') {
434                     continue;
435                 }
436 
437                 if (*s == LF || *s == CR) {
438                     continue;
439                 }
440 
441                 *++d = *s;
442             }
443 
444             if (*d != ' ') {
445                 d++;
446             }
447 
448             *d = '\0';
449 
450             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
451                            "SSL: %s, cipher: \"%s\"",
452                            SSL_get_version(c->ssl->connection), &buf[1]);
453 
454             if (SSL_session_reused(c->ssl->connection)) {
455                 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
456                                "SSL reused session");
457             }
458 
459         } else {
460             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
461                            "SSL no shared ciphers");
462         }
463         }
464 #endif
465 
466         c->ssl->handshaked = 1;
467 
468         c->recv = ngx_ssl_recv;
469         c->send = ngx_ssl_write;
470         c->recv_chain = ngx_ssl_recv_chain;
471         c->send_chain = ngx_ssl_send_chain;
472 
473         return NGX_OK;
474     }
475 
476     sslerr = SSL_get_error(c->ssl->connection, n);
477 
478     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
479 
480     if (sslerr == SSL_ERROR_WANT_READ) {
481         c->read->ready = 0;
482         c->read->handler = ngx_ssl_handshake_handler;
483         c->write->handler = ngx_ssl_handshake_handler;
484 
485         if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
486             return NGX_ERROR;
487         }
488 
489         return NGX_AGAIN;
490     }
491 
492     if (sslerr == SSL_ERROR_WANT_WRITE) {
493         c->write->ready = 0;
494         c->read->handler = ngx_ssl_handshake_handler;
495         c->write->handler = ngx_ssl_handshake_handler;
496 
497         if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
498             return NGX_ERROR;
499         }
500 
501         return NGX_AGAIN;
502     }
503 
504     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
505 
506     c->ssl->no_wait_shutdown = 1;
507     c->ssl->no_send_shutdown = 1;
508     c->read->eof = 1;
509 
510     if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
511         ngx_log_error(NGX_LOG_INFO, c->log, err,
512                       "peer closed connection in SSL handshake");
513 
514         return NGX_ERROR;
515     }
516 
517     c->read->error = 1;
518 
519     ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed");
520 
521     return NGX_ERROR;
522 }
523 
524 
525 static void
526 ngx_ssl_handshake_handler(ngx_event_t *ev)
527 {
528     ngx_connection_t  *c;
529 
530     c = ev->data;
531 
532     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
533                    "SSL handshake handler: %d", ev->write);
534 
535     if (ev->timedout) {
536         c->ssl->handler(c);
537         return;
538     }
539 
540     if (ngx_ssl_handshake(c) == NGX_AGAIN) {
541         return;
542     }
543 
544     c->ssl->handler(c);
545 }
546 
547 
548 ssize_t
549 ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl)
550 {
551     u_char     *last;
552     ssize_t     n, bytes;
553     ngx_buf_t  *b;
554 
555     bytes = 0;
556 
557     b = cl->buf;
558     last = b->last;
559 
560     for ( ;; ) {
561 
562         n = ngx_ssl_recv(c, last, b->end - last);
563 
564         if (n > 0) {
565             last += n;
566             bytes += n;
567 
568             if (last == b->end) {
569                 cl = cl->next;
570 
571                 if (cl == NULL) {
572                     return bytes;
573                 }
574 
575                 b = cl->buf;
576                 last = b->last;
577             }
578 
579             continue;
580         }
581 
582         if (bytes) {
583             return bytes;
584         }
585 
586         return n;
587     }
588 }
589 
590 
591 ssize_t
592 ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
593 {
594     int  n, bytes;
595 
596     if (c->ssl->last == NGX_ERROR) {
597         c->read->error = 1;
598         return NGX_ERROR;
599     }
600 
601     if (c->ssl->last == NGX_DONE) {
602         c->read->ready = 0;
603         c->read->eof = 1;
604         return 0;
605     }
606 
607     bytes = 0;
608 
609     ngx_ssl_clear_error(c->log);
610 
611     /*
612      * SSL_read() may return data in parts, so try to read
613      * until SSL_read() would return no data
614      */
615 
616     for ( ;; ) {
617 
618         n = SSL_read(c->ssl->connection, buf, size);
619 
620         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n);
621 
622         if (n > 0) {
623             bytes += n;
624         }
625 
626         c->ssl->last = ngx_ssl_handle_recv(c, n);
627 
628         if (c->ssl->last == NGX_OK) {
629 
630             size -= n;
631 
632             if (size == 0) {
633                 return bytes;
634             }
635 
636             buf += n;
637 
638             continue;
639         }
640 
641         if (bytes) {
642             return bytes;
643         }
644 
645         switch (c->ssl->last) {
646 
647         case NGX_DONE:
648             c->read->ready = 0;
649             c->read->eof = 1;
650             return 0;
651 
652         case NGX_ERROR:
653             c->read->error = 1;
654 
655             /* fall thruogh */
656 
657         case NGX_AGAIN:
658             return c->ssl->last;
659         }
660     }
661 }
662 
663 
664 static ngx_int_t
665 ngx_ssl_handle_recv(ngx_connection_t *c, int n)
666 {
667     int        sslerr;
668     ngx_err_t  err;
669 
670     if (n > 0) {
671 
672         if (c->ssl->saved_write_handler) {
673 
674             c->write->handler = c->ssl->saved_write_handler;
675             c->ssl->saved_write_handler = NULL;
676             c->write->ready = 1;
677 
678             if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
679                 return NGX_ERROR;
680             }
681 
682             ngx_post_event(c->write, &ngx_posted_events);
683         }
684 
685         return NGX_OK;
686     }
687 
688     sslerr = SSL_get_error(c->ssl->connection, n);
689 
690     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
691 
692     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
693 
694     if (sslerr == SSL_ERROR_WANT_READ) {
695         c->read->ready = 0;
696         return NGX_AGAIN;
697     }
698 
699     if (sslerr == SSL_ERROR_WANT_WRITE) {
700 
701         ngx_log_error(NGX_LOG_INFO, c->log, 0,
702                       "peer started SSL renegotiation");
703 
704         c->write->ready = 0;
705 
706         if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
707             return NGX_ERROR;
708         }
709 
710         /*
711          * we do not set the timer because there is already the read event timer
712          */
713 
714         if (c->ssl->saved_write_handler == NULL) {
715             c->ssl->saved_write_handler = c->write->handler;
716             c->write->handler = ngx_ssl_write_handler;
717         }
718 
719         return NGX_AGAIN;
720     }
721 
722     c->ssl->no_wait_shutdown = 1;
723     c->ssl->no_send_shutdown = 1;
724 
725     if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
726         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
727                        "peer shutdown SSL cleanly");
728         return NGX_DONE;
729     }
730 
731     ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed");
732 
733     return NGX_ERROR;
734 }
735 
736 
737 static void
738 ngx_ssl_write_handler(ngx_event_t *wev)
739 {
740     ngx_connection_t  *c;
741 
742     c = wev->data;
743 
744     c->read->handler(c->read);
745 }
746 
747 
748 /*
749  * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer
750  * before the SSL_write() call to decrease a SSL overhead.
751  *
752  * Besides for protocols such as HTTP it is possible to always buffer
753  * the output to decrease a SSL overhead some more.
754  */
755 
756 ngx_chain_t *
757 ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
758 {
759     int          n;
760     ngx_uint_t   flush;
761     ssize_t      send, size;
762     ngx_buf_t   *buf;
763 
764     if (!c->ssl->buffer
765         || (in && in->next == NULL && !(c->buffered & NGX_SSL_BUFFERED)))
766     {
767         /*
768          * we avoid a buffer copy if
769          *     we do not need to buffer the output
770          *     or the incoming buf is a single and our buffer is empty
771          */
772 
773         while (in) {
774             if (ngx_buf_special(in->buf)) {
775                 in = in->next;
776                 continue;
777             }
778 
779             n = ngx_ssl_write(c, in->buf->pos, in->buf->last - in->buf->pos);
780 
781             if (n == NGX_ERROR) {
782                 return NGX_CHAIN_ERROR;
783             }
784 
785             if (n == NGX_AGAIN) {
786                 c->buffered |= NGX_SSL_BUFFERED;
787                 return in;
788             }
789 
790             in->buf->pos += n;
791 
792             if (in->buf->pos == in->buf->last) {
793                 in = in->next;
794             }
795         }
796 
797         return in;
798     }
799 
800 
801     /* the maximum limit size is the maximum uint32_t value - the page size */
802 
803     if (limit == 0 || limit > (off_t) (NGX_MAX_UINT32_VALUE - ngx_pagesize)) {
804         limit = NGX_MAX_UINT32_VALUE - ngx_pagesize;
805     }
806 
807     buf = c->ssl->buf;
808 
809     if (buf == NULL) {
810         buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE);
811         if (buf == NULL) {
812             return NGX_CHAIN_ERROR;
813         }
814 
815         c->ssl->buf = buf;
816     }
817 
818     if (buf->start == NULL) {
819         buf->start = ngx_palloc(c->pool, NGX_SSL_BUFSIZE);
820         if (buf->start == NULL) {
821             return NGX_CHAIN_ERROR;
822         }
823 
824         buf->pos = buf->start;
825         buf->last = buf->start;
826         buf->end = buf->start + NGX_SSL_BUFSIZE;
827     }
828 
829     send = 0;
830     flush = (in == NULL) ? 1 : 0;
831 
832     for ( ;; ) {
833 
834         while (in && buf->last < buf->end) {
835             if (in->buf->last_buf || in->buf->flush) {
836                 flush = 1;
837             }
838 
839             if (ngx_buf_special(in->buf)) {
840                 in = in->next;
841                 continue;
842             }
843 
844             size = in->buf->last - in->buf->pos;
845 
846             if (size > buf->end - buf->last) {
847                 size = buf->end - buf->last;
848             }
849 
850             if (send + size > limit) {
851                 size = (ssize_t) (limit - send);
852                 flush = 1;
853             }
854 
855             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
856                            "SSL buf copy: %d", size);
857 
858             ngx_memcpy(buf->last, in->buf->pos, size);
859 
860             buf->last += size;
861 
862             in->buf->pos += size;
863 
864             if (in->buf->pos == in->buf->last) {
865                 in = in->next;
866             }
867         }
868 
869         size = buf->last - buf->pos;
870 
871         if (!flush && buf->last < buf->end && c->ssl->buffer) {
872             break;
873         }
874 
875         n = ngx_ssl_write(c, buf->pos, size);
876 
877         if (n == NGX_ERROR) {
878             return NGX_CHAIN_ERROR;
879         }
880 
881         if (n == NGX_AGAIN) {
882             c->buffered |= NGX_SSL_BUFFERED;
883             return in;
884         }
885 
886         buf->pos += n;
887         send += n;
888         c->sent += n;
889 
890         if (n < size) {
891             break;
892         }
893 
894         if (buf->pos == buf->last) {
895             buf->pos = buf->start;
896             buf->last = buf->start;
897         }
898 
899         if (in == NULL || send == limit) {
900             break;
901         }
902     }
903 
904     if (buf->pos < buf->last) {
905         c->buffered |= NGX_SSL_BUFFERED;
906 
907     } else {
908         c->buffered &= ~NGX_SSL_BUFFERED;
909     }
910 
911     return in;
912 }
913 
914 
915 ssize_t
916 ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
917 {
918     int        n, sslerr;
919     ngx_err_t  err;
920 
921     ngx_ssl_clear_error(c->log);
922 
923     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size);
924 
925     n = SSL_write(c->ssl->connection, data, size);
926 
927     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n);
928 
929     if (n > 0) {
930 
931         if (c->ssl->saved_read_handler) {
932 
933             c->read->handler = c->ssl->saved_read_handler;
934             c->ssl->saved_read_handler = NULL;
935             c->read->ready = 1;
936 
937             if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
938                 return NGX_ERROR;
939             }
940 
941             ngx_post_event(c->read, &ngx_posted_events);
942         }
943 
944         return n;
945     }
946 
947     sslerr = SSL_get_error(c->ssl->connection, n);
948 
949     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
950 
951     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
952 
953     if (sslerr == SSL_ERROR_WANT_WRITE) {
954         c->write->ready = 0;
955         return NGX_AGAIN;
956     }
957 
958     if (sslerr == SSL_ERROR_WANT_READ) {
959 
960         ngx_log_error(NGX_LOG_INFO, c->log, 0,
961                       "peer started SSL renegotiation");
962 
963         c->read->ready = 0;
964 
965         if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
966             return NGX_ERROR;
967         }
968 
969         /*
970          * we do not set the timer because there is already
971          * the write event timer
972          */
973 
974         if (c->ssl->saved_read_handler == NULL) {
975             c->ssl->saved_read_handler = c->read->handler;
976             c->read->handler = ngx_ssl_read_handler;
977         }
978 
979         return NGX_AGAIN;
980     }
981 
982     c->ssl->no_wait_shutdown = 1;
983     c->ssl->no_send_shutdown = 1;
984     c->write->error = 1;
985 
986     ngx_ssl_connection_error(c, sslerr, err, "SSL_write() failed");
987 
988     return NGX_ERROR;
989 }
990 
991 
992 static void
993 ngx_ssl_read_handler(ngx_event_t *rev)
994 {
995     ngx_connection_t  *c;
996 
997     c = rev->data;
998 
999     c->write->handler(c->write);
1000 }
1001 
1002 
1003 void
1004 ngx_ssl_free_buffer(ngx_connection_t *c)
1005 {
1006     if (c->ssl->buf && c->ssl->buf->start) {
1007         if (ngx_pfree(c->pool, c->ssl->buf->start) == NGX_OK) {
1008             c->ssl->buf->start = NULL;
1009         }
1010     }
1011 }
1012 
1013 
1014 ngx_int_t
1015 ngx_ssl_shutdown(ngx_connection_t *c)
1016 {
1017     int        n, sslerr, mode;
1018     ngx_err_t  err;
1019 
1020     if (c->timedout) {
1021         mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
1022 
1023     } else {
1024         mode = SSL_get_shutdown(c->ssl->connection);
1025 
1026         if (c->ssl->no_wait_shutdown) {
1027             mode |= SSL_RECEIVED_SHUTDOWN;
1028         }
1029 
1030         if (c->ssl->no_send_shutdown) {
1031             mode |= SSL_SENT_SHUTDOWN;
1032         }
1033     }
1034 
1035     SSL_set_shutdown(c->ssl->connection, mode);
1036 
1037     ngx_ssl_clear_error(c->log);
1038 
1039     n = SSL_shutdown(c->ssl->connection);
1040 
1041     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
1042 
1043     sslerr = 0;
1044 
1045     /* SSL_shutdown() never returns -1, on error it returns 0 */
1046 
1047     if (n != 1 && ERR_peek_error()) {
1048         sslerr = SSL_get_error(c->ssl->connection, n);
1049 
1050         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1051                        "SSL_get_error: %d", sslerr);
1052     }
1053 
1054     if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) {
1055         SSL_free(c->ssl->connection);
1056         c->ssl = NULL;
1057 
1058         return NGX_OK;
1059     }
1060 
1061     if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
1062         c->read->handler = ngx_ssl_shutdown_handler;
1063         c->write->handler = ngx_ssl_shutdown_handler;
1064 
1065         if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
1066             return NGX_ERROR;
1067         }
1068 
1069         if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
1070             return NGX_ERROR;
1071         }
1072 
1073         if (sslerr == SSL_ERROR_WANT_READ) {
1074             ngx_add_timer(c->read, 30000);
1075         }
1076 
1077         return NGX_AGAIN;
1078     }
1079 
1080     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
1081 
1082     ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
1083 
1084     SSL_free(c->ssl->connection);
1085     c->ssl = NULL;
1086 
1087     return NGX_ERROR;
1088 }
1089 
1090 
1091 static void
1092 ngx_ssl_shutdown_handler(ngx_event_t *ev)
1093 {
1094     ngx_connection_t           *c;
1095     ngx_connection_handler_pt   handler;
1096 
1097     c = ev->data;
1098     handler = c->ssl->handler;
1099 
1100     if (ev->timedout) {
1101         c->timedout = 1;
1102     }
1103 
1104     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "SSL shutdown handler");
1105 
1106     if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
1107         return;
1108     }
1109 
1110     handler(c);
1111 }
1112 
1113 
1114 static void
1115 ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
1116     char *text)
1117 {
1118     int         n;
1119     ngx_uint_t  level;
1120 
1121     level = NGX_LOG_CRIT;
1122 
1123     if (sslerr == SSL_ERROR_SYSCALL) {
1124 
1125         if (err == NGX_ECONNRESET
1126             || err == NGX_EPIPE
1127             || err == NGX_ENOTCONN
1128 #if !(NGX_CRIT_ETIMEDOUT)
1129             || err == NGX_ETIMEDOUT
1130 #endif
1131             || err == NGX_ECONNREFUSED
1132             || err == NGX_ENETDOWN
1133             || err == NGX_ENETUNREACH
1134             || err == NGX_EHOSTDOWN
1135             || err == NGX_EHOSTUNREACH)
1136         {
1137             switch (c->log_error) {
1138 
1139             case NGX_ERROR_IGNORE_ECONNRESET:
1140             case NGX_ERROR_INFO:
1141                 level = NGX_LOG_INFO;
1142                 break;
1143 
1144             case NGX_ERROR_ERR:
1145                 level = NGX_LOG_ERR;
1146                 break;
1147 
1148             default:
1149                 break;
1150             }
1151         }
1152 
1153     } else if (sslerr == SSL_ERROR_SSL) {
1154 
1155         n = ERR_GET_REASON(ERR_pe