fix 220486 fallback if pop3 authentication mechanism fails, patch by ch.ey@gmx.net, r/sr=bienvenu

This commit is contained in:
bienvenu%nventure.com 2003-10-09 19:18:26 +00:00
Родитель 70351dee50
Коммит 2f500d4123
2 изменённых файлов: 129 добавлений и 101 удалений

Просмотреть файл

@ -1118,33 +1118,23 @@ PRInt32 nsPop3Protocol::AuthResponse(nsIInputStream* inputStream,
if (!PL_strcmp(line, ".")) if (!PL_strcmp(line, "."))
{ {
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
// now that we've read all the AUTH responses, go for it // now that we've read all the AUTH responses, go for it
m_pop3ConData->next_state = POP3_SEND_CAPA; m_pop3ConData->next_state = POP3_SEND_CAPA;
m_pop3ConData->pause_for_read = PR_FALSE; /* don't pause */ m_pop3ConData->pause_for_read = PR_FALSE; /* don't pause */
} }
else else if (!PL_strcasecmp (line, "CRAM-MD5"))
if (!PL_strcasecmp (line, "CRAM-MD5"))
{ {
nsCOMPtr<nsISignatureVerifier> verifier = do_GetService(SIGNATURE_VERIFIER_CONTRACTID, &rv); nsCOMPtr<nsISignatureVerifier> verifier = do_GetService(SIGNATURE_VERIFIER_CONTRACTID, &rv);
// this checks if psm is installed... // this checks if psm is installed...
if (NS_SUCCEEDED(rv)) if (NS_SUCCEEDED(rv))
{
SetCapFlag(POP3_HAS_AUTH_CRAM_MD5); SetCapFlag(POP3_HAS_AUTH_CRAM_MD5);
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
} }
} else if (!PL_strcasecmp (line, "PLAIN"))
else
if (!PL_strcasecmp (line, "PLAIN"))
{
SetCapFlag(POP3_HAS_AUTH_PLAIN); SetCapFlag(POP3_HAS_AUTH_PLAIN);
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags); else if (!PL_strcasecmp (line, "LOGIN"))
}
else
if (!PL_strcasecmp (line, "LOGIN"))
{
SetCapFlag(POP3_HAS_AUTH_LOGIN); SetCapFlag(POP3_HAS_AUTH_LOGIN);
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
}
PR_Free(line); PR_Free(line);
return 0; return 0;
@ -1159,6 +1149,11 @@ PRInt32 nsPop3Protocol::SendCapa()
if(!m_pop3ConData->command_succeeded) if(!m_pop3ConData->command_succeeded)
return(Error(POP3_SERVER_ERROR)); return(Error(POP3_SERVER_ERROR));
// for use after mechs disabled fallbacks when login failed
// should better live in AuthResponse(), but it would only
// be called the first time then
BackupAuthFlags();
nsCAutoString command("CAPA" CRLF); nsCAutoString command("CAPA" CRLF);
m_pop3ConData->next_state_after_response = POP3_CAPA_RESPONSE; m_pop3ConData->next_state_after_response = POP3_CAPA_RESPONSE;
@ -1219,6 +1214,8 @@ PRInt32 nsPop3Protocol::CapaResponse(nsIInputStream* inputStream,
PRInt32 nsPop3Protocol::ProcessAuth() PRInt32 nsPop3Protocol::ProcessAuth()
{ {
m_password_already_sent = PR_FALSE;
if(m_useSecAuth) if(m_useSecAuth)
{ {
if (TestCapFlag(POP3_HAS_AUTH_CRAM_MD5)) if (TestCapFlag(POP3_HAS_AUTH_CRAM_MD5))
@ -1248,37 +1245,107 @@ PRInt32 nsPop3Protocol::ProcessAuth()
return 0; return 0;
} }
void nsPop3Protocol::BackupAuthFlags()
{
m_origAuthFlags = m_pop3ConData->capability_flags &
(POP3_HAS_AUTH_ANY | POP3_HAS_AUTH_ANY_SEC);
}
void nsPop3Protocol::RestoreAuthFlags()
{
m_pop3ConData->capability_flags |= m_origAuthFlags;
}
PRInt32 nsPop3Protocol::AuthFallback() PRInt32 nsPop3Protocol::AuthFallback()
{ {
if (m_pop3ConData->command_succeeded) if (m_pop3ConData->command_succeeded)
if(m_password_already_sent)
{
m_nsIPop3Sink->SetUserAuthenticated(PR_TRUE);
m_pop3ConData->next_state = (m_pop3ConData->get_url)
? POP3_SEND_GURL : POP3_SEND_STAT;
}
else
m_pop3ConData->next_state = POP3_SEND_PASSWORD; m_pop3ConData->next_state = POP3_SEND_PASSWORD;
else else
{ {
// response code received, // response code received,
// login failed not because of wrong password // login failed not because of wrong credential
if(TestFlag(POP3_STOPLOGIN) || if(TestFlag(POP3_STOPLOGIN) ||
TestCapFlag(POP3_HAS_AUTH_RESP_CODE) && !TestFlag(POP3_AUTH_FAILURE)) TestCapFlag(POP3_HAS_AUTH_RESP_CODE) && !TestFlag(POP3_AUTH_FAILURE))
return(Error(POP3_USERNAME_FAILURE)); return(Error((m_password_already_sent)
? POP3_PASSWORD_FAILURE : POP3_USERNAME_FAILURE));
if (m_useSecAuth)
{
// If one authentication failed, we're going to // If one authentication failed, we're going to
// fall back on a less secure login method. // fall back on a less secure login method.
if (TestCapFlag(POP3_HAS_AUTH_CRAM_MD5)) if (TestCapFlag(POP3_HAS_AUTH_CRAM_MD5))
// if CRAM-MD5 enabled, disable it // if CRAM-MD5 enabled, disable it
ClearCapFlag(POP3_HAS_AUTH_CRAM_MD5); ClearCapFlag(POP3_HAS_AUTH_CRAM_MD5);
else else if (TestCapFlag(POP3_HAS_AUTH_APOP))
if (TestCapFlag(POP3_HAS_AUTH_APOP)) {
// if APOP enabled, disable it // if APOP enabled, disable it
ClearCapFlag(POP3_HAS_AUTH_APOP); ClearCapFlag(POP3_HAS_AUTH_APOP);
// unsure because APOP failed and we can't determine why
Error(CANNOT_PROCESS_APOP_AUTH);
}
}
else else
{
if (TestCapFlag(POP3_HAS_AUTH_PLAIN)) if (TestCapFlag(POP3_HAS_AUTH_PLAIN))
// if PLAIN enabled, disable it // if PLAIN enabled, disable it
ClearCapFlag(POP3_HAS_AUTH_PLAIN); ClearCapFlag(POP3_HAS_AUTH_PLAIN);
else if(TestCapFlag(POP3_HAS_AUTH_LOGIN))
// if LOGIN enabled, disable it
ClearCapFlag(POP3_HAS_AUTH_LOGIN);
else if(TestCapFlag(POP3_HAS_AUTH_USER))
{
if(m_password_already_sent)
// if USER enabled, disable it
ClearCapFlag(POP3_HAS_AUTH_USER);
else else
if(TestCapFlag(POP3_HAS_AUTH_LOGIN | POP3_HAS_AUTH_USER)) // if USER enabled,
// if LOGIN or USER enabled,
// it was the username which was wrong - // it was the username which was wrong -
// no fallback but return error // no fallback but return error
return(Error(POP3_USERNAME_FAILURE)); return(Error(POP3_USERNAME_FAILURE));
}
}
// Only forget the password if we've no mechanism left.
if (m_useSecAuth && !TestCapFlag(POP3_HAS_AUTH_ANY_SEC) ||
!m_useSecAuth && !TestCapFlag(POP3_HAS_AUTH_ANY))
{
// Let's restore the original auth flags from SendEhloResponse so we can
// try them again with new password and username
RestoreAuthFlags();
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
Error(POP3_PASSWORD_FAILURE);
/* The password failed.
Sever the connection and go back to the `read password' state,
which, upon success, will re-open the connection. Set a flag
which causes the prompt to be different that time (to indicate
that the old password was bogus.)
But if we're just checking for new mail (biff) then don't bother
prompting the user for a password: just fail silently.
*/
SetFlag(POP3_PASSWORD_FAILED);
m_pop3ConData->logonFailureCount++;
// libmsg event sink
if (m_nsIPop3Sink)
{
m_nsIPop3Sink->SetUserAuthenticated(PR_FALSE);
m_nsIPop3Sink->SetMailAccountURL(NULL);
}
return 0;
}
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags); m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
@ -1346,8 +1413,7 @@ PRInt32 nsPop3Protocol::SendUsername()
{ {
if (TestCapFlag(POP3_HAS_AUTH_PLAIN)) if (TestCapFlag(POP3_HAS_AUTH_PLAIN))
cmd = "AUTH PLAIN"; cmd = "AUTH PLAIN";
else else if (TestCapFlag(POP3_HAS_AUTH_LOGIN))
if (TestCapFlag(POP3_HAS_AUTH_LOGIN))
{ {
char *base64Str = char *base64Str =
PL_Base64Encode(m_username.get(), m_username.Length(), nsnull); PL_Base64Encode(m_username.get(), m_username.Length(), nsnull);
@ -1422,7 +1488,7 @@ PRInt32 nsPop3Protocol::SendPassword()
} }
if (NS_FAILED(rv)) if (NS_FAILED(rv))
ClearFlag(POP3_HAS_AUTH_CRAM_MD5); cmd = "*";
} }
else else
if (TestCapFlag(POP3_HAS_AUTH_APOP)) if (TestCapFlag(POP3_HAS_AUTH_APOP))
@ -1448,7 +1514,7 @@ PRInt32 nsPop3Protocol::SendPassword()
} }
if (NS_FAILED(rv)) if (NS_FAILED(rv))
ClearFlag(POP3_HAS_AUTH_APOP); cmd = "*";
} }
} }
else else
@ -1480,70 +1546,24 @@ PRInt32 nsPop3Protocol::SendPassword()
else else
{ {
cmd = "PASS "; cmd = "PASS ";
cmd += (const char *) password; cmd += password;
} }
} }
cmd += CRLF; cmd += CRLF;
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags); m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
m_pop3ConData->next_state_after_response = (m_pop3ConData->get_url) m_pop3ConData->next_state_after_response = POP3_AUTH_FALLBACK;
? POP3_SEND_GURL : POP3_SEND_STAT;
m_pop3ConData->pause_for_read = PR_TRUE; m_pop3ConData->pause_for_read = PR_TRUE;
m_password_already_sent = PR_TRUE;
return SendData(m_url, cmd.get(), PR_TRUE); return SendData(m_url, cmd.get(), PR_TRUE);
} }
PRInt32 nsPop3Protocol::SendStatOrGurl(PRBool sendStat) PRInt32 nsPop3Protocol::SendStatOrGurl(PRBool sendStat)
{ {
/* check password response */
if(!m_pop3ConData->command_succeeded)
{
// response code received,
// login failed not because of wrong password
if(TestFlag(POP3_STOPLOGIN) ||
TestCapFlag(POP3_HAS_AUTH_RESP_CODE) && !TestFlag(POP3_AUTH_FAILURE))
return(Error(POP3_PASSWORD_FAILURE));
if(!TestCapFlag(POP3_HAS_AUTH_CRAM_MD5) &&
TestCapFlag(POP3_HAS_AUTH_APOP))
// unsure because APOP failed and we can't determine why
Error(CANNOT_PROCESS_APOP_AUTH);
else
Error(POP3_PASSWORD_FAILURE);
/* The password failed.
Sever the connection and go back to the `read password' state,
which, upon success, will re-open the connection. Set a flag
which causes the prompt to be different that time (to indicate
that the old password was bogus.)
But if we're just checking for new mail (biff) then don't bother
prompting the user for a password: just fail silently.
*/
SetFlag(POP3_PASSWORD_FAILED);
m_pop3ConData->logonFailureCount++;
// libmsg event sink
if (m_nsIPop3Sink)
{
m_nsIPop3Sink->SetUserAuthenticated(PR_FALSE);
m_nsIPop3Sink->SetMailAccountURL(NULL);
}
/* clear the bogus password in case
* we need to sync with auth smtp password
*/
return 0;
}
else
{
m_nsIPop3Sink->SetUserAuthenticated(PR_TRUE);
}
nsCAutoString cmd; nsCAutoString cmd;
if (sendStat) if (sendStat)
{ {

Просмотреть файл

@ -108,6 +108,9 @@ enum Pop3CapabilityEnum {
POP3_HAS_AUTH_RESP_CODE = 0x00020000 POP3_HAS_AUTH_RESP_CODE = 0x00020000
}; };
#define POP3_HAS_AUTH_ANY 0x00009002
#define POP3_HAS_AUTH_ANY_SEC 0x00006000
enum Pop3StatesEnum { enum Pop3StatesEnum {
POP3_READ_PASSWORD, // 0 POP3_READ_PASSWORD, // 0
// //
@ -323,11 +326,16 @@ private:
void Abort(); void Abort();
PRBool m_useSecAuth; PRBool m_useSecAuth;
PRBool m_password_already_sent;
void SetCapFlag(PRUint32 flag); void SetCapFlag(PRUint32 flag);
void ClearCapFlag(PRUint32 flag); void ClearCapFlag(PRUint32 flag);
PRBool TestCapFlag(PRUint32 flag); PRBool TestCapFlag(PRUint32 flag);
void BackupAuthFlags();
void RestoreAuthFlags();
PRInt32 m_origAuthFlags;
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// Begin Pop3 protocol state handlers // Begin Pop3 protocol state handlers
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////