Mercurial > hg > nginx
comparison src/mail/ngx_mail_auth_http_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 | 3b3f789655dc |
children | 6a7c6973d6fc |
comparison
equal
deleted
inserted
replaced
5988:3b3f789655dc | 5989:ec01b1d1fff1 |
---|---|
14 | 14 |
15 typedef struct { | 15 typedef struct { |
16 ngx_addr_t *peer; | 16 ngx_addr_t *peer; |
17 | 17 |
18 ngx_msec_t timeout; | 18 ngx_msec_t timeout; |
19 ngx_flag_t pass_client_cert; | |
19 | 20 |
20 ngx_str_t host_header; | 21 ngx_str_t host_header; |
21 ngx_str_t uri; | 22 ngx_str_t uri; |
22 ngx_str_t header; | 23 ngx_str_t header; |
23 | 24 |
104 ngx_mail_auth_http_header, | 105 ngx_mail_auth_http_header, |
105 NGX_MAIL_SRV_CONF_OFFSET, | 106 NGX_MAIL_SRV_CONF_OFFSET, |
106 0, | 107 0, |
107 NULL }, | 108 NULL }, |
108 | 109 |
110 { ngx_string("auth_http_pass_client_cert"), | |
111 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, | |
112 ngx_conf_set_flag_slot, | |
113 NGX_MAIL_SRV_CONF_OFFSET, | |
114 offsetof(ngx_mail_auth_http_conf_t, pass_client_cert), | |
115 NULL }, | |
116 | |
109 ngx_null_command | 117 ngx_null_command |
110 }; | 118 }; |
111 | 119 |
112 | 120 |
113 static ngx_mail_module_t ngx_mail_auth_http_module_ctx = { | 121 static ngx_mail_module_t ngx_mail_auth_http_module_ctx = { |
1141 ngx_mail_auth_http_conf_t *ahcf) | 1149 ngx_mail_auth_http_conf_t *ahcf) |
1142 { | 1150 { |
1143 size_t len; | 1151 size_t len; |
1144 ngx_buf_t *b; | 1152 ngx_buf_t *b; |
1145 ngx_str_t login, passwd; | 1153 ngx_str_t login, passwd; |
1154 #if (NGX_MAIL_SSL) | |
1155 ngx_str_t verify, subject, issuer, serial, fingerprint, | |
1156 raw_cert, cert; | |
1157 ngx_connection_t *c; | |
1158 #endif | |
1146 ngx_mail_core_srv_conf_t *cscf; | 1159 ngx_mail_core_srv_conf_t *cscf; |
1147 | 1160 |
1148 if (ngx_mail_auth_http_escape(pool, &s->login, &login) != NGX_OK) { | 1161 if (ngx_mail_auth_http_escape(pool, &s->login, &login) != NGX_OK) { |
1149 return NULL; | 1162 return NULL; |
1150 } | 1163 } |
1151 | 1164 |
1152 if (ngx_mail_auth_http_escape(pool, &s->passwd, &passwd) != NGX_OK) { | 1165 if (ngx_mail_auth_http_escape(pool, &s->passwd, &passwd) != NGX_OK) { |
1153 return NULL; | 1166 return NULL; |
1154 } | 1167 } |
1168 | |
1169 #if (NGX_MAIL_SSL) | |
1170 | |
1171 c = s->connection; | |
1172 | |
1173 if (c->ssl) { | |
1174 | |
1175 /* certificate details */ | |
1176 | |
1177 if (ngx_ssl_get_client_verify(c, pool, &verify) != NGX_OK) { | |
1178 return NULL; | |
1179 } | |
1180 | |
1181 if (ngx_ssl_get_subject_dn(c, pool, &subject) != NGX_OK) { | |
1182 return NULL; | |
1183 } | |
1184 | |
1185 if (ngx_ssl_get_issuer_dn(c, pool, &issuer) != NGX_OK) { | |
1186 return NULL; | |
1187 } | |
1188 | |
1189 if (ngx_ssl_get_serial_number(c, pool, &serial) != NGX_OK) { | |
1190 return NULL; | |
1191 } | |
1192 | |
1193 if (ngx_ssl_get_fingerprint(c, pool, &fingerprint) != NGX_OK) { | |
1194 return NULL; | |
1195 } | |
1196 | |
1197 if (ahcf->pass_client_cert) { | |
1198 | |
1199 /* certificate itself, if configured */ | |
1200 | |
1201 if (ngx_ssl_get_raw_certificate(c, pool, &raw_cert) != NGX_OK) { | |
1202 return NULL; | |
1203 } | |
1204 | |
1205 if (ngx_mail_auth_http_escape(pool, &raw_cert, &cert) != NGX_OK) { | |
1206 return NULL; | |
1207 } | |
1208 | |
1209 } else { | |
1210 ngx_str_null(&cert); | |
1211 } | |
1212 | |
1213 } else { | |
1214 ngx_str_null(&verify); | |
1215 ngx_str_null(&subject); | |
1216 ngx_str_null(&issuer); | |
1217 ngx_str_null(&serial); | |
1218 ngx_str_null(&fingerprint); | |
1219 ngx_str_null(&cert); | |
1220 } | |
1221 | |
1222 #endif | |
1155 | 1223 |
1156 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); | 1224 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); |
1157 | 1225 |
1158 len = sizeof("GET ") - 1 + ahcf->uri.len + sizeof(" HTTP/1.0" CRLF) - 1 | 1226 len = sizeof("GET ") - 1 + ahcf->uri.len + sizeof(" HTTP/1.0" CRLF) - 1 |
1159 + sizeof("Host: ") - 1 + ahcf->host_header.len + sizeof(CRLF) - 1 | 1227 + sizeof("Host: ") - 1 + ahcf->host_header.len + sizeof(CRLF) - 1 |
1173 + sizeof("Auth-SMTP-Helo: ") - 1 + s->smtp_helo.len + sizeof(CRLF) - 1 | 1241 + sizeof("Auth-SMTP-Helo: ") - 1 + s->smtp_helo.len + sizeof(CRLF) - 1 |
1174 + sizeof("Auth-SMTP-From: ") - 1 + s->smtp_from.len + sizeof(CRLF) - 1 | 1242 + sizeof("Auth-SMTP-From: ") - 1 + s->smtp_from.len + sizeof(CRLF) - 1 |
1175 + sizeof("Auth-SMTP-To: ") - 1 + s->smtp_to.len + sizeof(CRLF) - 1 | 1243 + sizeof("Auth-SMTP-To: ") - 1 + s->smtp_to.len + sizeof(CRLF) - 1 |
1176 #if (NGX_MAIL_SSL) | 1244 #if (NGX_MAIL_SSL) |
1177 + sizeof("Auth-SSL: on" CRLF) - 1 | 1245 + sizeof("Auth-SSL: on" CRLF) - 1 |
1246 + sizeof("Auth-SSL-Verify: ") - 1 + verify.len + sizeof(CRLF) - 1 | |
1247 + sizeof("Auth-SSL-Subject: ") - 1 + subject.len + sizeof(CRLF) - 1 | |
1248 + sizeof("Auth-SSL-Issuer: ") - 1 + issuer.len + sizeof(CRLF) - 1 | |
1249 + sizeof("Auth-SSL-Serial: ") - 1 + serial.len + sizeof(CRLF) - 1 | |
1250 + sizeof("Auth-SSL-Fingerprint: ") - 1 + fingerprint.len | |
1251 + sizeof(CRLF) - 1 | |
1252 + sizeof("Auth-SSL-Cert: ") - 1 + cert.len + sizeof(CRLF) - 1 | |
1178 #endif | 1253 #endif |
1179 + ahcf->header.len | 1254 + ahcf->header.len |
1180 + sizeof(CRLF) - 1; | 1255 + sizeof(CRLF) - 1; |
1181 | 1256 |
1182 b = ngx_create_temp_buf(pool, len); | 1257 b = ngx_create_temp_buf(pool, len); |
1258 | 1333 |
1259 } | 1334 } |
1260 | 1335 |
1261 #if (NGX_MAIL_SSL) | 1336 #if (NGX_MAIL_SSL) |
1262 | 1337 |
1263 if (s->connection->ssl) { | 1338 if (c->ssl) { |
1264 b->last = ngx_cpymem(b->last, "Auth-SSL: on" CRLF, | 1339 b->last = ngx_cpymem(b->last, "Auth-SSL: on" CRLF, |
1265 sizeof("Auth-SSL: on" CRLF) - 1); | 1340 sizeof("Auth-SSL: on" CRLF) - 1); |
1341 | |
1342 b->last = ngx_cpymem(b->last, "Auth-SSL-Verify: ", | |
1343 sizeof("Auth-SSL-Verify: ") - 1); | |
1344 b->last = ngx_copy(b->last, verify.data, verify.len); | |
1345 *b->last++ = CR; *b->last++ = LF; | |
1346 | |
1347 if (subject.len) { | |
1348 b->last = ngx_cpymem(b->last, "Auth-SSL-Subject: ", | |
1349 sizeof("Auth-SSL-Subject: ") - 1); | |
1350 b->last = ngx_copy(b->last, subject.data, subject.len); | |
1351 *b->last++ = CR; *b->last++ = LF; | |
1352 } | |
1353 | |
1354 if (issuer.len) { | |
1355 b->last = ngx_cpymem(b->last, "Auth-SSL-Issuer: ", | |
1356 sizeof("Auth-SSL-Issuer: ") - 1); | |
1357 b->last = ngx_copy(b->last, issuer.data, issuer.len); | |
1358 *b->last++ = CR; *b->last++ = LF; | |
1359 } | |
1360 | |
1361 if (serial.len) { | |
1362 b->last = ngx_cpymem(b->last, "Auth-SSL-Serial: ", | |
1363 sizeof("Auth-SSL-Serial: ") - 1); | |
1364 b->last = ngx_copy(b->last, serial.data, serial.len); | |
1365 *b->last++ = CR; *b->last++ = LF; | |
1366 } | |
1367 | |
1368 if (fingerprint.len) { | |
1369 b->last = ngx_cpymem(b->last, "Auth-SSL-Fingerprint: ", | |
1370 sizeof("Auth-SSL-Fingerprint: ") - 1); | |
1371 b->last = ngx_copy(b->last, fingerprint.data, fingerprint.len); | |
1372 *b->last++ = CR; *b->last++ = LF; | |
1373 } | |
1374 | |
1375 if (cert.len) { | |
1376 b->last = ngx_cpymem(b->last, "Auth-SSL-Cert: ", | |
1377 sizeof("Auth-SSL-Cert: ") - 1); | |
1378 b->last = ngx_copy(b->last, cert.data, cert.len); | |
1379 *b->last++ = CR; *b->last++ = LF; | |
1380 } | |
1266 } | 1381 } |
1267 | 1382 |
1268 #endif | 1383 #endif |
1269 | 1384 |
1270 if (ahcf->header.len) { | 1385 if (ahcf->header.len) { |
1326 if (ahcf == NULL) { | 1441 if (ahcf == NULL) { |
1327 return NULL; | 1442 return NULL; |
1328 } | 1443 } |
1329 | 1444 |
1330 ahcf->timeout = NGX_CONF_UNSET_MSEC; | 1445 ahcf->timeout = NGX_CONF_UNSET_MSEC; |
1446 ahcf->pass_client_cert = NGX_CONF_UNSET; | |
1331 | 1447 |
1332 ahcf->file = cf->conf_file->file.name.data; | 1448 ahcf->file = cf->conf_file->file.name.data; |
1333 ahcf->line = cf->conf_file->line; | 1449 ahcf->line = cf->conf_file->line; |
1334 | 1450 |
1335 return ahcf; | 1451 return ahcf; |
1361 } | 1477 } |
1362 } | 1478 } |
1363 | 1479 |
1364 ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); | 1480 ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); |
1365 | 1481 |
1482 ngx_conf_merge_value(conf->pass_client_cert, prev->pass_client_cert, 0); | |
1483 | |
1366 if (conf->headers == NULL) { | 1484 if (conf->headers == NULL) { |
1367 conf->headers = prev->headers; | 1485 conf->headers = prev->headers; |
1368 conf->header = prev->header; | 1486 conf->header = prev->header; |
1369 } | 1487 } |
1370 | 1488 |