boinc/clientsetup/win/password.cpp

140 lines
3.0 KiB
C++

// Berkeley Open Infrastructure for Network Computing
// http://boinc.berkeley.edu
//
// Source Code Originally from:
// http://support.microsoft.com/kb/814463
//
#include "stdafx.h"
#include "password.h"
//Generates a Random string of length nLen - 1. Buffer ppwd must allocate an extra character for null terminator.
//Returns TRUE if successful, FALSE if fails.
//Extended error information can be obtained from GetLastError().
BOOL GenPwd(TCHAR* ppwd, int nLen)
{
BOOL bResult = FALSE; //assume failure
HCRYPTPROV hProv = NULL;
HCRYPTHASH hHash = NULL;
//Storage for random string 4 times longer than the resulting password.
DWORD dwBufSize = nLen*4;
DWORD dwSize = Base64EncodeGetRequiredLength((int)dwBufSize);
LPSTR pEncodedString = NULL;
LPBYTE pRandomBuf = NULL;
TCHAR* pTRandomPwd = NULL;
try
{
pEncodedString = new char[dwSize];
pRandomBuf = new BYTE[dwBufSize];
// Try to acquire context to Crypto provider.
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT))
{
if (GetLastError() == NTE_BAD_KEYSET) //Test for non-existent keyset
{
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT | CRYPT_NEWKEYSET))
throw(GetLastError());
}
else
throw(GetLastError());
}
//Generate a random sequence.
if (!CryptGenRandom(hProv, dwBufSize, pRandomBuf))
{
throw(GetLastError());
}
//Get a handle to a hash, then hash the random stream.
if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
{
throw(GetLastError());
}
if (!CryptHashData(hHash, pRandomBuf, dwBufSize, NULL))
{
throw(GetLastError());
}
//Destroy the hash object.
CryptDestroyHash(hHash);
//Release Provider context
CryptReleaseContext(hProv, 0);
//Encode the hash value to base64.
if (!Base64Encode(pRandomBuf, dwBufSize, pEncodedString, (int*) &dwSize, 0))
{
throw(GetLastError());
}
//Determine how many tchars you need to convert string to base64.
int nTchars = (int) strlen(pEncodedString);
pTRandomPwd = new TCHAR[nTchars];
#ifdef UNICODE
if (MultiByteToWideChar(CP_UTF8, 0, pEncodedString, nTchars, pTRandomPwd, nTchars) == 0)
{
throw(GetLastError());
}
#else
_tcsncpy( pTRandomPwd, pEncodedString, nLen);
#endif
//Copy the first x characters of random string to output buffer.
_tcsncpy(ppwd, pTRandomPwd, nLen);
//Add null terminator to ppwd string.
ppwd[nLen] = _T('\0');
bResult = TRUE;
}
catch (DWORD)
{
//Set return value to false.
bResult = FALSE;
}
catch (...)
{
//Unknown error, throw.
throw;
}
//Clean up memory.
if (pRandomBuf)
{
delete[] pRandomBuf;
pRandomBuf = NULL;
}
if (pEncodedString)
{
delete[] pEncodedString;
pEncodedString = NULL;
}
if (pTRandomPwd)
{
delete[] pTRandomPwd;
pTRandomPwd = NULL;
}
return bResult;
}
BOOL GenerateRandomPassword( tstring& strPassword, DWORD dwDesiredLength )
{
TCHAR szBuffer[512];
BOOL bReturnValue = FALSE;
bReturnValue = GenPwd(szBuffer, dwDesiredLength);
strPassword = szBuffer;
return bReturnValue;
}