Klaus Demo nginx / 66c23ed
Mail: support SASL EXTERNAL (RFC 4422). This is needed to allow TLS client certificate auth to work. With ssl_verify_client configured, the auth daemon can choose to allow the connection to proceed based on the certificate data. This has been tested with Thunderbird for IMAP only. I've not yet found a client that will do client certificate auth for POP3 or SMTP, and the method is not really documented anywhere that I can find. That said, its simple enough that the way I've done is probably right. Rob N ★ 5 years ago
10 changed file(s) with 110 addition(s) and 15 deletion(s). Raw diff Collapse all Expand all
131131 ngx_pop3_auth_login_username,
132132 ngx_pop3_auth_login_password,
133133 ngx_pop3_auth_plain,
134 ngx_pop3_auth_cram_md5
134 ngx_pop3_auth_cram_md5,
135 ngx_pop3_auth_external
135136 } ngx_pop3_state_e;
136137
137138
141142 ngx_imap_auth_login_password,
142143 ngx_imap_auth_plain,
143144 ngx_imap_auth_cram_md5,
145 ngx_imap_auth_external,
144146 ngx_imap_login,
145147 ngx_imap_user,
146148 ngx_imap_passwd
153155 ngx_smtp_auth_login_password,
154156 ngx_smtp_auth_plain,
155157 ngx_smtp_auth_cram_md5,
158 ngx_smtp_auth_external,
156159 ngx_smtp_helo,
157160 ngx_smtp_helo_xclient,
158161 ngx_smtp_helo_from,
284287 #define NGX_MAIL_AUTH_LOGIN_USERNAME 2
285288 #define NGX_MAIL_AUTH_APOP 3
286289 #define NGX_MAIL_AUTH_CRAM_MD5 4
287 #define NGX_MAIL_AUTH_NONE 5
290 #define NGX_MAIL_AUTH_EXTERNAL 5
291 #define NGX_MAIL_AUTH_NONE 6
288292
289293
290294 #define NGX_MAIL_AUTH_PLAIN_ENABLED 0x0002
291295 #define NGX_MAIL_AUTH_LOGIN_ENABLED 0x0004
292296 #define NGX_MAIL_AUTH_APOP_ENABLED 0x0008
293297 #define NGX_MAIL_AUTH_CRAM_MD5_ENABLED 0x0010
294 #define NGX_MAIL_AUTH_NONE_ENABLED 0x0020
298 #define NGX_MAIL_AUTH_EXTERNAL_ENABLED 0x0020
299 #define NGX_MAIL_AUTH_NONE_ENABLED 0x0040
295300
296301
297302 #define NGX_MAIL_PARSE_INVALID_COMMAND 20
376381 ngx_int_t ngx_mail_auth_cram_md5_salt(ngx_mail_session_t *s,
377382 ngx_connection_t *c, char *prefix, size_t len);
378383 ngx_int_t ngx_mail_auth_cram_md5(ngx_mail_session_t *s, ngx_connection_t *c);
384 ngx_int_t ngx_mail_auth_external(ngx_mail_session_t *s, ngx_connection_t *c,
385 ngx_uint_t n);
379386 ngx_int_t ngx_mail_auth_parse(ngx_mail_session_t *s, ngx_connection_t *c);
380387
381388 void ngx_mail_send(ngx_event_t *wev);
150150 ngx_string("plain"),
151151 ngx_string("apop"),
152152 ngx_string("cram-md5"),
153 ngx_string("external"),
153154 ngx_string("none")
154155 };
155156
611611 }
612612
613613
614 ngx_int_t
615 ngx_mail_auth_external(ngx_mail_session_t *s, ngx_connection_t *c,
616 ngx_uint_t n)
617 {
618 ngx_str_t *arg, external;
619
620 arg = s->args.elts;
621
622 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
623 "mail auth external: \"%V\"", &arg[n]);
624
625 external.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[n].len));
626 if (external.data == NULL) {
627 return NGX_ERROR;
628 }
629
630 if (ngx_decode_base64(&external, &arg[n]) != NGX_OK) {
631 ngx_log_error(NGX_LOG_INFO, c->log, 0,
632 "client sent invalid base64 encoding in AUTH EXTERNAL command");
633 return NGX_MAIL_PARSE_INVALID_COMMAND;
634 }
635
636 s->login.len = external.len;
637 s->login.data = external.data;
638
639 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
640 "mail auth external: \"%V\"", &s->login);
641
642 s->auth_method = NGX_MAIL_AUTH_EXTERNAL;
643
644 return NGX_DONE;
645 }
646
647
614648 void
615649 ngx_mail_send(ngx_event_t *wev)
616650 {
221221 case ngx_imap_auth_cram_md5:
222222 rc = ngx_mail_auth_cram_md5(s, c);
223223 break;
224
225 case ngx_imap_auth_external:
226 rc = ngx_mail_auth_external(s, c, 0);
227 break;
224228 }
225229
226230 } else if (rc == NGX_IMAP_NEXT) {
398402 }
399403
400404 return NGX_ERROR;
405
406 case NGX_MAIL_AUTH_EXTERNAL:
407
408 ngx_str_set(&s->out, imap_username);
409 s->mail_state = ngx_imap_auth_external;
410
411 return NGX_OK;
401412 }
402413
403414 return rc;
2828 { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED },
2929 { ngx_string("login"), NGX_MAIL_AUTH_LOGIN_ENABLED },
3030 { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED },
31 { ngx_string("external"), NGX_MAIL_AUTH_EXTERNAL_ENABLED },
3132 { ngx_null_string, 0 }
3233 };
3334
3738 ngx_string("AUTH=LOGIN"),
3839 ngx_null_string, /* APOP */
3940 ngx_string("AUTH=CRAM-MD5"),
41 ngx_string("AUTH=EXTERNAL"),
4042 ngx_null_string /* NONE */
4143 };
4244
178180 }
179181
180182 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0;
181 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED;
183 m <= NGX_MAIL_AUTH_EXTERNAL_ENABLED;
182184 m <<= 1, i++)
183185 {
184186 if (m & conf->auth_methods) {
204206 auth = p;
205207
206208 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0;
207 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED;
209 m <= NGX_MAIL_AUTH_EXTERNAL_ENABLED;
208210 m <<= 1, i++)
209211 {
210212 if (m & conf->auth_methods) {
904904
905905 if (arg[0].len == 8) {
906906
907 if (s->args.nelts != 1) {
908 return NGX_MAIL_PARSE_INVALID_COMMAND;
909 }
910
911907 if (ngx_strncasecmp(arg[0].data, (u_char *) "CRAM-MD5", 8) == 0) {
908
909 if (s->args.nelts != 1) {
910 return NGX_MAIL_PARSE_INVALID_COMMAND;
911 }
912
912913 return NGX_MAIL_AUTH_CRAM_MD5;
913914 }
915
916 if (ngx_strncasecmp(arg[0].data, (u_char *) "EXTERNAL", 8) == 0) {
917
918 if (s->args.nelts == 1) {
919 return NGX_MAIL_AUTH_EXTERNAL;
920 }
921
922 if (s->args.nelts == 2) {
923 return ngx_mail_auth_external(s, c, 1);
924 }
925 }
926
927 return NGX_MAIL_PARSE_INVALID_COMMAND;
914928 }
915929
916930 return NGX_MAIL_PARSE_INVALID_COMMAND;
239239 case ngx_pop3_auth_cram_md5:
240240 rc = ngx_mail_auth_cram_md5(s, c);
241241 break;
242
243 case ngx_pop3_auth_external:
244 rc = ngx_mail_auth_external(s, c, 0);
245 break;
242246 }
243247 }
244248
493497 }
494498
495499 return NGX_ERROR;
500
501 case NGX_MAIL_AUTH_EXTERNAL:
502
503 ngx_str_set(&s->out, pop3_username);
504 s->mail_state = ngx_pop3_auth_external;
505
506 return NGX_OK;
496507 }
497508
498509 return rc;
2828 { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED },
2929 { ngx_string("apop"), NGX_MAIL_AUTH_APOP_ENABLED },
3030 { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED },
31 { ngx_string("external"), NGX_MAIL_AUTH_EXTERNAL_ENABLED },
3132 { ngx_null_string, 0 }
3233 };
3334
3738 ngx_string("LOGIN"),
3839 ngx_null_string, /* APOP */
3940 ngx_string("CRAM-MD5"),
41 ngx_string("EXTERNAL"),
4042 ngx_null_string /* NONE */
4143 };
4244
179181 size += sizeof("SASL") - 1 + sizeof(CRLF) - 1;
180182
181183 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0;
182 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED;
184 m <= NGX_MAIL_AUTH_EXTERNAL_ENABLED;
183185 m <<= 1, i++)
184186 {
185187 if (m & conf->auth_methods) {
206208 p = ngx_cpymem(p, "SASL", sizeof("SASL") - 1);
207209
208210 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0;
209 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED;
211 m <= NGX_MAIL_AUTH_EXTERNAL_ENABLED;
210212 m <<= 1, i++)
211213 {
212214 if (m & conf->auth_methods) {
242244 + sizeof("." CRLF) - 1;
243245
244246 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0;
245 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED;
247 m <= NGX_MAIL_AUTH_EXTERNAL_ENABLED;
246248 m <<= 1, i++)
247249 {
248250 if (m & conf->auth_methods) {
263265 sizeof("+OK methods supported:" CRLF) - 1);
264266
265267 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0;
266 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED;
268 m <= NGX_MAIL_AUTH_EXTERNAL_ENABLED;
267269 m <<= 1, i++)
268270 {
269271 if (m & conf->auth_methods) {
484484 case ngx_smtp_auth_cram_md5:
485485 rc = ngx_mail_auth_cram_md5(s, c);
486486 break;
487
488 case ngx_smtp_auth_external:
489 rc = ngx_mail_auth_external(s, c, 0);
490 break;
487491 }
488492 }
489493
651655 }
652656
653657 return NGX_ERROR;
658
659 case NGX_MAIL_AUTH_EXTERNAL:
660
661 ngx_str_set(&s->out, smtp_username);
662 s->mail_state = ngx_smtp_auth_external;
663
664 return NGX_OK;
654665 }
655666
656667 return rc;
2020 { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED },
2121 { ngx_string("login"), NGX_MAIL_AUTH_LOGIN_ENABLED },
2222 { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED },
23 { ngx_string("external"), NGX_MAIL_AUTH_EXTERNAL_ENABLED },
2324 { ngx_string("none"), NGX_MAIL_AUTH_NONE_ENABLED },
2425 { ngx_null_string, 0 }
2526 };
3031 ngx_string("LOGIN"),
3132 ngx_null_string, /* APOP */
3233 ngx_string("CRAM-MD5"),
34 ngx_string("EXTERNAL"),
3335 ngx_null_string /* NONE */
3436 };
3537
206208 auth_enabled = 0;
207209
208210 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0;
209 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED;
211 m <= NGX_MAIL_AUTH_EXTERNAL_ENABLED;
210212 m <<= 1, i++)
211213 {
212214 if (m & conf->auth_methods) {
249251 *p++ = 'A'; *p++ = 'U'; *p++ = 'T'; *p++ = 'H';
250252
251253 for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0;
252 m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED;
254 m <= NGX_MAIL_AUTH_EXTERNAL_ENABLED;
253255 m <<= 1, i++)
254256 {
255257 if (m & conf->auth_methods) {