зеркало из https://github.com/mozilla/pjs.git
fix 220486 fallback if pop3 authentication mechanism fails, patch by ch.ey@gmx.net, r/sr=bienvenu
This commit is contained in:
Родитель
70351dee50
Коммит
2f500d4123
|
@ -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
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Загрузка…
Ссылка в новой задаче