1449 lines
42 KiB
C++
1449 lines
42 KiB
C++
// Test.cpp : Defines the entry point for the console application.
|
||
//
|
||
|
||
#include "testglobal.h"
|
||
|
||
|
||
#include <stdio.h> // printf
|
||
|
||
|
||
#include <security.h> // General definition of a Security Support Provider
|
||
|
||
|
||
|
||
#define AUTH_USERNAME "test1"
|
||
#define AUTH_USERNAME_W L"test1"
|
||
#define AUTH_REALM "simple_digest"
|
||
#define AUTH_REALM_W L"simple_digest\"_widechar"
|
||
#define AUTH_NONCE "9b38dce631309cc25a653ebaad5b18ee01c8bf385260b26db0574a302be4c11367"
|
||
#define AUTH_METHOD "GET"
|
||
#define AUTH_ALGORITHM "md5-sess"
|
||
#define AUTH_QOP "auth"
|
||
#define AUTH_PASSWD "secret"
|
||
#define AUTH_CNONCE "34c52218425a779f41d5075931fe6c93"
|
||
#define AUTH_URI "/dir/index.html"
|
||
#define AUTH_URI_W L"/dir/index.html"
|
||
#define AUTH_URI2 "/simple_digest/progress.html"
|
||
#define AUTH_URI2_W L"/simple_digest/progress.html"
|
||
#define AUTH_NC "0000000b"
|
||
#define AUTH_NC1 "00000001"
|
||
#define AUTH_NC2 "00000002"
|
||
#define AUTH_NC3 "00000003"
|
||
#define AUTH_NC4 "00000004"
|
||
#define AUTH_REQDIGEST "60cac55049f9887c9fb853f485128368"
|
||
|
||
|
||
#define STR_BUF_SIZE 4000
|
||
|
||
|
||
// Prototypes
|
||
void PrintStatus(SECURITY_STATUS NetStatus);
|
||
void MyPrintTime(LPSTR Comment,TimeStamp ConvertTime);
|
||
|
||
|
||
int __cdecl
|
||
main(int argc, char* argv[])
|
||
{
|
||
int bPass = 1;
|
||
SECURITY_STATUS Status = STATUS_SUCCESS;
|
||
|
||
char cTemp[STR_BUF_SIZE]; // temp buffer for scratch data
|
||
char cOutputTemp[STR_BUF_SIZE];
|
||
char szOutSecBuf[STR_BUF_SIZE];
|
||
char szChallenge[STR_BUF_SIZE];
|
||
char szISCChallengeResponse[STR_BUF_SIZE]; // Output buffer from ISC
|
||
char szASCChallengeResponse[STR_BUF_SIZE]; // Output buffer from ASC
|
||
|
||
// SSPI Interface tests
|
||
|
||
ULONG PackageCount = 0;
|
||
int i = 0;
|
||
PSecPkgInfo pPackageInfo = NULL;
|
||
PSecPkgInfo pPackageTmp = NULL;
|
||
SECURITY_STATUS TmpStatus = STATUS_SUCCESS;
|
||
HANDLE hClientToken = NULL;
|
||
CredHandle ServerCred;
|
||
CredHandle ClientCred;
|
||
TimeStamp Lifetime;
|
||
BOOL bServerCred = FALSE;
|
||
BOOL bClientCred = FALSE;
|
||
BOOL bRC = FALSE;
|
||
|
||
|
||
ULONG ContextReqFlags = 0;
|
||
ULONG ContextFlagsUtilized = 0;
|
||
ULONG TargetDataRep = 0;
|
||
ULONG ContextAttributes = 0;
|
||
|
||
|
||
CtxtHandle OldContextHandle;
|
||
CtxtHandle ServerCtxtHandle;
|
||
CtxtHandle ClientCtxtHandle;
|
||
|
||
SecBufferDesc InputBuffers;
|
||
SecBufferDesc OutputBuffers;
|
||
SecBuffer TempTokensIn[6];
|
||
SecBuffer TempTokensOut[6];
|
||
|
||
SecPkgContext_Names SecServerName;
|
||
SecPkgCredentials_Names SecCredClientName;
|
||
SecPkgContext_StreamSizes StreamSizes;
|
||
TimeStamp SecContextExpiry;
|
||
|
||
PCHAR pcPtr = NULL;
|
||
int iLen = 0;
|
||
|
||
STRING strChallenge;
|
||
STRING strMethod;
|
||
STRING strURL;
|
||
STRING strHEntity;
|
||
STRING strOutBuffer;
|
||
|
||
UNICODE_STRING ustrUsername;
|
||
UNICODE_STRING ustrPassword;
|
||
UNICODE_STRING ustrDomain;
|
||
STRING strTemp;
|
||
|
||
ULONG ulMessSeqNo = 0;
|
||
ULONG ulQOP = 0;
|
||
|
||
SEC_WINNT_AUTH_IDENTITY_W AuthData;
|
||
|
||
printf("Begining TESTB...\n");
|
||
|
||
ZeroMemory(&ClientCred, sizeof(CredHandle));
|
||
ZeroMemory(&ServerCred, sizeof(CredHandle));
|
||
ZeroMemory(&OldContextHandle, sizeof(CtxtHandle));
|
||
ZeroMemory(&ServerCtxtHandle, sizeof(CtxtHandle));
|
||
ZeroMemory(&ClientCtxtHandle, sizeof(CtxtHandle));
|
||
ZeroMemory(&SecServerName, sizeof(SecPkgContext_Names));
|
||
ZeroMemory(&SecCredClientName, sizeof(SecPkgCredentials_Names));
|
||
ZeroMemory(&SecContextExpiry, sizeof(SecContextExpiry));
|
||
|
||
ZeroMemory(&ustrUsername, sizeof(ustrUsername));
|
||
ZeroMemory(&ustrPassword, sizeof(ustrPassword));
|
||
ZeroMemory(&ustrDomain, sizeof(ustrDomain));
|
||
ZeroMemory(&strTemp, sizeof(strTemp));
|
||
ZeroMemory(&StreamSizes, sizeof(StreamSizes));
|
||
|
||
// Pull out any command line args
|
||
if (argc > 1)
|
||
{
|
||
for (i = 1; i < argc; i++)
|
||
{
|
||
pcPtr = argv[i];
|
||
if (*pcPtr == '-')
|
||
{
|
||
iLen = strlen(pcPtr);
|
||
if (iLen >= 2)
|
||
{
|
||
switch (*(pcPtr + 1))
|
||
{
|
||
case 'u':
|
||
Status = RtlCreateUnicodeStringFromAsciiz(&ustrUsername, (pcPtr + 2));
|
||
break;
|
||
case 'd':
|
||
Status = RtlCreateUnicodeStringFromAsciiz(&ustrDomain, (pcPtr + 2));
|
||
break;
|
||
case 'p':
|
||
Status = RtlCreateUnicodeStringFromAsciiz(&ustrPassword, (pcPtr + 2));
|
||
break;
|
||
case '?':
|
||
default:
|
||
printf("Usage: %s -uUsername -pPassword -ddomain\n", argv[0]);
|
||
return(-1);
|
||
break;
|
||
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Get info about the security packages.
|
||
//
|
||
|
||
Status = EnumerateSecurityPackages( &PackageCount, &pPackageInfo );
|
||
TmpStatus = GetLastError();
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
printf( "FAILED: EnumerateSecurityPackages failed: 0x%x\n", Status);
|
||
PrintStatus( Status );
|
||
bPass = 0;
|
||
goto CleanUp;
|
||
}
|
||
|
||
printf( "PackageCount: %ld\n", PackageCount );
|
||
for ( i= 0; i< (int)PackageCount; i++)
|
||
{
|
||
pPackageTmp = (pPackageInfo + i);
|
||
printf( "Name: %ws Comment: %ws\n", pPackageTmp->Name, pPackageTmp->Comment );
|
||
printf( "Cap: %ld Version: %ld RPCid: %ld MaxToken: %ld\n\n",
|
||
pPackageTmp->fCapabilities,
|
||
pPackageTmp->wVersion,
|
||
pPackageTmp->wRPCID,
|
||
pPackageTmp->cbMaxToken );
|
||
}
|
||
|
||
//
|
||
// Get info about the security packages.
|
||
//
|
||
|
||
Status = QuerySecurityPackageInfo( WDIGEST_SP_NAME, &pPackageInfo );
|
||
TmpStatus = GetLastError();
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
printf( "FAILED: QuerySecurityPackageInfo failed: status 0x%x\n", Status);
|
||
PrintStatus( Status );
|
||
bPass = 0;
|
||
goto CleanUp;
|
||
}
|
||
|
||
printf( "Name: %ws Comment: %ws\n", pPackageInfo->Name, pPackageInfo->Comment );
|
||
printf( "Cap: %ld Version: %ld RPCid: %ld MaxToken: %ld\n\n",
|
||
pPackageInfo->fCapabilities,
|
||
pPackageInfo->wVersion,
|
||
pPackageInfo->wRPCID,
|
||
pPackageInfo->cbMaxToken );
|
||
|
||
|
||
//
|
||
// Acquire a credential handle for the server side
|
||
//
|
||
|
||
printf("Server AcquireCredentialHandle\n");
|
||
Status = AcquireCredentialsHandle(
|
||
NULL, // New principal
|
||
WDIGEST_SP_NAME, // Package Name
|
||
SECPKG_CRED_INBOUND,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
&ServerCred,
|
||
&Lifetime );
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
printf( "FAILED: AcquireCredentialsHandle failed: status 0x%x\n", Status);
|
||
// TmpStatus = GetLastError();
|
||
PrintStatus( Status );
|
||
bPass = 0;
|
||
ZeroMemory(&ServerCred, sizeof(CredHandle));
|
||
goto CleanUp;
|
||
}
|
||
bServerCred = TRUE;
|
||
MyPrintTime("Server ACH LifeTime: ", Lifetime);
|
||
|
||
//
|
||
// Acquire a credential handle for the client side
|
||
//
|
||
printf("Client AcquireCredentialHandle\n");
|
||
|
||
if (ustrUsername.Length || ustrPassword.Length || ustrDomain.Length)
|
||
{
|
||
printf("ACH Using supplied credentials\n");
|
||
printf(" Username %wZ Domain %wZ Password %wZ\n",
|
||
&ustrUsername, &ustrDomain, &ustrPassword);
|
||
|
||
ZeroMemory(&AuthData, sizeof(SEC_WINNT_AUTH_IDENTITY_W));
|
||
AuthData.Domain = ustrDomain.Buffer;
|
||
AuthData.DomainLength = ustrDomain.Length / sizeof(WCHAR);
|
||
AuthData.Password = ustrPassword.Buffer;
|
||
AuthData.PasswordLength = ustrPassword.Length / sizeof(WCHAR);
|
||
AuthData.User = ustrUsername.Buffer;
|
||
AuthData.UserLength = ustrUsername.Length / sizeof(WCHAR);
|
||
AuthData.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
|
||
|
||
Status = AcquireCredentialsHandle(
|
||
NULL, // AUTH_USERNAME_W, // get the creds for user digest
|
||
WDIGEST_SP_NAME, // Package Name
|
||
SECPKG_CRED_OUTBOUND,
|
||
NULL,
|
||
&AuthData, // Make NULL not to use any AuthData for cred
|
||
NULL,
|
||
NULL,
|
||
&ClientCred,
|
||
&Lifetime );
|
||
}
|
||
else
|
||
{
|
||
printf("ACH Using default credentials\n");
|
||
Status = AcquireCredentialsHandle(
|
||
NULL, // AUTH_USERNAME_W, // get the creds for user digest
|
||
WDIGEST_SP_NAME, // Package Name
|
||
SECPKG_CRED_OUTBOUND,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
&ClientCred,
|
||
&Lifetime );
|
||
}
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
printf( "FAILED: AcquireCredentialsHandle failed: status 0x%x\n", Status);
|
||
// TmpStatus = GetLastError();
|
||
PrintStatus( Status );
|
||
bPass = 0;
|
||
// ZeroMemory(&ClientCred, sizeof(CredHandle));
|
||
goto CleanUp;
|
||
}
|
||
else
|
||
bClientCred = TRUE;
|
||
|
||
|
||
printf( "ClientCred: 0x%lx 0x%lx ",
|
||
ClientCred.dwLower, ClientCred.dwUpper );
|
||
printf( "ServerCred: 0x%lx 0x%lx \n",
|
||
ServerCred.dwLower, ServerCred.dwUpper );
|
||
MyPrintTime( "Client ACH Lifetime: ", Lifetime );
|
||
|
||
|
||
// Big time - call Accept with no parameters to get a challenge
|
||
|
||
|
||
StringAllocate(&strChallenge, 1);
|
||
|
||
StringCharDuplicate(&strMethod, "GET");
|
||
StringCharDuplicate(&strURL, AUTH_URI);
|
||
StringAllocate(&strHEntity, NULL);
|
||
|
||
StringAllocate(&strOutBuffer, 4000);
|
||
|
||
|
||
// ZeroMemory(TempTokensIn, sizeof(TempTokensIn));
|
||
// ZeroMemory(TempTokensOut, sizeof(TempTokensOut));
|
||
ZeroMemory(&InputBuffers, sizeof(InputBuffers));
|
||
ZeroMemory(&OutputBuffers, sizeof(OutputBuffers));
|
||
|
||
|
||
InputBuffers.ulVersion = SECBUFFER_VERSION;
|
||
InputBuffers.cBuffers = 5;
|
||
InputBuffers.pBuffers = TempTokensIn;
|
||
|
||
TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
|
||
TempTokensIn[0].cbBuffer = 0; // for NULL
|
||
TempTokensIn[0].pvBuffer = NULL;
|
||
TempTokensIn[1].BufferType = SECBUFFER_PKG_PARAMS;
|
||
TempTokensIn[1].cbBuffer = 0; // for NULL
|
||
TempTokensIn[1].pvBuffer = NULL;
|
||
TempTokensIn[2].BufferType = SECBUFFER_PKG_PARAMS;
|
||
TempTokensIn[2].cbBuffer = 0; // for NULL
|
||
TempTokensIn[2].pvBuffer = NULL;
|
||
TempTokensIn[3].BufferType = SECBUFFER_PKG_PARAMS;
|
||
TempTokensIn[3].cbBuffer = 0; // strHEntity.Length + 1; // for NULL
|
||
TempTokensIn[3].pvBuffer = NULL; // strHEntity.Buffer;
|
||
TempTokensIn[4].BufferType = SECBUFFER_PKG_PARAMS;
|
||
TempTokensIn[4].cbBuffer = 0; // (wcslen(AUTH_REALM_W) + 1) * sizeof(WCHAR); // Realm size count to use for this challenge
|
||
TempTokensIn[4].pvBuffer = NULL; // AUTH_REALM_W; // Realm to use for this challenge
|
||
|
||
|
||
OutputBuffers.ulVersion = SECBUFFER_VERSION;
|
||
OutputBuffers.cBuffers = 1;
|
||
OutputBuffers.pBuffers = TempTokensOut;
|
||
|
||
TempTokensOut[0].BufferType = SECBUFFER_TOKEN;
|
||
TempTokensOut[0].cbBuffer = 0; // strOutBuffer.MaximumLength; // use any space here
|
||
TempTokensOut[0].pvBuffer = NULL; // strOutBuffer.Buffer;
|
||
|
||
ContextReqFlags = ASC_REQ_REPLAY_DETECT | ASC_REQ_CONNECTION | ASC_REQ_ALLOCATE_MEMORY;
|
||
|
||
printf("ASC will create the output buffer\n");
|
||
|
||
Status = AcceptSecurityContext(
|
||
&ServerCred,
|
||
NULL,
|
||
&InputBuffers,
|
||
ContextReqFlags,
|
||
TargetDataRep,
|
||
&ServerCtxtHandle,
|
||
&OutputBuffers,
|
||
&ContextAttributes,
|
||
&Lifetime);
|
||
|
||
if ((Status != SEC_I_CONTINUE_NEEDED) &&
|
||
(Status != STATUS_SUCCESS)) // Indicates that this is the challenge
|
||
{
|
||
printf("FAILED: SpAcceptLsaModeContext error status 0x%x\n", Status);
|
||
PrintStatus( Status );
|
||
bPass = 0;
|
||
goto CleanUp;
|
||
}
|
||
|
||
if (!OutputBuffers.pBuffers[0].pvBuffer && OutputBuffers.pBuffers[0].cbBuffer)
|
||
{
|
||
printf("FAILED: SpAcceptLsaModeContext invalid output buffer pointer with length provided\n");
|
||
Status = SEC_E_INTERNAL_ERROR;
|
||
PrintStatus( Status );
|
||
bPass = 0;
|
||
goto CleanUp;
|
||
}
|
||
|
||
ZeroMemory(cOutputTemp, STR_BUF_SIZE); // contains the output buffer
|
||
ZeroMemory(szChallenge, STR_BUF_SIZE); // contains the output buffer
|
||
strncpy(cOutputTemp, (char *)OutputBuffers.pBuffers[0].pvBuffer, OutputBuffers.pBuffers[0].cbBuffer);
|
||
cOutputTemp[OutputBuffers.pBuffers[0].cbBuffer] = '\0';
|
||
strncpy(szChallenge, (char *)OutputBuffers.pBuffers[0].pvBuffer, OutputBuffers.pBuffers[0].cbBuffer);
|
||
szChallenge[OutputBuffers.pBuffers[0].cbBuffer] = '\0';
|
||
|
||
Status = FreeContextBuffer(OutputBuffers.pBuffers[0].pvBuffer);
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
printf("FAILED: FreeContextBuffer error: status 0x%x\n", Status);
|
||
TmpStatus = GetLastError();
|
||
PrintStatus( Status );
|
||
bPass = 0;
|
||
goto CleanUp;
|
||
}
|
||
|
||
printf("Context Flags Req 0x%lx Ret 0x%lx\n", ContextReqFlags, ContextAttributes);
|
||
|
||
printf("Challenge Output Buffer is:\n%s\n\n", cOutputTemp);
|
||
|
||
MyPrintTime("Server ASC LifeTime: ", Lifetime);
|
||
|
||
printf("Now call the SSPI InitializeSecCtxt to generate the ChallengeResponse\n");
|
||
|
||
|
||
InputBuffers.ulVersion = SECBUFFER_VERSION;
|
||
InputBuffers.cBuffers = 3;
|
||
InputBuffers.pBuffers = TempTokensIn;
|
||
|
||
TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
|
||
TempTokensIn[0].cbBuffer = strlen(szChallenge) + 1; // for NULL
|
||
TempTokensIn[0].pvBuffer = szChallenge;
|
||
TempTokensIn[1].BufferType = SECBUFFER_PKG_PARAMS;
|
||
TempTokensIn[1].cbBuffer = strMethod.Length + 1; // for NULL
|
||
TempTokensIn[1].pvBuffer = strMethod.Buffer;
|
||
TempTokensIn[2].BufferType = SECBUFFER_PKG_PARAMS;
|
||
TempTokensIn[2].cbBuffer = 0; // strHEntity.Length + 1; // for NULL
|
||
TempTokensIn[2].pvBuffer = NULL; // strHEntity.Buffer;
|
||
|
||
|
||
OutputBuffers.ulVersion = SECBUFFER_VERSION;
|
||
OutputBuffers.cBuffers = 1;
|
||
OutputBuffers.pBuffers = TempTokensOut;
|
||
|
||
TempTokensOut[0].BufferType = SECBUFFER_TOKEN;
|
||
TempTokensOut[0].cbBuffer = strOutBuffer.MaximumLength; // use any space here
|
||
TempTokensOut[0].pvBuffer = strOutBuffer.Buffer;
|
||
|
||
ContextReqFlags = ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION;
|
||
|
||
Status = InitializeSecurityContext(&ClientCred,
|
||
NULL,
|
||
AUTH_URI_W,
|
||
ContextReqFlags,
|
||
NULL,
|
||
SECURITY_NATIVE_DREP,
|
||
&InputBuffers,
|
||
NULL,
|
||
&ClientCtxtHandle,
|
||
&OutputBuffers,
|
||
&ContextFlagsUtilized,
|
||
&Lifetime);
|
||
|
||
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
printf("FAILED: InitializeSecurityContext error: status 0x%x\n", Status);
|
||
TmpStatus = GetLastError();
|
||
PrintStatus( Status );
|
||
bPass = 0;
|
||
goto CleanUp;
|
||
}
|
||
|
||
printf("InitializeSecurityContext SUCCEEDED with Context Handle (0x%x,0x%x)\n",
|
||
ClientCtxtHandle.dwLower, ClientCtxtHandle.dwUpper );
|
||
|
||
|
||
printf("Context Flags Req 0x%lx Ret 0x%lx\n", ContextReqFlags, ContextFlagsUtilized);
|
||
MyPrintTime("Client ISC LifeTime: ", Lifetime);
|
||
|
||
ZeroMemory(cOutputTemp, STR_BUF_SIZE); // contains the output buffer
|
||
ZeroMemory(szChallenge, STR_BUF_SIZE); // contains the output buffer
|
||
strncpy(cOutputTemp, (char *)OutputBuffers.pBuffers[0].pvBuffer, OutputBuffers.pBuffers[0].cbBuffer);
|
||
cOutputTemp[OutputBuffers.pBuffers[0].cbBuffer] = '\0';
|
||
strncpy(szISCChallengeResponse, (char *)OutputBuffers.pBuffers[0].pvBuffer, OutputBuffers.pBuffers[0].cbBuffer);
|
||
szISCChallengeResponse[OutputBuffers.pBuffers[0].cbBuffer] = '\0';
|
||
|
||
printf("\nISC: Challenge Response Output Buffer is\n%s\n\n", szISCChallengeResponse);
|
||
|
||
InputBuffers.ulVersion = SECBUFFER_VERSION;
|
||
InputBuffers.cBuffers = 5;
|
||
InputBuffers.pBuffers = TempTokensIn;
|
||
|
||
TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
|
||
TempTokensIn[0].cbBuffer = strlen(cOutputTemp) + 1; // for NULL
|
||
TempTokensIn[0].pvBuffer = cOutputTemp;
|
||
TempTokensIn[1].BufferType = SECBUFFER_PKG_PARAMS;
|
||
TempTokensIn[1].cbBuffer = strMethod.Length + 1; // for NULL
|
||
TempTokensIn[1].pvBuffer = strMethod.Buffer;
|
||
TempTokensIn[2].BufferType = SECBUFFER_PKG_PARAMS;
|
||
TempTokensIn[2].cbBuffer = strURL.Length + 1; // for NULL
|
||
TempTokensIn[2].pvBuffer = strURL.Buffer;
|
||
TempTokensIn[3].BufferType = SECBUFFER_PKG_PARAMS;
|
||
TempTokensIn[3].cbBuffer = 0; // strHEntity.Length + 1; // for NULL
|
||
TempTokensIn[3].pvBuffer = NULL; // strHEntity.Buffer;
|
||
TempTokensIn[4].BufferType = SECBUFFER_PKG_PARAMS;
|
||
TempTokensIn[4].cbBuffer = 0; // Realm not used for challengeresponse
|
||
TempTokensIn[4].pvBuffer = NULL; // not used for challengeresponse
|
||
|
||
|
||
OutputBuffers.ulVersion = SECBUFFER_VERSION;
|
||
OutputBuffers.cBuffers = 1;
|
||
OutputBuffers.pBuffers = TempTokensOut;
|
||
|
||
TempTokensOut[0].BufferType = SECBUFFER_TOKEN;
|
||
TempTokensOut[0].cbBuffer = strOutBuffer.MaximumLength; // use any space here
|
||
TempTokensOut[0].pvBuffer = strOutBuffer.Buffer;
|
||
|
||
ContextReqFlags = ASC_REQ_REPLAY_DETECT | ASC_REQ_CONNECTION; // | ASC_REQ_ALLOCATE_MEMORY;
|
||
|
||
|
||
printf("Calling the AcceptSC with a ChallengeResponse (should talk to the DC)!\n");
|
||
Status = AcceptSecurityContext(
|
||
&ServerCred,
|
||
NULL,
|
||
&InputBuffers,
|
||
ContextReqFlags,
|
||
TargetDataRep,
|
||
&ServerCtxtHandle,
|
||
&OutputBuffers,
|
||
&ContextAttributes,
|
||
&Lifetime);
|
||
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
printf("FAILED: AcceptSecurityContext 2nd Call: status 0x%x\n", Status);
|
||
PrintStatus( Status );
|
||
bPass = 0;
|
||
goto CleanUp;
|
||
}
|
||
|
||
strcpy(szASCChallengeResponse, (char *)InputBuffers.pBuffers[0].pvBuffer);
|
||
|
||
printf("ASC has accepted the Challenge Resposne\n");
|
||
|
||
printf("Now have a valid Security Context handle from ISC and ASC\n\n");
|
||
|
||
printf("Context Flags Req 0x%lx Ret 0x%lx\n", ContextReqFlags, ContextAttributes);
|
||
|
||
MyPrintTime("Server ASC LifeTime: ", Lifetime);
|
||
|
||
|
||
Status = FreeContextBuffer(OutputBuffers.pBuffers[0].pvBuffer);
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
printf("FAILED: FreeContextBuffer error: status 0x%x\n", Status);
|
||
TmpStatus = GetLastError();
|
||
PrintStatus( Status );
|
||
bPass = 0;
|
||
goto CleanUp;
|
||
}
|
||
|
||
// Now get some info on the securitycontexts
|
||
Status = QueryContextAttributes(&ServerCtxtHandle, SECPKG_ATTR_NAMES, &SecServerName);
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
printf("FAILED: QueryContextAttributes error: status 0x%x\n", Status);
|
||
PrintStatus( Status );
|
||
bPass = 0;
|
||
goto CleanUp;
|
||
}
|
||
|
||
if (SecServerName.sUserName)
|
||
{
|
||
printf("QueryContextAttributes reports that Username is %S\n", SecServerName.sUserName);
|
||
}
|
||
|
||
// Now get some info on the securitycontexts
|
||
Status = QueryContextAttributes(&ServerCtxtHandle, SECPKG_ATTR_PASSWORD_EXPIRY, &SecContextExpiry);
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
printf("FAILED: QueryContextAttributes error: status 0x%x\n", Status);
|
||
PrintStatus( Status );
|
||
bPass = 0;
|
||
goto CleanUp;
|
||
}
|
||
|
||
MyPrintTime("QueryContextAttributes reports server context expires: ", SecContextExpiry);
|
||
|
||
|
||
// Now get some info on the securitycontexts
|
||
Status = QueryContextAttributes(&ServerCtxtHandle, SECPKG_ATTR_STREAM_SIZES, &StreamSizes);
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
printf("FAILED: QueryContextAttributes SECPKG_ATTR_STREAM_SIZES error: status 0x%x\n", Status);
|
||
PrintStatus( Status );
|
||
bPass = 0;
|
||
goto CleanUp;
|
||
}
|
||
|
||
printf("Server Context(StreamSizes): MaxBuf %lu Blocksize %lu\n",
|
||
StreamSizes.cbMaximumMessage, StreamSizes.cbBlockSize);
|
||
|
||
// Now get some info on the securitycontexts
|
||
Status = QueryCredentialsAttributes(&ClientCred, SECPKG_CRED_ATTR_NAMES, &SecCredClientName);
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
printf("FAILED: QueryCredentialAttributes error: status 0x%x\n", Status);
|
||
PrintStatus( Status );
|
||
bPass = 0;
|
||
goto CleanUp;
|
||
}
|
||
|
||
if (SecCredClientName.sUserName)
|
||
{
|
||
printf("QueryCredentialAttributes reports that Username is %S\n", SecCredClientName.sUserName);
|
||
}
|
||
|
||
InputBuffers.ulVersion = SECBUFFER_VERSION;
|
||
InputBuffers.cBuffers = 5;
|
||
InputBuffers.pBuffers = TempTokensIn;
|
||
|
||
// The first call to MakeSignature this represents the SECOND request on this Nonce!
|
||
TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
|
||
TempTokensIn[0].cbBuffer = 0; // strlen(szISCChallengeResponse) + 1; // for NULL
|
||
TempTokensIn[0].pvBuffer = NULL; // szISCChallengeResponse;
|
||
TempTokensIn[1].BufferType = SECBUFFER_PKG_PARAMS;
|
||
TempTokensIn[1].cbBuffer = strMethod.Length + 1; // for NULL
|
||
TempTokensIn[1].pvBuffer = strMethod.Buffer;
|
||
TempTokensIn[2].BufferType = SECBUFFER_PKG_PARAMS;
|
||
TempTokensIn[2].cbBuffer = (strlen(AUTH_URI2) + 1) * sizeof(CHAR); // Realm size count to use for this challenge
|
||
TempTokensIn[2].pvBuffer = AUTH_URI2; // Realm to use for this challenge
|
||
TempTokensIn[3].BufferType = SECBUFFER_PKG_PARAMS;
|
||
TempTokensIn[3].cbBuffer = 0; // strHEntity.Length + 1; // for NULL
|
||
TempTokensIn[3].pvBuffer = NULL; // strHEntity.Buffer;
|
||
TempTokensIn[4].BufferType = SECBUFFER_PKG_PARAMS; // There is no OutputBuffers
|
||
TempTokensIn[4].cbBuffer = 4000; // So tack on another bufffer on end for output
|
||
TempTokensIn[4].pvBuffer = szOutSecBuf;
|
||
|
||
Status = MakeSignature(&ClientCtxtHandle,
|
||
ulQOP,
|
||
&InputBuffers,
|
||
0);
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
printf("FAILED: MakeSignature error: status 0x%x\n", Status);
|
||
PrintStatus( Status );
|
||
bPass = 0;
|
||
goto CleanUp;
|
||
}
|
||
|
||
printf("\nMakeSig: Challenge Response Output Buffer for 2nd message is\n%s\n", szOutSecBuf);
|
||
|
||
|
||
// You now send Output buffer to Server - in this case the buffer is szOutSecBuf
|
||
|
||
printf("Now verify that the 2nd message is Authenticate\n");
|
||
|
||
// The First message to VerifySignature is the Input to the final call of ASC
|
||
strcpy(cOutputTemp, szOutSecBuf);
|
||
TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
|
||
TempTokensIn[0].cbBuffer = strlen(cOutputTemp) + 1; // for NULL
|
||
TempTokensIn[0].pvBuffer = cOutputTemp;
|
||
|
||
Status = VerifySignature(&ServerCtxtHandle,
|
||
&InputBuffers,
|
||
ulMessSeqNo,
|
||
&ulQOP);
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
printf("FAILED: VerifySignature 1st Call error : status 0x%x\n", Status);
|
||
PrintStatus( Status );
|
||
bPass = 0;
|
||
goto CleanUp;
|
||
}
|
||
printf("Now have a authenticated 1st message under context 0x%x !\n", ServerCtxtHandle);
|
||
|
||
printf("VerifySig: Check if still OK: Output Buffer (Verify should not have modified it) is\n%s\n\n", cOutputTemp);
|
||
|
||
Status = VerifySignature(&ServerCtxtHandle,
|
||
&InputBuffers,
|
||
ulMessSeqNo,
|
||
&ulQOP);
|
||
if (NT_SUCCESS(Status))
|
||
{
|
||
printf("FAILED: VerifySignature 2nd Call should not have succeeded status 0x%x\n", Status);
|
||
bPass = 0;
|
||
goto CleanUp;
|
||
}
|
||
printf("Verified that replay does not work!!\n");
|
||
|
||
goto CleanUp;
|
||
|
||
|
||
|
||
CleanUp:
|
||
|
||
printf("Leaving NT Digest testb\n\n\n");
|
||
|
||
if (pPackageInfo)
|
||
{
|
||
FreeContextBuffer(pPackageInfo);
|
||
}
|
||
|
||
if (SecServerName.sUserName)
|
||
{
|
||
FreeContextBuffer(SecServerName.sUserName);
|
||
}
|
||
|
||
if (SecCredClientName.sUserName)
|
||
{
|
||
FreeContextBuffer(SecCredClientName.sUserName);
|
||
}
|
||
|
||
|
||
|
||
printf("About to call deletesecuritycontext\n");
|
||
|
||
//
|
||
// Free the security context handle
|
||
//
|
||
if (ServerCtxtHandle.dwLower || ServerCtxtHandle.dwUpper)
|
||
{
|
||
Status = DeleteSecurityContext(&ServerCtxtHandle);
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
printf("ERROR: DeleteSecurityContext ServerCtxtHandle failed: ");
|
||
PrintStatus(Status);
|
||
}
|
||
}
|
||
|
||
if (ClientCtxtHandle.dwLower || ClientCtxtHandle.dwUpper)
|
||
{
|
||
Status = DeleteSecurityContext(&ClientCtxtHandle);
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
printf("ERROR: DeleteSecurityContext ClientCtxtHandle failed: ");
|
||
PrintStatus(Status);
|
||
}
|
||
}
|
||
//
|
||
// Free the credential handles
|
||
//
|
||
|
||
printf("Now calling to Free the ServerCred\n");
|
||
if (bServerCred)
|
||
{
|
||
Status = FreeCredentialsHandle( &ServerCred );
|
||
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
printf( "FreeCredentialsHandle failed for ServerCred: " );
|
||
PrintStatus(Status);
|
||
}
|
||
}
|
||
|
||
printf("Now calling to Free the ServerCred\n");
|
||
if (bClientCred)
|
||
{
|
||
Status = FreeCredentialsHandle(&ClientCred);
|
||
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
printf( "FreeCredentialsHandle failed for ClientCred: " );
|
||
PrintStatus( Status );
|
||
}
|
||
}
|
||
|
||
StringFree(&strChallenge);
|
||
StringFree(&strMethod);
|
||
StringFree(&strURL);
|
||
StringFree(&strHEntity);
|
||
StringFree(&strOutBuffer);
|
||
|
||
|
||
if (bPass != 1)
|
||
{
|
||
printf("FAILED test run with one or more tests failing.\n");
|
||
}
|
||
else
|
||
{
|
||
printf("All tests passed.\n");
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
void
|
||
PrintStatus(
|
||
SECURITY_STATUS NetStatus
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Print a net status code.
|
||
|
||
Arguments:
|
||
|
||
NetStatus - The net status code to print.
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
{
|
||
printf( "Status = 0x%lx",NetStatus );
|
||
|
||
switch (NetStatus) {
|
||
|
||
case ERROR_LOGON_FAILURE:
|
||
printf( " ERROR_LOGON_FAILURE" );
|
||
break;
|
||
|
||
case ERROR_ACCESS_DENIED:
|
||
printf( " ERROR_ACCESS_DENIED" );
|
||
break;
|
||
|
||
case ERROR_NOT_SUPPORTED:
|
||
printf( " ERROR_NOT_SUPPORTED" );
|
||
break;
|
||
|
||
case ERROR_NO_LOGON_SERVERS:
|
||
printf( " ERROR_NO_LOGON_SERVERS" );
|
||
break;
|
||
|
||
case ERROR_NO_SUCH_DOMAIN:
|
||
printf( " ERROR_NO_SUCH_DOMAIN" );
|
||
break;
|
||
|
||
case ERROR_NO_TRUST_LSA_SECRET:
|
||
printf( " ERROR_NO_TRUST_LSA_SECRET" );
|
||
break;
|
||
|
||
case ERROR_NO_TRUST_SAM_ACCOUNT:
|
||
printf( " ERROR_NO_TRUST_SAM_ACCOUNT" );
|
||
break;
|
||
|
||
case ERROR_DOMAIN_TRUST_INCONSISTENT:
|
||
printf( " ERROR_DOMAIN_TRUST_INCONSISTENT" );
|
||
break;
|
||
|
||
case ERROR_BAD_NETPATH:
|
||
printf( " ERROR_BAD_NETPATH" );
|
||
break;
|
||
|
||
case ERROR_FILE_NOT_FOUND:
|
||
printf( " ERROR_FILE_NOT_FOUND" );
|
||
break;
|
||
case SEC_E_NO_SPM:
|
||
printf( " SEC_E_NO_SPM" );
|
||
break;
|
||
case SEC_E_BAD_PKGID:
|
||
printf( " SEC_E_BAD_PKGID" ); break;
|
||
case SEC_E_NOT_OWNER:
|
||
printf( " SEC_E_NOT_OWNER" ); break;
|
||
case SEC_E_CANNOT_INSTALL:
|
||
printf( " SEC_E_CANNOT_INSTALL" ); break;
|
||
case SEC_E_INVALID_TOKEN:
|
||
printf( " SEC_E_INVALID_TOKEN" ); break;
|
||
case SEC_E_CANNOT_PACK:
|
||
printf( " SEC_E_CANNOT_PACK" ); break;
|
||
case SEC_E_QOP_NOT_SUPPORTED:
|
||
printf( " SEC_E_QOP_NOT_SUPPORTED" ); break;
|
||
case SEC_E_NO_IMPERSONATION:
|
||
printf( " SEC_E_NO_IMPERSONATION" ); break;
|
||
case SEC_E_LOGON_DENIED:
|
||
printf( " SEC_E_LOGON_DENIED" ); break;
|
||
case SEC_E_UNKNOWN_CREDENTIALS:
|
||
printf( " SEC_E_UNKNOWN_CREDENTIALS" ); break;
|
||
case SEC_E_NO_CREDENTIALS:
|
||
printf( " SEC_E_NO_CREDENTIALS" ); break;
|
||
case SEC_E_MESSAGE_ALTERED:
|
||
printf( " SEC_E_MESSAGE_ALTERED" ); break;
|
||
case SEC_E_OUT_OF_SEQUENCE:
|
||
printf( " SEC_E_OUT_OF_SEQUENCE" ); break;
|
||
case SEC_E_INSUFFICIENT_MEMORY:
|
||
printf( " SEC_E_INSUFFICIENT_MEMORY" ); break;
|
||
case SEC_E_INVALID_HANDLE:
|
||
printf( " SEC_E_INVALID_HANDLE" ); break;
|
||
case SEC_E_NOT_SUPPORTED:
|
||
printf( " SEC_E_NOT_SUPPORTED" ); break;
|
||
case SEC_I_CONTINUE_NEEDED:
|
||
printf( " SEC_I_CONTINUE_NEEDED" ); break;
|
||
}
|
||
|
||
printf( "\n" );
|
||
}
|
||
|
||
|
||
|
||
void
|
||
MyPrintTime(
|
||
LPSTR Comment,
|
||
TimeStamp ConvertTime
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Print the specified time
|
||
|
||
Arguments:
|
||
|
||
Comment - Comment to print in front of the time
|
||
|
||
Time - Local time to print
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
{
|
||
LARGE_INTEGER LocalTime;
|
||
NTSTATUS Status;
|
||
|
||
printf( "%s High/low 0x%x/0x%x: ", Comment, ConvertTime.HighPart, ConvertTime.LowPart);
|
||
|
||
//
|
||
// If the time is infinite,
|
||
// just say so.
|
||
//
|
||
|
||
if ( (ConvertTime.HighPart == 0x7FFFFFFF) && (ConvertTime.LowPart == 0xFFFFFFFF) ) {
|
||
printf( "Infinite\n" );
|
||
|
||
//
|
||
// Otherwise print it more clearly
|
||
//
|
||
|
||
} else {
|
||
|
||
LocalTime.HighPart = 0;
|
||
LocalTime.LowPart = 0;
|
||
|
||
Status = RtlSystemTimeToLocalTime( &ConvertTime, &LocalTime );
|
||
if (!NT_SUCCESS( Status )) {
|
||
printf( "Can't convert time from GMT to Local time\n" );
|
||
LocalTime = ConvertTime;
|
||
}
|
||
|
||
TIME_FIELDS TimeFields;
|
||
|
||
RtlTimeToTimeFields( &LocalTime, &TimeFields );
|
||
|
||
printf( "%ld/%ld/%ld %ld:%2.2ld:%2.2ld\n",
|
||
TimeFields.Month,
|
||
TimeFields.Day,
|
||
TimeFields.Year,
|
||
TimeFields.Hour,
|
||
TimeFields.Minute,
|
||
TimeFields.Second );
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
// Support Routines
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: StringAllocate
|
||
//
|
||
// Synopsis: Allocates cb chars to STRING Buffer
|
||
//
|
||
// Arguments: pString - pointer to String to allocate memory to
|
||
//
|
||
// Returns: STATUS_SUCCESS - Normal completion
|
||
//
|
||
// Requires:
|
||
//
|
||
// Effects: allocates memory and sets STRING sizes
|
||
//
|
||
// Notes: Must call StringFree() to release memory
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
StringAllocate(
|
||
IN PSTRING pString,
|
||
IN USHORT cb
|
||
)
|
||
{
|
||
// DebugLog((DEB_TRACE, "NTDigest:Entering StringAllocate\n"));
|
||
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
||
cb = cb + 1; // Add in extra room for the terminating NULL
|
||
|
||
if (ARGUMENT_PRESENT(pString))
|
||
{
|
||
pString->Length = 0;
|
||
|
||
pString->Buffer = (char *)DigestAllocateMemory((ULONG)(cb * sizeof(CHAR)));
|
||
if (pString->Buffer)
|
||
{
|
||
pString->MaximumLength = cb;
|
||
}
|
||
else
|
||
{
|
||
pString->MaximumLength = 0;
|
||
Status = STATUS_NO_MEMORY;
|
||
goto CleanUp;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Status = STATUS_INVALID_PARAMETER;
|
||
goto CleanUp;
|
||
}
|
||
|
||
CleanUp:
|
||
// DebugLog((DEB_TRACE, "NTDigest: Leaving StringAllocate\n"));
|
||
return(Status);
|
||
|
||
}
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: StringFree
|
||
//
|
||
// Synopsis: Clears a String and releases the memory
|
||
//
|
||
// Arguments: pString - pointer to String to clear
|
||
//
|
||
// Returns: SEC_E_OK - released memory succeeded
|
||
//
|
||
// Requires:
|
||
//
|
||
// Effects: de-allocates memory with LsaFunctions.AllocateLsaHeap
|
||
//
|
||
// Notes:
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
StringFree(
|
||
IN PSTRING pString
|
||
)
|
||
{
|
||
// DebugLog((DEB_TRACE, "NTDigest:Entering StringFree\n"));
|
||
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
||
if (ARGUMENT_PRESENT(pString) &&
|
||
(pString->Buffer != NULL))
|
||
{
|
||
DigestFreeMemory(pString->Buffer);
|
||
pString->Length = 0;
|
||
pString->MaximumLength = 0;
|
||
pString->Buffer = NULL;
|
||
}
|
||
|
||
// DebugLog((DEB_TRACE, "NTDigest: Leaving StringFree\n"));
|
||
return(Status);
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: StringCharDuplicate
|
||
//
|
||
// Synopsis: Duplicates a NULL terminated char. If the source string buffer is
|
||
// NULL the destionation will be too.
|
||
//
|
||
// Arguments: Destination - Receives a copy of the source NULL Term char *
|
||
// czSource - String to copy
|
||
//
|
||
// Returns: SEC_E_OK - the copy succeeded
|
||
// SEC_E_INSUFFICIENT_MEMORY - the call to allocate
|
||
// memory failed.
|
||
//
|
||
// Requires:
|
||
//
|
||
// Effects: allocates memory with LsaFunctions.AllocateLsaHeap
|
||
//
|
||
// Notes:
|
||
//
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
StringCharDuplicate(
|
||
OUT PSTRING DestinationString,
|
||
IN OPTIONAL char *czSource
|
||
)
|
||
{
|
||
// DebugLog((DEB_TRACE, "NTDigest: Entering StringCharDuplicate\n"));
|
||
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
USHORT cbSourceCz = 0;
|
||
|
||
DestinationString->Buffer = NULL;
|
||
DestinationString->Length = 0;
|
||
DestinationString->MaximumLength = 0;
|
||
|
||
if ((ARGUMENT_PRESENT(czSource)) &&
|
||
((cbSourceCz = strlen(czSource)) != 0))
|
||
{
|
||
|
||
DestinationString->Buffer = (LPSTR) DigestAllocateMemory(cbSourceCz + sizeof(CHAR));
|
||
if (DestinationString->Buffer != NULL)
|
||
{
|
||
|
||
DestinationString->Length = cbSourceCz;
|
||
DestinationString->MaximumLength = cbSourceCz + sizeof(CHAR);
|
||
RtlCopyMemory(
|
||
DestinationString->Buffer,
|
||
czSource,
|
||
cbSourceCz
|
||
);
|
||
|
||
DestinationString->Buffer[cbSourceCz/sizeof(CHAR)] = '\0';
|
||
}
|
||
else
|
||
{
|
||
Status = STATUS_NO_MEMORY;
|
||
// DebugLog((DEB_ERROR, "NTDigest: StringCharDuplicate, DigestAllocateMemory returns NULL\n"));
|
||
goto CleanUp;
|
||
}
|
||
}
|
||
|
||
CleanUp:
|
||
|
||
// DebugLog((DEB_TRACE, "NTDigest: Leaving StringCharDuplicate\n"));
|
||
return(Status);
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: DigestAllocateMemory
|
||
//
|
||
// Synopsis: Allocate memory in either lsa mode or user mode
|
||
//
|
||
// Effects: Allocated chunk is zeroed out
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
PVOID
|
||
DigestAllocateMemory(
|
||
IN ULONG BufferSize
|
||
)
|
||
{
|
||
PVOID Buffer = NULL;
|
||
// DebugLog((DEB_TRACE, "Entering DigestAllocateMemory\n"));
|
||
|
||
Buffer = LocalAlloc(LPTR, BufferSize);
|
||
|
||
// DebugLog((DEB_TRACE, "Leaving DigestAllocateMemory\n"));
|
||
return Buffer;
|
||
}
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: NtLmFree
|
||
//
|
||
// Synopsis: Free memory in either lsa mode or user mode
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
VOID
|
||
DigestFreeMemory(
|
||
IN PVOID Buffer
|
||
)
|
||
{
|
||
// DebugLog((DEB_TRACE, "Entering DigestFreeMemory\n"));
|
||
|
||
LocalFree(Buffer);
|
||
|
||
// DebugLog((DEB_TRACE, "Leaving DigestFreeMemory\n"));
|
||
}
|
||
|
||
/*
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: DecodeUnicodeString
|
||
//
|
||
// Synopsis: Convert an encoded string into Unicode
|
||
//
|
||
// Arguments: pstrSource - pointer to String with encoded input
|
||
//
|
||
// pustrDestination - pointer to a destination Unicode string
|
||
//
|
||
// Returns: STATUS_SUCCESS - Normal completion
|
||
//
|
||
// Requires:
|
||
//
|
||
// Effects: allocates memory and sets UNICODE_STRING sizes
|
||
//
|
||
// Notes: Must call UnicodeStringFree() to release memory
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
DecodeUnicodeString(
|
||
IN PSTRING pstrSource,
|
||
IN UINT CodePage,
|
||
OUT PUNICODE_STRING pustrDestination
|
||
)
|
||
{
|
||
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
int cNumWChars = 0; // number of wide characters
|
||
int cb = 0; // number of bytes to allocate
|
||
int iRC = 0; // return code
|
||
DWORD dwError = 0;
|
||
|
||
// Handle case if there is no characters to convert
|
||
if (!pstrSource->Length)
|
||
{
|
||
pustrDestination->Length = 0;
|
||
pustrDestination->MaximumLength = 0;
|
||
pustrDestination->Buffer = NULL;
|
||
goto CleanUp;
|
||
}
|
||
|
||
// Determine number of characters needed in unicode string
|
||
cNumWChars = MultiByteToWideChar(CodePage,
|
||
0,
|
||
pstrSource->Buffer,
|
||
pstrSource->Length,
|
||
NULL,
|
||
0);
|
||
if (cNumWChars <= 0)
|
||
{
|
||
Status = E_FAIL;
|
||
dwError = GetLastError();
|
||
goto CleanUp;
|
||
}
|
||
|
||
Status = UnicodeStringAllocate(pustrDestination, (USHORT)cNumWChars);
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
goto CleanUp;
|
||
}
|
||
|
||
// We now have the space allocated so convert encoded unicode
|
||
iRC = MultiByteToWideChar(CodePage,
|
||
0,
|
||
pstrSource->Buffer,
|
||
pstrSource->Length,
|
||
pustrDestination->Buffer,
|
||
cNumWChars);
|
||
if (iRC == 0)
|
||
{
|
||
UnicodeStringFree(pustrDestination); // Free up allocation on error
|
||
Status = E_FAIL;
|
||
dwError = GetLastError();
|
||
goto CleanUp;
|
||
}
|
||
|
||
// decoding successful set size of unicode string
|
||
|
||
pustrDestination->Length = (USHORT)(iRC * sizeof(WCHAR));
|
||
|
||
|
||
CleanUp:
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: UnicodeStringDuplicate
|
||
//
|
||
// Synopsis: Duplicates a UNICODE_STRING. If the source string buffer is
|
||
// NULL the destionation will be too. Assumes Destination has
|
||
// no string info (called ClearUnicodeString)
|
||
//
|
||
// Arguments: DestinationString - Receives a copy of the source string
|
||
// SourceString - String to copy
|
||
//
|
||
// Returns: SEC_E_OK - the copy succeeded
|
||
// SEC_E_INSUFFICIENT_MEMORY - the call to allocate
|
||
// memory failed.
|
||
//
|
||
// Requires:
|
||
//
|
||
// Effects: allocates memory with DigestAllocateMemory
|
||
//
|
||
// Notes: will add a NULL character to resulting UNICODE_STRING
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
UnicodeStringDuplicate(
|
||
OUT PUNICODE_STRING DestinationString,
|
||
IN OPTIONAL PUNICODE_STRING SourceString
|
||
)
|
||
{
|
||
// DebugLog((DEB_TRACE, "NTDigest:Entering DuplicateUnicodeString\n"));
|
||
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
||
DestinationString->Buffer = NULL;
|
||
DestinationString->Length = 0;
|
||
DestinationString->MaximumLength = 0;
|
||
|
||
if ((ARGUMENT_PRESENT(SourceString)) &&
|
||
(SourceString->Buffer != NULL))
|
||
{
|
||
|
||
DestinationString->Buffer = (LPWSTR) DigestAllocateMemory(SourceString->Length + sizeof(WCHAR));
|
||
if (DestinationString->Buffer != NULL)
|
||
{
|
||
|
||
DestinationString->Length = SourceString->Length;
|
||
DestinationString->MaximumLength = SourceString->Length + sizeof(WCHAR);
|
||
RtlCopyMemory(
|
||
DestinationString->Buffer,
|
||
SourceString->Buffer,
|
||
SourceString->Length
|
||
);
|
||
|
||
DestinationString->Buffer[SourceString->Length/sizeof(WCHAR)] = L'\0';
|
||
}
|
||
else
|
||
{
|
||
Status = SEC_E_INSUFFICIENT_MEMORY;
|
||
goto CleanUp;
|
||
}
|
||
}
|
||
|
||
CleanUp:
|
||
|
||
// DebugLog((DEB_TRACE, "NTDigest: Leaving UnicodeStringDuplicate\n"));
|
||
return(Status);
|
||
}
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: UnicodeStringAllocate
|
||
//
|
||
// Synopsis: Allocates cb wide chars to STRING Buffer
|
||
//
|
||
// Arguments: pString - pointer to String to allocate memory to
|
||
//
|
||
// Returns: STATUS_SUCCESS - Normal completion
|
||
//
|
||
// Requires:
|
||
//
|
||
// Effects: allocates memory and sets STRING sizes
|
||
//
|
||
// Notes: Must call StringFree() to release memory
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
UnicodeStringAllocate(
|
||
IN PUNICODE_STRING pString,
|
||
IN USHORT cNumWChars
|
||
)
|
||
{
|
||
// DebugLog((DEB_TRACE, "Entering UnicodeStringAllocate\n"));
|
||
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
USHORT cb = 0;
|
||
|
||
cb = cNumWChars + 1; // Add in extra room for the terminating NULL
|
||
|
||
cb = cb * sizeof(WCHAR); // now convert to wide characters
|
||
|
||
|
||
if (ARGUMENT_PRESENT(pString))
|
||
{
|
||
pString->Length = 0;
|
||
|
||
pString->Buffer = (PWSTR)DigestAllocateMemory((ULONG)(cb));
|
||
if (pString->Buffer)
|
||
{
|
||
pString->MaximumLength = cb; // this value is in terms of bytes not WCHAR count
|
||
}
|
||
else
|
||
{
|
||
pString->MaximumLength = 0;
|
||
Status = SEC_E_INSUFFICIENT_MEMORY;
|
||
goto CleanUp;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Status = STATUS_INVALID_PARAMETER;
|
||
goto CleanUp;
|
||
}
|
||
|
||
CleanUp:
|
||
return(Status);
|
||
|
||
}
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: UnicodeStringClear
|
||
//
|
||
// Synopsis: Clears a UnicodeString and releases the memory
|
||
//
|
||
// Arguments: pString - pointer to UnicodeString to clear
|
||
//
|
||
// Returns: SEC_E_OK - released memory succeeded
|
||
//
|
||
// Requires:
|
||
//
|
||
// Effects: de-allocates memory with LsaFunctions.AllocateLsaHeap
|
||
//
|
||
// Notes:
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
UnicodeStringFree(
|
||
OUT PUNICODE_STRING pString
|
||
)
|
||
{
|
||
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
||
if (ARGUMENT_PRESENT(pString) &&
|
||
(pString->Buffer != NULL))
|
||
{
|
||
DigestFreeMemory(pString->Buffer);
|
||
pString->Length = 0;
|
||
pString->MaximumLength = 0;
|
||
pString->Buffer = NULL;
|
||
}
|
||
|
||
return(Status);
|
||
|
||
}
|
||
|
||
|
||
*/
|