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