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