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