Mercurial > hg > nginx-quic
annotate src/event/ngx_event_openssl.c @ 647:95d7da23ea53 release-0.3.45
nginx-0.3.45-RELEASE import
*) Feature: the "ssl_verify_client", "ssl_verify_depth", and
"ssl_client_certificate" directives.
*) Change: the $request_method variable now returns the main request
method.
*) Change: the ° symbol codes were changed in koi-win conversion
table.
*) Feature: the euro and N symbols were added to koi-win conversion
table.
*) Bugfix: if nginx distributed the requests among several backends and
some backend failed, then requests intended for this backend was
directed to one live backend only instead of being distributed among
the rest.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sat, 06 May 2006 16:28:56 +0000 |
parents | 3f8a2132b93d |
children | cec32b3753ac |
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, | |
647 | 167 SSL_FILETYPE_PEM) |
168 == 0) | |
563 | 169 { |
170 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | |
171 "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key->data); | |
547 | 172 return NGX_ERROR; |
173 } | |
174 | |
175 return NGX_OK; | |
176 } | |
177 | |
178 | |
179 ngx_int_t | |
647 | 180 ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert) |
181 { | |
182 if (ngx_conf_full_name(cf->cycle, cert) == NGX_ERROR) { | |
183 return NGX_ERROR; | |
184 } | |
185 | |
186 if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL) | |
187 == 0) | |
188 { | |
189 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | |
190 "SSL_CTX_load_verify_locations(\"%s\") failed", | |
191 cert->data); | |
192 return NGX_ERROR; | |
193 } | |
194 | |
195 return NGX_OK; | |
196 } | |
197 | |
198 | |
199 ngx_int_t | |
547 | 200 ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl) |
201 { | |
559 | 202 if (SSL_CTX_need_tmp_RSA(ssl->ctx) == 0) { |
203 return NGX_OK; | |
204 } | |
205 | |
547 | 206 ssl->rsa512_key = RSA_generate_key(512, RSA_F4, NULL, NULL); |
207 | |
208 if (ssl->rsa512_key) { | |
209 SSL_CTX_set_tmp_rsa(ssl->ctx, ssl->rsa512_key); | |
210 return NGX_OK; | |
211 } | |
212 | |
213 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "RSA_generate_key(512) failed"); | |
214 | |
215 return NGX_ERROR; | |
216 } | |
217 | |
218 | |
219 ngx_int_t | |
220 ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags) | |
577 | 221 { |
547 | 222 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
|
223 |
547 | 224 sc = ngx_pcalloc(c->pool, sizeof(ngx_ssl_connection_t)); |
225 if (sc == NULL) { | |
393
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
226 return NGX_ERROR; |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
227 } |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
228 |
543 | 229 if (flags & NGX_SSL_BUFFER) { |
547 | 230 sc->buffer = 1; |
543 | 231 |
547 | 232 sc->buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE); |
233 if (sc->buf == NULL) { | |
543 | 234 return NGX_ERROR; |
235 } | |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
236 } |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
237 |
547 | 238 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
|
239 |
547 | 240 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
|
241 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
|
242 return NGX_ERROR; |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
243 } |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
244 |
547 | 245 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
|
246 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
|
247 return NGX_ERROR; |
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
248 } |
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
249 |
577 | 250 if (flags & NGX_SSL_CLIENT) { |
251 SSL_set_connect_state(sc->connection); | |
252 | |
253 } else { | |
254 SSL_set_accept_state(sc->connection); | |
255 } | |
393
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
256 |
547 | 257 c->ssl = sc; |
393
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
258 |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
259 return NGX_OK; |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
260 } |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
261 |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
262 |
547 | 263 ngx_int_t |
577 | 264 ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session) |
265 { | |
266 if (session) { | |
267 if (SSL_set_session(c->ssl->connection, session) == 0) { | |
268 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_session() failed"); | |
269 return NGX_ERROR; | |
270 } | |
271 } | |
272 | |
273 return NGX_OK; | |
274 } | |
275 | |
276 | |
277 ngx_int_t | |
547 | 278 ngx_ssl_handshake(ngx_connection_t *c) |
279 { | |
280 int n, sslerr; | |
281 ngx_err_t err; | |
282 | |
283 n = SSL_do_handshake(c->ssl->connection); | |
284 | |
577 | 285 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n); |
547 | 286 |
287 if (n == 1) { | |
288 | |
289 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { | |
290 return NGX_ERROR; | |
291 } | |
292 | |
293 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { | |
294 return NGX_ERROR; | |
295 } | |
296 | |
297 #if (NGX_DEBUG) | |
298 { | |
299 char buf[129], *s, *d; | |
300 SSL_CIPHER *cipher; | |
301 | |
302 cipher = SSL_get_current_cipher(c->ssl->connection); | |
303 | |
304 if (cipher) { | |
305 SSL_CIPHER_description(cipher, &buf[1], 128); | |
306 | |
307 for (s = &buf[1], d = buf; *s; s++) { | |
308 if (*s == ' ' && *d == ' ') { | |
309 continue; | |
310 } | |
311 | |
312 if (*s == LF || *s == CR) { | |
313 continue; | |
314 } | |
315 | |
316 *++d = *s; | |
317 } | |
318 | |
319 if (*d != ' ') { | |
320 d++; | |
321 } | |
322 | |
323 *d = '\0'; | |
324 | |
583 | 325 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, |
547 | 326 "SSL: %s, cipher: \"%s\"", |
577 | 327 SSL_get_version(c->ssl->connection), &buf[1]); |
547 | 328 |
329 if (SSL_session_reused(c->ssl->connection)) { | |
583 | 330 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, |
547 | 331 "SSL reused session"); |
332 } | |
333 | |
334 } else { | |
335 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
577 | 336 "SSL no shared ciphers"); |
547 | 337 } |
338 } | |
339 #endif | |
340 | |
341 c->ssl->handshaked = 1; | |
342 | |
343 c->recv = ngx_ssl_recv; | |
344 c->send = ngx_ssl_write; | |
577 | 345 c->recv_chain = ngx_ssl_recv_chain; |
346 c->send_chain = ngx_ssl_send_chain; | |
547 | 347 |
348 return NGX_OK; | |
349 } | |
350 | |
351 sslerr = SSL_get_error(c->ssl->connection, n); | |
352 | |
353 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr); | |
354 | |
355 if (sslerr == SSL_ERROR_WANT_READ) { | |
356 c->read->ready = 0; | |
357 c->read->handler = ngx_ssl_handshake_handler; | |
591 | 358 c->write->handler = ngx_ssl_handshake_handler; |
547 | 359 |
360 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { | |
361 return NGX_ERROR; | |
362 } | |
363 | |
364 return NGX_AGAIN; | |
365 } | |
366 | |
367 if (sslerr == SSL_ERROR_WANT_WRITE) { | |
368 c->write->ready = 0; | |
591 | 369 c->read->handler = ngx_ssl_handshake_handler; |
547 | 370 c->write->handler = ngx_ssl_handshake_handler; |
371 | |
372 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { | |
373 return NGX_ERROR; | |
374 } | |
375 | |
376 return NGX_AGAIN; | |
377 } | |
378 | |
379 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0; | |
380 | |
381 c->ssl->no_wait_shutdown = 1; | |
382 c->ssl->no_send_shutdown = 1; | |
591 | 383 c->read->eof = 1; |
547 | 384 |
385 if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) { | |
386 ngx_log_error(NGX_LOG_INFO, c->log, err, | |
577 | 387 "peer closed connection in SSL handshake"); |
547 | 388 |
389 return NGX_ERROR; | |
390 } | |
391 | |
591 | 392 c->read->error = 1; |
393 | |
547 | 394 ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed"); |
395 | |
396 return NGX_ERROR; | |
397 } | |
398 | |
399 | |
400 static void | |
401 ngx_ssl_handshake_handler(ngx_event_t *ev) | |
402 { | |
403 ngx_connection_t *c; | |
404 | |
405 c = ev->data; | |
406 | |
549 | 407 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, |
577 | 408 "SSL handshake handler: %d", ev->write); |
547 | 409 |
591 | 410 if (ev->timedout) { |
411 c->ssl->handler(c); | |
412 return; | |
413 } | |
414 | |
547 | 415 if (ngx_ssl_handshake(c) == NGX_AGAIN) { |
416 return; | |
417 } | |
418 | |
419 c->ssl->handler(c); | |
420 } | |
421 | |
422 | |
489 | 423 ssize_t |
577 | 424 ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl) |
425 { | |
426 ssize_t n, bytes; | |
427 ngx_buf_t *b; | |
428 | |
429 bytes = 0; | |
430 | |
431 while (cl) { | |
432 b = cl->buf; | |
433 | |
434 n = ngx_ssl_recv(c, b->last, b->end - b->last); | |
435 | |
436 if (n > 0) { | |
437 b->last += n; | |
438 bytes += n; | |
439 | |
440 if (b->last == b->end) { | |
441 cl = cl->next; | |
442 } | |
443 | |
444 continue; | |
445 } | |
446 | |
447 if (bytes) { | |
448 return bytes; | |
449 } | |
450 | |
451 return n; | |
452 } | |
453 | |
454 return bytes; | |
455 } | |
456 | |
457 | |
458 ssize_t | |
489 | 459 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
|
460 { |
489 | 461 int n, bytes; |
462 | |
463 if (c->ssl->last == NGX_ERROR) { | |
464 return NGX_ERROR; | |
465 } | |
466 | |
577 | 467 if (c->ssl->last == NGX_DONE) { |
468 return 0; | |
469 } | |
470 | |
489 | 471 bytes = 0; |
393
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
472 |
489 | 473 /* |
474 * SSL_read() may return data in parts, so try to read | |
475 * until SSL_read() would return no data | |
476 */ | |
477 | |
478 for ( ;; ) { | |
393
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
479 |
543 | 480 n = SSL_read(c->ssl->connection, buf, size); |
489 | 481 |
577 | 482 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
|
483 |
489 | 484 if (n > 0) { |
485 bytes += n; | |
486 } | |
487 | |
488 c->ssl->last = ngx_ssl_handle_recv(c, n); | |
489 | |
490 if (c->ssl->last != NGX_OK) { | |
479 | 491 |
489 | 492 if (bytes) { |
493 return bytes; | |
577 | 494 } |
489 | 495 |
577 | 496 if (c->ssl->last == NGX_DONE) { |
497 return 0; | |
479 | 498 } |
577 | 499 |
500 return c->ssl->last; | |
479 | 501 } |
502 | |
489 | 503 size -= n; |
504 | |
505 if (size == 0) { | |
506 return bytes; | |
507 } | |
508 | |
509 buf += n; | |
510 } | |
511 } | |
512 | |
513 | |
514 static ngx_int_t | |
515 ngx_ssl_handle_recv(ngx_connection_t *c, int n) | |
516 { | |
547 | 517 int sslerr; |
518 ngx_err_t err; | |
489 | 519 |
520 if (n > 0) { | |
479 | 521 |
473 | 522 if (c->ssl->saved_write_handler) { |
523 | |
509 | 524 c->write->handler = c->ssl->saved_write_handler; |
473 | 525 c->ssl->saved_write_handler = NULL; |
526 c->write->ready = 1; | |
527 | |
528 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { | |
529 return NGX_ERROR; | |
530 } | |
531 | |
563 | 532 ngx_post_event(c->write, &ngx_posted_events); |
473 | 533 } |
534 | |
489 | 535 return NGX_OK; |
393
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
536 } |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
537 |
543 | 538 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
|
539 |
396
6f3b20c1ac50
nginx-0.0.7-2004-07-18-23:11:20 import
Igor Sysoev <igor@sysoev.ru>
parents:
395
diff
changeset
|
540 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
|
541 |
396
6f3b20c1ac50
nginx-0.0.7-2004-07-18-23:11:20 import
Igor Sysoev <igor@sysoev.ru>
parents:
395
diff
changeset
|
542 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
|
543 |
395
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
544 if (sslerr == SSL_ERROR_WANT_READ) { |
455 | 545 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
|
546 return NGX_AGAIN; |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
547 } |
394
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
548 |
445
f26432a1935a
nginx-0.1.0-2004-09-30-10:38:49 import
Igor Sysoev <igor@sysoev.ru>
parents:
444
diff
changeset
|
549 if (sslerr == SSL_ERROR_WANT_WRITE) { |
539 | 550 |
547 | 551 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
577 | 552 "peer started SSL renegotiation"); |
473 | 553 |
554 c->write->ready = 0; | |
555 | |
556 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { | |
557 return NGX_ERROR; | |
558 } | |
559 | |
560 /* | |
561 * we do not set the timer because there is already the read event timer | |
562 */ | |
563 | |
564 if (c->ssl->saved_write_handler == NULL) { | |
509 | 565 c->ssl->saved_write_handler = c->write->handler; |
566 c->write->handler = ngx_ssl_write_handler; | |
473 | 567 } |
568 | |
393
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
569 return NGX_AGAIN; |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
570 } |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
571 |
547 | 572 c->ssl->no_wait_shutdown = 1; |
573 c->ssl->no_send_shutdown = 1; | |
589 | 574 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
|
575 |
395
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
576 if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) { |
577 | 577 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, |
578 "peer shutdown SSL cleanly"); | |
579 return NGX_DONE; | |
393
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
580 } |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
581 |
591 | 582 c->read->error = 1; |
547 | 583 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
|
584 |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
585 return NGX_ERROR; |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
586 } |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
587 |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
588 |
489 | 589 static void |
590 ngx_ssl_write_handler(ngx_event_t *wev) | |
473 | 591 { |
592 ngx_connection_t *c; | |
593 | |
594 c = wev->data; | |
547 | 595 |
509 | 596 c->read->handler(c->read); |
473 | 597 } |
598 | |
599 | |
398
201b5f68b59f
nginx-0.0.7-2004-07-23-21:05:37 import
Igor Sysoev <igor@sysoev.ru>
parents:
397
diff
changeset
|
600 /* |
201b5f68b59f
nginx-0.0.7-2004-07-23-21:05:37 import
Igor Sysoev <igor@sysoev.ru>
parents:
397
diff
changeset
|
601 * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer |
473 | 602 * 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
|
603 * |
201b5f68b59f
nginx-0.0.7-2004-07-23-21:05:37 import
Igor Sysoev <igor@sysoev.ru>
parents:
397
diff
changeset
|
604 * 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
|
605 * 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
|
606 */ |
201b5f68b59f
nginx-0.0.7-2004-07-23-21:05:37 import
Igor Sysoev <igor@sysoev.ru>
parents:
397
diff
changeset
|
607 |
489 | 608 ngx_chain_t * |
609 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
|
610 { |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
611 int n; |
399
4e21d1291a14
nginx-0.0.7-2004-07-25-22:34:14 import
Igor Sysoev <igor@sysoev.ru>
parents:
398
diff
changeset
|
612 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
|
613 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
|
614 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
|
615 |
597 | 616 if (!c->ssl->buffer |
617 || (in && in->next == NULL && !(c->buffered & NGX_SSL_BUFFERED))) | |
618 { | |
395
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
619 |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
620 /* |
577 | 621 * we avoid a buffer copy if |
622 * we do not need to buffer the output | |
623 * 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
|
624 */ |
395
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
625 |
577 | 626 while (in) { |
627 if (ngx_buf_special(in->buf)) { | |
628 in = in->next; | |
629 continue; | |
630 } | |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
631 |
577 | 632 n = ngx_ssl_write(c, in->buf->pos, in->buf->last - in->buf->pos); |
633 | |
634 if (n == NGX_ERROR) { | |
635 return NGX_CHAIN_ERROR; | |
636 } | |
398
201b5f68b59f
nginx-0.0.7-2004-07-23-21:05:37 import
Igor Sysoev <igor@sysoev.ru>
parents:
397
diff
changeset
|
637 |
577 | 638 if (n == NGX_AGAIN) { |
597 | 639 c->buffered |= NGX_SSL_BUFFERED; |
577 | 640 return in; |
641 } | |
642 | |
643 in->buf->pos += n; | |
644 | |
645 if (in->buf->pos == in->buf->last) { | |
646 in = in->next; | |
647 } | |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
648 } |
395
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
649 |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
650 return in; |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
651 } |
395
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
652 |
473 | 653 |
654 /* the maximum limit size is the maximum uint32_t value - the page size */ | |
655 | |
656 if (limit == 0 || limit > NGX_MAX_UINT32_VALUE - ngx_pagesize) { | |
657 limit = NGX_MAX_UINT32_VALUE - ngx_pagesize; | |
658 } | |
659 | |
660 | |
577 | 661 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
|
662 send = 0; |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
663 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
|
664 |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
665 for ( ;; ) { |
395
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
666 |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
667 while (in && buf->last < buf->end) { |
583 | 668 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
|
669 flush = 1; |
395
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
670 } |
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 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
|
673 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
|
674 continue; |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
675 } |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
676 |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
677 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
|
678 |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
679 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
|
680 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
|
681 } |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
682 |
395
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
683 if (send + size > limit) { |
577 | 684 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
|
685 flush = 1; |
395
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
686 } |
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
687 |
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
688 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
|
689 "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
|
690 |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
691 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
|
692 |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
693 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
|
694 |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
695 in->buf->pos += size; |
577 | 696 |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
697 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
|
698 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
|
699 } |
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
700 } |
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
701 |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
702 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
|
703 |
398
201b5f68b59f
nginx-0.0.7-2004-07-23-21:05:37 import
Igor Sysoev <igor@sysoev.ru>
parents:
397
diff
changeset
|
704 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
|
705 break; |
201b5f68b59f
nginx-0.0.7-2004-07-23-21:05:37 import
Igor Sysoev <igor@sysoev.ru>
parents:
397
diff
changeset
|
706 } |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
707 |
398
201b5f68b59f
nginx-0.0.7-2004-07-23-21:05:37 import
Igor Sysoev <igor@sysoev.ru>
parents:
397
diff
changeset
|
708 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
|
709 |
201b5f68b59f
nginx-0.0.7-2004-07-23-21:05:37 import
Igor Sysoev <igor@sysoev.ru>
parents:
397
diff
changeset
|
710 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
|
711 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
|
712 } |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
713 |
511 | 714 if (n == NGX_AGAIN) { |
597 | 715 c->buffered |= NGX_SSL_BUFFERED; |
511 | 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 buf->pos += n; |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
720 send += n; |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
721 c->sent += n; |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
722 |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
723 if (n < size) { |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
724 break; |
395
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
725 } |
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
726 |
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
727 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
|
728 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
|
729 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
|
730 } |
395
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
731 |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
732 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
|
733 break; |
395
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
734 } |
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
735 } |
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
736 |
597 | 737 if (buf->pos < buf->last) { |
738 c->buffered |= NGX_SSL_BUFFERED; | |
739 | |
740 } else { | |
741 c->buffered &= ~NGX_SSL_BUFFERED; | |
742 } | |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
743 |
399
4e21d1291a14
nginx-0.0.7-2004-07-25-22:34:14 import
Igor Sysoev <igor@sysoev.ru>
parents:
398
diff
changeset
|
744 return in; |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
745 } |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
746 |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
747 |
539 | 748 ssize_t |
489 | 749 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
|
750 { |
547 | 751 int n, sslerr; |
752 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
|
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 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
|
755 |
543 | 756 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
|
757 |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
758 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
|
759 |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
760 if (n > 0) { |
539 | 761 |
473 | 762 if (c->ssl->saved_read_handler) { |
763 | |
509 | 764 c->read->handler = c->ssl->saved_read_handler; |
473 | 765 c->ssl->saved_read_handler = NULL; |
766 c->read->ready = 1; | |
767 | |
768 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { | |
769 return NGX_ERROR; | |
770 } | |
771 | |
563 | 772 ngx_post_event(c->read, &ngx_posted_events); |
473 | 773 } |
774 | |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
775 return n; |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
776 } |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
777 |
543 | 778 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
|
779 |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
780 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
|
781 |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
782 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
|
783 |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
784 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
|
785 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
|
786 return NGX_AGAIN; |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
787 } |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
788 |
445
f26432a1935a
nginx-0.1.0-2004-09-30-10:38:49 import
Igor Sysoev <igor@sysoev.ru>
parents:
444
diff
changeset
|
789 if (sslerr == SSL_ERROR_WANT_READ) { |
452 | 790 |
547 | 791 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
577 | 792 "peer started SSL renegotiation"); |
473 | 793 |
794 c->read->ready = 0; | |
795 | |
796 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { | |
797 return NGX_ERROR; | |
798 } | |
799 | |
800 /* | |
801 * we do not set the timer because there is already | |
802 * the write event timer | |
803 */ | |
804 | |
805 if (c->ssl->saved_read_handler == NULL) { | |
509 | 806 c->ssl->saved_read_handler = c->read->handler; |
807 c->read->handler = ngx_ssl_read_handler; | |
473 | 808 } |
809 | |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
810 return NGX_AGAIN; |
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
811 } |
395
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
812 |
547 | 813 c->ssl->no_wait_shutdown = 1; |
814 c->ssl->no_send_shutdown = 1; | |
591 | 815 c->write->error = 1; |
543 | 816 |
547 | 817 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
|
818 |
397
de797f3b4c27
nginx-0.0.7-2004-07-23-09:37:29 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
819 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
|
820 } |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
821 |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
822 |
489 | 823 static void |
824 ngx_ssl_read_handler(ngx_event_t *rev) | |
473 | 825 { |
826 ngx_connection_t *c; | |
827 | |
828 c = rev->data; | |
547 | 829 |
509 | 830 c->write->handler(c->write); |
473 | 831 } |
832 | |
833 | |
489 | 834 ngx_int_t |
835 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
|
836 { |
473 | 837 int n, sslerr, mode; |
591 | 838 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
|
839 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
|
840 |
577 | 841 if (c->timedout) { |
547 | 842 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
|
843 |
547 | 844 } else { |
845 mode = SSL_get_shutdown(c->ssl->connection); | |
473 | 846 |
547 | 847 if (c->ssl->no_wait_shutdown) { |
848 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
|
849 } |
6f3b20c1ac50
nginx-0.0.7-2004-07-18-23:11:20 import
Igor Sysoev <igor@sysoev.ru>
parents:
395
diff
changeset
|
850 |
547 | 851 if (c->ssl->no_send_shutdown) { |
852 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
|
853 } |
394
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
854 } |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
855 |
547 | 856 SSL_set_shutdown(c->ssl->connection, mode); |
857 | |
394
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
858 again = 0; |
461 | 859 sslerr = 0; |
394
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
860 |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
861 for ( ;; ) { |
543 | 862 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
|
863 |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
864 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
|
865 |
577 | 866 if (n == 1 || (n == 0 && c->timedout)) { |
543 | 867 SSL_free(c->ssl->connection); |
473 | 868 c->ssl = NULL; |
543 | 869 |
473 | 870 return NGX_OK; |
871 } | |
872 | |
394
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
873 if (n == 0) { |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
874 again = 1; |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
875 break; |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
876 } |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
877 |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
878 break; |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
879 } |
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 if (!again) { |
543 | 882 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
|
883 |
396
6f3b20c1ac50
nginx-0.0.7-2004-07-18-23:11:20 import
Igor Sysoev <igor@sysoev.ru>
parents:
395
diff
changeset
|
884 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
|
885 "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
|
886 } |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
887 |
589 | 888 if (again |
889 || sslerr == SSL_ERROR_WANT_READ | |
890 || sslerr == SSL_ERROR_WANT_WRITE) | |
891 { | |
577 | 892 c->read->handler = ngx_ssl_shutdown_handler; |
589 | 893 c->write->handler = ngx_ssl_shutdown_handler; |
577 | 894 |
394
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
895 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
|
896 return NGX_ERROR; |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
897 } |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
898 |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
899 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
|
900 return NGX_ERROR; |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
901 } |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
902 |
589 | 903 if (again || sslerr == SSL_ERROR_WANT_READ) { |
904 ngx_add_timer(c->read, 30000); | |
905 } | |
906 | |
394
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
907 return NGX_AGAIN; |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
908 } |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
909 |
591 | 910 err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0; |
911 | |
912 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
|
913 |
543 | 914 SSL_free(c->ssl->connection); |
915 c->ssl = NULL; | |
916 | |
394
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
917 return NGX_ERROR; |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
918 } |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
919 |
e7a68e14ccd3
nginx-0.0.7-2004-07-16-10:33:35 import
Igor Sysoev <igor@sysoev.ru>
parents:
393
diff
changeset
|
920 |
547 | 921 static void |
577 | 922 ngx_ssl_shutdown_handler(ngx_event_t *ev) |
923 { | |
924 ngx_connection_t *c; | |
925 ngx_connection_handler_pt handler; | |
926 | |
927 c = ev->data; | |
928 handler = c->ssl->handler; | |
929 | |
930 if (ev->timedout) { | |
931 c->timedout = 1; | |
932 } | |
933 | |
934 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, "SSL shutdown handler"); | |
935 | |
936 if (ngx_ssl_shutdown(c) == NGX_AGAIN) { | |
937 return; | |
938 } | |
939 | |
940 handler(c); | |
941 } | |
942 | |
943 | |
944 static void | |
547 | 945 ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err, |
946 char *text) | |
947 { | |
948 ngx_uint_t level; | |
949 | |
950 level = NGX_LOG_CRIT; | |
951 | |
952 if (sslerr == SSL_ERROR_SYSCALL) { | |
953 | |
954 if (err == NGX_ECONNRESET | |
955 || err == NGX_EPIPE | |
956 || err == NGX_ENOTCONN | |
589 | 957 #if !(NGX_CRIT_ETIMEDOUT) |
958 || err == NGX_ETIMEDOUT | |
959 #endif | |
547 | 960 || err == NGX_ECONNREFUSED |
961 || err == NGX_EHOSTUNREACH) | |
962 { | |
963 switch (c->log_error) { | |
964 | |
965 case NGX_ERROR_IGNORE_ECONNRESET: | |
966 case NGX_ERROR_INFO: | |
967 level = NGX_LOG_INFO; | |
968 break; | |
969 | |
970 case NGX_ERROR_ERR: | |
971 level = NGX_LOG_ERR; | |
972 break; | |
973 | |
974 default: | |
975 break; | |
976 } | |
977 } | |
978 } | |
979 | |
980 ngx_ssl_error(level, c->log, err, text); | |
981 } | |
982 | |
983 | |
583 | 984 void ngx_cdecl |
489 | 985 ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...) |
577 | 986 { |
547 | 987 u_long n; |
988 va_list args; | |
461 | 989 u_char errstr[NGX_MAX_CONF_ERRSTR], *p, *last; |
990 | |
991 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
|
992 |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
993 va_start(args, fmt); |
461 | 994 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
|
995 va_end(args); |
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
996 |
547 | 997 p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p); |
998 | |
583 | 999 while (p < last) { |
1000 | |
1001 n = ERR_get_error(); | |
1002 | |
1003 if (n == 0) { | |
1004 break; | |
1005 } | |
547 | 1006 |
1007 *p++ = ' '; | |
393
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
1008 |
547 | 1009 ERR_error_string_n(n, (char *) p, last - p); |
1010 | |
1011 while (p < last && *p) { | |
1012 p++; | |
1013 } | |
1014 } | |
393
5659d773cfa8
nginx-0.0.7-2004-07-15-20:35:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
1015 |
395
f8f0f1834266
nginx-0.0.7-2004-07-16-21:11:43 import
Igor Sysoev <igor@sysoev.ru>
parents:
394
diff
changeset
|
1016 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
|
1017 } |
509 | 1018 |
1019 | |
1020 void | |
1021 ngx_ssl_cleanup_ctx(void *data) | |
1022 { | |
589 | 1023 ngx_ssl_t *ssl = data; |
509 | 1024 |
589 | 1025 if (ssl->rsa512_key) { |
1026 RSA_free(ssl->rsa512_key); | |
1027 } | |
559 | 1028 |
589 | 1029 SSL_CTX_free(ssl->ctx); |
509 | 1030 } |
541 | 1031 |
1032 | |
611 | 1033 u_char * |
1034 ngx_ssl_get_protocol(ngx_connection_t *c) | |
1035 { | |
1036 return (u_char *) SSL_get_version(c->ssl->connection); | |
1037 } | |
1038 | |
1039 | |
1040 u_char * | |
1041 ngx_ssl_get_cipher_name(ngx_connection_t *c) | |
1042 { | |
1043 return (u_char *) SSL_get_cipher_name(c->ssl->connection); | |
1044 } | |
1045 | |
1046 | |
647 | 1047 ngx_int_t |
1048 ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) | |
1049 { | |
1050 char *p; | |
1051 size_t len; | |
1052 X509 *cert; | |
1053 X509_NAME *name; | |
1054 | |
1055 s->len = 0; | |
1056 | |
1057 cert = SSL_get_peer_certificate(c->ssl->connection); | |
1058 | |
1059 if (cert == NULL) { | |
1060 return NGX_OK; | |
1061 } | |
1062 | |
1063 name = X509_get_subject_name(cert); | |
1064 | |
1065 if (name == NULL) { | |
1066 return NGX_ERROR; | |
1067 } | |
1068 | |
1069 p = X509_NAME_oneline(name, NULL, 0); | |
1070 | |
1071 for (len = 0; p[len]; len++) { /* void */ } | |
1072 | |
1073 s->len = len; | |
1074 s->data = ngx_palloc(pool, len); | |
1075 if (s->data == NULL) { | |
1076 OPENSSL_free(p); | |
1077 return NGX_ERROR; | |
1078 } | |
1079 | |
1080 ngx_memcpy(s->data, p, len); | |
1081 | |
1082 OPENSSL_free(p); | |
1083 | |
1084 return NGX_OK; | |
1085 } | |
1086 | |
1087 | |
1088 ngx_int_t | |
1089 ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) | |
1090 { | |
1091 char *p; | |
1092 size_t len; | |
1093 X509 *cert; | |
1094 X509_NAME *name; | |
1095 | |
1096 s->len = 0; | |
1097 | |
1098 cert = SSL_get_peer_certificate(c->ssl->connection); | |
1099 | |
1100 if (cert == NULL) { | |
1101 return NGX_OK; | |
1102 } | |
1103 | |
1104 name = X509_get_issuer_name(cert); | |
1105 | |
1106 if (name == NULL) { | |
1107 return NGX_ERROR; | |
1108 } | |
1109 | |
1110 p = X509_NAME_oneline(name, NULL, 0); | |
1111 | |
1112 for (len = 0; p[len]; len++) { /* void */ } | |
1113 | |
1114 s->len = len; | |
1115 s->data = ngx_palloc(pool, len); | |
1116 if (s->data == NULL) { | |
1117 OPENSSL_free(p); | |
1118 return NGX_ERROR; | |
1119 } | |
1120 | |
1121 ngx_memcpy(s->data, p, len); | |
1122 | |
1123 OPENSSL_free(p); | |
1124 | |
1125 return NGX_OK; | |
1126 } | |
1127 | |
1128 | |
541 | 1129 static void * |
1130 ngx_openssl_create_conf(ngx_cycle_t *cycle) | |
1131 { | |
1132 ngx_openssl_conf_t *oscf; | |
577 | 1133 |
541 | 1134 oscf = ngx_pcalloc(cycle->pool, sizeof(ngx_openssl_conf_t)); |
1135 if (oscf == NULL) { | |
1136 return NGX_CONF_ERROR; | |
1137 } | |
577 | 1138 |
541 | 1139 /* |
1140 * set by ngx_pcalloc(): | |
577 | 1141 * |
541 | 1142 * oscf->engine.len = 0; |
1143 * oscf->engine.data = NULL; | |
577 | 1144 */ |
541 | 1145 |
1146 return oscf; | |
1147 } | |
1148 | |
1149 | |
1150 static char * | |
1151 ngx_openssl_init_conf(ngx_cycle_t *cycle, void *conf) | |
1152 { | |
1153 #if (NGX_SSL_ENGINE) | |
1154 ngx_openssl_conf_t *oscf = conf; | |
571 | 1155 |
541 | 1156 ENGINE *engine; |
1157 | |
1158 if (oscf->engine.len == 0) { | |
1159 return NGX_CONF_OK; | |
1160 } | |
577 | 1161 |
541 | 1162 engine = ENGINE_by_id((const char *) oscf->engine.data); |
1163 | |
1164 if (engine == NULL) { | |
1165 ngx_ssl_error(NGX_LOG_WARN, cycle->log, 0, | |
1166 "ENGINE_by_id(\"%V\") failed", &oscf->engine); | |
1167 return NGX_CONF_ERROR; | |
1168 } | |
1169 | |
1170 if (ENGINE_set_default(engine, ENGINE_METHOD_ALL) == 0) { | |
1171 ngx_ssl_error(NGX_LOG_WARN, cycle->log, 0, | |
1172 "ENGINE_set_default(\"%V\", ENGINE_METHOD_ALL) failed", | |
1173 &oscf->engine); | |
1174 return NGX_CONF_ERROR; | |
1175 } | |
1176 | |
1177 ENGINE_free(engine); | |
1178 | |
1179 #endif | |
1180 | |
1181 return NGX_CONF_OK; | |
1182 } | |
1183 | |
1184 | |
1185 #if !(NGX_SSL_ENGINE) | |
1186 | |
1187 static char * | |
1188 ngx_openssl_noengine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
1189 { | |
1190 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
563 | 1191 "\"ssl_engine\" directive is available only in " |
1192 "OpenSSL 0.9.7 and higher,"); | |
541 | 1193 |
1194 return NGX_CONF_ERROR; | |
1195 } | |
1196 | |
1197 #endif | |
571 | 1198 |
1199 | |
1200 static void | |
1201 ngx_openssl_exit(ngx_cycle_t *cycle) | |
1202 { | |
1203 #if (NGX_SSL_ENGINE) | |
1204 ENGINE_cleanup(); | |
1205 #endif | |
1206 } |