1
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_stream.h>
11
12
13 typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
14 ngx_pool_t *pool, ngx_str_t *s);
15
16
17 #define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5"
18 #define NGX_DEFAULT_ECDH_CURVE "auto"
19
20
21 static ngx_int_t ngx_stream_ssl_handler(ngx_stream_session_t *s);
22 static ngx_int_t ngx_stream_ssl_init_connection(ngx_ssl_t *ssl,
23 ngx_connection_t *c);
24 static void ngx_stream_ssl_handshake_handler(ngx_connection_t *c);
25 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
26 int ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg);
27 #endif
28 #ifdef SSL_R_CERT_CB_ERROR
29 static int ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg);
30 #endif
31 static ngx_int_t ngx_stream_ssl_static_variable(ngx_stream_session_t *s,
32 ngx_stream_variable_value_t *v, uintptr_t data);
33 static ngx_int_t ngx_stream_ssl_variable(ngx_stream_session_t *s,
34 ngx_stream_variable_value_t *v, uintptr_t data);
35
36 static ngx_int_t ngx_stream_ssl_add_variables(ngx_conf_t *cf);
37 static void *ngx_stream_ssl_create_conf(ngx_conf_t *cf);
38 static char *ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent,
39 void *child);
40
41 static ngx_int_t ngx_stream_ssl_compile_certificates(ngx_conf_t *cf,
42 ngx_stream_ssl_conf_t *conf);
43
44 static char *ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
45 void *conf);
46 static char *ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
47 void *conf);
48
49 static char *ngx_stream_ssl_conf_command_check(ngx_conf_t *cf, void *post,
50 void *data);
51
52 static ngx_int_t ngx_stream_ssl_init(ngx_conf_t *cf);
53
54
55 static ngx_conf_bitmask_t ngx_stream_ssl_protocols[] = {
56 { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
57 { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
58 { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
59 { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
60 { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
61 { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 },
62 { ngx_null_string, 0 }
63 };
64
65
66 static ngx_conf_enum_t ngx_stream_ssl_verify[] = {
67 { ngx_string("off"), 0 },
68 { ngx_string("on"), 1 },
69 { ngx_string("optional"), 2 },
70 { ngx_string("optional_no_ca"), 3 },
71 { ngx_null_string, 0 }
72 };
73
74
75 static ngx_conf_post_t ngx_stream_ssl_conf_command_post =
76 { ngx_stream_ssl_conf_command_check };
77
78
79 static ngx_command_t ngx_stream_ssl_commands[] = {
80
81 { ngx_string("ssl_handshake_timeout"),
82 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
83 ngx_conf_set_msec_slot,
84 NGX_STREAM_SRV_CONF_OFFSET,
85 offsetof(ngx_stream_ssl_conf_t, handshake_timeout),
86 NULL },
87
88 { ngx_string("ssl_certificate"),
89 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
90 ngx_conf_set_str_array_slot,
91 NGX_STREAM_SRV_CONF_OFFSET,
92 offsetof(ngx_stream_ssl_conf_t, certificates),
93 NULL },
94
95 { ngx_string("ssl_certificate_key"),
96 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
97 ngx_conf_set_str_array_slot,
98 NGX_STREAM_SRV_CONF_OFFSET,
99 offsetof(ngx_stream_ssl_conf_t, certificate_keys),
100 NULL },
101
102 { ngx_string("ssl_password_file"),
103 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
104 ngx_stream_ssl_password_file,
105 NGX_STREAM_SRV_CONF_OFFSET,
106 0,
107 NULL },
108
109 { ngx_string("ssl_dhparam"),
110 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
111 ngx_conf_set_str_slot,
112 NGX_STREAM_SRV_CONF_OFFSET,
113 offsetof(ngx_stream_ssl_conf_t, dhparam),
114 NULL },
115
116 { ngx_string("ssl_ecdh_curve"),
117 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
118 ngx_conf_set_str_slot,
119 NGX_STREAM_SRV_CONF_OFFSET,
120 offsetof(ngx_stream_ssl_conf_t, ecdh_curve),
121 NULL },
122
123 { ngx_string("ssl_protocols"),
124 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
125 ngx_conf_set_bitmask_slot,
126 NGX_STREAM_SRV_CONF_OFFSET,
127 offsetof(ngx_stream_ssl_conf_t, protocols),
128 &ngx_stream_ssl_protocols },
129
130 { ngx_string("ssl_ciphers"),
131 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
132 ngx_conf_set_str_slot,
133 NGX_STREAM_SRV_CONF_OFFSET,
134 offsetof(ngx_stream_ssl_conf_t, ciphers),
135 NULL },
136
137 { ngx_string("ssl_verify_client"),
138 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
139 ngx_conf_set_enum_slot,
140 NGX_STREAM_SRV_CONF_OFFSET,
141 offsetof(ngx_stream_ssl_conf_t, verify),
142 &ngx_stream_ssl_verify },
143
144 { ngx_string("ssl_verify_depth"),
145 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
146 ngx_conf_set_num_slot,
147 NGX_STREAM_SRV_CONF_OFFSET,
148 offsetof(ngx_stream_ssl_conf_t, verify_depth),
149 NULL },
150
151 { ngx_string("ssl_client_certificate"),
152 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
153 ngx_conf_set_str_slot,
154 NGX_STREAM_SRV_CONF_OFFSET,
155 offsetof(ngx_stream_ssl_conf_t, client_certificate),
156 NULL },
157
158 { ngx_string("ssl_trusted_certificate"),
159 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
160 ngx_conf_set_str_slot,
161 NGX_STREAM_SRV_CONF_OFFSET,
162 offsetof(ngx_stream_ssl_conf_t, trusted_certificate),
163 NULL },
164
165 { ngx_string("ssl_prefer_server_ciphers"),
166 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
167 ngx_conf_set_flag_slot,
168 NGX_STREAM_SRV_CONF_OFFSET,
169 offsetof(ngx_stream_ssl_conf_t, prefer_server_ciphers),
170 NULL },
171
172 { ngx_string("ssl_session_cache"),
173 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE12,
174 ngx_stream_ssl_session_cache,
175 NGX_STREAM_SRV_CONF_OFFSET,
176 0,
177 NULL },
178
179 { ngx_string("ssl_session_tickets"),
180 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
181 ngx_conf_set_flag_slot,
182 NGX_STREAM_SRV_CONF_OFFSET,
183 offsetof(ngx_stream_ssl_conf_t, session_tickets),
184 NULL },
185
186 { ngx_string("ssl_session_ticket_key"),
187 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
188 ngx_conf_set_str_array_slot,
189 NGX_STREAM_SRV_CONF_OFFSET,
190 offsetof(ngx_stream_ssl_conf_t, session_ticket_keys),
191 NULL },
192
193 { ngx_string("ssl_session_timeout"),
194 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
195 ngx_conf_set_sec_slot,
196 NGX_STREAM_SRV_CONF_OFFSET,
197 offsetof(ngx_stream_ssl_conf_t, session_timeout),
198 NULL },
199
200 { ngx_string("ssl_crl"),
201 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
202 ngx_conf_set_str_slot,
203 NGX_STREAM_SRV_CONF_OFFSET,
204 offsetof(ngx_stream_ssl_conf_t, crl),
205 NULL },
206
207 { ngx_string("ssl_conf_command"),
208 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE2,
209 ngx_conf_set_keyval_slot,
210 NGX_STREAM_SRV_CONF_OFFSET,
211 offsetof(ngx_stream_ssl_conf_t, conf_commands),
212 &ngx_stream_ssl_conf_command_post },
213
214 ngx_null_command
215 };
216
217
218 static ngx_stream_module_t ngx_stream_ssl_module_ctx = {
219 ngx_stream_ssl_add_variables, /* preconfiguration */
220 ngx_stream_ssl_init, /* postconfiguration */
221
222 NULL, /* create main configuration */
223 NULL, /* init main configuration */
224
225 ngx_stream_ssl_create_conf, /* create server configuration */
226 ngx_stream_ssl_merge_conf /* merge server configuration */
227 };
228
229
230 ngx_module_t ngx_stream_ssl_module = {
231 NGX_MODULE_V1,
232 &ngx_stream_ssl_module_ctx, /* module context */
233 ngx_stream_ssl_commands, /* module directives */
234 NGX_STREAM_MODULE, /* module type */
235 NULL, /* init master */
236 NULL, /* init module */
237 NULL, /* init process */
238 NULL, /* init thread */
239 NULL, /* exit thread */
240 NULL, /* exit process */
241 NULL, /* exit master */
242 NGX_MODULE_V1_PADDING
243 };
244
245
246 static ngx_stream_variable_t ngx_stream_ssl_vars[] = {
247
248 { ngx_string("ssl_protocol"), NULL, ngx_stream_ssl_static_variable,
249 (uintptr_t) ngx_ssl_get_protocol, NGX_STREAM_VAR_CHANGEABLE, 0 },
250
251 { ngx_string("ssl_cipher"), NULL, ngx_stream_ssl_static_variable,
252 (uintptr_t) ngx_ssl_get_cipher_name, NGX_STREAM_VAR_CHANGEABLE, 0 },
253
254 { ngx_string("ssl_ciphers"), NULL, ngx_stream_ssl_variable,
255 (uintptr_t) ngx_ssl_get_ciphers, NGX_STREAM_VAR_CHANGEABLE, 0 },
256
257 { ngx_string("ssl_curves"), NULL, ngx_stream_ssl_variable,
258 (uintptr_t) ngx_ssl_get_curves, NGX_STREAM_VAR_CHANGEABLE, 0 },
259
260 { ngx_string("ssl_session_id"), NULL, ngx_stream_ssl_variable,
261 (uintptr_t) ngx_ssl_get_session_id, NGX_STREAM_VAR_CHANGEABLE, 0 },
262
263 { ngx_string("ssl_session_reused"), NULL, ngx_stream_ssl_variable,
264 (uintptr_t) ngx_ssl_get_session_reused, NGX_STREAM_VAR_CHANGEABLE, 0 },
265
266 { ngx_string("ssl_server_name"), NULL, ngx_stream_ssl_variable,
267 (uintptr_t) ngx_ssl_get_server_name, NGX_STREAM_VAR_CHANGEABLE, 0 },
268
269 { ngx_string("ssl_client_cert"), NULL, ngx_stream_ssl_variable,
270 (uintptr_t) ngx_ssl_get_certificate, NGX_STREAM_VAR_CHANGEABLE, 0 },
271
272 { ngx_string("ssl_client_raw_cert"), NULL, ngx_stream_ssl_variable,
273 (uintptr_t) ngx_ssl_get_raw_certificate,
274 NGX_STREAM_VAR_CHANGEABLE, 0 },
275
276 { ngx_string("ssl_client_escaped_cert"), NULL, ngx_stream_ssl_variable,
277 (uintptr_t) ngx_ssl_get_escaped_certificate,
278 NGX_STREAM_VAR_CHANGEABLE, 0 },
279
280 { ngx_string("ssl_client_s_dn"), NULL, ngx_stream_ssl_variable,
281 (uintptr_t) ngx_ssl_get_subject_dn, NGX_STREAM_VAR_CHANGEABLE, 0 },
282
283 { ngx_string("ssl_client_i_dn"), NULL, ngx_stream_ssl_variable,
284 (uintptr_t) ngx_ssl_get_issuer_dn, NGX_STREAM_VAR_CHANGEABLE, 0 },
285
286 { ngx_string("ssl_client_serial"), NULL, ngx_stream_ssl_variable,
287 (uintptr_t) ngx_ssl_get_serial_number, NGX_STREAM_VAR_CHANGEABLE, 0 },
288
289 { ngx_string("ssl_client_fingerprint"), NULL, ngx_stream_ssl_variable,
290 (uintptr_t) ngx_ssl_get_fingerprint, NGX_STREAM_VAR_CHANGEABLE, 0 },
291
292 { ngx_string("ssl_client_verify"), NULL, ngx_stream_ssl_variable,
293 (uintptr_t) ngx_ssl_get_client_verify, NGX_STREAM_VAR_CHANGEABLE, 0 },
294
295 { ngx_string("ssl_client_v_start"), NULL, ngx_stream_ssl_variable,
296 (uintptr_t) ngx_ssl_get_client_v_start, NGX_STREAM_VAR_CHANGEABLE, 0 },
297
298 { ngx_string("ssl_client_v_end"), NULL, ngx_stream_ssl_variable,
299 (uintptr_t) ngx_ssl_get_client_v_end, NGX_STREAM_VAR_CHANGEABLE, 0 },
300
301 { ngx_string("ssl_client_v_remain"), NULL, ngx_stream_ssl_variable,
302 (uintptr_t) ngx_ssl_get_client_v_remain, NGX_STREAM_VAR_CHANGEABLE, 0 },
303
304 ngx_stream_null_variable
305 };
306
307
308 static ngx_str_t ngx_stream_ssl_sess_id_ctx = ngx_string("STREAM");
309
310
311 static ngx_int_t
ngx_stream_ssl_handler(ngx_stream_session_t * s)312 ngx_stream_ssl_handler(ngx_stream_session_t *s)
313 {
314 long rc;
315 X509 *cert;
316 ngx_int_t rv;
317 ngx_connection_t *c;
318 ngx_stream_ssl_conf_t *sslcf;
319
320 if (!s->ssl) {
321 return NGX_OK;
322 }
323
324 c = s->connection;
325
326 sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
327
328 if (c->ssl == NULL) {
329 c->log->action = "SSL handshaking";
330
331 rv = ngx_stream_ssl_init_connection(&sslcf->ssl, c);
332
333 if (rv != NGX_OK) {
334 return rv;
335 }
336 }
337
338 if (sslcf->verify) {
339 rc = SSL_get_verify_result(c->ssl->connection);
340
341 if (rc != X509_V_OK
342 && (sslcf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
343 {
344 ngx_log_error(NGX_LOG_INFO, c->log, 0,
345 "client SSL certificate verify error: (%l:%s)",
346 rc, X509_verify_cert_error_string(rc));
347
348 ngx_ssl_remove_cached_session(c->ssl->session_ctx,
349 (SSL_get0_session(c->ssl->connection)));
350 return NGX_ERROR;
351 }
352
353 if (sslcf->verify == 1) {
354 cert = SSL_get_peer_certificate(c->ssl->connection);
355
356 if (cert == NULL) {
357 ngx_log_error(NGX_LOG_INFO, c->log, 0,
358 "client sent no required SSL certificate");
359
360 ngx_ssl_remove_cached_session(c->ssl->session_ctx,
361 (SSL_get0_session(c->ssl->connection)));
362 return NGX_ERROR;
363 }
364
365 X509_free(cert);
366 }
367 }
368
369 return NGX_OK;
370 }
371
372
373 static ngx_int_t
ngx_stream_ssl_init_connection(ngx_ssl_t * ssl,ngx_connection_t * c)374 ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c)
375 {
376 ngx_int_t rc;
377 ngx_stream_session_t *s;
378 ngx_stream_ssl_conf_t *sslcf;
379 ngx_stream_core_srv_conf_t *cscf;
380
381 s = c->data;
382
383 cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
384
385 if (cscf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) {
386 return NGX_ERROR;
387 }
388
389 if (ngx_ssl_create_connection(ssl, c, 0) != NGX_OK) {
390 return NGX_ERROR;
391 }
392
393 rc = ngx_ssl_handshake(c);
394
395 if (rc == NGX_ERROR) {
396 return NGX_ERROR;
397 }
398
399 if (rc == NGX_AGAIN) {
400 sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
401
402 ngx_add_timer(c->read, sslcf->handshake_timeout);
403
404 c->ssl->handler = ngx_stream_ssl_handshake_handler;
405
406 return NGX_AGAIN;
407 }
408
409 /* rc == NGX_OK */
410
411 return NGX_OK;
412 }
413
414
415 static void
ngx_stream_ssl_handshake_handler(ngx_connection_t * c)416 ngx_stream_ssl_handshake_handler(ngx_connection_t *c)
417 {
418 ngx_stream_session_t *s;
419
420 s = c->data;
421
422 if (!c->ssl->handshaked) {
423 ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
424 return;
425 }
426
427 if (c->read->timer_set) {
428 ngx_del_timer(c->read);
429 }
430
431 ngx_stream_core_run_phases(s);
432 }
433
434
435 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
436
437 int
ngx_stream_ssl_servername(ngx_ssl_conn_t * ssl_conn,int * ad,void * arg)438 ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
439 {
440 return SSL_TLSEXT_ERR_OK;
441 }
442
443 #endif
444
445
446 #ifdef SSL_R_CERT_CB_ERROR
447
448 int
ngx_stream_ssl_certificate(ngx_ssl_conn_t * ssl_conn,void * arg)449 ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg)
450 {
451 ngx_str_t cert, key;
452 ngx_uint_t i, nelts;
453 ngx_connection_t *c;
454 ngx_stream_session_t *s;
455 ngx_stream_ssl_conf_t *sslcf;
456 ngx_stream_complex_value_t *certs, *keys;
457
458 c = ngx_ssl_get_connection(ssl_conn);
459
460 if (c->ssl->handshaked) {
461 return 0;
462 }
463
464 s = c->data;
465
466 sslcf = arg;
467
468 nelts = sslcf->certificate_values->nelts;
469 certs = sslcf->certificate_values->elts;
470 keys = sslcf->certificate_key_values->elts;
471
472 for (i = 0; i < nelts; i++) {
473
474 if (ngx_stream_complex_value(s, &certs[i], &cert) != NGX_OK) {
475 return 0;
476 }
477
478 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
479 "ssl cert: \"%s\"", cert.data);
480
481 if (ngx_stream_complex_value(s, &keys[i], &key) != NGX_OK) {
482 return 0;
483 }
484
485 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
486 "ssl key: \"%s\"", key.data);
487
488 if (ngx_ssl_connection_certificate(c, c->pool, &cert, &key,
489 sslcf->passwords)
490 != NGX_OK)
491 {
492 return 0;
493 }
494 }
495
496 return 1;
497 }
498
499 #endif
500
501
502 static ngx_int_t
ngx_stream_ssl_static_variable(ngx_stream_session_t * s,ngx_stream_variable_value_t * v,uintptr_t data)503 ngx_stream_ssl_static_variable(ngx_stream_session_t *s,
504 ngx_stream_variable_value_t *v, uintptr_t data)
505 {
506 ngx_ssl_variable_handler_pt handler = (ngx_ssl_variable_handler_pt) data;
507
508 size_t len;
509 ngx_str_t str;
510
511 if (s->connection->ssl) {
512
513 (void) handler(s->connection, NULL, &str);
514
515 v->data = str.data;
516
517 for (len = 0; v->data[len]; len++) { /* void */ }
518
519 v->len = len;
520 v->valid = 1;
521 v->no_cacheable = 0;
522 v->not_found = 0;
523
524 return NGX_OK;
525 }
526
527 v->not_found = 1;
528
529 return NGX_OK;
530 }
531
532
533 static ngx_int_t
ngx_stream_ssl_variable(ngx_stream_session_t * s,ngx_stream_variable_value_t * v,uintptr_t data)534 ngx_stream_ssl_variable(ngx_stream_session_t *s,
535 ngx_stream_variable_value_t *v, uintptr_t data)
536 {
537 ngx_ssl_variable_handler_pt handler = (ngx_ssl_variable_handler_pt) data;
538
539 ngx_str_t str;
540
541 if (s->connection->ssl) {
542
543 if (handler(s->connection, s->connection->pool, &str) != NGX_OK) {
544 return NGX_ERROR;
545 }
546
547 v->len = str.len;
548 v->data = str.data;
549
550 if (v->len) {
551 v->valid = 1;
552 v->no_cacheable = 0;
553 v->not_found = 0;
554
555 return NGX_OK;
556 }
557 }
558
559 v->not_found = 1;
560
561 return NGX_OK;
562 }
563
564
565 static ngx_int_t
ngx_stream_ssl_add_variables(ngx_conf_t * cf)566 ngx_stream_ssl_add_variables(ngx_conf_t *cf)
567 {
568 ngx_stream_variable_t *var, *v;
569
570 for (v = ngx_stream_ssl_vars; v->name.len; v++) {
571 var = ngx_stream_add_variable(cf, &v->name, v->flags);
572 if (var == NULL) {
573 return NGX_ERROR;
574 }
575
576 var->get_handler = v->get_handler;
577 var->data = v->data;
578 }
579
580 return NGX_OK;
581 }
582
583
584 static void *
ngx_stream_ssl_create_conf(ngx_conf_t * cf)585 ngx_stream_ssl_create_conf(ngx_conf_t *cf)
586 {
587 ngx_stream_ssl_conf_t *scf;
588
589 scf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_ssl_conf_t));
590 if (scf == NULL) {
591 return NULL;
592 }
593
594 /*
595 * set by ngx_pcalloc():
596 *
597 * scf->listen = 0;
598 * scf->protocols = 0;
599 * scf->certificate_values = NULL;
600 * scf->dhparam = { 0, NULL };
601 * scf->ecdh_curve = { 0, NULL };
602 * scf->client_certificate = { 0, NULL };
603 * scf->trusted_certificate = { 0, NULL };
604 * scf->crl = { 0, NULL };
605 * scf->ciphers = { 0, NULL };
606 * scf->shm_zone = NULL;
607 */
608
609 scf->handshake_timeout = NGX_CONF_UNSET_MSEC;
610 scf->certificates = NGX_CONF_UNSET_PTR;
611 scf->certificate_keys = NGX_CONF_UNSET_PTR;
612 scf->passwords = NGX_CONF_UNSET_PTR;
613 scf->conf_commands = NGX_CONF_UNSET_PTR;
614 scf->prefer_server_ciphers = NGX_CONF_UNSET;
615 scf->verify = NGX_CONF_UNSET_UINT;
616 scf->verify_depth = NGX_CONF_UNSET_UINT;
617 scf->builtin_session_cache = NGX_CONF_UNSET;
618 scf->session_timeout = NGX_CONF_UNSET;
619 scf->session_tickets = NGX_CONF_UNSET;
620 scf->session_ticket_keys = NGX_CONF_UNSET_PTR;
621
622 return scf;
623 }
624
625
626 static char *
ngx_stream_ssl_merge_conf(ngx_conf_t * cf,void * parent,void * child)627 ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
628 {
629 ngx_stream_ssl_conf_t *prev = parent;
630 ngx_stream_ssl_conf_t *conf = child;
631
632 ngx_pool_cleanup_t *cln;
633
634 ngx_conf_merge_msec_value(conf->handshake_timeout,
635 prev->handshake_timeout, 60000);
636
637 ngx_conf_merge_value(conf->session_timeout,
638 prev->session_timeout, 300);
639
640 ngx_conf_merge_value(conf->prefer_server_ciphers,
641 prev->prefer_server_ciphers, 0);
642
643 ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
644 (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
645 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
646
647 ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
648 ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);
649
650 ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL);
651 ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys,
652 NULL);
653
654 ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL);
655
656 ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");
657
658 ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate,
659 "");
660 ngx_conf_merge_str_value(conf->trusted_certificate,
661 prev->trusted_certificate, "");
662 ngx_conf_merge_str_value(conf->crl, prev->crl, "");
663
664 ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,
665 NGX_DEFAULT_ECDH_CURVE);
666
667 ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
668
669 ngx_conf_merge_ptr_value(conf->conf_commands, prev->conf_commands, NULL);
670
671
672 conf->ssl.log = cf->log;
673
674 if (!conf->listen) {
675 return NGX_CONF_OK;
676 }
677
678 if (conf->certificates == NULL) {
679 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
680 "no \"ssl_certificate\" is defined for "
681 "the \"listen ... ssl\" directive in %s:%ui",
682 conf->file, conf->line);
683 return NGX_CONF_ERROR;
684 }
685
686 if (conf->certificate_keys == NULL) {
687 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
688 "no \"ssl_certificate_key\" is defined for "
689 "the \"listen ... ssl\" directive in %s:%ui",
690 conf->file, conf->line);
691 return NGX_CONF_ERROR;
692 }
693
694 if (conf->certificate_keys->nelts < conf->certificates->nelts) {
695 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
696 "no \"ssl_certificate_key\" is defined "
697 "for certificate \"%V\" and "
698 "the \"listen ... ssl\" directive in %s:%ui",
699 ((ngx_str_t *) conf->certificates->elts)
700 + conf->certificates->nelts - 1,
701 conf->file, conf->line);
702 return NGX_CONF_ERROR;
703 }
704
705 if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) {
706 return NGX_CONF_ERROR;
707 }
708
709 cln = ngx_pool_cleanup_add(cf->pool, 0);
710 if (cln == NULL) {
711 ngx_ssl_cleanup_ctx(&conf->ssl);
712 return NGX_CONF_ERROR;
713 }
714
715 cln->handler = ngx_ssl_cleanup_ctx;
716 cln->data = &conf->ssl;
717
718 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
719 SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
720 ngx_stream_ssl_servername);
721 #endif
722
723 if (ngx_stream_ssl_compile_certificates(cf, conf) != NGX_OK) {
724 return NGX_CONF_ERROR;
725 }
726
727 if (conf->certificate_values) {
728
729 #ifdef SSL_R_CERT_CB_ERROR
730
731 /* install callback to lookup certificates */
732
733 SSL_CTX_set_cert_cb(conf->ssl.ctx, ngx_stream_ssl_certificate, conf);
734
735 #else
736 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
737 "variables in "
738 "\"ssl_certificate\" and \"ssl_certificate_key\" "
739 "directives are not supported on this platform");
740 return NGX_CONF_ERROR;
741 #endif
742
743 } else {
744
745 /* configure certificates */
746
747 if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
748 conf->certificate_keys, conf->passwords)
749 != NGX_OK)
750 {
751 return NGX_CONF_ERROR;
752 }
753 }
754
755 if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
756 conf->prefer_server_ciphers)
757 != NGX_OK)
758 {
759 return NGX_CONF_ERROR;
760 }
761
762 if (conf->verify) {
763
764 if (conf->client_certificate.len == 0 && conf->verify != 3) {
765 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
766 "no ssl_client_certificate for ssl_verify_client");
767 return NGX_CONF_ERROR;
768 }
769
770 if (ngx_ssl_client_certificate(cf, &conf->ssl,
771 &conf->client_certificate,
772 conf->verify_depth)
773 != NGX_OK)
774 {
775 return NGX_CONF_ERROR;
776 }
777
778 if (ngx_ssl_trusted_certificate(cf, &conf->ssl,
779 &conf->trusted_certificate,
780 conf->verify_depth)
781 != NGX_OK)
782 {
783 return NGX_CONF_ERROR;
784 }
785
786 if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) {
787 return NGX_CONF_ERROR;
788 }
789 }
790
791 if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
792 return NGX_CONF_ERROR;
793 }
794
795 if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) {
796 return NGX_CONF_ERROR;
797 }
798
799 ngx_conf_merge_value(conf->builtin_session_cache,
800 prev->builtin_session_cache, NGX_SSL_NONE_SCACHE);
801
802 if (conf->shm_zone == NULL) {
803 conf->shm_zone = prev->shm_zone;
804 }
805
806 if (ngx_ssl_session_cache(&conf->ssl, &ngx_stream_ssl_sess_id_ctx,
807 conf->certificates, conf->builtin_session_cache,
808 conf->shm_zone, conf->session_timeout)
809 != NGX_OK)
810 {
811 return NGX_CONF_ERROR;
812 }
813
814 ngx_conf_merge_value(conf->session_tickets,
815 prev->session_tickets, 1);
816
817 #ifdef SSL_OP_NO_TICKET
818 if (!conf->session_tickets) {
819 SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET);
820 }
821 #endif
822
823 ngx_conf_merge_ptr_value(conf->session_ticket_keys,
824 prev->session_ticket_keys, NULL);
825
826 if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys)
827 != NGX_OK)
828 {
829 return NGX_CONF_ERROR;
830 }
831
832 if (ngx_ssl_conf_commands(cf, &conf->ssl, conf->conf_commands) != NGX_OK) {
833 return NGX_CONF_ERROR;
834 }
835
836 return NGX_CONF_OK;
837 }
838
839
840 static ngx_int_t
ngx_stream_ssl_compile_certificates(ngx_conf_t * cf,ngx_stream_ssl_conf_t * conf)841 ngx_stream_ssl_compile_certificates(ngx_conf_t *cf,
842 ngx_stream_ssl_conf_t *conf)
843 {
844 ngx_str_t *cert, *key;
845 ngx_uint_t i, nelts;
846 ngx_stream_complex_value_t *cv;
847 ngx_stream_compile_complex_value_t ccv;
848
849 cert = conf->certificates->elts;
850 key = conf->certificate_keys->elts;
851 nelts = conf->certificates->nelts;
852
853 for (i = 0; i < nelts; i++) {
854
855 if (ngx_stream_script_variables_count(&cert[i])) {
856 goto found;
857 }
858
859 if (ngx_stream_script_variables_count(&key[i])) {
860 goto found;
861 }
862 }
863
864 return NGX_OK;
865
866 found:
867
868 conf->certificate_values = ngx_array_create(cf->pool, nelts,
869 sizeof(ngx_stream_complex_value_t));
870 if (conf->certificate_values == NULL) {
871 return NGX_ERROR;
872 }
873
874 conf->certificate_key_values = ngx_array_create(cf->pool, nelts,
875 sizeof(ngx_stream_complex_value_t));
876 if (conf->certificate_key_values == NULL) {
877 return NGX_ERROR;
878 }
879
880 for (i = 0; i < nelts; i++) {
881
882 cv = ngx_array_push(conf->certificate_values);
883 if (cv == NULL) {
884 return NGX_ERROR;
885 }
886
887 ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t));
888
889 ccv.cf = cf;
890 ccv.value = &cert[i];
891 ccv.complex_value = cv;
892 ccv.zero = 1;
893
894 if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
895 return NGX_ERROR;
896 }
897
898 cv = ngx_array_push(conf->certificate_key_values);
899 if (cv == NULL) {
900 return NGX_ERROR;
901 }
902
903 ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t));
904
905 ccv.cf = cf;
906 ccv.value = &key[i];
907 ccv.complex_value = cv;
908 ccv.zero = 1;
909
910 if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
911 return NGX_ERROR;
912 }
913 }
914
915 conf->passwords = ngx_ssl_preserve_passwords(cf, conf->passwords);
916 if (conf->passwords == NULL) {
917 return NGX_ERROR;
918 }
919
920 return NGX_OK;
921 }
922
923
924 static char *
ngx_stream_ssl_password_file(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)925 ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
926 {
927 ngx_stream_ssl_conf_t *scf = conf;
928
929 ngx_str_t *value;
930
931 if (scf->passwords != NGX_CONF_UNSET_PTR) {
932 return "is duplicate";
933 }
934
935 value = cf->args->elts;
936
937 scf->passwords = ngx_ssl_read_password_file(cf, &value[1]);
938
939 if (scf->passwords == NULL) {
940 return NGX_CONF_ERROR;
941 }
942
943 return NGX_CONF_OK;
944 }
945
946
947 static char *
ngx_stream_ssl_session_cache(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)948 ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
949 {
950 ngx_stream_ssl_conf_t *scf = conf;
951
952 size_t len;
953 ngx_str_t *value, name, size;
954 ngx_int_t n;
955 ngx_uint_t i, j;
956
957 value = cf->args->elts;
958
959 for (i = 1; i < cf->args->nelts; i++) {
960
961 if (ngx_strcmp(value[i].data, "off") == 0) {
962 scf->builtin_session_cache = NGX_SSL_NO_SCACHE;
963 continue;
964 }
965
966 if (ngx_strcmp(value[i].data, "none") == 0) {
967 scf->builtin_session_cache = NGX_SSL_NONE_SCACHE;
968 continue;
969 }
970
971 if (ngx_strcmp(value[i].data, "builtin") == 0) {
972 scf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE;
973 continue;
974 }
975
976 if (value[i].len > sizeof("builtin:") - 1
977 && ngx_strncmp(value[i].data, "builtin:", sizeof("builtin:") - 1)
978 == 0)
979 {
980 n = ngx_atoi(value[i].data + sizeof("builtin:") - 1,
981 value[i].len - (sizeof("builtin:") - 1));
982
983 if (n == NGX_ERROR) {
984 goto invalid;
985 }
986
987 scf->builtin_session_cache = n;
988
989 continue;
990 }
991
992 if (value[i].len > sizeof("shared:") - 1
993 && ngx_strncmp(value[i].data, "shared:", sizeof("shared:") - 1)
994 == 0)
995 {
996 len = 0;
997
998 for (j = sizeof("shared:") - 1; j < value[i].len; j++) {
999 if (value[i].data[j] == ':') {
1000 break;
1001 }
1002
1003 len++;
1004 }
1005
1006 if (len == 0) {
1007 goto invalid;
1008 }
1009
1010 name.len = len;
1011 name.data = value[i].data + sizeof("shared:") - 1;
1012
1013 size.len = value[i].len - j - 1;
1014 size.data = name.data + len + 1;
1015
1016 n = ngx_parse_size(&size);
1017
1018 if (n == NGX_ERROR) {
1019 goto invalid;
1020 }
1021
1022 if (n < (ngx_int_t) (8 * ngx_pagesize)) {
1023 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1024 "session cache \"%V\" is too small",
1025 &value[i]);
1026
1027 return NGX_CONF_ERROR;
1028 }
1029
1030 scf->shm_zone = ngx_shared_memory_add(cf, &name, n,
1031 &ngx_stream_ssl_module);
1032 if (scf->shm_zone == NULL) {
1033 return NGX_CONF_ERROR;
1034 }
1035
1036 scf->shm_zone->init = ngx_ssl_session_cache_init;
1037
1038 continue;
1039 }
1040
1041 goto invalid;
1042 }
1043
1044 if (scf->shm_zone && scf->builtin_session_cache == NGX_CONF_UNSET) {
1045 scf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
1046 }
1047
1048 return NGX_CONF_OK;
1049
1050 invalid:
1051
1052 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1053 "invalid session cache \"%V\"", &value[i]);
1054
1055 return NGX_CONF_ERROR;
1056 }
1057
1058
1059 static char *
ngx_stream_ssl_conf_command_check(ngx_conf_t * cf,void * post,void * data)1060 ngx_stream_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
1061 {
1062 #ifndef SSL_CONF_FLAG_FILE
1063 return "is not supported on this platform";
1064 #else
1065 return NGX_CONF_OK;
1066 #endif
1067 }
1068
1069
1070 static ngx_int_t
ngx_stream_ssl_init(ngx_conf_t * cf)1071 ngx_stream_ssl_init(ngx_conf_t *cf)
1072 {
1073 ngx_stream_handler_pt *h;
1074 ngx_stream_core_main_conf_t *cmcf;
1075
1076 cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
1077
1078 h = ngx_array_push(&cmcf->phases[NGX_STREAM_SSL_PHASE].handlers);
1079 if (h == NULL) {
1080 return NGX_ERROR;
1081 }
1082
1083 *h = ngx_stream_ssl_handler;
1084
1085 return NGX_OK;
1086 }
1087