Mercurial > hg > nginx-quic
annotate src/event/ngx_event_openssl.c @ 668:9a9d671aa343
release-0.3.55 tag
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 28 Jul 2006 15:16:17 +0000 |
parents | 95d7da23ea53 |
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 } |