comparison src/event/ngx_event_openssl.c @ 96:ca4f70b3ccc6 NGINX_0_2_2

nginx 0.2.2 *) Feature: the "config errmsg" command of the ngx_http_ssi_module. *) Change: the ngx_http_geo_module variables can be overridden by the "set" directive. *) Feature: the "ssl_protocols" and "ssl_prefer_server_ciphers" directives of the ngx_http_ssl_module and ngx_imap_ssl_module. *) Bugfix: the ngx_http_autoindex_module did not show correctly the long file names; *) Bugfix: the ngx_http_autoindex_module now do not show the files starting by dot. *) Bugfix: if the SSL handshake failed then another connection may be closed too. Thanks to Rob Mueller. *) Bugfix: the export versions of MSIE 5.x could not connect via HTTPS.
author Igor Sysoev <http://sysoev.ru>
date Fri, 30 Sep 2005 00:00:00 +0400
parents 45945fa8b8ba
children 8bf57caa374a
comparison
equal deleted inserted replaced
95:2f95911bc4b4 96:ca4f70b3ccc6
12 typedef struct { 12 typedef struct {
13 ngx_str_t engine; 13 ngx_str_t engine;
14 } ngx_openssl_conf_t; 14 } ngx_openssl_conf_t;
15 15
16 16
17 static void ngx_ssl_handshake_handler(ngx_event_t *ev);
17 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n); 18 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
18 static void ngx_ssl_write_handler(ngx_event_t *wev); 19 static void ngx_ssl_write_handler(ngx_event_t *wev);
19 static void ngx_ssl_read_handler(ngx_event_t *rev); 20 static void ngx_ssl_read_handler(ngx_event_t *rev);
21 static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
22 ngx_err_t err, char *text);
20 static void *ngx_openssl_create_conf(ngx_cycle_t *cycle); 23 static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
21 static char *ngx_openssl_init_conf(ngx_cycle_t *cycle, void *conf); 24 static char *ngx_openssl_init_conf(ngx_cycle_t *cycle, void *conf);
22 25
23 #if !(NGX_SSL_ENGINE) 26 #if !(NGX_SSL_ENGINE)
24 static char *ngx_openssl_noengine(ngx_conf_t *cf, ngx_command_t *cmd, 27 static char *ngx_openssl_noengine(ngx_conf_t *cf, ngx_command_t *cmd,
61 NULL, /* init thread */ 64 NULL, /* init thread */
62 NULL, /* exit thread */ 65 NULL, /* exit thread */
63 NULL, /* exit process */ 66 NULL, /* exit process */
64 NULL, /* exit master */ 67 NULL, /* exit master */
65 NGX_MODULE_V1_PADDING 68 NGX_MODULE_V1_PADDING
66 }; 69 };
70
71
72 static long ngx_ssl_protocols[] = {
73 SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1,
74 SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1,
75 SSL_OP_NO_SSLv2|SSL_OP_NO_TLSv1,
76 SSL_OP_NO_TLSv1,
77 SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3,
78 SSL_OP_NO_SSLv3,
79 SSL_OP_NO_SSLv2,
80 0,
81 };
67 82
68 83
69 ngx_int_t 84 ngx_int_t
70 ngx_ssl_init(ngx_log_t *log) 85 ngx_ssl_init(ngx_log_t *log)
71 { 86 {
79 return NGX_OK; 94 return NGX_OK;
80 } 95 }
81 96
82 97
83 ngx_int_t 98 ngx_int_t
84 ngx_ssl_create_connection(ngx_ssl_ctx_t *ssl_ctx, ngx_connection_t *c, 99 ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols)
85 ngx_uint_t flags) 100 {
101 ssl->ctx = SSL_CTX_new(SSLv23_server_method());
102
103 if (ssl->ctx == NULL) {
104 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_new() failed");
105 return NGX_ERROR;
106 }
107
108 SSL_CTX_set_options(ssl->ctx, SSL_OP_ALL);
109
110 if (ngx_ssl_protocols[protocols >> 1] != 0) {
111 SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]);
112 }
113
114 SSL_CTX_set_mode(ssl->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
115
116 SSL_CTX_set_read_ahead(ssl->ctx, 1);
117
118 return NGX_OK;
119 }
120
121
122 ngx_int_t
123 ngx_ssl_certificate(ngx_ssl_t *ssl, u_char *cert, u_char *key)
124 {
125 if (SSL_CTX_use_certificate_chain_file(ssl->ctx, (char *) cert) == 0) {
126 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
127 "SSL_CTX_use_certificate_chain_file(\"%s\") failed",
128 cert);
129 return NGX_ERROR;
130 }
131
132 if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key, SSL_FILETYPE_PEM)
133 == 0)
134 {
135 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
136 "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key);
137 return NGX_ERROR;
138 }
139
140 return NGX_OK;
141 }
142
143
144 ngx_int_t
145 ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl)
146 {
147 ssl->rsa512_key = RSA_generate_key(512, RSA_F4, NULL, NULL);
148
149 if (ssl->rsa512_key) {
150 SSL_CTX_set_tmp_rsa(ssl->ctx, ssl->rsa512_key);
151 return NGX_OK;
152 }
153
154 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "RSA_generate_key(512) failed");
155
156 return NGX_ERROR;
157 }
158
159
160 ngx_int_t
161 ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
86 { 162 {
87 ngx_ssl_t *ssl; 163 ngx_ssl_connection_t *sc;
88 164
89 ssl = ngx_pcalloc(c->pool, sizeof(ngx_ssl_t)); 165 sc = ngx_pcalloc(c->pool, sizeof(ngx_ssl_connection_t));
90 if (ssl == NULL) { 166 if (sc == NULL) {
91 return NGX_ERROR; 167 return NGX_ERROR;
92 } 168 }
93 169
94 if (flags & NGX_SSL_BUFFER) { 170 if (flags & NGX_SSL_BUFFER) {
95 ssl->buffer = 1; 171 sc->buffer = 1;
96 172
97 ssl->buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE); 173 sc->buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE);
98 if (ssl->buf == NULL) { 174 if (sc->buf == NULL) {
99 return NGX_ERROR; 175 return NGX_ERROR;
100 } 176 }
101 } 177 }
102 178
103 ssl->connection = SSL_new(ssl_ctx); 179 sc->connection = SSL_new(ssl->ctx);
104 180
105 if (ssl->connection == NULL) { 181 if (sc->connection == NULL) {
106 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed"); 182 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed");
107 return NGX_ERROR; 183 return NGX_ERROR;
108 } 184 }
109 185
110 if (SSL_set_fd(ssl->connection, c->fd) == 0) { 186 if (SSL_set_fd(sc->connection, c->fd) == 0) {
111 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_fd() failed"); 187 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_fd() failed");
112 return NGX_ERROR; 188 return NGX_ERROR;
113 } 189 }
114 190
115 SSL_set_accept_state(ssl->connection); 191 SSL_set_accept_state(sc->connection);
116 192
117 c->ssl = ssl; 193 c->ssl = sc;
118 194
119 return NGX_OK; 195 return NGX_OK;
196 }
197
198
199 ngx_int_t
200 ngx_ssl_handshake(ngx_connection_t *c)
201 {
202 int n, sslerr;
203 ngx_err_t err;
204
205 n = SSL_do_handshake(c->ssl->connection);
206
207 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
208
209 if (n == 1) {
210
211 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
212 return NGX_ERROR;
213 }
214
215 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
216 return NGX_ERROR;
217 }
218
219 #if (NGX_DEBUG)
220 {
221 char buf[129], *s, *d;
222 SSL_CIPHER *cipher;
223
224 cipher = SSL_get_current_cipher(c->ssl->connection);
225
226 if (cipher) {
227 SSL_CIPHER_description(cipher, &buf[1], 128);
228
229 for (s = &buf[1], d = buf; *s; s++) {
230 if (*s == ' ' && *d == ' ') {
231 continue;
232 }
233
234 if (*s == LF || *s == CR) {
235 continue;
236 }
237
238 *++d = *s;
239 }
240
241 if (*d != ' ') {
242 d++;
243 }
244
245 *d = '\0';
246
247 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
248 "SSL: %s, cipher: \"%s\"",
249 SSL_get_version(c->ssl->connection), &buf[1]);
250
251 if (SSL_session_reused(c->ssl->connection)) {
252 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
253 "SSL reused session");
254 }
255
256 } else {
257 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
258 "SSL no shared ciphers");
259 }
260 }
261 #endif
262
263 c->ssl->handshaked = 1;
264
265 c->recv = ngx_ssl_recv;
266 c->send = ngx_ssl_write;
267 c->send_chain = ngx_ssl_send_chain;
268
269 return NGX_OK;
270 }
271
272 sslerr = SSL_get_error(c->ssl->connection, n);
273
274 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
275
276 if (sslerr == SSL_ERROR_WANT_READ) {
277 c->read->ready = 0;
278 c->read->handler = ngx_ssl_handshake_handler;
279
280 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
281 return NGX_ERROR;
282 }
283
284 return NGX_AGAIN;
285 }
286
287 if (sslerr == SSL_ERROR_WANT_WRITE) {
288 c->write->ready = 0;
289 c->write->handler = ngx_ssl_handshake_handler;
290
291 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
292 return NGX_ERROR;
293 }
294
295 return NGX_AGAIN;
296 }
297
298 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
299
300 c->ssl->no_wait_shutdown = 1;
301 c->ssl->no_send_shutdown = 1;
302
303 if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
304 ngx_log_error(NGX_LOG_INFO, c->log, err,
305 "client closed connection in SSL handshake");
306
307 return NGX_ERROR;
308 }
309
310 ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed");
311
312 return NGX_ERROR;
313 }
314
315
316 static void
317 ngx_ssl_handshake_handler(ngx_event_t *ev)
318 {
319 ngx_connection_t *c;
320
321 c = ev->data;
322
323 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
324 "ssl handshake handler: %d", ev->write);
325
326 if (ngx_ssl_handshake(c) == NGX_AGAIN) {
327 return;
328 }
329
330 c->ssl->handler(c);
120 } 331 }
121 332
122 333
123 ssize_t 334 ssize_t
124 ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size) 335 ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
141 n = SSL_read(c->ssl->connection, buf, size); 352 n = SSL_read(c->ssl->connection, buf, size);
142 353
143 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n); 354 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n);
144 355
145 if (n > 0) { 356 if (n > 0) {
146
147 bytes += n; 357 bytes += n;
148
149 #if (NGX_DEBUG)
150
151 if (!c->ssl->handshaked && SSL_is_init_finished(c->ssl->connection))
152 {
153 char buf[129], *s, *d;
154 SSL_CIPHER *cipher;
155
156 c->ssl->handshaked = 1;
157
158 cipher = SSL_get_current_cipher(c->ssl->connection);
159
160 if (cipher) {
161 SSL_CIPHER_description(cipher, &buf[1], 128);
162
163 for (s = &buf[1], d = buf; *s; s++) {
164 if (*s == ' ' && *d == ' ') {
165 continue;
166 }
167
168 if (*s == LF || *s == CR) {
169 continue;
170 }
171
172 *++d = *s;
173 }
174
175 if (*d != ' ') {
176 d++;
177 }
178
179 *d = '\0';
180
181 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
182 "SSL cipher: \"%s\"", &buf[1]);
183
184 if (SSL_session_reused(c->ssl->connection)) {
185 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
186 "SSL reused session");
187 }
188
189 } else {
190 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
191 "SSL no shared ciphers");
192 }
193 }
194 #endif
195
196 } 358 }
197 359
198 c->ssl->last = ngx_ssl_handle_recv(c, n); 360 c->ssl->last = ngx_ssl_handle_recv(c, n);
199 361
200 if (c->ssl->last != NGX_OK) { 362 if (c->ssl->last != NGX_OK) {
219 381
220 382
221 static ngx_int_t 383 static ngx_int_t
222 ngx_ssl_handle_recv(ngx_connection_t *c, int n) 384 ngx_ssl_handle_recv(ngx_connection_t *c, int n)
223 { 385 {
224 int sslerr; 386 int sslerr;
225 char *handshake; 387 ngx_err_t err;
226 ngx_err_t err;
227 ngx_uint_t level;
228 388
229 if (n > 0) { 389 if (n > 0) {
230 390
231 if (c->ssl->saved_write_handler) { 391 if (c->ssl->saved_write_handler) {
232 392
248 } 408 }
249 409
250 return NGX_OK; 410 return NGX_OK;
251 } 411 }
252 412
253 if (!SSL_is_init_finished(c->ssl->connection)) {
254 handshake = " in SSL handshake";
255
256 } else {
257 handshake = "";
258 }
259
260 sslerr = SSL_get_error(c->ssl->connection, n); 413 sslerr = SSL_get_error(c->ssl->connection, n);
261 414
262 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0; 415 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
263 416
264 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr); 417 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
268 return NGX_AGAIN; 421 return NGX_AGAIN;
269 } 422 }
270 423
271 if (sslerr == SSL_ERROR_WANT_WRITE) { 424 if (sslerr == SSL_ERROR_WANT_WRITE) {
272 425
273 ngx_log_error(NGX_LOG_INFO, c->log, err, 426 ngx_log_error(NGX_LOG_INFO, c->log, 0,
274 "client does SSL %shandshake", 427 "client started SSL renegotiation");
275 SSL_is_init_finished(c->ssl->connection) ? "re" : "");
276 428
277 c->write->ready = 0; 429 c->write->ready = 0;
278 430
279 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { 431 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
280 return NGX_ERROR; 432 return NGX_ERROR;
290 } 442 }
291 443
292 return NGX_AGAIN; 444 return NGX_AGAIN;
293 } 445 }
294 446
295 c->ssl->no_rcv_shut = 1; 447 c->ssl->no_wait_shutdown = 1;
296 c->ssl->no_send_shut = 1; 448 c->ssl->no_send_shutdown = 1;
297 449
298 if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) { 450 if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
299 ngx_log_error(NGX_LOG_INFO, c->log, err, 451 ngx_log_error(NGX_LOG_INFO, c->log, err, "client closed connection");
300 "client closed connection%s", handshake);
301 452
302 return NGX_ERROR; 453 return NGX_ERROR;
303 } 454 }
455
456 ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed");
457
458 return NGX_ERROR;
459 }
460
461
462 static void
463 ngx_ssl_write_handler(ngx_event_t *wev)
464 {
465 ngx_connection_t *c;
466
467 c = wev->data;
468
469 c->read->handler(c->read);
470 }
471
472
473 /*
474 * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer
475 * before the SSL_write() call to decrease a SSL overhead.
476 *
477 * Besides for protocols such as HTTP it is possible to always buffer
478 * the output to decrease a SSL overhead some more.
479 */
480
481 ngx_chain_t *
482 ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
483 {
484 int n;
485 ngx_uint_t flush;
486 ssize_t send, size;
487 ngx_buf_t *buf;
488
489 buf = c->ssl->buf;
490
491 if (in && in->next == NULL && !c->buffered && !c->ssl->buffer) {
492
493 /*
494 * we avoid a buffer copy if the incoming buf is a single,
495 * our buffer is empty, and we do not need to buffer the output
496 */
497
498 n = ngx_ssl_write(c, in->buf->pos, in->buf->last - in->buf->pos);
499
500 if (n == NGX_ERROR) {
501 return NGX_CHAIN_ERROR;
502 }
503
504 if (n == NGX_AGAIN) {
505 c->buffered = 1;
506 return in;
507 }
508
509 in->buf->pos += n;
510
511 return in;
512 }
513
514
515 /* the maximum limit size is the maximum uint32_t value - the page size */
516
517 if (limit == 0 || limit > NGX_MAX_UINT32_VALUE - ngx_pagesize) {
518 limit = NGX_MAX_UINT32_VALUE - ngx_pagesize;
519 }
520
521
522 send = 0;
523 flush = (in == NULL) ? 1 : 0;
524
525 for ( ;; ) {
526
527 while (in && buf->last < buf->end) {
528 if (in->buf->last_buf) {
529 flush = 1;
530 }
531
532 if (ngx_buf_special(in->buf)) {
533 in = in->next;
534 continue;
535 }
536
537 size = in->buf->last - in->buf->pos;
538
539 if (size > buf->end - buf->last) {
540 size = buf->end - buf->last;
541 }
542
543 /*
544 * TODO: the taking in->buf->flush into account can be
545 * implemented using the limit on the higher level
546 */
547
548 if (send + size > limit) {
549 size = limit - send;
550 flush = 1;
551 }
552
553 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
554 "SSL buf copy: %d", size);
555
556 ngx_memcpy(buf->last, in->buf->pos, size);
557
558 buf->last += size;
559
560 in->buf->pos += size;
561 if (in->buf->pos == in->buf->last) {
562 in = in->next;
563 }
564 }
565
566 size = buf->last - buf->pos;
567
568 if (!flush && buf->last < buf->end && c->ssl->buffer) {
569 break;
570 }
571
572 n = ngx_ssl_write(c, buf->pos, size);
573
574 if (n == NGX_ERROR) {
575 return NGX_CHAIN_ERROR;
576 }
577
578 if (n == NGX_AGAIN) {
579 c->buffered = 1;
580 return in;
581 }
582
583 buf->pos += n;
584 send += n;
585 c->sent += n;
586
587 if (n < size) {
588 break;
589 }
590
591 if (buf->pos == buf->last) {
592 buf->pos = buf->start;
593 buf->last = buf->start;
594 }
595
596 if (in == NULL || send == limit) {
597 break;
598 }
599 }
600
601 c->buffered = (buf->pos < buf->last) ? 1 : 0;
602
603 return in;
604 }
605
606
607 ssize_t
608 ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
609 {
610 int n, sslerr;
611 ngx_err_t err;
612
613 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size);
614
615 n = SSL_write(c->ssl->connection, data, size);
616
617 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n);
618
619 if (n > 0) {
620
621 if (c->ssl->saved_read_handler) {
622
623 c->read->handler = c->ssl->saved_read_handler;
624 c->ssl->saved_read_handler = NULL;
625 c->read->ready = 1;
626
627 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
628 return NGX_ERROR;
629 }
630
631 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
632 return NGX_ERROR;
633 }
634
635 ngx_post_event(c->read);
636
637 ngx_mutex_unlock(ngx_posted_events_mutex);
638 }
639
640 return n;
641 }
642
643 sslerr = SSL_get_error(c->ssl->connection, n);
644
645 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
646
647 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
648
649 if (sslerr == SSL_ERROR_WANT_WRITE) {
650 c->write->ready = 0;
651 return NGX_AGAIN;
652 }
653
654 if (sslerr == SSL_ERROR_WANT_READ) {
655
656 ngx_log_error(NGX_LOG_INFO, c->log, 0,
657 "client started SSL renegotiation");
658
659 c->read->ready = 0;
660
661 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
662 return NGX_ERROR;
663 }
664
665 /*
666 * we do not set the timer because there is already
667 * the write event timer
668 */
669
670 if (c->ssl->saved_read_handler == NULL) {
671 c->ssl->saved_read_handler = c->read->handler;
672 c->read->handler = ngx_ssl_read_handler;
673 }
674
675 return NGX_AGAIN;
676 }
677
678 c->ssl->no_wait_shutdown = 1;
679 c->ssl->no_send_shutdown = 1;
680
681 ngx_ssl_connection_error(c, sslerr, err, "SSL_write() failed");
682
683 return NGX_ERROR;
684 }
685
686
687 static void
688 ngx_ssl_read_handler(ngx_event_t *rev)
689 {
690 ngx_connection_t *c;
691
692 c = rev->data;
693
694 c->write->handler(c->write);
695 }
696
697
698 ngx_int_t
699 ngx_ssl_shutdown(ngx_connection_t *c)
700 {
701 int n, sslerr, mode;
702 ngx_uint_t again;
703
704 if (c->read->timedout) {
705 mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
706
707 } else {
708 mode = SSL_get_shutdown(c->ssl->connection);
709
710 if (c->ssl->no_wait_shutdown) {
711 mode |= SSL_RECEIVED_SHUTDOWN;
712 }
713
714 if (c->ssl->no_send_shutdown) {
715 mode |= SSL_SENT_SHUTDOWN;
716 }
717 }
718
719 SSL_set_shutdown(c->ssl->connection, mode);
720
721 again = 0;
722 #if (NGX_SUPPRESS_WARN)
723 sslerr = 0;
724 #endif
725
726 for ( ;; ) {
727 n = SSL_shutdown(c->ssl->connection);
728
729 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
730
731 if (n == 1 || (n == 0 && c->read->timedout)) {
732 SSL_free(c->ssl->connection);
733 c->ssl = NULL;
734
735 return NGX_OK;
736 }
737
738 if (n == 0) {
739 again = 1;
740 break;
741 }
742
743 break;
744 }
745
746 if (!again) {
747 sslerr = SSL_get_error(c->ssl->connection, n);
748
749 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
750 "SSL_get_error: %d", sslerr);
751 }
752
753 if (again || sslerr == SSL_ERROR_WANT_READ) {
754
755 ngx_add_timer(c->read, 30000);
756
757 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
758 return NGX_ERROR;
759 }
760
761 return NGX_AGAIN;
762 }
763
764 if (sslerr == SSL_ERROR_WANT_WRITE) {
765
766 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
767 return NGX_ERROR;
768 }
769
770 return NGX_AGAIN;
771 }
772
773 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_shutdown() failed");
774
775 SSL_free(c->ssl->connection);
776 c->ssl = NULL;
777
778 return NGX_ERROR;
779 }
780
781
782 static void
783 ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
784 char *text)
785 {
786 ngx_uint_t level;
304 787
305 level = NGX_LOG_CRIT; 788 level = NGX_LOG_CRIT;
306 789
307 if (sslerr == SSL_ERROR_SYSCALL) { 790 if (sslerr == SSL_ERROR_SYSCALL) {
308 791
327 break; 810 break;
328 } 811 }
329 } 812 }
330 } 813 }
331 814
332 ngx_ssl_error(level, c->log, err, "SSL_read() failed%s", handshake); 815 ngx_ssl_error(level, c->log, err, text);
333
334 return NGX_ERROR;
335 }
336
337
338 static void
339 ngx_ssl_write_handler(ngx_event_t *wev)
340 {
341 ngx_connection_t *c;
342
343 c = wev->data;
344 c->read->handler(c->read);
345 }
346
347
348 /*
349 * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer
350 * before the SSL_write() call to decrease a SSL overhead.
351 *
352 * Besides for protocols such as HTTP it is possible to always buffer
353 * the output to decrease a SSL overhead some more.
354 */
355
356 ngx_chain_t *
357 ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
358 {
359 int n;
360 ngx_uint_t flush;
361 ssize_t send, size;
362 ngx_buf_t *buf;
363
364 buf = c->ssl->buf;
365
366 if (in && in->next == NULL && !c->buffered && !c->ssl->buffer) {
367
368 /*
369 * we avoid a buffer copy if the incoming buf is a single,
370 * our buffer is empty, and we do not need to buffer the output
371 */
372
373 n = ngx_ssl_write(c, in->buf->pos, in->buf->last - in->buf->pos);
374
375 if (n == NGX_ERROR) {
376 return NGX_CHAIN_ERROR;
377 }
378
379 if (n == NGX_AGAIN) {
380 c->buffered = 1;
381 return in;
382 }
383
384 in->buf->pos += n;
385
386 return in;
387 }
388
389
390 /* the maximum limit size is the maximum uint32_t value - the page size */
391
392 if (limit == 0 || limit > NGX_MAX_UINT32_VALUE - ngx_pagesize) {
393 limit = NGX_MAX_UINT32_VALUE - ngx_pagesize;
394 }
395
396
397 send = 0;
398 flush = (in == NULL) ? 1 : 0;
399
400 for ( ;; ) {
401
402 while (in && buf->last < buf->end) {
403 if (in->buf->last_buf) {
404 flush = 1;
405 }
406
407 if (ngx_buf_special(in->buf)) {
408 in = in->next;
409 continue;
410 }
411
412 size = in->buf->last - in->buf->pos;
413
414 if (size > buf->end - buf->last) {
415 size = buf->end - buf->last;
416 }
417
418 /*
419 * TODO: the taking in->buf->flush into account can be
420 * implemented using the limit on the higher level
421 */
422
423 if (send + size > limit) {
424 size = limit - send;
425 flush = 1;
426 }
427
428 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
429 "SSL buf copy: %d", size);
430
431 ngx_memcpy(buf->last, in->buf->pos, size);
432
433 buf->last += size;
434
435 in->buf->pos += size;
436 if (in->buf->pos == in->buf->last) {
437 in = in->next;
438 }
439 }
440
441 size = buf->last - buf->pos;
442
443 if (!flush && buf->last < buf->end && c->ssl->buffer) {
444 break;
445 }
446
447 n = ngx_ssl_write(c, buf->pos, size);
448
449 if (n == NGX_ERROR) {
450 return NGX_CHAIN_ERROR;
451 }
452
453 if (n == NGX_AGAIN) {
454 c->buffered = 1;
455 return in;
456 }
457
458 buf->pos += n;
459 send += n;
460 c->sent += n;
461
462 if (n < size) {
463 break;
464 }
465
466 if (buf->pos == buf->last) {
467 buf->pos = buf->start;
468 buf->last = buf->start;
469 }
470
471 if (in == NULL || send == limit) {
472 break;
473 }
474 }
475
476 c->buffered = (buf->pos < buf->last) ? 1 : 0;
477
478 return in;
479 }
480
481
482 ssize_t
483 ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
484 {
485 int n, sslerr;
486 ngx_err_t err;
487 ngx_uint_t level;
488
489 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size);
490
491 n = SSL_write(c->ssl->connection, data, size);
492
493 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n);
494
495 if (n > 0) {
496
497 #if (NGX_DEBUG)
498
499 if (!c->ssl->handshaked && SSL_is_init_finished(c->ssl->connection)) {
500 char buf[129], *s, *d;
501 SSL_CIPHER *cipher;
502
503 c->ssl->handshaked = 1;
504
505 cipher = SSL_get_current_cipher(c->ssl->connection);
506
507 if (cipher) {
508 SSL_CIPHER_description(cipher, &buf[1], 128);
509
510 for (s = &buf[1], d = buf; *s; s++) {
511 if (*s == ' ' && *d == ' ') {
512 continue;
513 }
514
515 if (*s == LF || *s == CR) {
516 continue;
517 }
518
519 *++d = *s;
520 }
521
522 if (*d != ' ') {
523 d++;
524 }
525
526 *d = '\0';
527
528 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
529 "SSL cipher: \"%s\"", &buf[1]);
530
531 if (SSL_session_reused(c->ssl->connection)) {
532 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
533 "SSL reused session");
534 }
535
536 } else {
537 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
538 "SSL no shared ciphers");
539 }
540 }
541 #endif
542
543 if (c->ssl->saved_read_handler) {
544
545 c->read->handler = c->ssl->saved_read_handler;
546 c->ssl->saved_read_handler = NULL;
547 c->read->ready = 1;
548
549 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
550 return NGX_ERROR;
551 }
552
553 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
554 return NGX_ERROR;
555 }
556
557 ngx_post_event(c->read);
558
559 ngx_mutex_unlock(ngx_posted_events_mutex);
560 }
561
562 return n;
563 }
564
565 sslerr = SSL_get_error(c->ssl->connection, n);
566
567 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
568
569 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
570
571 if (sslerr == SSL_ERROR_WANT_WRITE) {
572 c->write->ready = 0;
573 return NGX_AGAIN;
574 }
575
576 if (sslerr == SSL_ERROR_WANT_READ) {
577
578 ngx_log_error(NGX_LOG_INFO, c->log, err,
579 "client does SSL %shandshake",
580 SSL_is_init_finished(c->ssl->connection) ? "re" : "");
581
582 c->read->ready = 0;
583
584 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
585 return NGX_ERROR;
586 }
587
588 /*
589 * we do not set the timer because there is already
590 * the write event timer
591 */
592
593 if (c->ssl->saved_read_handler == NULL) {
594 c->ssl->saved_read_handler = c->read->handler;
595 c->read->handler = ngx_ssl_read_handler;
596 }
597
598 return NGX_AGAIN;
599 }
600
601 c->ssl->no_rcv_shut = 1;
602 c->ssl->no_send_shut = 1;
603
604 level = NGX_LOG_CRIT;
605
606 if (sslerr == SSL_ERROR_SYSCALL) {
607
608 if (err == NGX_ECONNRESET
609 || err == NGX_EPIPE
610 || err == NGX_ENOTCONN
611 || err == NGX_ECONNREFUSED
612 || err == NGX_EHOSTUNREACH)
613 {
614 switch (c->log_error) {
615
616 case NGX_ERROR_IGNORE_ECONNRESET:
617 case NGX_ERROR_INFO:
618 level = NGX_LOG_INFO;
619 break;
620
621 case NGX_ERROR_ERR:
622 level = NGX_LOG_ERR;
623 break;
624
625 default:
626 break;
627 }
628 }
629 }
630
631 ngx_ssl_error(level, c->log, err, "SSL_write() failed");
632
633 return NGX_ERROR;
634 }
635
636
637 static void
638 ngx_ssl_read_handler(ngx_event_t *rev)
639 {
640 ngx_connection_t *c;
641
642 c = rev->data;
643 c->write->handler(c->write);
644 }
645
646
647 ngx_int_t
648 ngx_ssl_shutdown(ngx_connection_t *c)
649 {
650 int n, sslerr, mode;
651 ngx_uint_t again;
652
653 if (!c->ssl->shutdown_set) {
654
655 /* it seems that SSL_set_shutdown() could be called once only */
656
657 if (c->read->timedout) {
658 mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
659
660 } else {
661 mode = 0;
662
663 if (c->ssl->no_rcv_shut) {
664 mode = SSL_RECEIVED_SHUTDOWN;
665 }
666
667 if (c->ssl->no_send_shut) {
668 mode |= SSL_SENT_SHUTDOWN;
669 }
670 }
671
672 if (mode) {
673 SSL_set_shutdown(c->ssl->connection, mode);
674 c->ssl->shutdown_set = 1;
675 }
676 }
677
678 again = 0;
679 #if (NGX_SUPPRESS_WARN)
680 sslerr = 0;
681 #endif
682
683 for ( ;; ) {
684 n = SSL_shutdown(c->ssl->connection);
685
686 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
687
688 if (n == 1 || (n == 0 && c->read->timedout)) {
689 SSL_free(c->ssl->connection);
690 c->ssl = NULL;
691
692 return NGX_OK;
693 }
694
695 if (n == 0) {
696 again = 1;
697 break;
698 }
699
700 break;
701 }
702
703 if (!again) {
704 sslerr = SSL_get_error(c->ssl->connection, n);
705
706 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
707 "SSL_get_error: %d", sslerr);
708 }
709
710 if (again || sslerr == SSL_ERROR_WANT_READ) {
711
712 ngx_add_timer(c->read, 30000);
713
714 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
715 return NGX_ERROR;
716 }
717
718 return NGX_AGAIN;
719 }
720
721 if (sslerr == SSL_ERROR_WANT_WRITE) {
722
723 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
724 return NGX_ERROR;
725 }
726
727 return NGX_AGAIN;
728 }
729
730 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_shutdown() failed");
731
732 SSL_free(c->ssl->connection);
733 c->ssl = NULL;
734
735 return NGX_ERROR;
736 } 816 }
737 817
738 818
739 void 819 void
740 ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...) 820 ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
741 { 821 {
822 u_long n;
823 va_list args;
742 u_char errstr[NGX_MAX_CONF_ERRSTR], *p, *last; 824 u_char errstr[NGX_MAX_CONF_ERRSTR], *p, *last;
743 va_list args;
744 825
745 last = errstr + NGX_MAX_CONF_ERRSTR; 826 last = errstr + NGX_MAX_CONF_ERRSTR;
746 827
747 va_start(args, fmt); 828 va_start(args, fmt);
748 p = ngx_vsnprintf(errstr, sizeof(errstr) - 1, fmt, args); 829 p = ngx_vsnprintf(errstr, sizeof(errstr) - 1, fmt, args);
749 va_end(args); 830 va_end(args);
750 831
751 p = ngx_cpystrn(p, (u_char *) " (SSL: ", last - p); 832 p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p);
752 833
753 ERR_error_string_n(ERR_get_error(), (char *) p, last - p); 834 while (p < last && (n = ERR_get_error())) {
835
836 *p++ = ' ';
837
838 ERR_error_string_n(n, (char *) p, last - p);
839
840 while (p < last && *p) {
841 p++;
842 }
843 }
754 844
755 ngx_log_error(level, log, err, "%s)", errstr); 845 ngx_log_error(level, log, err, "%s)", errstr);
756 } 846 }
757 847
758 848
759 void 849 void
760 ngx_ssl_cleanup_ctx(void *data) 850 ngx_ssl_cleanup_ctx(void *data)
761 { 851 {
762 SSL_CTX *ctx = data; 852 ngx_ssl_t *ssl = data;
763 853
764 SSL_CTX_free(ctx); 854 RSA_free(ssl->rsa512_key);
855 SSL_CTX_free(ssl->ctx);
765 } 856 }
766 857
767 858
768 static void * 859 static void *
769 ngx_openssl_create_conf(ngx_cycle_t *cycle) 860 ngx_openssl_create_conf(ngx_cycle_t *cycle)