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