From: Nic Bernstein <[email protected]>
Date: 9/8/2015 19:40:26
> Could you add a stanza to /lib/imapoptions describing any configuration
> options you've added? Don't worry if it's perfect, just get something
> in there so we documentation folk can make sure they get into the man pages.
Attached v3 patch. Including "/lib/imapoptions" changes, clarifying
allowplaintext and forcetlsauth.
Let me know if it is ok.
Regards,
Carlos Velasco
diff -ur a/imap/httpd.c b/imap/httpd.c
--- a/imap/httpd.c 2015-07-06 02:40:07.000000000 +0200
+++ b/imap/httpd.c 2015-08-09 19:57:23.128095427 +0200
@@ -602,7 +602,10 @@
}
}
}
- httpd_tls_required = !avail_auth_schemes;
+ if (config_getswitch(IMAPOPT_FORCETLSAUTH))
+ httpd_tls_required = 1;
+ else
+ httpd_tls_required = !avail_auth_schemes;
proc_register("httpd", httpd_clienthost, NULL, NULL, NULL);
diff -ur a/imap/imapd.c b/imap/imapd.c
--- a/imap/imapd.c 2015-07-06 02:40:07.000000000 +0200
+++ b/imap/imapd.c 2015-08-09 19:57:23.148096314 +0200
@@ -2398,9 +2398,11 @@
}
/* possibly disallow login */
- if (!imapd_starttls_done && (extprops_ssf < 2) &&
- !config_getswitch(IMAPOPT_ALLOWPLAINTEXT) &&
- !is_userid_anonymous(canon_user)) {
+ if ((!imapd_starttls_done && (extprops_ssf < 2) &&
+ !config_getswitch(IMAPOPT_ALLOWPLAINTEXT) &&
+ !is_userid_anonymous(canon_user)) ||
+ (!imapd_starttls_done &&
+ config_getswitch(IMAPOPT_FORCETLSAUTH))) {
eatline(imapd_in, ' ');
prot_printf(imapd_out, "%s NO Login only available under a layer\r\n",
tag);
@@ -2548,6 +2550,14 @@
int r;
int failedloginpause;
+ if (!imapd_starttls_done &&
+ config_getswitch(IMAPOPT_FORCETLSAUTH)) {
+ eatline(imapd_in, ' ');
+ prot_printf(imapd_out, "%s NO Auth only available under a layer\r\n",
+ tag);
+ return;
+ }
+
r = saslserver(imapd_saslconn, authtype, resp, "", "+ ", "",
imapd_in, imapd_out, &sasl_result, NULL);
@@ -3039,6 +3049,7 @@
/* add the SASL mechs */
if ((!imapd_authstate || saslprops.ssf) &&
+ (imapd_starttls_done || !config_getswitch(IMAPOPT_FORCETLSAUTH)) &&
sasl_listmech(imapd_saslconn, NULL,
"AUTH=", " AUTH=",
!imapd_authstate ? " SASL-IR" : "", &sasllist,
diff -ur a/imap/nntpd.c b/imap/nntpd.c
--- a/imap/nntpd.c 2015-07-06 02:40:07.000000000 +0200
+++ b/imap/nntpd.c 2015-08-09 19:57:23.148096314 +0200
@@ -1813,20 +1813,22 @@
if (tls_enabled() && !nntp_starttls_done && !nntp_authstate)
prot_printf(nntp_out, "STARTTLS\r\n");
- /* check for SASL mechs */
- sasl_listmech(nntp_saslconn, NULL, "SASL ", " ", "\r\n",
- &mechlist, NULL, &mechcount);
-
- /* add the AUTHINFO variants */
- if (!nntp_authstate) {
- prot_printf(nntp_out, "AUTHINFO%s%s\r\n",
+ if (nntp_starttls_done || !config_getswitch(IMAPOPT_FORCETLSAUTH)) {
+ /* check for SASL mechs */
+ sasl_listmech(nntp_saslconn, NULL, "SASL ", " ", "\r\n",
+ &mechlist, NULL, &mechcount);
+
+ /* add the AUTHINFO variants */
+ if (!nntp_authstate) {
+ prot_printf(nntp_out, "AUTHINFO%s%s\r\n",
(nntp_starttls_done || (extprops_ssf > 1) ||
config_getswitch(IMAPOPT_ALLOWPLAINTEXT)) ?
" USER" : "", mechcount ? " SASL" : "");
- }
+ }
- /* add the SASL mechs */
- if (mechcount) prot_printf(nntp_out, "%s", mechlist);
+ /* add the SASL mechs */
+ if (mechcount) prot_printf(nntp_out, "%s", mechlist);
+ }
/* add the reader capabilities/extensions */
if ((nntp_capa & MODE_READ) && (nntp_authstate || allowanonymous)) {
@@ -1974,9 +1976,10 @@
return;
}
- /* possibly disallow USER */
- if (!(nntp_starttls_done || (extprops_ssf > 1) ||
- config_getswitch(IMAPOPT_ALLOWPLAINTEXT))) {
+ /* possibly disallow AUTHINFO USER */
+ if ((!(nntp_starttls_done || (extprops_ssf > 1) ||
+ config_getswitch(IMAPOPT_ALLOWPLAINTEXT))) ||
+ (!nntp_starttls_done && config_getswitch(IMAPOPT_FORCETLSAUTH))) {
prot_printf(nntp_out,
"483 AUTHINFO USER command only available under a layer\r\n");
return;
@@ -2085,6 +2088,13 @@
int failedloginpause;
struct proc_limits limits;
+ /* possibly disallow AUTHINFO SASL */
+ if (!nntp_starttls_done && config_getswitch(IMAPOPT_FORCETLSAUTH)) {
+ prot_printf(nntp_out,
+ "483 AUTHINFO SASL command only available under a layer\r\n");
+ return;
+ }
+
/* Conceal initial response in telemetry log */
if (nntp_logfd != -1 && resp) {
r = ftruncate(nntp_logfd,
diff -ur a/imap/pop3d.c b/imap/pop3d.c
--- a/imap/pop3d.c 2015-07-06 02:40:07.000000000 +0200
+++ b/imap/pop3d.c 2015-08-09 19:57:23.148096314 +0200
@@ -1349,6 +1349,13 @@
const void *canon_user;
int failedloginpause;
+ /* possibly disallow APOP */
+ if (!popd_starttls_done && config_getswitch(IMAPOPT_FORCETLSAUTH)) {
+ prot_printf(popd_out,
+ "-ERR [AUTH] APOP command only available under a layer\r\n");
+ return;
+ }
+
assert(response != NULL);
if (popd_userid) {
@@ -1418,7 +1425,8 @@
/* possibly disallow USER */
if (!(kflag || popd_starttls_done || (extprops_ssf > 1) ||
- config_getswitch(IMAPOPT_ALLOWPLAINTEXT))) {
+ config_getswitch(IMAPOPT_ALLOWPLAINTEXT)) ||
+ (!popd_starttls_done && config_getswitch(IMAPOPT_FORCETLSAUTH))) {
prot_printf(popd_out,
"-ERR [AUTH] USER command only available under a layer\r\n");
return;
@@ -1570,6 +1578,7 @@
/* SASL special case: print SASL, then a list of supported capabilities */
if ((!popd_authstate || saslprops.ssf) &&
+ (popd_starttls_done || !config_getswitch(IMAPOPT_FORCETLSAUTH)) &&
sasl_listmech(popd_saslconn,
NULL, /* should be id string */
"SASL ", " ", "\r\n",
@@ -1594,9 +1603,10 @@
prot_printf(popd_out, "RESP-CODES\r\n");
prot_printf(popd_out, "AUTH-RESP-CODE\r\n");
- if (!popd_authstate &&
- (kflag || popd_starttls_done || (extprops_ssf > 1)
- || config_getswitch(IMAPOPT_ALLOWPLAINTEXT))) {
+ if ((!popd_authstate &&
+ (kflag || popd_starttls_done || (extprops_ssf > 1)
+ || config_getswitch(IMAPOPT_ALLOWPLAINTEXT))) &&
+ (popd_starttls_done || !config_getswitch(IMAPOPT_FORCETLSAUTH))) {
prot_printf(popd_out, "USER\r\n");
}
@@ -1619,6 +1629,13 @@
const char *canon_user;
int failedloginpause;
+ /* possibly disallow AUTH */
+ if (!popd_starttls_done && config_getswitch(IMAPOPT_FORCETLSAUTH)) {
+ prot_printf(popd_out,
+ "-ERR [AUTH] AUTH command only available under a layer\r\n");
+ return;
+ }
+
/* if client didn't specify an argument we give them the list
*
* XXX This method of mechanism discovery is an undocumented feature
diff -ur a/lib/imapoptions b/lib/imapoptions
--- a/lib/imapoptions 2015-07-06 02:40:07.000000000 +0200
+++ b/lib/imapoptions 2015-08-09 20:08:43.088273694 +0200
@@ -147,7 +147,19 @@
enabled when absolutely necessary. */
{ "allowplaintext", 0, SWITCH }
-/* Allow the use of cleartext passwords on the wire. */
+/* If enabled, allows the use of cleartext passwords on the wire.
+.PP
+ In its default setting (disabled) disallow cleartext passwords without
+ TLS/SSL encryption, but allows authentication with encrypted password,
+ like SHA1/MD5, without TLS/SSL encryption needed. */
+
+{ "forcetlsauth", 0, SWITCH }
+/* Force TLS/SSL encryption before any authentication take place.
+.PP
+ Note this option is somehow independent of "allowplaintext".
+ Enabling this option makes sure all sessions, and passwords, are
+ always protected by TLS/SSL security layer. All authentication is
+ disabled until a TLS/SSL session is started. */
{ "allowusermoves", 0, SWITCH }
/* Allow moving user accounts (with associated meta-data) via RENAME
diff -ur a/lib/imapopts.c b/lib/imapopts.c
--- a/lib/imapopts.c 2015-07-06 03:24:21.000000000 +0200
+++ b/lib/imapopts.c 2015-08-09 19:57:23.148096314 +0200
@@ -64,6 +64,10 @@
(union config_value)((long) 0),
(union config_value)((long) 0),
{ { NULL, IMAP_ENUM_ZERO } } },
+ { IMAPOPT_FORCETLSAUTH, "forcetlsauth", 0, OPT_SWITCH,
+ (union config_value)((long) 0),
+ (union config_value)((long) 0),
+ { { NULL, IMAP_ENUM_ZERO } } },
{ IMAPOPT_ALLOWUSERMOVES, "allowusermoves", 0, OPT_SWITCH,
(union config_value)((long) 0),
(union config_value)((long) 0),
diff -ur a/lib/imapopts.h b/lib/imapopts.h
--- a/lib/imapopts.h 2015-07-06 03:24:21.000000000 +0200
+++ b/lib/imapopts.h 2015-08-09 19:57:23.148096314 +0200
@@ -26,6 +26,7 @@
IMAPOPT_ALLOWAPOP,
IMAPOPT_ALLOWNEWNEWS,
IMAPOPT_ALLOWPLAINTEXT,
+ IMAPOPT_FORCETLSAUTH,
IMAPOPT_ALLOWUSERMOVES,
IMAPOPT_ALTNAMESPACE,
IMAPOPT_ANNOTATION_DB,
diff -ur a/timsieved/actions.c b/timsieved/actions.c
--- a/timsieved/actions.c 2015-07-06 02:40:07.000000000 +0200
+++ b/timsieved/actions.c 2015-08-09 19:57:23.148096314 +0200
@@ -177,12 +177,23 @@
int mechcount;
/* implementation */
- prot_printf(conn,
+ if (config_serverinfo == IMAP_ENUM_SERVERINFO_ON) {
+ prot_printf(conn,
"\"IMPLEMENTATION\" \"Cyrus timsieved%s %s\"\r\n",
config_mupdate_server ? " (Murder)" : "", cyrus_version());
+ } else if (config_serverinfo == IMAP_ENUM_SERVERINFO_MIN) {
+ prot_printf(conn,
+ "\"IMPLEMENTATION\" \"Cyrus timsieved%s\"\r\n",
+ config_mupdate_server ? " (Murder)" : "");
+ } else {
+ /* IMAP_ENUM_SERVERINFO_OFF */
+ prot_printf(conn,
+ "\"IMPLEMENTATION\" \"ManageSieve\"\r\n");
+ }
/* SASL */
if ((!authenticated || sasl_ssf) &&
+ (starttls_done || !config_getswitch(IMAPOPT_FORCETLSAUTH)) &&
sasl_listmech(saslconn, NULL,
"\"SASL\" \"", " ", "\"\r\n",
&sasllist,
diff -ur a/timsieved/parser.c b/timsieved/parser.c
--- a/timsieved/parser.c 2015-07-06 02:40:07.000000000 +0200
+++ b/timsieved/parser.c 2015-08-09 19:57:23.148096314 +0200
@@ -187,6 +187,10 @@
break;
case AUTHENTICATE:
+ if (!starttls_done && config_getswitch(IMAPOPT_FORCETLSAUTH)) {
+ error_msg = "AUTHENTICATE only available under a layer";
+ goto error;
+ }
if (timlex(NULL, NULL, sieved_in)!=SPACE)
{
error_msg = "SPACE must occur after AUTHENTICATE";