diff options
Diffstat (limited to '')
-rw-r--r-- | security/manager/ssl/CredentialManagerSecret.cpp | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/security/manager/ssl/CredentialManagerSecret.cpp b/security/manager/ssl/CredentialManagerSecret.cpp new file mode 100644 index 0000000000..fdfe7b8ea8 --- /dev/null +++ b/security/manager/ssl/CredentialManagerSecret.cpp @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "CredentialManagerSecret.h" + +#include <windows.h> +#include <wincred.h> + +#include "mozilla/Logging.h" +#include "mozilla/SyncRunnable.h" + +// This is the implementation of CredentialManagerSecretSecret, an instantiation +// of OSKeyStore for Windows. It uses the system credential manager, hence the +// name. + +using namespace mozilla; + +LazyLogModule gCredentialManagerSecretLog("credentialmanagersecret"); +struct ScopedDelete { + void operator()(CREDENTIALA* cred) { CredFree(cred); } +}; + +template <class T> +struct ScopedMaybeDelete { + void operator()(T* ptr) { + if (ptr) { + ScopedDelete del; + del(ptr); + } + } +}; +typedef std::unique_ptr<CREDENTIALA, ScopedMaybeDelete<CREDENTIALA>> + ScopedCREDENTIALA; + +CredentialManagerSecret::CredentialManagerSecret() {} + +CredentialManagerSecret::~CredentialManagerSecret() {} + +nsresult CredentialManagerSecret::Lock() { + // The Windows credential manager can't be locked. + return NS_OK; +} + +nsresult CredentialManagerSecret::Unlock() { + // The Windows credential manager is always unlocked when the user is logged + // in. + return NS_OK; +} + +nsresult CredentialManagerSecret::StoreSecret(const nsACString& aSecret, + const nsACString& aLabel) { + if (aSecret.Length() > CRED_MAX_CREDENTIAL_BLOB_SIZE) { + // Windows doesn't allow blobs larger than CRED_MAX_CREDENTIAL_BLOB_SIZE + // bytes. + MOZ_LOG(gCredentialManagerSecretLog, LogLevel::Debug, + ("StoreSecret secret must not be larger than 512 bytes (got %zd)", + aSecret.Length())); + return NS_ERROR_FAILURE; + } + CREDENTIALA cred = {0}; + cred.Type = CRED_TYPE_GENERIC; + const nsCString& label = PromiseFlatCString(aLabel); + cred.TargetName = const_cast<LPSTR>(label.get()); + cred.CredentialBlobSize = aSecret.Length(); + const nsCString& secret = PromiseFlatCString(aSecret); + cred.CredentialBlob = (LPBYTE)secret.get(); + cred.Persist = CRED_PERSIST_LOCAL_MACHINE; + cred.UserName = const_cast<char*>(""); // -Wwritable-strings + + // https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credwritea + BOOL ok = CredWriteA(&cred, 0); + if (!ok) { + MOZ_LOG(gCredentialManagerSecretLog, LogLevel::Debug, + ("CredWriteW failed %lu", GetLastError())); + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +nsresult CredentialManagerSecret::DeleteSecret(const nsACString& aLabel) { + // https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-creddeletea + const nsCString& label = PromiseFlatCString(aLabel); + BOOL ok = CredDeleteA(label.get(), CRED_TYPE_GENERIC, 0); + int error = GetLastError(); + if (!ok && error != ERROR_NOT_FOUND) { + MOZ_LOG(gCredentialManagerSecretLog, LogLevel::Debug, + ("CredDeleteA failed %d", error)); + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +nsresult CredentialManagerSecret::RetrieveSecret( + const nsACString& aLabel, + /* out */ nsACString& aSecret) { + aSecret.Truncate(); + PCREDENTIALA pcred_raw = nullptr; + const nsCString& label = PromiseFlatCString(aLabel); + // https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credreada + BOOL ok = CredReadA(label.get(), CRED_TYPE_GENERIC, 0, &pcred_raw); + ScopedCREDENTIALA pcred(pcred_raw); + if (!ok) { + MOZ_LOG(gCredentialManagerSecretLog, LogLevel::Debug, + ("CredReadA failed %lu", GetLastError())); + return NS_ERROR_FAILURE; + } + MOZ_ASSERT(pcred); + aSecret.Assign(reinterpret_cast<const char*>(pcred->CredentialBlob), + pcred->CredentialBlobSize); + return NS_OK; +} |