comparison src/mail/ngx_mail_ssl_module.c @ 5989:ec01b1d1fff1

Mail: client SSL certificates support. The "ssl_verify_client", "ssl_verify_depth", "ssl_client_certificate", "ssl_trusted_certificate", and "ssl_crl" directives introduced to control SSL client certificate verification in mail proxy module. If there is a certificate, detail of the certificate are passed to the auth_http script configured via Auth-SSL-Verify, Auth-SSL-Subject, Auth-SSL-Issuer, Auth-SSL-Serial, Auth-SSL-Fingerprint headers. If the auth_http_pass_client_cert directive is set, client certificate in PEM format will be passed in the Auth-SSL-Cert header (urlencoded). If there is no required certificate provided during an SSL handshake or certificate verification fails then a protocol-specific error is returned after the SSL handshake and the connection is closed. Based on previous work by Sven Peter, Franck Levionnois and Filipe Da Silva.
author Maxim Dounin <mdounin@mdounin.ru>
date Wed, 25 Feb 2015 17:48:05 +0300
parents 42114bf12da0
children a84267233877
comparison
equal deleted inserted replaced
5988:3b3f789655dc 5989:ec01b1d1fff1
44 { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, 44 { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
45 { ngx_null_string, 0 } 45 { ngx_null_string, 0 }
46 }; 46 };
47 47
48 48
49 static ngx_conf_enum_t ngx_mail_ssl_verify[] = {
50 { ngx_string("off"), 0 },
51 { ngx_string("on"), 1 },
52 { ngx_string("optional"), 2 },
53 { ngx_string("optional_no_ca"), 3 },
54 { ngx_null_string, 0 }
55 };
56
57
49 static ngx_command_t ngx_mail_ssl_commands[] = { 58 static ngx_command_t ngx_mail_ssl_commands[] = {
50 59
51 { ngx_string("ssl"), 60 { ngx_string("ssl"),
52 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, 61 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
53 ngx_mail_ssl_enable, 62 ngx_mail_ssl_enable,
142 { ngx_string("ssl_session_timeout"), 151 { ngx_string("ssl_session_timeout"),
143 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, 152 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
144 ngx_conf_set_sec_slot, 153 ngx_conf_set_sec_slot,
145 NGX_MAIL_SRV_CONF_OFFSET, 154 NGX_MAIL_SRV_CONF_OFFSET,
146 offsetof(ngx_mail_ssl_conf_t, session_timeout), 155 offsetof(ngx_mail_ssl_conf_t, session_timeout),
156 NULL },
157
158 { ngx_string("ssl_verify_client"),
159 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
160 ngx_conf_set_enum_slot,
161 NGX_MAIL_SRV_CONF_OFFSET,
162 offsetof(ngx_mail_ssl_conf_t, verify),
163 &ngx_mail_ssl_verify },
164
165 { ngx_string("ssl_verify_depth"),
166 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
167 ngx_conf_set_num_slot,
168 NGX_MAIL_SRV_CONF_OFFSET,
169 offsetof(ngx_mail_ssl_conf_t, verify_depth),
170 NULL },
171
172 { ngx_string("ssl_client_certificate"),
173 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
174 ngx_conf_set_str_slot,
175 NGX_MAIL_SRV_CONF_OFFSET,
176 offsetof(ngx_mail_ssl_conf_t, client_certificate),
177 NULL },
178
179 { ngx_string("ssl_trusted_certificate"),
180 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
181 ngx_conf_set_str_slot,
182 NGX_MAIL_SRV_CONF_OFFSET,
183 offsetof(ngx_mail_ssl_conf_t, trusted_certificate),
184 NULL },
185
186 { ngx_string("ssl_crl"),
187 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
188 ngx_conf_set_str_slot,
189 NGX_MAIL_SRV_CONF_OFFSET,
190 offsetof(ngx_mail_ssl_conf_t, crl),
147 NULL }, 191 NULL },
148 192
149 ngx_null_command 193 ngx_null_command
150 }; 194 };
151 195
196 * scf->protocols = 0; 240 * scf->protocols = 0;
197 * scf->certificate = { 0, NULL }; 241 * scf->certificate = { 0, NULL };
198 * scf->certificate_key = { 0, NULL }; 242 * scf->certificate_key = { 0, NULL };
199 * scf->dhparam = { 0, NULL }; 243 * scf->dhparam = { 0, NULL };
200 * scf->ecdh_curve = { 0, NULL }; 244 * scf->ecdh_curve = { 0, NULL };
245 * scf->client_certificate = { 0, NULL };
246 * scf->trusted_certificate = { 0, NULL };
247 * scf->crl = { 0, NULL };
201 * scf->ciphers = { 0, NULL }; 248 * scf->ciphers = { 0, NULL };
202 * scf->shm_zone = NULL; 249 * scf->shm_zone = NULL;
203 */ 250 */
204 251
205 scf->enable = NGX_CONF_UNSET; 252 scf->enable = NGX_CONF_UNSET;
206 scf->starttls = NGX_CONF_UNSET_UINT; 253 scf->starttls = NGX_CONF_UNSET_UINT;
207 scf->passwords = NGX_CONF_UNSET_PTR; 254 scf->passwords = NGX_CONF_UNSET_PTR;
208 scf->prefer_server_ciphers = NGX_CONF_UNSET; 255 scf->prefer_server_ciphers = NGX_CONF_UNSET;
256 scf->verify = NGX_CONF_UNSET_UINT;
257 scf->verify_depth = NGX_CONF_UNSET_UINT;
209 scf->builtin_session_cache = NGX_CONF_UNSET; 258 scf->builtin_session_cache = NGX_CONF_UNSET;
210 scf->session_timeout = NGX_CONF_UNSET; 259 scf->session_timeout = NGX_CONF_UNSET;
211 scf->session_tickets = NGX_CONF_UNSET; 260 scf->session_tickets = NGX_CONF_UNSET;
212 scf->session_ticket_keys = NGX_CONF_UNSET_PTR; 261 scf->session_ticket_keys = NGX_CONF_UNSET_PTR;
213 262
236 285
237 ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, 286 ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
238 (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1 287 (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1
239 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); 288 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
240 289
290 ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
291 ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);
292
241 ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); 293 ngx_conf_merge_str_value(conf->certificate, prev->certificate, "");
242 ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); 294 ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, "");
243 295
244 ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); 296 ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL);
245 297
246 ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); 298 ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");
247 299
248 ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, 300 ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,
249 NGX_DEFAULT_ECDH_CURVE); 301 NGX_DEFAULT_ECDH_CURVE);
302
303 ngx_conf_merge_str_value(conf->client_certificate,
304 prev->client_certificate, "");
305 ngx_conf_merge_str_value(conf->trusted_certificate,
306 prev->trusted_certificate, "");
307 ngx_conf_merge_str_value(conf->crl, prev->crl, "");
250 308
251 ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); 309 ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
252 310
253 311
254 conf->ssl.log = cf->log; 312 conf->ssl.log = cf->log;
316 if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, 374 if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate,
317 &conf->certificate_key, conf->passwords) 375 &conf->certificate_key, conf->passwords)
318 != NGX_OK) 376 != NGX_OK)
319 { 377 {
320 return NGX_CONF_ERROR; 378 return NGX_CONF_ERROR;
379 }
380
381 if (conf->verify) {
382
383 if (conf->client_certificate.len == 0 && conf->verify != 3) {
384 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
385 "no ssl_client_certificate for ssl_client_verify");
386 return NGX_CONF_ERROR;
387 }
388
389 if (ngx_ssl_client_certificate(cf, &conf->ssl,
390 &conf->client_certificate,
391 conf->verify_depth)
392 != NGX_OK)
393 {
394 return NGX_CONF_ERROR;
395 }
396
397 if (ngx_ssl_trusted_certificate(cf, &conf->ssl,
398 &conf->trusted_certificate,
399 conf->verify_depth)
400 != NGX_OK)
401 {
402 return NGX_CONF_ERROR;
403 }
404
405 if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) {
406 return NGX_CONF_ERROR;
407 }
321 } 408 }
322 409
323 if (SSL_CTX_set_cipher_list(conf->ssl.ctx, 410 if (SSL_CTX_set_cipher_list(conf->ssl.ctx,
324 (const char *) conf->ciphers.data) 411 (const char *) conf->ciphers.data)
325 == 0) 412 == 0)