aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--imap.c95
-rw-r--r--options.c12
-rw-r--r--pop3.c77
3 files changed, 118 insertions, 66 deletions
diff --git a/imap.c b/imap.c
index 915ed920..3dce0a8d 100644
--- a/imap.c
+++ b/imap.c
@@ -236,8 +236,10 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
capabilities[0] = '\0';
if ((ok = gen_transact(sock, "CAPABILITY")) == PS_SUCCESS)
{
- /* UW-IMAP server 10.173 notifies in all caps */
- if (strstr(capabilities, "IMAP4REV1"))
+ /* UW-IMAP server 10.173 notifies in all caps, but RFC2060 says we
+ should expect a response in mixed-case */
+ if (strstr(capabilities, "IMAP4REV1") ||
+ strstr(capabilities, "IMAP4rev1"))
{
imap_version = IMAP4rev1;
if (outlevel >= O_DEBUG)
@@ -295,26 +297,38 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
* Time to authenticate the user.
* Try the protocol variants that don't require passwords first.
*/
+ ok = PS_AUTHFAIL;
+
#ifdef GSSAPI
if ((ctl->server.authenticate == A_ANY
- || ctl->server.authenticate==A_GSSAPI)
+ || ctl->server.authenticate == A_GSSAPI)
&& strstr(capabilities, "AUTH=GSSAPI"))
- if(!(ok = do_gssauth(sock, "AUTHENTICATE", ctl->server.truename, ctl->remotename)))
- {
- return ok;
- }
+ if(ok = do_gssauth(sock, "AUTHENTICATE", ctl->server.truename, ctl->remotename))
+ {
+ /* SASL cancellation of authentication */
+ gen_send(sock, "*");
+ if(ctl->server.authenticate != A_ANY)
+ return ok;
+ }
+ else
+ return ok;
#endif /* GSSAPI */
#ifdef KERBEROS_V4
if ((ctl->server.authenticate == A_ANY
- || ctl->server.authenticate==A_KERBEROS_V4
- || ctl->server.authenticate==A_KERBEROS_V5)
+ || ctl->server.authenticate == A_KERBEROS_V4
+ || ctl->server.authenticate == A_KERBEROS_V5)
&& strstr(capabilities, "AUTH=KERBEROS_V4"))
{
- if (!(ok = do_rfc1731(sock, "AUTHENTICATE", ctl->server.truename)))
+ if ((ok = do_rfc1731(sock, "AUTHENTICATE", ctl->server.truename)))
+ {
/* SASL cancellation of authentication */
gen_send(sock, "*");
- return(ok);
+ if(ctl->server.authenticate != A_ANY)
+ return ok;
+ }
+ else
+ return ok;
}
#endif /* KERBEROS_V4 */
@@ -324,40 +338,59 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
*/
if ((ctl->server.authenticate == A_ANY
- || ctl->server.authenticate==A_CRAM_MD5)
+ || ctl->server.authenticate == A_CRAM_MD5)
&& strstr(capabilities, "AUTH=CRAM-MD5"))
{
if ((ok = do_cram_md5 (sock, "AUTHENTICATE", ctl)))
+ {
/* SASL cancellation of authentication */
gen_send(sock, "*");
- return(ok);
+ if(ctl->server.authenticate != A_ANY)
+ return ok;
+ }
+ else
+ return ok;
}
#if OPIE_ENABLE
if ((ctl->server.authenticate == A_ANY
- || ctl->server.authenticate==A_OTP)
+ || ctl->server.authenticate == A_OTP)
&& strstr(capabilities, "AUTH=X-OTP"))
- return(do_otp(sock, "AUTHENTICATE", ctl));
+ if ((ok = do_otp(sock, "AUTHENTICATE", ctl)))
+ {
+ /* SASL cancellation of authentication */
+ gen_send(sock, "*");
+ if(ctl->server.authenticate != A_ANY)
+ return ok;
+ }
+ else
+ return ok;
#else
- if (ctl->server.authenticate==A_NTLM)
+ if (ctl->server.authenticate == A_NTLM)
{
report(stderr,
_("Required OTP capability not compiled into fetchmail\n"));
- return(PS_AUTHFAIL);
}
#endif /* OPIE_ENABLE */
#ifdef NTLM_ENABLE
if ((ctl->server.authenticate == A_ANY
- || ctl->server.authenticate==A_NTLM)
+ || ctl->server.authenticate == A_NTLM)
&& strstr (capabilities, "AUTH=NTLM"))
- return(do_imap_ntlm(sock, ctl));
+ if ((ok = do_imap_ntlm(sock, ctl)))
+ {
+ /* SASL cancellation of authentication */
+ gen_send(sock, "*");
+ if(ctl->server.authenticate != A_ANY)
+ return ok;
+ }
+ else
+ return(ok);
#else
- if (ctl->server.authenticate==A_NTLM)
+ if (ctl->server.authenticate == A_NTLM)
{
report(stderr,
_("Required NTLM capability not compiled into fetchmail\n"));
- return(PS_AUTHFAIL);
}
#endif /* NTLM_ENABLE */
@@ -367,26 +400,34 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
{
report(stderr,
_("Required LOGIN capability not supported by server\n"));
- return PS_AUTHFAIL;
}
#endif /* __UNUSED__ */
/* we're stuck with sending the password en clair */
+ if ((ctl->server.authenticate == A_ANY
+ || ctl->server.authenticate == A_PASSWORD)
+ && !strstr (capabilities, "LOGINDISABLED"))
{
/* these sizes guarantee no buffer overflow */
char remotename[NAMELEN*2+1], password[PASSWORDLEN*2+1];
imap_canonicalize(remotename, ctl->remotename, NAMELEN);
imap_canonicalize(password, ctl->password, PASSWORDLEN);
- imap_canonicalize(shroud, ctl->password, PASSWORDLEN);
+
ok = gen_transact(sock, "LOGIN \"%s\" \"%s\"", remotename, password);
shroud[0] = '\0';
+ if (ok)
+ {
+ /* SASL cancellation of authentication */
+ gen_send(sock, "*");
+ if(ctl->server.authenticate != A_ANY)
+ return ok;
+ }
+ else
+ return(ok);
}
- if (ok)
- return(ok);
-
- return(PS_SUCCESS);
+ return(ok);
}
static int internal_expunge(int sock)
diff --git a/options.c b/options.c
index 97d6b7bb..71003d21 100644
--- a/options.c
+++ b/options.c
@@ -396,6 +396,18 @@ struct query *ctl; /* option record to be initialized */
ctl->server.authenticate = A_KERBEROS_V4;
else if (strcmp(optarg, "ssh") == 0)
ctl->server.authenticate = A_SSH;
+ else if (strcmp(optarg, "otp") == 0)
+ ctl->server.authenticate = A_OTP;
+ else if (strcmp(optarg, "ntlm") == 0)
+ ctl->server.authenticate = A_NTLM;
+ else if (strcmp(optarg, "cram") == 0)
+ ctl->server.authenticate = A_CRAM_MD5;
+ else if (strcmp(optarg, "cram-md5") == 0)
+ ctl->server.authenticate = A_CRAM_MD5;
+ else if (strcmp(optarg, "gssapi") == 0)
+ ctl->server.authenticate = A_GSSAPI;
+ else if (strcmp(optarg, "any") == 0)
+ ctl->server.authenticate = A_ANY;
else {
fprintf(stderr,_("Invalid authentication `%s' specified.\n"), optarg);
errflag++;
diff --git a/pop3.c b/pop3.c
index 718c09c8..0ff1cd45 100644
--- a/pop3.c
+++ b/pop3.c
@@ -131,6 +131,16 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
#if OPIE_ENABLE
char *challenge;
#endif /* OPIE_ENABLE */
+#if defined(GSSAPI)
+ flag has_gssapi = FALSE;
+#endif /* defined(GSSAPI) */
+#if defined(KERBEROS_V4) || defined(KERBEROS_V5)
+ flag has_kerberos = FALSE;
+#endif /* defined(KERBEROS_V4) || defined(KERBEROS_V5) */
+ flag has_cram = FALSE;
+#ifdef OPIE_ENABLE
+ flag has_otp = FALSE;
+#endif /* OPIE_ENABLE */
#ifdef SDPS_ENABLE
/*
@@ -190,16 +200,6 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
&& strchr(greeting, '<')
&& gen_transact(sock, "CAPA") == 0)
{
-#if defined(GSSAPI)
- flag has_gssapi = FALSE;
-#endif /* defined(GSSAPI) */
-#if defined(KERBEROS_V4) || defined(KERBEROS_V5)
- flag has_kerberos = FALSE;
-#endif /* defined(KERBEROS_V4) || defined(KERBEROS_V5) */
- flag has_cram = FALSE;
-#ifdef OPIE_ENABLE
- flag has_otp = FALSE;
-#endif /* OPIE_ENABLE */
char buffer[64];
/* determine what authentication methods we have available */
@@ -222,25 +222,6 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
if (strstr(buffer, "CRAM-MD5"))
has_cram = TRUE;
}
-
- /*
- * Here's where we set priorities. Note that we must do tests
- * in *reverse* order of desirability.
- */
- if (has_cram)
- ctl->server.authenticate = A_CRAM_MD5;
-#ifdef OPIE_ENABLE
- if (has_otp)
- ctl->server.authenticate = A_OTP;
-#endif /* OPIE_ENABLE */
-#if defined(GSSAPI)
- if (has_gssapi)
- ctl->server.authenticate = A_GSSAPI;
-#endif /* defined(GSSAPI) */
-#if defined(KERBEROS_V4) || defined(KERBEROS_V5)
- if (has_kerberos)
- ctl->server.authenticate = A_KERBEROS_V4;
-#endif /* defined(KERBEROS_V4) || defined(KERBEROS_V5) */
}
/*
@@ -251,27 +232,45 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
* Servers doing KPOP have to go through a dummy login sequence
* rather than doing SASL.
*/
- if (
+ if (has_kerberos &&
#if INET6_ENABLE
ctl->server.service && (strcmp(ctl->server.service, KPOP_PORT)!=0)
#else /* INET6_ENABLE */
ctl->server.port != KPOP_PORT
#endif /* INET6_ENABLE */
&& (ctl->server.authenticate == A_KERBEROS_V4
- || ctl->server.authenticate == A_KERBEROS_V5))
- return(do_rfc1731(sock, "AUTH", ctl->server.truename));
+ || ctl->server.authenticate == A_KERBEROS_V5
+ || ctl->server.authenticate == A_ANY))
+ if(ok = do_rfc1731(sock, "AUTH", ctl->server.truename))
+ if(ctl->server.authenticate != A_ANY)
+ break;
#endif /* defined(KERBEROS_V4) || defined(KERBEROS_V5) */
+
#if defined(GSSAPI)
- if (ctl->server.authenticate==A_GSSAPI)
- return(do_gssauth(sock, "AUTH",
- ctl->server.truename, ctl->remotename));
+ if (has_gssapi &&
+ (ctl->server.authenticate == A_GSSAPI ||
+ ctl->server.authenticate == A_ANY))
+ if(ok = do_gssauth(sock, "AUTH",
+ ctl->server.truename, ctl->remotename))
+ if(ctl->server.authenticate != A_ANY)
+ break;
#endif /* defined(GSSAPI) */
+
#ifdef OPIE_ENABLE
- if (ctl->server.authenticate == A_OTP)
- do_otp(sock, "AUTH", ctl);
+ if (has_otp &&
+ (ctl->server.authenticate == A_OTP ||
+ ctl->server.authenticate == A_ANY))
+ if(ok = do_otp(sock, "AUTH", ctl))
+ if(ctl->server.authenticate != A_ANY)
+ break;
#endif /* OPIE_ENABLE */
- if (ctl->server.authenticate == A_CRAM_MD5)
- return(do_cram_md5(sock, "AUTH", ctl));
+
+ if (has_cram &&
+ (ctl->server.authenticate == A_CRAM_MD5 ||
+ ctl->server.authenticate == A_ANY))
+ if(ok = do_cram_md5(sock, "AUTH", ctl))
+ if(ctl->server.authenticate != A_ANY)
+ break;
/* ordinary validation, no one-time password or RPA */
gen_transact(sock, "USER %s", ctl->remotename);