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