fix bug 286581, allow imap auth external, r=bienvenu
authorStacy Millions <stacy@millions.ca>
Sat, 20 Nov 2010 16:16:34 -0800
changeset 6727 667919b9f8a3ea087ce067d71d185f8032461a32
parent 6726 c785aae4b1d19ca95392ef9bf6cf51811777ead6
child 6728 39b78698b329ce48e38528e54792da9cda87ed15
push idunknown
push userunknown
push dateunknown
reviewersbienvenu
bugs286581
fix bug 286581, allow imap auth external, r=bienvenu
mail/locales/en-US/chrome/messenger/messenger.properties
mailnews/base/prefs/content/am-server.js
mailnews/base/prefs/content/am-server.xul
mailnews/base/public/MailNewsTypes2.idl
mailnews/imap/src/nsImapCore.h
mailnews/imap/src/nsImapProtocol.cpp
mailnews/imap/src/nsImapServerResponseParser.cpp
suite/locales/en-US/chrome/mailnews/messenger.properties
--- a/mail/locales/en-US/chrome/messenger/messenger.properties
+++ b/mail/locales/en-US/chrome/messenger/messenger.properties
@@ -135,16 +135,17 @@ smtpServers-confirmServerDeletion=Are yo
 
 # Account Settings - Both Incoming and SMTP server
 authNo=No authentication
 authOld=Password, original method (insecure)
 authPasswordCleartextInsecurely=Password, transmitted insecurely
 authPasswordCleartextViaSSL=Normal password
 authPasswordEncrypted=Encrypted password
 authKerberos=Kerberos / GSSAPI
+authExternal=TLS Certificate
 authNTLM=NTLM
 authAnySecure=Any secure method (deprecated)
 authAny=Any method (insecure)
 
 # LOCALIZATION NOTE(serverType-nntp): Do not translate "NNTP" in the line below
 serverType-nntp=News Server (NNTP)
 # LOCALIZATION NOTE(serverType-pop3): Do not translate "POP" in the line below
 serverType-pop3=POP Mail Server
--- a/mailnews/base/prefs/content/am-server.js
+++ b/mailnews/base/prefs/content/am-server.js
@@ -90,16 +90,17 @@ function initServerType()
   var verboseName = messengerBundle.getString(propertyName);
   setDivText("servertype.verbose", verboseName);
 
   secureSelect(true);
 
   setLabelFromStringBundle("authMethod-no", "authNo");
   setLabelFromStringBundle("authMethod-old", "authOld");
   setLabelFromStringBundle("authMethod-kerberos", "authKerberos");
+  setLabelFromStringBundle("authMethod-external", "authExternal");
   setLabelFromStringBundle("authMethod-ntlm", "authNTLM");
   setLabelFromStringBundle("authMethod-anysecure", "authAnySecure");
   setLabelFromStringBundle("authMethod-any", "authAny");
   setLabelFromStringBundle("authMethod-password-encrypted",
       "authPasswordEncrypted");
   //authMethod-password-cleartext already set in selectSelect()
 
   // Hide deprecated/hidden auth options, unless selected
--- a/mailnews/base/prefs/content/am-server.xul
+++ b/mailnews/base/prefs/content/am-server.xul
@@ -151,16 +151,17 @@
                     prefstring="mail.server.%serverkey%.authMethod">
             <menupopup id="server.authMethodPopup">
               <menuitem id="authMethod-no" value="1"/>
               <menuitem id="authMethod-old" value="2"/>
               <menuitem id="authMethod-password-cleartext" value="3"/>
               <menuitem id="authMethod-password-encrypted" value="4"/>
               <menuitem id="authMethod-kerberos" value="5"/>
               <menuitem id="authMethod-ntlm" value="6"/>
+              <menuitem id="authMethod-external" value="7"/>
               <menuitem id="authMethod-anysecure" value="8"/>
               <menuitem id="authMethod-any" value="9"/>
             </menupopup>
           </menulist>
         </row>
       </rows>
     </grid>
   </groupbox>
--- a/mailnews/base/public/MailNewsTypes2.idl
+++ b/mailnews/base/public/MailNewsTypes2.idl
@@ -99,16 +99,18 @@ interface nsMsgAuthMethod {
     const nsMsgAuthMethodValue passwordCleartext = 3;
     /// hashed password. CRAM-MD5, DIGEST-MD5
     const nsMsgAuthMethodValue passwordEncrypted = 4;
     /// Kerberos / GSSAPI (Unix single-signon)
     const nsMsgAuthMethodValue GSSAPI = 5;
     /// NTLM is a Windows single-singon scheme.
     /// Includes MSN / Passport.net, which is the same with a different name.
     const nsMsgAuthMethodValue NTLM = 6;
+    /// Auth External is cert-based authentication
+    const nsMsgAuthMethodValue External = 7;
     /// Encrypted password or Kerberos / GSSAPI or NTLM.
     /// @deprecated - for migration only.
     const nsMsgAuthMethodValue secure = 8;
     /// Let us pick any of the auth types supported by the server.
     /// Discouraged, because vulnerable to MITM attacks, even if server offers secure auth.
     const nsMsgAuthMethodValue anything = 9;
 };
 
--- a/mailnews/imap/src/nsImapCore.h
+++ b/mailnews/imap/src/nsImapCore.h
@@ -145,17 +145,18 @@ typedef enum {
     kHasAuthNTLMCapability = 0x00100000,  /* AUTH NTLM extension */
     kHasAuthMSNCapability = 0x00200000,   /* AUTH MSN extension */
     kHasStartTLSCapability = 0x00400000,   /* STARTTLS support */
     kHasAuthNoneCapability = 0x00800000, /* needs no login */
     kHasAuthGssApiCapability = 0x01000000, /* GSSAPI AUTH */
     kHasCondStoreCapability =  0x02000000, /* RFC 3551 CondStore extension */
     kHasEnableCapability    =  0x04000000, /* RFC 5161 ENABLE extension */
     kHasXListCapability    =  0x08000000,  /* XLIST extension */
-    kHasCompressDeflateCapability  =  0x10000000  /* RFC 4978 COMPRESS extension */
+    kHasCompressDeflateCapability  = 0x10000000,  /* RFC 4978 COMPRESS extension */
+    kHasAuthExternalCapability  = 0x20000000  /* RFC 2222 SASL AUTH EXTERNAL */
 } eIMAPCapabilityFlag;
 
 // this used to be part of the connection object class - maybe we should move it into 
 // something similar
 typedef enum {
     kEveryThingRFC822,
     kEveryThingRFC822Peek,
     kHeadersRFC822andUid,
--- a/mailnews/imap/src/nsImapProtocol.cpp
+++ b/mailnews/imap/src/nsImapProtocol.cpp
@@ -5466,32 +5466,36 @@ void nsImapProtocol::InitPrefAuthMethods
         m_prefAuthMethods = kHasCRAMCapability;
         break;
       case nsMsgAuthMethod::NTLM:
         m_prefAuthMethods = kHasAuthNTLMCapability | kHasAuthMSNCapability;
         break;
       case nsMsgAuthMethod::GSSAPI:
         m_prefAuthMethods = kHasAuthGssApiCapability;
         break;
+      case nsMsgAuthMethod::External:
+        m_prefAuthMethods = kHasAuthExternalCapability;
+        break;
       case nsMsgAuthMethod::secure:
         m_prefAuthMethods = kHasCRAMCapability |
             kHasAuthGssApiCapability |
             kHasAuthNTLMCapability | kHasAuthMSNCapability;
         break;
       default:
         NS_ASSERTION(false, "IMAP: authMethod pref invalid");
         // TODO log to error console
         PR_LOG(IMAP, PR_LOG_ERROR,
             ("IMAP: bad pref authMethod = %d\n", authMethodPrefValue));
         // fall to any
       case nsMsgAuthMethod::anything:
         m_prefAuthMethods = kHasAuthOldLoginCapability |
             kHasAuthLoginCapability | kHasAuthPlainCapability |
             kHasCRAMCapability | kHasAuthGssApiCapability |
-            kHasAuthNTLMCapability | kHasAuthMSNCapability;
+            kHasAuthNTLMCapability | kHasAuthMSNCapability |
+            kHasAuthExternalCapability;
         break;
     }
     NS_ASSERTION(m_prefAuthMethods != kCapabilityUndefined,
          "IMAP: InitPrefAuthMethods() didn't work");
 }
 
 /**
  * Changes m_currentAuthMethod to pick the best remaining one
@@ -5501,22 +5505,25 @@ void nsImapProtocol::InitPrefAuthMethods
 nsresult nsImapProtocol::ChooseAuthMethod()
 {
   PRInt32 serverCaps = GetServerStateParser().GetCapabilityFlag();
   PRInt32 availCaps = serverCaps & m_prefAuthMethods & ~m_failedAuthMethods;
 
   PR_LOG(IMAP, PR_LOG_DEBUG, ("IMAP auth: server caps 0x%X, pref 0x%X, failed 0x%X, avail caps 0x%X",
         serverCaps, m_prefAuthMethods, m_failedAuthMethods, availCaps));
   PR_LOG(IMAP, PR_LOG_DEBUG, ("(GSSAPI = 0x%X, CRAM = 0x%X, NTLM = 0x%X, "
-        "MSN =  0x%X, PLAIN = 0x%X, LOGIN = 0x%X, old-style IMAP login = 0x%X)",
+        "MSN =  0x%X, PLAIN = 0x%X, LOGIN = 0x%X, old-style IMAP login = 0x%X)"
+        "auth external IMAP login = 0x%X",
         kHasAuthGssApiCapability, kHasCRAMCapability, kHasAuthNTLMCapability,
         kHasAuthMSNCapability, kHasAuthPlainCapability, kHasAuthLoginCapability,
-        kHasAuthOldLoginCapability));
-
-  if (kHasAuthGssApiCapability & availCaps)
+        kHasAuthOldLoginCapability, kHasAuthExternalCapability));
+
+  if (kHasAuthExternalCapability & availCaps)
+    m_currentAuthMethod = kHasAuthExternalCapability;
+  else if (kHasAuthGssApiCapability & availCaps)
     m_currentAuthMethod = kHasAuthGssApiCapability;
   else if (kHasCRAMCapability & availCaps)
     m_currentAuthMethod = kHasCRAMCapability;
   else if (kHasAuthNTLMCapability & availCaps)
     m_currentAuthMethod = kHasAuthNTLMCapability;
   else if (kHasAuthMSNCapability & availCaps)
     m_currentAuthMethod = kHasAuthMSNCapability;
   else if (kHasAuthPlainCapability & availCaps)
@@ -5556,17 +5563,32 @@ nsresult nsImapProtocol::AuthLogin(const
   ProgressEventFunctionUsingId (IMAP_STATUS_SENDING_AUTH_LOGIN);
   IncrementCommandTagNumber();
 
   char * currentCommand=nsnull;
   nsresult rv;
 
   PR_LOG(IMAP, PR_LOG_DEBUG, ("IMAP: trying auth method 0x%X", m_currentAuthMethod));
 
-  if (flag & kHasCRAMCapability)
+  if (flag & kHasAuthExternalCapability)
+  {
+      char *base64UserName = PL_Base64Encode(userName, strlen(userName), nsnull);
+      nsCAutoString command (GetServerCommandTag());
+      command.Append(" authenticate EXTERNAL " );
+      command.Append(base64UserName);
+      command.Append(CRLF);
+	  PR_Free(base64UserName);
+      rv = SendData(command.get());
+      ParseIMAPandCheckForNewMail();
+      nsImapServerResponseParser &parser = GetServerStateParser();
+      if (parser.LastCommandSuccessful())
+        return NS_OK;
+      parser.SetCapabilityFlag(parser.GetCapabilityFlag() & ~kHasAuthExternalCapability);
+  }
+  else if (flag & kHasCRAMCapability)
   {
     NS_ENSURE_TRUE(m_imapServerSink, NS_ERROR_NULL_POINTER);
     PR_LOG(IMAP, PR_LOG_DEBUG, ("MD5 auth"));
     // inform the server that we want to begin a CRAM authentication procedure...
     nsCAutoString command (GetServerCommandTag());
     command.Append(" authenticate CRAM-MD5" CRLF);
     rv = SendData(command.get());
     NS_ENSURE_SUCCESS(rv, rv);
@@ -8263,16 +8285,17 @@ PRBool nsImapProtocol::TryToLogon()
    */
 
   PRBool newPasswordRequested = PR_FALSE;
   // This loops over 1) auth methods (only one per loop) and 2) password tries (with UI)
   while (!loginSucceeded && !skipLoop && !DeathSignalReceived())
   {
       // Get password
       if (m_currentAuthMethod != kHasAuthGssApiCapability && // GSSAPI uses no pw in apps
+          m_currentAuthMethod != kHasAuthExternalCapability &&
           m_currentAuthMethod != kHasAuthNoneCapability)
       {
           rv = GetPassword(password, newPasswordRequested);
           newPasswordRequested = PR_FALSE;
           if (rv == NS_MSG_PASSWORD_PROMPT_CANCELLED || NS_FAILED(rv))
           {
             PR_LOG(IMAP, PR_LOG_ERROR, ("IMAP: password prompt failed or user canceled it"));
             break;
--- a/mailnews/imap/src/nsImapServerResponseParser.cpp
+++ b/mailnews/imap/src/nsImapServerResponseParser.cpp
@@ -2215,16 +2215,18 @@ void nsImapServerResponseParser::capabil
       else if (token.Equals("AUTH=CRAM-MD5", nsCaseInsensitiveCStringComparator()))
         fCapabilityFlag |= kHasCRAMCapability;
       else if (token.Equals("AUTH=NTLM", nsCaseInsensitiveCStringComparator()))
         fCapabilityFlag |= kHasAuthNTLMCapability;
       else if (token.Equals("AUTH=GSSAPI", nsCaseInsensitiveCStringComparator()))
         fCapabilityFlag |= kHasAuthGssApiCapability;
       else if (token.Equals("AUTH=MSN", nsCaseInsensitiveCStringComparator()))
         fCapabilityFlag |= kHasAuthMSNCapability;
+      else if (token.Equals("AUTH=EXTERNAL", nsCaseInsensitiveCStringComparator()))
+        fCapabilityFlag |= kHasAuthExternalCapability;
       else if (token.Equals("STARTTLS", nsCaseInsensitiveCStringComparator()))
         fCapabilityFlag |= kHasStartTLSCapability;
       else if (token.Equals("LOGINDISABLED", nsCaseInsensitiveCStringComparator()))
         fCapabilityFlag &= ~kHasAuthOldLoginCapability; // remove flag
       else if (token.Equals("XSENDER", nsCaseInsensitiveCStringComparator()))
         fCapabilityFlag |= kHasXSenderCapability;
       else if (token.Equals("IMAP4", nsCaseInsensitiveCStringComparator()))
         fCapabilityFlag |= kIMAP4Capability;
--- a/suite/locales/en-US/chrome/mailnews/messenger.properties
+++ b/suite/locales/en-US/chrome/mailnews/messenger.properties
@@ -139,16 +139,17 @@ smtpServers-confirmServerDeletion=Are yo
 
 # Account Settings - Both Incoming and SMTP server
 authNo=No authentication
 authOld=Password, original method (insecure)
 authPasswordCleartextInsecurely=Password, transmitted insecurely
 authPasswordCleartextViaSSL=Normal password
 authPasswordEncrypted=Encrypted password
 authKerberos=Kerberos / GSSAPI
+authExternal=TLS Certificate
 authNTLM=NTLM
 authAnySecure=Any secure method (deprecated)
 authAny=Any method (insecure)
 
 # LOCALIZATION NOTE(serverType-nntp): Do not translate "NNTP" in the line below
 serverType-nntp=News Server (NNTP)
 # LOCALIZATION NOTE(serverType-pop3): Do not translate "POP" in the line below
 serverType-pop3=POP Mail Server