Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

307 lines
6.2 KiB

/*++
Copyright (c) 2002 Microsoft Corporation
Module Name:
crypt.hxx
Abstract:
CSecureString: Encrypted string for holding passwords
History:
12-April-2002 MattRim Created
6-June-2002 MattRim Adapted for ADMT use
--*/
#include "stdafx.h"
#include <wincrypt.h>
#include <comutil.h>
#include "crypt.hxx"
#define BAIL() goto exit;
CSecureString::CSecureString() :
m_fEncrypted(false),
m_fEmpty(true),
m_pszUnencryptedString(NULL)
{
m_EncryptedData.pbData = NULL;
m_EncryptedData.cbData = 0;
return;
}
CSecureString::~CSecureString()
{
Reset();
return;
}
void
CSecureString::Reset()
{
if (m_pszUnencryptedString) {
SecureZeroMemory(m_pszUnencryptedString, wcslen(m_pszUnencryptedString) * sizeof(WCHAR));
delete [] m_pszUnencryptedString;
m_pszUnencryptedString = NULL;
}
if (m_EncryptedData.pbData) {
SecureZeroMemory(m_EncryptedData.pbData, m_EncryptedData.cbData);
LocalFree(m_EncryptedData.pbData);
m_EncryptedData.pbData = NULL;
m_EncryptedData.cbData = 0;
}
m_fEmpty = true;
return;
}
CSecureString&
CSecureString::operator=(const CSecureString& rhs)
{
bool fSucceeded = false;
//
// Free up our existing contents and reset to an empty state
//
Reset();
//
// Copy the object
//
m_fEncrypted = rhs.m_fEncrypted;
m_fEmpty = rhs.m_fEmpty;
if (rhs.m_pszUnencryptedString) {
m_pszUnencryptedString = new WCHAR[wcslen(rhs.m_pszUnencryptedString)+1];
if (!m_pszUnencryptedString) {
BAIL();
}
wcscpy(m_pszUnencryptedString, rhs.m_pszUnencryptedString);
}
if (rhs.m_EncryptedData.pbData) {
m_EncryptedData.pbData = new BYTE[rhs.m_EncryptedData.cbData];
if (!m_EncryptedData.pbData) {
BAIL();
}
m_EncryptedData.cbData = rhs.m_EncryptedData.cbData;
memcpy(m_EncryptedData.pbData, rhs.m_EncryptedData.pbData, rhs.m_EncryptedData.cbData);
}
fSucceeded = true;
exit:
if (!fSucceeded) {
Reset();
_com_issue_error(E_OUTOFMEMORY);
}
return *this;
}
CSecureString&
CSecureString::operator=(const PWCHAR& rhs)
{
bool fSucceeded = false;
//
// Free up our existing contents and reset to an empty state
//
Reset();
//
// If we're being set to an empty string, nothing much
// to do.
//
if (rhs == NULL || rhs[0] == L'\0') {
// we're done, empty string
return *this;
}
//
// Non-empty string, do the encryption
//
if (GenerateEncryptedData(rhs)) {
fSucceeded = true;
}
if (!fSucceeded) {
Reset();
_com_issue_error(E_OUTOFMEMORY);
}
m_fEncrypted = true;
m_fEmpty = false;
return *this;
}
bool
CSecureString::Decrypt()
{
DATA_BLOB DecryptedData = {0, NULL};
DWORD dwStringLength = 0;
bool fSuccess = false;
//
// Validate
//
// if already decrypted, or nothing to decrypt, nothing to do
if (!m_fEncrypted || m_EncryptedData.pbData == NULL) {
m_fEncrypted = false;
fSuccess = true;
BAIL();
}
//
// Try to decrypt the data
//
if (!CryptUnprotectData(&m_EncryptedData, // encrypted data
NULL, // description
NULL, // entropy
NULL, // reserved
NULL, // prompt structure
CRYPTPROTECT_UI_FORBIDDEN, // no UI
&DecryptedData)) {
BAIL()
}
//
// Copy the decrypted string into m_pszUnencryptedString
//
dwStringLength = DecryptedData.cbData / sizeof(WCHAR);
m_pszUnencryptedString = new WCHAR[dwStringLength];
if (!m_pszUnencryptedString) {
BAIL();
}
memcpy(m_pszUnencryptedString, DecryptedData.pbData, DecryptedData.cbData);
m_fEncrypted = false;
fSuccess = true;
exit:
if (DecryptedData.pbData) {
SecureZeroMemory (DecryptedData.pbData, DecryptedData.cbData);
LocalFree(DecryptedData.pbData);
}
return fSuccess;
}
void
CSecureString::ReleaseString()
{
//
// We always store an encrypted copy of the data, so this is basically a no-op.
// We just need to destroy the unencrypted buffer.
//
if (m_pszUnencryptedString) {
SecureZeroMemory(m_pszUnencryptedString, wcslen(m_pszUnencryptedString) * sizeof(WCHAR));
delete [] m_pszUnencryptedString;
m_pszUnencryptedString = NULL;
}
m_fEncrypted = true;
return;
}
bool
CSecureString::GetString(PWCHAR *ppszString)
{
*ppszString = NULL;
if (m_fEncrypted) {
if (!Decrypt()) {
return false;
}
}
*ppszString = m_pszUnencryptedString;
return true;
}
bool
CSecureString::GenerateEncryptedData(const PWCHAR pszSource)
{
DATA_BLOB RawData = {0, NULL};
bool fSuccess = false;
_ASSERT(pszSource != NULL);
RawData.pbData = reinterpret_cast<PBYTE>(const_cast<PWCHAR>(pszSource));
RawData.cbData = (wcslen(pszSource)+1) * sizeof(WCHAR);
if (!CryptProtectData(&RawData, // unencrypted data
L"", // description -- note: this cannot be NULL before XP
NULL, // entropy
NULL, // reserved
NULL, // prompt structure
CRYPTPROTECT_UI_FORBIDDEN | CRYPTPROTECT_LOCAL_MACHINE, // flags
&m_EncryptedData)) {
BAIL()
}
_ASSERT(m_EncryptedData.pbData != NULL);
_ASSERT(m_EncryptedData.cbData != 0);
fSuccess = true;
exit:
return fSuccess;
}