add support for POP3 CAPA command, patch by ch.ey@gmx.net, r/sr=bienvenu 219282

git-svn-id: svn://10.0.0.236/trunk@147003 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
bienvenu%nventure.com
2003-09-17 21:12:34 +00:00
parent ca8a6d2045
commit 484de384d5
2 changed files with 119 additions and 27 deletions

View File

@@ -944,8 +944,6 @@ nsPop3Protocol::WaitForResponse(nsIInputStream* inputStream, PRUint32 length)
{
if(!PL_strncasecmp(line, "+OK", 3))
m_commandResponse = line + 4;
// else if(PL_strncasecmp(m_commandResponse.get(), "Invalid login", 13))
// m_commandResponse = "+";
else // challenge answer to AUTH CRAM-MD5 and LOGIN username/password
m_commandResponse = line + 2;
}
@@ -960,11 +958,19 @@ nsPop3Protocol::WaitForResponse(nsIInputStream* inputStream, PRUint32 length)
else
m_commandResponse = line;
// search for the response codes (RFC 2449, chapter 8)
if(m_commandResponse.Find("[LOGIN-DELAY", PR_TRUE) >= 0 ||
m_commandResponse.Find("[IN-USE", PR_TRUE) >= 0)
// search for the response codes (RFC 2449, chapter 8 and RFC 3206)
if(TestCapFlag(POP3_HAS_RESP_CODES | POP3_HAS_AUTH_RESP_CODE))
{
// code for authentication failure due to the user's credentials
if(m_commandResponse.Find("[AUTH", PR_TRUE) >= 0)
SetFlag(POP3_AUTH_FAILURE);
// codes for failures due to other reasons
if(m_commandResponse.Find("[LOGIN-DELAY", PR_TRUE) >= 0 ||
m_commandResponse.Find("[IN-USE", PR_TRUE) >= 0 ||
m_commandResponse.Find("[SYS", PR_TRUE) >= 0)
SetFlag(POP3_STOPLOGIN);
// remove the codes from the response string presented to the user
PRInt32 i = m_commandResponse.FindChar(']');
if(i >= 0)
@@ -1088,7 +1094,7 @@ PRInt32 nsPop3Protocol::AuthResponse(nsIInputStream* inputStream,
*/
m_pop3ConData->command_succeeded = PR_TRUE;
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
m_pop3ConData->next_state = POP3_PROCESS_AUTH;
m_pop3ConData->next_state = POP3_SEND_CAPA;
return 0;
}
@@ -1107,7 +1113,7 @@ PRInt32 nsPop3Protocol::AuthResponse(nsIInputStream* inputStream,
if (!PL_strcmp(line, "."))
{
// now that we've read all the AUTH responses, go for it
m_pop3ConData->next_state = POP3_PROCESS_AUTH;
m_pop3ConData->next_state = POP3_SEND_CAPA;
m_pop3ConData->pause_for_read = PR_FALSE; /* don't pause */
}
else
@@ -1116,9 +1122,11 @@ PRInt32 nsPop3Protocol::AuthResponse(nsIInputStream* inputStream,
nsCOMPtr<nsISignatureVerifier> verifier = do_GetService(SIGNATURE_VERIFIER_CONTRACTID, &rv);
// this checks if psm is installed...
if (NS_SUCCEEDED(rv))
{
SetCapFlag(POP3_HAS_AUTH_CRAM_MD5);
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
}
}
else
if (!PL_strcasecmp (line, "PLAIN"))
{
@@ -1136,6 +1144,73 @@ PRInt32 nsPop3Protocol::AuthResponse(nsIInputStream* inputStream,
return 0;
}
/*
* POP3 CAPA extention, see RFC 2449, chapter 5
*/
PRInt32 nsPop3Protocol::SendCapa()
{
if(!m_pop3ConData->command_succeeded)
return(Error(POP3_SERVER_ERROR));
nsCAutoString command("CAPA" CRLF);
m_pop3ConData->next_state_after_response = POP3_CAPA_RESPONSE;
return SendData(m_url, command.get());
}
PRInt32 nsPop3Protocol::CapaResponse(nsIInputStream* inputStream,
PRUint32 length)
{
char * line;
PRUint32 ln = 0;
if (!m_pop3ConData->command_succeeded)
{
/* CAPA command not implemented */
m_pop3ConData->command_succeeded = PR_TRUE;
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
m_pop3ConData->next_state = POP3_PROCESS_AUTH;
return 0;
}
PRBool pauseForMoreData = PR_FALSE;
line = m_lineStreamBuffer->ReadNextLine(inputStream, ln, pauseForMoreData);
if(pauseForMoreData || !line)
{
m_pop3ConData->pause_for_read = PR_TRUE; /* pause */
PR_Free(line);
return(0);
}
PR_LOG(POP3LOGMODULE, PR_LOG_ALWAYS,("RECV: %s", line));
if (!PL_strcmp(line, "."))
{
// now that we've read all the CAPA responses, go for it
m_pop3ConData->next_state = POP3_PROCESS_AUTH;
m_pop3ConData->pause_for_read = PR_FALSE; /* don't pause */
}
else
// see RFC 2449, chapter 6.4
if (!PL_strcasecmp(line, "RESP-CODES"))
{
SetCapFlag(POP3_HAS_RESP_CODES);
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
}
else
// see RFC 3206, chapter 6
if (!PL_strcasecmp(line, "AUTH-RESP-CODE"))
{
SetCapFlag(POP3_HAS_AUTH_RESP_CODE);
m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
}
PR_Free(line);
return 0;
}
PRInt32 nsPop3Protocol::ProcessAuth()
{
if(m_useSecAuth)
@@ -1173,9 +1248,10 @@ PRInt32 nsPop3Protocol::AuthFallback()
m_pop3ConData->next_state = POP3_SEND_PASSWORD;
else
{
// response code received, login failed
// not because of wrong username
if(TestFlag(POP3_STOPLOGIN))
// 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_USERNAME_FAILURE));
// If one authentication failed, we're going to
@@ -1418,9 +1494,10 @@ 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))
// 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) &&
@@ -3057,7 +3134,7 @@ nsresult nsPop3Protocol::ProcessProtocolState(nsIURI * url, nsIInputStream * aIn
if (TestCapFlag(POP3_AUTH_MECH_UNDEFINED))
m_pop3ConData->next_state = POP3_SEND_AUTH;
else
m_pop3ConData->next_state = POP3_PROCESS_AUTH;
m_pop3ConData->next_state = POP3_SEND_CAPA;
}
else
m_pop3ConData->next_state = POP3_SEND_USERNAME;;
@@ -3098,7 +3175,7 @@ nsresult nsPop3Protocol::ProcessProtocolState(nsIURI * url, nsIInputStream * aIn
if (TestCapFlag(POP3_AUTH_MECH_UNDEFINED))
m_pop3ConData->next_state = POP3_SEND_AUTH;
else
m_pop3ConData->next_state = POP3_PROCESS_AUTH;
m_pop3ConData->next_state = POP3_SEND_CAPA;
}
else
m_pop3ConData->next_state = POP3_SEND_USERNAME;;
@@ -3115,6 +3192,14 @@ nsresult nsPop3Protocol::ProcessProtocolState(nsIURI * url, nsIInputStream * aIn
status = AuthResponse(aInputStream, aLength);
break;
case POP3_SEND_CAPA:
status = SendCapa();
break;
case POP3_CAPA_RESPONSE:
status = CapaResponse(aInputStream, aLength);
break;
case POP3_PROCESS_AUTH:
status = ProcessAuth();
break;

View File

@@ -103,7 +103,9 @@ enum Pop3CapabilityEnum {
POP3_HAS_AUTH_USER = 0x00001000,
POP3_HAS_AUTH_CRAM_MD5 = 0x00002000,
POP3_HAS_AUTH_APOP = 0x00004000,
POP3_HAS_AUTH_PLAIN = 0x00008000
POP3_HAS_AUTH_PLAIN = 0x00008000,
POP3_HAS_RESP_CODES = 0x00010000,
POP3_HAS_AUTH_RESP_CODE = 0x00020000
};
enum Pop3StatesEnum {
@@ -145,19 +147,20 @@ enum Pop3StatesEnum {
POP3_GET_FAKE_UIDL_TOP, // 28
POP3_SEND_AUTH, // 29
POP3_AUTH_RESPONSE, // 30
POP3_PROCESS_AUTH, // 31
POP3_AUTH_FALLBACK, // 32
POP3_SEND_CAPA, // 31
POP3_CAPA_RESPONSE, // 32
POP3_PROCESS_AUTH, // 33
POP3_AUTH_FALLBACK, // 34
POP3_AUTH_LOGIN, // 33
POP3_AUTH_LOGIN_RESPONSE, // 34
POP3_SEND_XSENDER, // 35
POP3_XSENDER_RESPONSE, // 36
POP3_SEND_GURL, // 37
POP3_AUTH_LOGIN, // 35
POP3_AUTH_LOGIN_RESPONSE, // 36
POP3_SEND_XSENDER, // 37
POP3_XSENDER_RESPONSE, // 38
POP3_SEND_GURL, // 39
POP3_GURL_RESPONSE, // 38
POP3_QUIT_RESPONSE,
POP3_INTERRUPTED,
POP3_STOPLOGIN
POP3_GURL_RESPONSE, // 40
POP3_QUIT_RESPONSE, // 41
POP3_INTERRUPTED // 42
};
@@ -260,6 +263,8 @@ typedef struct _Pop3ConData {
// commands, etc. I do not intend it to refer to protocol state)
#define POP3_PAUSE_FOR_READ 0x00000001 /* should we pause for the next read */
#define POP3_PASSWORD_FAILED 0x00000002
#define POP3_STOPLOGIN 0x00000004 /* error loging in, so stop here */
#define POP3_AUTH_FAILURE 0x00000008 /* extended code said authentication failed */
class nsPop3Protocol : public nsMsgProtocol, public nsMsgLineBuffer
@@ -332,6 +337,8 @@ private:
PRInt32 Error(PRInt32 err_code);
PRInt32 SendAuth();
PRInt32 AuthResponse(nsIInputStream* inputStream, PRUint32 length);
PRInt32 SendCapa();
PRInt32 CapaResponse(nsIInputStream* inputStream, PRUint32 length);
PRInt32 ProcessAuth();
PRInt32 AuthFallback();
PRInt32 AuthLogin();