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 }