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.
 
 
 
 
 
 

531 lines
14 KiB

#include <pch.cpp>
#pragma hdrstop
#define MAX_PW_LEN 160
#define MAX_STRING_RSC_SIZE 512
#define WSZ_NULLSTRING L""
extern HINSTANCE g_hInst;
extern "C" {
typedef DWORD (WINAPI *WNETGETUSERA)(
LPCSTR lpName,
LPSTR lpUserName,
LPDWORD lpnLength
);
extern WNETGETUSERA _WNetGetUserA;
}
typedef struct _GETWINPW_DIALOGARGS
{
LPWSTR* ppszPW;
PST_PROVIDER_HANDLE *phPSTProv;
} GETWINPW_DIALOGARGS, *PGETWINPW_DIALOGARGS;
INT_PTR CALLBACK DialogGetWindowsPassword(
HWND hDlg, // handle to dialog box
UINT message, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
int iRet = IDCANCEL; // assume cancel
BOOL bSuccess = FALSE; // assume error
WCHAR szMessage[MAX_STRING_RSC_SIZE];
WCHAR szDlgTitle[MAX_STRING_RSC_SIZE];
switch (message)
{
case WM_INITDIALOG:
{
UINT uResString;
SetLastError( 0 ); // as per win32 documentation
if(SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)lParam) == 0) {
if(GetLastError() != ERROR_SUCCESS) {
EndDialog(hDlg, IDCANCEL);
return FALSE;
}
}
if(FIsWinNT()) {
uResString = IDS_GET_WINDOWS_PASSWORD_NT;
} else {
uResString = IDS_GET_WINDOWS_PASSWORD_95;
}
LoadStringU(
g_hInst,
uResString,
szMessage,
MAX_STRING_RSC_SIZE);
SetWindowTextU(GetDlgItem(hDlg, IDC_MESSAGE), szMessage);
return TRUE;
}
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
PGETWINPW_DIALOGARGS pDlgArgs;
LPWSTR* ppszPW;
WCHAR sz1[MAX_PW_LEN];
DWORD cch1 = 0;
BOOL bPasswordVerified;
pDlgArgs = (PGETWINPW_DIALOGARGS)GetWindowLongPtr(hDlg, GWLP_USERDATA);
if(pDlgArgs == 0) break; // TODO: bail out
ppszPW = pDlgArgs->ppszPW;
*ppszPW = NULL;
// must impersonate client. If it fails, bail.
if(!FImpersonateClient(pDlgArgs->phPSTProv))
break;
cch1 = GetDlgItemTextU(
hDlg,
IDC_EDIT1,
sz1,
MAX_PW_LEN);
// push an hourglass to the screen
HCURSOR curOld;
curOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
// validate password
bPasswordVerified = VerifyWindowsPassword(sz1);
// put old cursor back
SetCursor(curOld);
FRevertToSelf(pDlgArgs->phPSTProv);
// Clear any queued user keyboard entry turds before returning
MSG sMsg;
while (PeekMessage(&sMsg, hDlg, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE))
;
if(!bPasswordVerified)
{
szMessage[0] = L'\0';
LoadStringU(
g_hInst,
IDS_PASSWORD_NOVERIFY,
szMessage,
MAX_STRING_RSC_SIZE);
szDlgTitle[0] = L'\0';
LoadStringU(
g_hInst,
IDS_PASSWORD_ERROR_DLGTITLE,
szDlgTitle,
MAX_STRING_RSC_SIZE);
// this W implemented in both Win95 & NT!
MessageBoxW(
NULL, // hDlg,
szMessage,
szDlgTitle,
MB_OK|MB_ICONEXCLAMATION|MB_SERVICE_NOTIFICATION);
SetWindowTextU(GetDlgItem(hDlg, IDC_EDIT1), WSZ_NULLSTRING);
goto cleanup;
}
// now bite it: save
SS_ASSERT(ppszPW != NULL);
*ppszPW = (LPWSTR)SSAlloc( (cch1+1) * sizeof(WCHAR) );
if(*ppszPW == NULL) goto cleanup;
//
// sfield: defer copying strings until we know everything succeeded.
// this way, we don't have to zero these buffers if some
// allocs + copies succeed, and others fail.
//
wcscpy(*ppszPW, sz1);
iRet = IDOK;
bSuccess = TRUE;
cleanup:
if(cch1) RtlSecureZeroMemory(sz1, cch1 * sizeof(WCHAR));
if(!bSuccess)
{
if(*ppszPW)
{
SSFree(*ppszPW);
*ppszPW = NULL;
}
return FALSE;
}
break; // things went OK, just bail to EndDialog
} // IDOK
if( LOWORD(wParam) == IDCANCEL )
break;
default:
return FALSE;
}
EndDialog(hDlg, iRet);
return bSuccess;
}
BOOL
FGetWindowsPassword(
IN PST_PROVIDER_HANDLE *hPSTProv,
IN BYTE rgbPasswordDerivedBytes[],
IN DWORD cbPasswordDerivedBytes
)
{
BOOL fRet;
LPWSTR pszPW = NULL;
if ((rgbPasswordDerivedBytes == NULL) || (cbPasswordDerivedBytes < A_SHA_DIGEST_LEN))
return FALSE;
//
// the general event flow for this routine:
//
// 1. Search cache for credentials. WinNT requires impersonating around search.
// 2. If search fails on Win95, try to get the password directly from MPR
// 3. If search fails on WinNT, check for special cases like LocalSystem and NETWORK
// Allow Local System by building fixed credential.
// Disallow NETWORK because no credentials exist (return FAILURE).
// 4. If we still don't have credentials, prompt user via UI.
//
//
// we must be impersonating around this call !!!
//
if(!FImpersonateClient(hPSTProv))
return FALSE;
fRet = GetPasswordNT(rgbPasswordDerivedBytes);
FRevertToSelf(hPSTProv);
// if either GetPassword routine fails
if (!fRet)
{
INT_PTR iRet;
DWORD cbPassword;
BOOL fCachePassword = TRUE; // cache the results by default
BOOL fSpecialCase;
if(!FImpersonateClient(hPSTProv))
goto Ret;
//
// WinNT: check for some special cases, namely, if we are runninng
// under Local System or Network credentials.
//
fRet = GetSpecialCasePasswordNT(
rgbPasswordDerivedBytes, // derived bits when fSpecialCase == TRUE
&fSpecialCase // legal special case encountered?
);
FRevertToSelf(hPSTProv);
//
// if the query failed bail out, since we encountered an illegal
// or inapproriate condition.
//
if(!fRet)
goto Ret;
//
// now, set fRet to the result of the special case test.
// so, if we encountered an allowed special case, we have an
// validly filled rgbPasswordDerivedBytes buffer. If we didn't
// encounter a legal special case, we continue on our quest for
// a password.
//
fRet = fSpecialCase;
//
// re-evaluate fRet for the special hack for Win95 above.
//
if(!fRet) {
// return a validated password
GETWINPW_DIALOGARGS DialogArgs = {&pszPW, hPSTProv};
iRet = DialogBoxParam(
g_hInst,
MAKEINTRESOURCE(IDD_GET_WINDOWS_PASSWORD),
NULL,
DialogGetWindowsPassword,
(LPARAM)&DialogArgs);
if(iRet != IDOK) goto Ret;
if (pszPW == NULL)
goto Ret;
//
// everything went fine, now derive the password bits!
//
cbPassword = WSZ_BYTECOUNT(pszPW) - sizeof(WCHAR) ;
// hash pwd, copy out
A_SHA_CTX sSHAHash;
A_SHAInit(&sSHAHash);
A_SHAUpdate(&sSHAHash, (BYTE *) pszPW, cbPassword);
RtlSecureZeroMemory(pszPW, cbPassword); // sfield: zero the password
// Finish off the hash
A_SHAFinal(&sSHAHash, rgbPasswordDerivedBytes);
}
//
// now, update the password cache
//
if(fCachePassword)
{
LUID AuthenticationId;
// get user LUID
//
// we must be impersonating around this call !!!
//
if(!FImpersonateClient(hPSTProv))
goto Ret;
if(!GetThreadAuthenticationId(
GetCurrentThread(),
&AuthenticationId))
{
FRevertToSelf(hPSTProv);
goto Ret;
}
if (!SetPasswordNT(
&AuthenticationId,
rgbPasswordDerivedBytes))
{
FRevertToSelf(hPSTProv);
goto Ret;
}
FRevertToSelf(hPSTProv);
} // fCachePassword
}
fRet = TRUE;
Ret:
if (pszPW)
SSFree(pszPW);
return fRet;
}
BOOL
FIsACLSatisfied(
IN PST_PROVIDER_HANDLE *hPSTProv,
IN PST_ACCESSRULESET *psRules,
IN DWORD dwAccess,
IN OUT LPVOID // coming soon: fill a status structure with data about access attempt
)
{
if ((psRules->cRules == 0)||(psRules->rgRules == NULL))
return TRUE;
//
// parent exe name. cached through loop
//
LPWSTR pszParentExeName = NULL;
//
// direct caller image. cached through loop
//
LPWSTR pszDirectCaller = NULL;
//
// base address of direct call module
//
DWORD_PTR BaseAddressDirect;
//
// module that is the subject of analysis
//
LPWSTR szHashTarget;
//
// search for a list of terms that are completely satisfied
//
for(DWORD cRule=0; cRule<psRules->cRules; cRule++)
{
// check only those rules that govern the right access
//
// loop while we still have dwAccess modes to check
//
if (0 == (psRules->rgRules[cRule].AccessModeFlags & dwAccess))
continue;
// evaluate the ith term
PPST_ACCESSCLAUSE pClause;
// walk down list
for(DWORD cClause=0; cClause<psRules->rgRules[cRule].cClauses; cClause++)
{
pClause = &psRules->rgRules[cRule].rgClauses[cClause];
// for each term, make sure ALL ENTRIES are satisfied
// TODO: what to do if clause data not self relative?
// not possible at this point in time, but it may come up later
//
switch(pClause->ClauseType & ~PST_SELF_RELATIVE_CLAUSE)
{
// for each type, may use the pClause->pbClauseData
case PST_SECURITY_DESCRIPTOR:
{
// passed test
continue; // next clause
}
case PST_AUTHENTICODE:
{
// passed test
continue; // next clause
}
case PST_BINARY_CHECK:
{
// passed test
continue; // next clause
}
default:
// unknown type in ACL: this chain failed, goto next chain
goto NextRule; // next rule
}
}
// YES! ALL clauses evaluated and OK
// turn off the bits that got us into this clause chain
dwAccess &= ~ psRules->rgRules[cRule].AccessModeFlags;
NextRule:
continue;
}
//Cleanup:
// cleanup
if (pszParentExeName)
SSFree(pszParentExeName);
if(pszDirectCaller)
SSFree(pszDirectCaller);
return (dwAccess == 0);
}
BOOL FGetUser(
PST_PROVIDER_HANDLE *hPSTProv,
LPWSTR* ppszUser)
{
return FGetUserName(hPSTProv, ppszUser);
}
BOOL
FGetCallerName(
IN PST_PROVIDER_HANDLE *hPSTProv,
OUT LPWSTR* ppszCallerName,
OUT DWORD_PTR *lpdwBaseAddress
)
{
return FGetParentFileName(hPSTProv, ppszCallerName, lpdwBaseAddress);
}
BOOL
FGetServerParam(
IN PST_PROVIDER_HANDLE *hPSTProv,
IN DWORD dwParam,
IN LPVOID pData,
IN OUT DWORD *pcbData
)
{
//
// check for the server get param that asks for private dispatch interfaces
//
if( dwParam == SS_SERVERPARAM_CALLBACKS &&
*pcbData >= sizeof( PRIVATE_CALLBACKS )) {
PRIVATE_CALLBACKS *PrivateCallbacks = (PRIVATE_CALLBACKS *)pData;
PrivateCallbacks->cbSize = sizeof( PRIVATE_CALLBACKS );
PrivateCallbacks->pfnFGetWindowsPassword = FGetWindowsPassword;
PrivateCallbacks->pfnAuthenticodeInitPolicy = NULL;
PrivateCallbacks->pfnAuthenticodeFinalPolicy = NULL;
*pcbData = sizeof( PRIVATE_CALLBACKS );
return TRUE;
}
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
BOOL
FSetServerParam(
IN PST_PROVIDER_HANDLE *hPSTProv,
IN DWORD dwParam,
IN LPVOID pData,
IN DWORD pcbData
)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}