diff options
Diffstat (limited to 'imap.c')
-rw-r--r-- | imap.c | 120 |
1 files changed, 58 insertions, 62 deletions
@@ -369,12 +369,8 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting) /* apply for connection authorization */ { int ok = 0; -#ifdef SSL_ENABLE - flag did_stls = FALSE; - flag using_tls = FALSE; -#endif /* SSL_ENABLE */ - (void)greeting; + /* * Assumption: expunges are cheap, so we want to do them * after every message unless user said otherwise. @@ -398,54 +394,64 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting) #ifdef SSL_ENABLE if ((!ctl->sslproto || !strcasecmp(ctl->sslproto,"tls1")) - && !ctl->use_ssl - && strstr(capabilities, "STARTTLS")) + && !ctl->use_ssl + && strstr(capabilities, "STARTTLS")) { - char *realhost; - - realhost = ctl->server.via ? ctl->server.via : ctl->server.pollname; - ok = gen_transact(sock, "STARTTLS"); - - /* We use "tls1" instead of ctl->sslproto, as we want STARTTLS, - * not other SSL protocols - */ - if (ok == PS_SUCCESS && - SSLOpen(sock,ctl->sslcert,ctl->sslkey,"tls1",ctl->sslcertck, - ctl->sslcertpath,ctl->sslfingerprint, - realhost,ctl->server.pollname,&ctl->remotename) == -1) - { - if (!ctl->sslproto && !ctl->wehaveauthed) - { - ctl->sslproto = xstrdup(""); - /* repoll immediately with TLS disabled */ - return(PS_REPOLL); - } - report(stderr, - GT_("TLS connection failed.\n")); - return PS_SOCKET; - } else { - using_tls = TRUE; - if (outlevel >= O_VERBOSE && !ctl->sslproto) - report(stdout, GT_("%s: opportunistic upgrade to TLS.\n"), realhost); - } - did_stls = TRUE; - - /* - * RFC 2595 says this: - * - * "Once TLS has been started, the client MUST discard cached - * information about server capabilities and SHOULD re-issue the - * CAPABILITY command. This is necessary to protect against - * man-in-the-middle attacks which alter the capabilities list prior - * to STARTTLS. The server MAY advertise different capabilities - * after STARTTLS." - */ - capa_probe(sock, ctl); - } - /* Check if TLS was enforced. */ - if ((ctl->sslproto && !strcasecmp(ctl->sslproto,"tls1")) && !ctl->use_ssl && !using_tls) { - report(stderr, GT_("TLS connection failed.\n")); - return PS_SOCKET; + char *realhost = ctl->server.via ? ctl->server.via : ctl->server.pollname; + + /* Use "tls1" rather than ctl->sslproto because tls1 is the only + * protocol that will work with STARTTLS. Don't need to worry + * whether TLS is mandatory or opportunistic unless SSLOpen() fails + * (see below). */ + if (gen_transact(sock, "STARTTLS") == PS_SUCCESS + && SSLOpen(sock, ctl->sslcert, ctl->sslkey, "tls1", ctl->sslcertck, + ctl->sslcertpath, ctl->sslfingerprint, realhost, + ctl->server.pollname, &ctl->remotename) != -1) + { + /* + * RFC 2595 says this: + * + * "Once TLS has been started, the client MUST discard cached + * information about server capabilities and SHOULD re-issue the + * CAPABILITY command. This is necessary to protect against + * man-in-the-middle attacks which alter the capabilities list prior + * to STARTTLS. The server MAY advertise different capabilities + * after STARTTLS." + * + * Now that we're confident in our TLS connection we can + * guarantee a secure capability re-probe. + */ + capa_probe(sock, ctl); + if (outlevel >= O_VERBOSE) + { + report(stdout, GT_("%s: upgrade to TLS succeeded.\n"), realhost); + } + } + else if (ctl->sslfingerprint || ctl->sslcertck + || (ctl->sslproto && !strcasecmp(ctl->sslproto, "tls1"))) + { + /* Config required TLS but we couldn't guarantee it, so we must + * stop. */ + report(stderr, GT_("%s: upgrade to TLS failed.\n"), realhost); + return PS_SOCKET; + } + else + { + if (outlevel >= O_VERBOSE) + { + report(stdout, GT_("%s: opportunistic upgrade to TLS failed, trying to continue\n"), realhost); + } + /* We don't know whether the connection is in a working state, so + * test by issuing a NOOP. */ + if (gen_transact(sock, "NOOP") != PS_SUCCESS) + { + /* Not usable. Empty sslproto to force an unencrypted + * connection on the next attempt, and repoll. */ + ctl->sslproto = xstrdup(""); + return PS_REPOLL; + } + /* Usable. Proceed with authenticating insecurely. */ + } } #endif /* SSL_ENABLE */ @@ -605,16 +611,6 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting) shroud[0] = '\0'; free(password); free(remotename); -#ifdef SSL_ENABLE - /* this is for servers which claim to support TLS, but actually - * don't! */ - if (did_stls && ok == PS_SOCKET && !ctl->sslproto && !ctl->wehaveauthed) - { - ctl->sslproto = xstrdup(""); - /* repoll immediately */ - ok = PS_REPOLL; - } -#endif if (ok) { /* SASL cancellation of authentication */ |