diff options
-rw-r--r-- | imap.c | 95 | ||||
-rw-r--r-- | options.c | 12 | ||||
-rw-r--r-- | pop3.c | 77 |
3 files changed, 118 insertions, 66 deletions
@@ -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) @@ -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++; @@ -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); |