Bug 1505197 - allow the user to retry reauthentication on Windows 2 times r=keeler
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Wed, 14 Nov 2018 09:07:20 +0000
changeset 446169 37dc10164964096bf7779e27ade88ee6cdaef085
parent 446168 033a89b3e00d8210043a4696ab7ad66c2bd88fe3
child 446170 c1a4345c810358c1555b38256e8d3deca325d984
push id35038
push userrmaries@mozilla.com
push dateWed, 14 Nov 2018 22:12:17 +0000
treeherdermozilla-central@4e1b2b7e0c37 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskeeler
bugs1505197
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1505197 - allow the user to retry reauthentication on Windows 2 times r=keeler This adds a hard coded number of retries for Windos re-auth. I also changed to always return NS_OK unless a real error occurred to make this behave like the macOS version. Differential Revision: https://phabricator.services.mozilla.com/D11438
security/manager/ssl/OSReauthenticator.cpp
--- a/security/manager/ssl/OSReauthenticator.cpp
+++ b/security/manager/ssl/OSReauthenticator.cpp
@@ -83,131 +83,141 @@ GetUserTokenInfo()
 // Use the Windows credential prompt to ask the user to authenticate the
 // currently used account.
 static nsresult
 ReauthenticateUserWindows(const nsACString& aPrompt,
                           /* out */ bool& reauthenticated)
 {
   reauthenticated = false;
 
-  HANDLE lsa;
-  // Get authentication handle for future user authentications.
-  // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaconnectuntrusted
-  if (LsaConnectUntrusted(&lsa) != ERROR_SUCCESS) {
-    MOZ_LOG(gCredentialManagerSecretLog,
-            LogLevel::Debug,
-            ("Error aquiring lsa. Authentication attempts will fail."));
-    return NS_ERROR_FAILURE;
-  }
-  ScopedHANDLE scopedLsa(lsa);
-
+  // Is used in next iteration if the previous login failed.
+  DWORD err = 0;
+  uint8_t numAttempts = 3;
   std::unique_ptr<char[]> userTokenInfo = GetUserTokenInfo();
-  if (!userTokenInfo || lsa == INVALID_HANDLE_VALUE) {
-    MOZ_LOG(gCredentialManagerSecretLog,
-            LogLevel::Debug,
-            ("Error setting up login and user token."));
-    return NS_ERROR_FAILURE;
-  }
 
   // CredUI prompt.
   CREDUI_INFOW credui = {};
   credui.cbSize = sizeof(credui);
   // TODO: maybe set parent (Firefox) here.
   credui.hwndParent = nullptr;
   const nsString& prompt = PromiseFlatString(NS_ConvertUTF8toUTF16(aPrompt));
   credui.pszMessageText = prompt.get();
   credui.pszCaptionText = nullptr;
   credui.hbmBanner = nullptr; // ignored
 
-  ULONG authPackage = 0;
-  LPVOID outCredBuffer = nullptr;
-  ULONG outCredSize = 0;
-  BOOL save = false;
-  // Could be used in next iteration if the previous login failed.
-  DWORD err = 0;
+  while (!reauthenticated && numAttempts > 0) {
+    --numAttempts;
+
+    HANDLE lsa;
+    // Get authentication handle for future user authentications.
+    // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaconnectuntrusted
+    if (LsaConnectUntrusted(&lsa) != ERROR_SUCCESS) {
+      MOZ_LOG(gCredentialManagerSecretLog,
+              LogLevel::Debug,
+              ("Error aquiring lsa. Authentication attempts will fail."));
+      return NS_ERROR_FAILURE;
+    }
+    ScopedHANDLE scopedLsa(lsa);
 
-  // Get user's Windows credentials.
-  // https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-creduipromptforwindowscredentialsw
-  err = CredUIPromptForWindowsCredentialsW(&credui, err, &authPackage,
-                          nullptr, 0, &outCredBuffer, &outCredSize, &save,
-                          CREDUIWIN_ENUMERATE_CURRENT_USER);
-  ScopedBuffer scopedOutCredBuffer(outCredBuffer);
-  if (err != ERROR_SUCCESS) {
-    MOZ_LOG(gCredentialManagerSecretLog,
-            LogLevel::Debug,
-            ("Error getting authPackage for user login"));
-    return NS_ERROR_FAILURE;
-  }
+    if (!userTokenInfo || lsa == INVALID_HANDLE_VALUE) {
+      MOZ_LOG(gCredentialManagerSecretLog,
+              LogLevel::Debug,
+              ("Error setting up login and user token."));
+      return NS_ERROR_FAILURE;
+    }
+
+    ULONG authPackage = 0;
+    ULONG outCredSize = 0;
+    LPVOID outCredBuffer = nullptr;
+    BOOL save = false;
 
-  // Verify the credentials.
-  TOKEN_SOURCE source;
-  PCHAR contextName = const_cast<PCHAR>("Mozilla");
-  size_t nameLength = std::min(TOKEN_SOURCE_LENGTH,
-                               static_cast<int>(strlen(contextName)));
-  // Note that the string must not be longer than TOKEN_SOURCE_LENGTH.
-  memcpy(source.SourceName, contextName, nameLength);
-  // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-allocatelocallyuniqueid
-  if (!AllocateLocallyUniqueId(&source.SourceIdentifier)) {
+    // Get user's Windows credentials.
+    // https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-creduipromptforwindowscredentialsw
+    err = CredUIPromptForWindowsCredentialsW(&credui, err, &authPackage,
+                            nullptr, 0, &outCredBuffer, &outCredSize, &save,
+                            CREDUIWIN_ENUMERATE_CURRENT_USER);
+    ScopedBuffer scopedOutCredBuffer(outCredBuffer);
+    if (err == ERROR_CANCELLED) {
+      MOZ_LOG(gCredentialManagerSecretLog,
+              LogLevel::Debug,
+              ("Error getting authPackage for user login, user cancel."));
+      return NS_OK; 
+    }
+    if (err != ERROR_SUCCESS) {
       MOZ_LOG(gCredentialManagerSecretLog,
               LogLevel::Debug,
-              ("Error allocating ID for logon process."));
+              ("Error getting authPackage for user login."));
       return NS_ERROR_FAILURE;
-  }
+    }
+
+    // Verify the credentials.
+    TOKEN_SOURCE source;
+    PCHAR contextName = const_cast<PCHAR>("Mozilla");
+    size_t nameLength = std::min(TOKEN_SOURCE_LENGTH,
+                                 static_cast<int>(strlen(contextName)));
+    // Note that the string must not be longer than TOKEN_SOURCE_LENGTH.
+    memcpy(source.SourceName, contextName, nameLength);
+    // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-allocatelocallyuniqueid
+    if (!AllocateLocallyUniqueId(&source.SourceIdentifier)) {
+        MOZ_LOG(gCredentialManagerSecretLog,
+                LogLevel::Debug,
+                ("Error allocating ID for logon process."));
+        return NS_ERROR_FAILURE;
+    }
 
-  NTSTATUS substs;
-  void* profileBuffer = nullptr;
-  ULONG profileBufferLength = 0;
-  QUOTA_LIMITS limits = {0};
-  LUID luid;
-  HANDLE token;
-  LSA_STRING name;
-  name.Buffer = contextName;
-  name.Length = strlen(name.Buffer);
-  name.MaximumLength = name.Length;
-  // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsalogonuser
-  NTSTATUS sts = LsaLogonUser(scopedLsa.get(), &name, (SECURITY_LOGON_TYPE)Interactive,
-                      authPackage, scopedOutCredBuffer.get(),
-                      outCredSize, nullptr, &source, &profileBuffer,
-                      &profileBufferLength, &luid, &token, &limits,
-                      &substs);
-  ScopedHANDLE scopedToken(token);
-  LsaFreeReturnBuffer(profileBuffer);
-  LsaDeregisterLogonProcess(scopedLsa.get());
-  if (sts == ERROR_SUCCESS) {
-      MOZ_LOG(gCredentialManagerSecretLog,
-              LogLevel::Debug,
-              ("User logged in successfully."));
-  } else {
-      MOZ_LOG(gCredentialManagerSecretLog,
-              LogLevel::Debug,
-              ("Login failed with %lx (%lx).", sts, LsaNtStatusToWinError(sts)));
-      return NS_ERROR_FAILURE;
+    NTSTATUS substs;
+    void* profileBuffer = nullptr;
+    ULONG profileBufferLength = 0;
+    QUOTA_LIMITS limits = {0};
+    LUID luid;
+    HANDLE token;
+    LSA_STRING name;
+    name.Buffer = contextName;
+    name.Length = strlen(name.Buffer);
+    name.MaximumLength = name.Length;
+    // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsalogonuser
+    NTSTATUS sts = LsaLogonUser(scopedLsa.get(), &name, (SECURITY_LOGON_TYPE)Interactive,
+                        authPackage, scopedOutCredBuffer.get(),
+                        outCredSize, nullptr, &source, &profileBuffer,
+                        &profileBufferLength, &luid, &token, &limits,
+                        &substs);
+    ScopedHANDLE scopedToken(token);
+    LsaFreeReturnBuffer(profileBuffer);
+    LsaDeregisterLogonProcess(scopedLsa.get());
+    if (sts == ERROR_SUCCESS) {
+        MOZ_LOG(gCredentialManagerSecretLog,
+                LogLevel::Debug,
+                ("User logged in successfully."));
+    } else {
+        MOZ_LOG(gCredentialManagerSecretLog,
+                LogLevel::Debug,
+                ("Login failed with %lx (%lx).", sts, LsaNtStatusToWinError(sts)));
+        continue;
+    }
+
+    // The user can select any user to log-in on the authentication prompt.
+    // Make sure that the logged in user is the current user.
+    std::unique_ptr<char[]> logonTokenInfo = GetTokenInfo(scopedToken);
+    if (!logonTokenInfo) {
+        MOZ_LOG(gCredentialManagerSecretLog,
+                LogLevel::Debug,
+                ("Error getting logon token info."));
+        return NS_ERROR_FAILURE;
+    }
+    PSID logonSID = reinterpret_cast<TOKEN_USER*>(logonTokenInfo.get())->User.Sid;
+    PSID userSID = reinterpret_cast<TOKEN_USER*>(userTokenInfo.get())->User.Sid;
+    if (EqualSid(userSID, logonSID)) {
+        MOZ_LOG(gCredentialManagerSecretLog,
+                LogLevel::Debug,
+                ("Login successfully (correct user)."));
+        reauthenticated = true;
+        break;
+    }
   }
-
-  // The user can select any user to log-in on the authentication prompt.
-  // Make sure that the logged in user is the current user.
-  std::unique_ptr<char[]> logonTokenInfo = GetTokenInfo(scopedToken);
-  if (!logonTokenInfo) {
-      MOZ_LOG(gCredentialManagerSecretLog,
-              LogLevel::Debug,
-              ("Error getting logon token info."));
-      return NS_ERROR_FAILURE;
-  }
-  PSID logonSID = reinterpret_cast<TOKEN_USER*>(logonTokenInfo.get())->User.Sid;
-  PSID userSID = reinterpret_cast<TOKEN_USER*>(userTokenInfo.get())->User.Sid;
-  if (EqualSid(userSID, logonSID)) {
-      MOZ_LOG(gCredentialManagerSecretLog,
-              LogLevel::Debug,
-              ("Login successfully (correct user)."));
-      reauthenticated = true;
-      return NS_OK;
-  }
-  MOZ_LOG(gCredentialManagerSecretLog, LogLevel::Debug,
-          ("Login failed (wrong user)."));
-  return NS_ERROR_FAILURE;
+  return NS_OK;
 }
 #endif // XP_WIN
 
 #ifdef XP_MACOSX
 #include <CoreFoundation/CoreFoundation.h>
 #include <Security/Security.h>
 
 static nsresult