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