comparison src/stream/ngx_stream_ssl_module.c @ 6850:41cb1b64561d

Stream: client SSL certificates verification support. New directives: "ssl_verify_client", "ssl_verify_depth", "ssl_client_certificate", "ssl_trusted_certificate", and "ssl_crl". New variables: $ssl_client_cert, $ssl_client_raw_cert, $ssl_client_s_dn, $ssl_client_i_dn, $ssl_client_serial, $ssl_client_fingerprint, $ssl_client_verify, $ssl_client_v_start, $ssl_client_v_end, and $ssl_client_v_remain.
author Vladimir Homutov <vl@nginx.com>
date Tue, 20 Dec 2016 12:05:14 +0300
parents e75e854657ba
children 0a08a8babf53
comparison
equal deleted inserted replaced
6849:01adb18a5d23 6850:41cb1b64561d
47 { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, 47 { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
48 { ngx_null_string, 0 } 48 { ngx_null_string, 0 }
49 }; 49 };
50 50
51 51
52 static ngx_conf_enum_t ngx_stream_ssl_verify[] = {
53 { ngx_string("off"), 0 },
54 { ngx_string("on"), 1 },
55 { ngx_string("optional"), 2 },
56 { ngx_string("optional_no_ca"), 3 },
57 { ngx_null_string, 0 }
58 };
59
60
52 static ngx_command_t ngx_stream_ssl_commands[] = { 61 static ngx_command_t ngx_stream_ssl_commands[] = {
53 62
54 { ngx_string("ssl_handshake_timeout"), 63 { ngx_string("ssl_handshake_timeout"),
55 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 64 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
56 ngx_conf_set_msec_slot, 65 ngx_conf_set_msec_slot,
105 ngx_conf_set_str_slot, 114 ngx_conf_set_str_slot,
106 NGX_STREAM_SRV_CONF_OFFSET, 115 NGX_STREAM_SRV_CONF_OFFSET,
107 offsetof(ngx_stream_ssl_conf_t, ciphers), 116 offsetof(ngx_stream_ssl_conf_t, ciphers),
108 NULL }, 117 NULL },
109 118
119 { ngx_string("ssl_verify_client"),
120 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
121 ngx_conf_set_enum_slot,
122 NGX_STREAM_SRV_CONF_OFFSET,
123 offsetof(ngx_stream_ssl_conf_t, verify),
124 &ngx_stream_ssl_verify },
125
126 { ngx_string("ssl_verify_depth"),
127 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
128 ngx_conf_set_num_slot,
129 NGX_STREAM_SRV_CONF_OFFSET,
130 offsetof(ngx_stream_ssl_conf_t, verify_depth),
131 NULL },
132
133 { ngx_string("ssl_client_certificate"),
134 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
135 ngx_conf_set_str_slot,
136 NGX_STREAM_SRV_CONF_OFFSET,
137 offsetof(ngx_stream_ssl_conf_t, client_certificate),
138 NULL },
139
140 { ngx_string("ssl_trusted_certificate"),
141 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
142 ngx_conf_set_str_slot,
143 NGX_STREAM_SRV_CONF_OFFSET,
144 offsetof(ngx_stream_ssl_conf_t, trusted_certificate),
145 NULL },
146
110 { ngx_string("ssl_prefer_server_ciphers"), 147 { ngx_string("ssl_prefer_server_ciphers"),
111 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, 148 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
112 ngx_conf_set_flag_slot, 149 ngx_conf_set_flag_slot,
113 NGX_STREAM_SRV_CONF_OFFSET, 150 NGX_STREAM_SRV_CONF_OFFSET,
114 offsetof(ngx_stream_ssl_conf_t, prefer_server_ciphers), 151 offsetof(ngx_stream_ssl_conf_t, prefer_server_ciphers),
138 { ngx_string("ssl_session_timeout"), 175 { ngx_string("ssl_session_timeout"),
139 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 176 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
140 ngx_conf_set_sec_slot, 177 ngx_conf_set_sec_slot,
141 NGX_STREAM_SRV_CONF_OFFSET, 178 NGX_STREAM_SRV_CONF_OFFSET,
142 offsetof(ngx_stream_ssl_conf_t, session_timeout), 179 offsetof(ngx_stream_ssl_conf_t, session_timeout),
180 NULL },
181
182 { ngx_string("ssl_crl"),
183 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
184 ngx_conf_set_str_slot,
185 NGX_STREAM_SRV_CONF_OFFSET,
186 offsetof(ngx_stream_ssl_conf_t, crl),
143 NULL }, 187 NULL },
144 188
145 ngx_null_command 189 ngx_null_command
146 }; 190 };
147 191
195 (uintptr_t) ngx_ssl_get_session_reused, NGX_STREAM_VAR_CHANGEABLE, 0 }, 239 (uintptr_t) ngx_ssl_get_session_reused, NGX_STREAM_VAR_CHANGEABLE, 0 },
196 240
197 { ngx_string("ssl_server_name"), NULL, ngx_stream_ssl_variable, 241 { ngx_string("ssl_server_name"), NULL, ngx_stream_ssl_variable,
198 (uintptr_t) ngx_ssl_get_server_name, NGX_STREAM_VAR_CHANGEABLE, 0 }, 242 (uintptr_t) ngx_ssl_get_server_name, NGX_STREAM_VAR_CHANGEABLE, 0 },
199 243
244 { ngx_string("ssl_client_cert"), NULL, ngx_stream_ssl_variable,
245 (uintptr_t) ngx_ssl_get_certificate, NGX_STREAM_VAR_CHANGEABLE, 0 },
246
247 { ngx_string("ssl_client_raw_cert"), NULL, ngx_stream_ssl_variable,
248 (uintptr_t) ngx_ssl_get_raw_certificate,
249 NGX_STREAM_VAR_CHANGEABLE, 0 },
250
251 { ngx_string("ssl_client_s_dn"), NULL, ngx_stream_ssl_variable,
252 (uintptr_t) ngx_ssl_get_subject_dn, NGX_STREAM_VAR_CHANGEABLE, 0 },
253
254 { ngx_string("ssl_client_i_dn"), NULL, ngx_stream_ssl_variable,
255 (uintptr_t) ngx_ssl_get_issuer_dn, NGX_STREAM_VAR_CHANGEABLE, 0 },
256
257 { ngx_string("ssl_client_serial"), NULL, ngx_stream_ssl_variable,
258 (uintptr_t) ngx_ssl_get_serial_number, NGX_STREAM_VAR_CHANGEABLE, 0 },
259
260 { ngx_string("ssl_client_fingerprint"), NULL, ngx_stream_ssl_variable,
261 (uintptr_t) ngx_ssl_get_fingerprint, NGX_STREAM_VAR_CHANGEABLE, 0 },
262
263 { ngx_string("ssl_client_verify"), NULL, ngx_stream_ssl_variable,
264 (uintptr_t) ngx_ssl_get_client_verify, NGX_STREAM_VAR_CHANGEABLE, 0 },
265
266 { ngx_string("ssl_client_v_start"), NULL, ngx_stream_ssl_variable,
267 (uintptr_t) ngx_ssl_get_client_v_start, NGX_STREAM_VAR_CHANGEABLE, 0 },
268
269 { ngx_string("ssl_client_v_end"), NULL, ngx_stream_ssl_variable,
270 (uintptr_t) ngx_ssl_get_client_v_end, NGX_STREAM_VAR_CHANGEABLE, 0 },
271
272 { ngx_string("ssl_client_v_remain"), NULL, ngx_stream_ssl_variable,
273 (uintptr_t) ngx_ssl_get_client_v_remain, NGX_STREAM_VAR_CHANGEABLE, 0 },
274
200 { ngx_null_string, NULL, NULL, 0, 0, 0 } 275 { ngx_null_string, NULL, NULL, 0, 0, 0 }
201 }; 276 };
202 277
203 278
204 static ngx_str_t ngx_stream_ssl_sess_id_ctx = ngx_string("STREAM"); 279 static ngx_str_t ngx_stream_ssl_sess_id_ctx = ngx_string("STREAM");
205 280
206 281
207 static ngx_int_t 282 static ngx_int_t
208 ngx_stream_ssl_handler(ngx_stream_session_t *s) 283 ngx_stream_ssl_handler(ngx_stream_session_t *s)
209 { 284 {
285 long rc;
286 X509 *cert;
210 ngx_connection_t *c; 287 ngx_connection_t *c;
211 ngx_stream_ssl_conf_t *sslcf; 288 ngx_stream_ssl_conf_t *sslcf;
212 289
213 c = s->connection; 290 c = s->connection;
214 291
223 "in server listening on SSL port"); 300 "in server listening on SSL port");
224 return NGX_ERROR; 301 return NGX_ERROR;
225 } 302 }
226 303
227 return ngx_stream_ssl_init_connection(&sslcf->ssl, c); 304 return ngx_stream_ssl_init_connection(&sslcf->ssl, c);
305 }
306
307 if (sslcf->verify) {
308 rc = SSL_get_verify_result(c->ssl->connection);
309
310 if (rc != X509_V_OK
311 && (sslcf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
312 {
313 ngx_log_error(NGX_LOG_INFO, c->log, 0,
314 "client SSL certificate verify error: (%l:%s)",
315 rc, X509_verify_cert_error_string(rc));
316
317 ngx_ssl_remove_cached_session(sslcf->ssl.ctx,
318 (SSL_get0_session(c->ssl->connection)));
319 return NGX_ERROR;
320 }
321
322 if (sslcf->verify == 1) {
323 cert = SSL_get_peer_certificate(c->ssl->connection);
324
325 if (cert == NULL) {
326 ngx_log_error(NGX_LOG_INFO, c->log, 0,
327 "client sent no required SSL certificate");
328
329 ngx_ssl_remove_cached_session(sslcf->ssl.ctx,
330 (SSL_get0_session(c->ssl->connection)));
331 return NGX_ERROR;
332 }
333
334 X509_free(cert);
335 }
228 } 336 }
229 337
230 return NGX_OK; 338 return NGX_OK;
231 } 339 }
232 340
382 * set by ngx_pcalloc(): 490 * set by ngx_pcalloc():
383 * 491 *
384 * scf->protocols = 0; 492 * scf->protocols = 0;
385 * scf->dhparam = { 0, NULL }; 493 * scf->dhparam = { 0, NULL };
386 * scf->ecdh_curve = { 0, NULL }; 494 * scf->ecdh_curve = { 0, NULL };
495 * scf->client_certificate = { 0, NULL };
496 * scf->trusted_certificate = { 0, NULL };
497 * scf->crl = { 0, NULL };
387 * scf->ciphers = { 0, NULL }; 498 * scf->ciphers = { 0, NULL };
388 * scf->shm_zone = NULL; 499 * scf->shm_zone = NULL;
389 */ 500 */
390 501
391 scf->handshake_timeout = NGX_CONF_UNSET_MSEC; 502 scf->handshake_timeout = NGX_CONF_UNSET_MSEC;
392 scf->certificates = NGX_CONF_UNSET_PTR; 503 scf->certificates = NGX_CONF_UNSET_PTR;
393 scf->certificate_keys = NGX_CONF_UNSET_PTR; 504 scf->certificate_keys = NGX_CONF_UNSET_PTR;
394 scf->passwords = NGX_CONF_UNSET_PTR; 505 scf->passwords = NGX_CONF_UNSET_PTR;
395 scf->prefer_server_ciphers = NGX_CONF_UNSET; 506 scf->prefer_server_ciphers = NGX_CONF_UNSET;
507 scf->verify = NGX_CONF_UNSET_UINT;
508 scf->verify_depth = NGX_CONF_UNSET_UINT;
396 scf->builtin_session_cache = NGX_CONF_UNSET; 509 scf->builtin_session_cache = NGX_CONF_UNSET;
397 scf->session_timeout = NGX_CONF_UNSET; 510 scf->session_timeout = NGX_CONF_UNSET;
398 scf->session_tickets = NGX_CONF_UNSET; 511 scf->session_tickets = NGX_CONF_UNSET;
399 scf->session_ticket_keys = NGX_CONF_UNSET_PTR; 512 scf->session_ticket_keys = NGX_CONF_UNSET_PTR;
400 513
421 534
422 ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, 535 ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
423 (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 536 (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
424 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); 537 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
425 538
539 ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
540 ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);
541
426 ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL); 542 ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL);
427 ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys, 543 ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys,
428 NULL); 544 NULL);
429 545
430 ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); 546 ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL);
431 547
432 ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); 548 ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");
549
550 ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate,
551 "");
552 ngx_conf_merge_str_value(conf->trusted_certificate,
553 prev->trusted_certificate, "");
554 ngx_conf_merge_str_value(conf->crl, prev->crl, "");
433 555
434 ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, 556 ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,
435 NGX_DEFAULT_ECDH_CURVE); 557 NGX_DEFAULT_ECDH_CURVE);
436 558
437 ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); 559 ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
478 != NGX_OK) 600 != NGX_OK)
479 { 601 {
480 return NGX_CONF_ERROR; 602 return NGX_CONF_ERROR;
481 } 603 }
482 604
605 if (conf->verify) {
606
607 if (conf->client_certificate.len == 0 && conf->verify != 3) {
608 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
609 "no ssl_client_certificate for ssl_client_verify");
610 return NGX_CONF_ERROR;
611 }
612
613 if (ngx_ssl_client_certificate(cf, &conf->ssl,
614 &conf->client_certificate,
615 conf->verify_depth)
616 != NGX_OK)
617 {
618 return NGX_CONF_ERROR;
619 }
620
621 if (ngx_ssl_trusted_certificate(cf, &conf->ssl,
622 &conf->trusted_certificate,
623 conf->verify_depth)
624 != NGX_OK)
625 {
626 return NGX_CONF_ERROR;
627 }
628
629 if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) {
630 return NGX_CONF_ERROR;
631 }
632 }
633
483 if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { 634 if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
484 return NGX_CONF_ERROR; 635 return NGX_CONF_ERROR;
485 } 636 }
486 637
487 if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) { 638 if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) {