tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CredentialManagerSecret.cpp (3813B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 *
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "CredentialManagerSecret.h"
      8 
      9 #include <windows.h>
     10 #include <wincred.h>
     11 
     12 #include "mozilla/Logging.h"
     13 #include "mozilla/SyncRunnable.h"
     14 
     15 // This is the implementation of CredentialManagerSecretSecret, an instantiation
     16 // of OSKeyStore for Windows. It uses the system credential manager, hence the
     17 // name.
     18 
     19 using namespace mozilla;
     20 
     21 LazyLogModule gCredentialManagerSecretLog("credentialmanagersecret");
     22 struct ScopedDelete {
     23  void operator()(CREDENTIALA* cred) { CredFree(cred); }
     24 };
     25 
     26 template <class T>
     27 struct ScopedMaybeDelete {
     28  void operator()(T* ptr) {
     29    if (ptr) {
     30      ScopedDelete del;
     31      del(ptr);
     32    }
     33  }
     34 };
     35 typedef std::unique_ptr<CREDENTIALA, ScopedMaybeDelete<CREDENTIALA>>
     36    ScopedCREDENTIALA;
     37 
     38 CredentialManagerSecret::CredentialManagerSecret() {}
     39 
     40 CredentialManagerSecret::~CredentialManagerSecret() {}
     41 
     42 nsresult CredentialManagerSecret::StoreSecret(const nsACString& aSecret,
     43                                              const nsACString& aLabel) {
     44  if (aSecret.Length() > CRED_MAX_CREDENTIAL_BLOB_SIZE) {
     45    // Windows doesn't allow blobs larger than CRED_MAX_CREDENTIAL_BLOB_SIZE
     46    // bytes.
     47    MOZ_LOG(gCredentialManagerSecretLog, LogLevel::Debug,
     48            ("StoreSecret secret must not be larger than 512 bytes (got %zd)",
     49             aSecret.Length()));
     50    return NS_ERROR_FAILURE;
     51  }
     52  CREDENTIALA cred = {0};
     53  cred.Type = CRED_TYPE_GENERIC;
     54  const nsCString& label = PromiseFlatCString(aLabel);
     55  cred.TargetName = const_cast<LPSTR>(label.get());
     56  cred.CredentialBlobSize = aSecret.Length();
     57  const nsCString& secret = PromiseFlatCString(aSecret);
     58  cred.CredentialBlob = (LPBYTE)secret.get();
     59  cred.Persist = CRED_PERSIST_LOCAL_MACHINE;
     60  cred.UserName = const_cast<char*>("");  // -Wwritable-strings
     61 
     62  // https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credwritea
     63  BOOL ok = CredWriteA(&cred, 0);
     64  if (!ok) {
     65    MOZ_LOG(gCredentialManagerSecretLog, LogLevel::Debug,
     66            ("CredWriteW failed %lu", GetLastError()));
     67    return NS_ERROR_FAILURE;
     68  }
     69  return NS_OK;
     70 }
     71 
     72 nsresult CredentialManagerSecret::DeleteSecret(const nsACString& aLabel) {
     73  // https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-creddeletea
     74  const nsCString& label = PromiseFlatCString(aLabel);
     75  BOOL ok = CredDeleteA(label.get(), CRED_TYPE_GENERIC, 0);
     76  int error = GetLastError();
     77  if (!ok && error != ERROR_NOT_FOUND) {
     78    MOZ_LOG(gCredentialManagerSecretLog, LogLevel::Debug,
     79            ("CredDeleteA failed %d", error));
     80    return NS_ERROR_FAILURE;
     81  }
     82  return NS_OK;
     83 }
     84 
     85 nsresult CredentialManagerSecret::RetrieveSecret(
     86    const nsACString& aLabel,
     87    /* out */ nsACString& aSecret) {
     88  aSecret.Truncate();
     89  PCREDENTIALA pcred_raw = nullptr;
     90  const nsCString& label = PromiseFlatCString(aLabel);
     91  // https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credreada
     92  BOOL ok = CredReadA(label.get(), CRED_TYPE_GENERIC, 0, &pcred_raw);
     93  ScopedCREDENTIALA pcred(pcred_raw);
     94 
     95  unsigned long error = GetLastError();
     96  if (!ok && error == ERROR_NOT_FOUND) {
     97    MOZ_LOG(gCredentialManagerSecretLog, LogLevel::Debug,
     98            ("Key not found in key store"));
     99    return NS_ERROR_NOT_AVAILABLE;
    100  }
    101 
    102  if (!ok) {
    103    MOZ_LOG(gCredentialManagerSecretLog, LogLevel::Debug,
    104            ("CredReadA failed %lu", error));
    105    return NS_ERROR_FAILURE;
    106  }
    107  MOZ_ASSERT(pcred);
    108  aSecret.Assign(reinterpret_cast<const char*>(pcred->CredentialBlob),
    109                 pcred->CredentialBlobSize);
    110  return NS_OK;
    111 }