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