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.
1762 lines
49 KiB
1762 lines
49 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
|
|
Module Name:
|
|
|
|
ScLogon2
|
|
|
|
Abstract:
|
|
|
|
|
|
|
|
Author:
|
|
|
|
reidk
|
|
|
|
Environment:
|
|
|
|
Win32, C++ w/ Exceptions
|
|
|
|
--*/
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Includes
|
|
|
|
#if !defined(_X86_) && !defined(_AMD64_) && !defined(_IA64_)
|
|
#define _X86_ 1
|
|
#endif
|
|
#ifndef _WIN32_WINNT
|
|
#define _WIN32_WINNT 0x0400
|
|
#ifndef UNICODE
|
|
#define UNICODE
|
|
#endif
|
|
#endif
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN 1
|
|
#endif
|
|
|
|
|
|
extern "C" {
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <ntlsa.h>
|
|
}
|
|
|
|
#include <windows.h>
|
|
#include <winscard.h>
|
|
#include <wincrypt.h>
|
|
#include <softpub.h>
|
|
#include <stddef.h>
|
|
#include <crtdbg.h>
|
|
#include "sclogon.h"
|
|
#include "sclogon2.h"
|
|
#include "unicodes.h"
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
#include <tchar.h>
|
|
|
|
#include "sclgnrpc.h"
|
|
|
|
|
|
typedef struct _KERB_PUBLIC_KEY_HPROV {
|
|
RPC_BINDING_HANDLE hRPCBinding;
|
|
BINDING_CONTEXT hCertAndKey;
|
|
} KERB_PUBLIC_KEY_HPROV, *PKERB_PUBLIC_KEY_HPROV;
|
|
|
|
|
|
//
|
|
// from secpkg.h
|
|
//
|
|
typedef NTSTATUS (NTAPI LSA_IMPERSONATE_CLIENT) (VOID);
|
|
typedef LSA_IMPERSONATE_CLIENT * PLSA_IMPERSONATE_CLIENT;
|
|
|
|
|
|
bool
|
|
GetImpersonationToken(HANDLE *phThreadToken)
|
|
{
|
|
bool ret = false;
|
|
|
|
//
|
|
// This will fail if not impersonating.
|
|
//
|
|
if (OpenThreadToken(
|
|
GetCurrentThread(),
|
|
TOKEN_IMPERSONATE | TOKEN_QUERY,
|
|
TRUE,
|
|
phThreadToken))
|
|
{
|
|
ret = true;
|
|
}
|
|
else if (GetLastError() == ERROR_NO_TOKEN)
|
|
{
|
|
ret = true;
|
|
}
|
|
else
|
|
{
|
|
DbgPrint("OpenThreadToken failed - %lx\n", GetLastError());
|
|
}
|
|
|
|
return (ret);
|
|
}
|
|
|
|
DWORD
|
|
GetTSSessionID(HANDLE hThreadToken)
|
|
{
|
|
bool fRet = false;
|
|
PLIST_ENTRY Module;
|
|
PLDR_DATA_TABLE_ENTRY Entry;
|
|
BOOL fRunningInLsa = false;
|
|
HMODULE hLsa = NULL;
|
|
PLSA_IMPERSONATE_CLIENT pLsaImpersonateClient = NULL;
|
|
bool bImpersonating = false;
|
|
HANDLE hLocalThreadToken = INVALID_HANDLE_VALUE;
|
|
DWORD dwTSSessionID = 0;
|
|
DWORD dwSize;
|
|
bool fAlreadyImpersonating;
|
|
|
|
//
|
|
// Make sure we are running in LSA
|
|
//
|
|
Module = NtCurrentPeb()->Ldr->InLoadOrderModuleList.Flink;
|
|
Entry = CONTAINING_RECORD(Module,
|
|
LDR_DATA_TABLE_ENTRY,
|
|
InLoadOrderLinks);
|
|
|
|
fRunningInLsa = (0 == _wcsicmp(Entry->BaseDllName.Buffer, L"lsass.exe"));
|
|
|
|
if (!fRunningInLsa)
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
//
|
|
// Check to see if we are already impersonating by checking the thread token passed in
|
|
//
|
|
if(hThreadToken == INVALID_HANDLE_VALUE)
|
|
{
|
|
//
|
|
// If we aren't already impernonating, then we need to call the special LssImpersonateClient
|
|
//
|
|
hLsa = GetModuleHandleW(L"lsasrv.dll");
|
|
if (hLsa == NULL)
|
|
{
|
|
DbgPrint("failed to get lsa module handle\n");
|
|
goto Return;
|
|
}
|
|
|
|
pLsaImpersonateClient = (PLSA_IMPERSONATE_CLIENT) GetProcAddress(hLsa, "LsaIImpersonateClient");
|
|
if (pLsaImpersonateClient == NULL)
|
|
{
|
|
DbgPrint("failed to get proc address\n");
|
|
goto Return;
|
|
}
|
|
|
|
if (pLsaImpersonateClient() != STATUS_SUCCESS)
|
|
{
|
|
DbgPrint("failed to impersonate\n");
|
|
goto Return;
|
|
}
|
|
bImpersonating = true;
|
|
|
|
if (!OpenThreadToken(
|
|
GetCurrentThread(),
|
|
TOKEN_QUERY,
|
|
FALSE,
|
|
&hLocalThreadToken))
|
|
{
|
|
DbgPrint("OpenThreadToken failed\n");
|
|
goto Return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// see if the calling thread token has a TS session ID...
|
|
// if so, then we are being called on behalf of a process in a TS session
|
|
//
|
|
if (!GetTokenInformation(
|
|
(hThreadToken == INVALID_HANDLE_VALUE) ? hLocalThreadToken : hThreadToken,
|
|
TokenSessionId,
|
|
&dwTSSessionID,
|
|
sizeof(dwTSSessionID),
|
|
&dwSize))
|
|
{
|
|
DbgPrint("GetTokenInformation failed\n");
|
|
}
|
|
|
|
Return:
|
|
|
|
if (hLocalThreadToken != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(hLocalThreadToken);
|
|
}
|
|
|
|
if (bImpersonating)
|
|
{
|
|
RevertToSelf();
|
|
}
|
|
|
|
return (dwTSSessionID);
|
|
}
|
|
|
|
void
|
|
_TeardownRPCConnection(
|
|
RPC_BINDING_HANDLE *phRPCBinding)
|
|
{
|
|
__try
|
|
{
|
|
RpcBindingFree(phRPCBinding);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DbgPrint("Exception occurred during RpcBindingFree - %lx\n", _exception_code());
|
|
}
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
_SetupRPCConnection(
|
|
RPC_BINDING_HANDLE *phRPCBinding,
|
|
HANDLE hThreadToken)
|
|
{
|
|
LPWSTR pStringBinding = NULL;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
DWORD dwTSSessionID = 0;
|
|
WCHAR wszLocalEndpoint[256];
|
|
LPWSTR pwszLocalEndpoint = NULL;
|
|
RPC_SECURITY_QOS RpcSecurityQOS;
|
|
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
|
|
PSID pSID = NULL;
|
|
WCHAR szName[64]; // SYSTEM
|
|
DWORD cbName = 64;
|
|
WCHAR szDomainName[256]; // max domain is 255
|
|
DWORD cbDomainName = 256;
|
|
SID_NAME_USE Use;
|
|
|
|
//
|
|
// Get the ID of the winlogon RPC server to connect to
|
|
//
|
|
dwTSSessionID = GetTSSessionID(hThreadToken);
|
|
|
|
if (dwTSSessionID != 0)
|
|
{
|
|
wsprintfW(
|
|
wszLocalEndpoint,
|
|
SZ_ENDPOINT_NAME_FORMAT,
|
|
SCLOGONRPC_LOCAL_ENDPOINT,
|
|
dwTSSessionID);
|
|
|
|
pwszLocalEndpoint = wszLocalEndpoint;
|
|
}
|
|
else
|
|
{
|
|
pwszLocalEndpoint = SCLOGONRPC_LOCAL_ENDPOINT;
|
|
}
|
|
|
|
//
|
|
// get a binding handle
|
|
//
|
|
if (RPC_S_OK != (rpcStatus = RpcStringBindingComposeW(
|
|
NULL,
|
|
SCLOGONRPC_LOCAL_PROT_SEQ,
|
|
NULL, //LPC - no machine name
|
|
pwszLocalEndpoint,
|
|
0,
|
|
&pStringBinding)))
|
|
{
|
|
DbgPrint("RpcStringBindingComposeW failed\n");
|
|
|
|
status = I_RpcMapWin32Status(rpcStatus);
|
|
//
|
|
// if I_RpcMapWin32Status() can't map the error code it returns
|
|
// the same error back, so check for that
|
|
//
|
|
if (status == rpcStatus)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
}
|
|
goto Return;
|
|
}
|
|
|
|
if (RPC_S_OK != (rpcStatus = RpcBindingFromStringBindingW(
|
|
pStringBinding,
|
|
phRPCBinding)))
|
|
{
|
|
DbgPrint("RpcBindingFromStringBindingW failed\n");
|
|
status = I_RpcMapWin32Status(rpcStatus);
|
|
//
|
|
// if I_RpcMapWin32Status() can't map the error code it returns
|
|
// the same error back, so check for that
|
|
//
|
|
if (status == rpcStatus)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
}
|
|
goto Return;
|
|
}
|
|
|
|
if (RPC_S_OK != (rpcStatus = RpcEpResolveBinding(
|
|
*phRPCBinding,
|
|
IRPCSCLogon_v1_0_c_ifspec)))
|
|
{
|
|
DbgPrint("RpcEpResolveBinding failed\n");
|
|
status = I_RpcMapWin32Status(rpcStatus);
|
|
//
|
|
// if I_RpcMapWin32Status() can't map the error code it returns
|
|
// the same error back, so check for that
|
|
//
|
|
if (status == rpcStatus)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
}
|
|
_TeardownRPCConnection(phRPCBinding);
|
|
goto Return;
|
|
}
|
|
|
|
//
|
|
// Set the autorization so that we will only call a Local System process
|
|
//
|
|
memset(&RpcSecurityQOS, 0, sizeof(RpcSecurityQOS));
|
|
RpcSecurityQOS.Version = RPC_C_SECURITY_QOS_VERSION;
|
|
RpcSecurityQOS.Capabilities = RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH;
|
|
RpcSecurityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
|
|
RpcSecurityQOS.ImpersonationType = RPC_C_IMP_LEVEL_DELEGATE;
|
|
|
|
if (AllocateAndInitializeSid(&SIDAuth, 1,
|
|
SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
&pSID) == 0)
|
|
{
|
|
DbgPrint("AllocateAndInitializeSid failed\n");
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
goto Return;
|
|
}
|
|
|
|
if (LookupAccountSid(NULL,
|
|
pSID,
|
|
szName,
|
|
&cbName,
|
|
szDomainName,
|
|
&cbDomainName,
|
|
&Use) == 0)
|
|
{
|
|
DbgPrint("LookupAccountSid failed\n");
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
goto Return;
|
|
}
|
|
|
|
if (RPC_S_OK != (rpcStatus = RpcBindingSetAuthInfoEx(
|
|
*phRPCBinding,
|
|
szName,
|
|
RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
|
|
RPC_C_AUTHN_WINNT,
|
|
NULL,
|
|
0,
|
|
&RpcSecurityQOS)))
|
|
{
|
|
DbgPrint("RpcBindingSetAuthInfoEx failed\n");
|
|
status = I_RpcMapWin32Status(rpcStatus);
|
|
goto Return;
|
|
}
|
|
|
|
Return:
|
|
if (pStringBinding != NULL)
|
|
{
|
|
RpcStringFreeW(&pStringBinding);
|
|
}
|
|
|
|
if (pSID != NULL)
|
|
{
|
|
FreeSid( pSID );
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
typedef struct _SCLOGON_PIPE
|
|
{
|
|
RPC_BINDING_HANDLE hRPCBinding;
|
|
BINDING_CONTEXT BindingContext;
|
|
} SCLOGON_PIPE;
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ScLogon APIs
|
|
//
|
|
|
|
|
|
//***************************************************************************************
|
|
//
|
|
// __ScHelperInitializeContext:
|
|
//
|
|
//***************************************************************************************
|
|
NTSTATUS WINAPI
|
|
__ScHelperInitializeContext(
|
|
IN OUT PBYTE pbLogonInfo,
|
|
IN ULONG cbLogonInfo
|
|
)
|
|
{
|
|
SCLOGON_PIPE *pSCLogonPipe;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
BOOL fRPCBindingInitialized = FALSE;
|
|
LogonInfo *pLI = (LogonInfo *)pbLogonInfo;
|
|
|
|
if ((cbLogonInfo < sizeof(ULONG)) ||
|
|
(cbLogonInfo != pLI->dwLogonInfoLen))
|
|
{
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
pLI->ContextInformation = malloc(sizeof(SCLOGON_PIPE));
|
|
if (pLI->ContextInformation == NULL)
|
|
{
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
|
|
|
|
status = _SetupRPCConnection(&(pSCLogonPipe->hRPCBinding), INVALID_HANDLE_VALUE);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
fRPCBindingInitialized = TRUE;
|
|
|
|
pSCLogonPipe->BindingContext = NULL;
|
|
|
|
__try
|
|
{
|
|
status = RPC_ScHelperInitializeContext(
|
|
pSCLogonPipe->hRPCBinding,
|
|
cbLogonInfo,
|
|
pbLogonInfo,
|
|
&(pSCLogonPipe->BindingContext));
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
DbgPrint("Exception occurred during RPC_ScHelperInitializeContext - %lx\n", _exception_code());
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
DbgPrint("RPC_ScHelperInitializeContext failed - %lx\n", status);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
Return:
|
|
|
|
return (status);
|
|
|
|
ErrorReturn:
|
|
|
|
if (pSCLogonPipe != NULL)
|
|
{
|
|
if (fRPCBindingInitialized)
|
|
{
|
|
_TeardownRPCConnection(&(pSCLogonPipe->hRPCBinding));
|
|
}
|
|
|
|
free(pSCLogonPipe);
|
|
}
|
|
|
|
goto Return;
|
|
}
|
|
|
|
|
|
//***************************************************************************************
|
|
//
|
|
// __ScHelperRelease:
|
|
//
|
|
//***************************************************************************************
|
|
VOID WINAPI
|
|
__ScHelperRelease(
|
|
IN OUT PBYTE pbLogonInfo
|
|
)
|
|
{
|
|
_ASSERTE(NULL != pbLogonInfo);
|
|
LogonInfo *pLI = (LogonInfo *)pbLogonInfo;
|
|
SCLOGON_PIPE * pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
|
|
BOOL fReleaseFailed = TRUE;
|
|
|
|
if (pSCLogonPipe != NULL)
|
|
{
|
|
__try
|
|
{
|
|
RPC_ScHelperRelease(
|
|
pSCLogonPipe->hRPCBinding,
|
|
&(pSCLogonPipe->BindingContext));
|
|
|
|
fReleaseFailed = FALSE;
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DbgPrint("Exception occurred during RPC_ScHelperRelease - %lx\n", _exception_code());
|
|
}
|
|
|
|
//
|
|
// RPC_ScHelperRelease will throw an exception if the winlogon process it is trying
|
|
// to talk to has gone away. If that is the case, then we need to manually free
|
|
// the BINDING_CONTEXT since it won't get free'd by RPC.
|
|
//
|
|
// NOTE: RPC will free the BINDING_CONTEXT when the server sets it to NULL, which
|
|
// does happen if the RPC_ScHelperRelease function executes
|
|
//
|
|
if (fReleaseFailed)
|
|
{
|
|
__try
|
|
{
|
|
RpcSsDestroyClientContext(&(pSCLogonPipe->BindingContext));
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DbgPrint("Exception occurred during RpcSsDestroyClientContext - %lx\n", _exception_code());
|
|
}
|
|
}
|
|
|
|
_TeardownRPCConnection(&(pSCLogonPipe->hRPCBinding));
|
|
|
|
free(pSCLogonPipe);
|
|
pLI->ContextInformation = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//***************************************************************************************
|
|
//
|
|
// __ScHelperGetCertFromLogonInfo:
|
|
//
|
|
//***************************************************************************************
|
|
NTSTATUS WINAPI
|
|
__ScHelperGetCertFromLogonInfo(
|
|
IN PBYTE pbLogonInfo,
|
|
IN PUNICODE_STRING pucPIN,
|
|
OUT PCCERT_CONTEXT *CertificateContext
|
|
)
|
|
{
|
|
_ASSERTE(NULL != pbLogonInfo);
|
|
|
|
LogonInfo *pLI = (LogonInfo *)pbLogonInfo;
|
|
SCLOGON_PIPE *pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PCCERT_CONTEXT pCertCtx = NULL;
|
|
OUT_BUFFER1 CertBytes;
|
|
CUnicodeString szPIN(pucPIN);
|
|
|
|
memset(&CertBytes, 0, sizeof(CertBytes));
|
|
|
|
//
|
|
// Make sure pin got initialized correctly in constructor
|
|
//
|
|
if (NULL != pucPIN)
|
|
{
|
|
if (!szPIN.Valid())
|
|
{
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make the call
|
|
//
|
|
__try
|
|
{
|
|
status = RPC_ScHelperGetCertFromLogonInfo(
|
|
pSCLogonPipe->hRPCBinding,
|
|
pSCLogonPipe->BindingContext,
|
|
(LPCWSTR)szPIN,
|
|
&CertBytes);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
DbgPrint("Exception occurred during RPC_ScHelperGetCertFromLogonInfo - %lx\n", _exception_code());
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
DbgPrint("RPC_ScHelperGetCertFromLogonInfo failed - %lx\n", status);
|
|
goto Return;
|
|
}
|
|
|
|
//
|
|
// Create the return CertContext based on the bytes returned
|
|
//
|
|
pCertCtx = CertCreateCertificateContext(
|
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
|
CertBytes.pb,
|
|
CertBytes.cb);
|
|
if (pCertCtx == NULL)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
}
|
|
|
|
Return:
|
|
|
|
if (CertBytes.pb != NULL)
|
|
{
|
|
MIDL_user_free(CertBytes.pb);
|
|
}
|
|
|
|
*CertificateContext = pCertCtx;
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
//***************************************************************************************
|
|
//
|
|
// __ScHelperGetProvParam:
|
|
//
|
|
//***************************************************************************************
|
|
NTSTATUS WINAPI
|
|
__ScHelperGetProvParam(
|
|
IN PUNICODE_STRING pucPIN,
|
|
IN PBYTE pbLogonInfo,
|
|
IN ULONG_PTR KerbHProv,
|
|
DWORD dwParam,
|
|
BYTE *pbData,
|
|
DWORD *pdwDataLen,
|
|
DWORD dwFlags
|
|
)
|
|
{
|
|
_ASSERTE(NULL != pbLogonInfo);
|
|
|
|
LogonInfo *pLI;
|
|
SCLOGON_PIPE *pSCLogonPipe;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
CUnicodeString szPIN(pucPIN);
|
|
OUT_BUFFER1 Data;
|
|
PKERB_PUBLIC_KEY_HPROV pKerbHProv;
|
|
handle_t hRPCBinding;
|
|
BINDING_CONTEXT BindingContext;
|
|
BOOL fBindingIsCertAndKey = FALSE;
|
|
|
|
//
|
|
// Decide which rpc binding to use
|
|
//
|
|
if (KerbHProv != NULL)
|
|
{
|
|
pKerbHProv = (PKERB_PUBLIC_KEY_HPROV) KerbHProv;
|
|
hRPCBinding = pKerbHProv->hRPCBinding;
|
|
BindingContext = pKerbHProv->hCertAndKey;
|
|
fBindingIsCertAndKey = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pLI = (LogonInfo *)pbLogonInfo;
|
|
pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
|
|
hRPCBinding = pSCLogonPipe->hRPCBinding;
|
|
BindingContext = pSCLogonPipe->BindingContext;
|
|
}
|
|
|
|
memset(&Data, 0, sizeof(Data));
|
|
|
|
//
|
|
// Make sure pin got initialized correctly in constructor
|
|
//
|
|
if (NULL != pucPIN)
|
|
{
|
|
if (!szPIN.Valid())
|
|
{
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make the call
|
|
//
|
|
__try
|
|
{
|
|
status = RPC_ScHelperGetProvParam(
|
|
hRPCBinding,
|
|
BindingContext,
|
|
(LPCWSTR)szPIN,
|
|
fBindingIsCertAndKey,
|
|
dwParam,
|
|
pdwDataLen,
|
|
&Data,
|
|
dwFlags);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
if ((_exception_code() == RPC_S_CALL_FAILED_DNE) ||
|
|
(_exception_code() == RPC_S_SERVER_UNAVAILABLE))
|
|
{
|
|
// Special case to trigger the balloon when the session
|
|
// went away (transfer of credentials case)
|
|
status = STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED;
|
|
}
|
|
else
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
}
|
|
DbgPrint("Exception occurred during RPC_ScHelperGetProvParam - %lx\n", _exception_code());
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
DbgPrint("RPC_ScHelperGetProvParam failed - %lx\n", status);
|
|
goto Return;
|
|
}
|
|
|
|
//
|
|
// if Data.cb is not 0, then the called is getting back data
|
|
//
|
|
if (Data.cb != 0)
|
|
{
|
|
memcpy(pbData, Data.pb, Data.cb);
|
|
}
|
|
|
|
Return:
|
|
|
|
if (Data.pb != NULL)
|
|
{
|
|
MIDL_user_free(Data.pb);
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
//***************************************************************************************
|
|
//
|
|
// __ScHelperGenRandBits:
|
|
//
|
|
//***************************************************************************************
|
|
NTSTATUS WINAPI
|
|
__ScHelperGenRandBits(
|
|
IN PBYTE pbLogonInfo,
|
|
IN OUT ScHelper_RandomCredBits* psc_rcb
|
|
)
|
|
{
|
|
_ASSERTE(NULL != pbLogonInfo);
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
LogonInfo *pLI = (LogonInfo *)pbLogonInfo;
|
|
SCLOGON_PIPE *pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
|
|
|
|
__try
|
|
{
|
|
status = RPC_ScHelperGenRandBits(
|
|
pSCLogonPipe->hRPCBinding,
|
|
pSCLogonPipe->BindingContext,
|
|
psc_rcb->bR1,
|
|
psc_rcb->bR2);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
DbgPrint("Exception occurred during RPC_ScHelperGenRandBits - %lx\n", _exception_code());
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
//***************************************************************************************
|
|
//
|
|
// __ScHelperVerifyCardAndCreds:
|
|
//
|
|
//***************************************************************************************
|
|
NTSTATUS WINAPI
|
|
__ScHelperVerifyCardAndCreds(
|
|
IN PUNICODE_STRING pucPIN,
|
|
IN PCCERT_CONTEXT CertificateContext,
|
|
IN PBYTE pbLogonInfo,
|
|
IN PBYTE EncryptedData,
|
|
IN ULONG EncryptedDataSize,
|
|
OUT OPTIONAL PBYTE CleartextData,
|
|
OUT PULONG CleartextDataSize
|
|
)
|
|
{
|
|
_ASSERTE(NULL != pbLogonInfo);
|
|
|
|
LogonInfo *pLI = (LogonInfo *)pbLogonInfo;
|
|
SCLOGON_PIPE *pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
CUnicodeString szPIN(pucPIN);
|
|
OUT_BUFFER2 CleartextDataBuffer;
|
|
|
|
memset(&CleartextDataBuffer, 0, sizeof(CleartextDataBuffer));
|
|
|
|
//
|
|
// Make sure pin got initialized correctly in constructor
|
|
//
|
|
if (NULL != pucPIN)
|
|
{
|
|
if (!szPIN.Valid())
|
|
{
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make the call
|
|
//
|
|
__try
|
|
{
|
|
status = RPC_ScHelperVerifyCardAndCreds(
|
|
pSCLogonPipe->hRPCBinding,
|
|
pSCLogonPipe->BindingContext,
|
|
(LPCWSTR)szPIN,
|
|
EncryptedDataSize,
|
|
EncryptedData,
|
|
CleartextDataSize,
|
|
&CleartextDataBuffer);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
DbgPrint("Exception occurred during RPC_ScHelperVerifyCardAndCreds - %lx\n", _exception_code());
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
DbgPrint("RPC_ScHelperVerifyCardAndCreds failed - %lx\n", status);
|
|
goto Return;
|
|
}
|
|
|
|
//
|
|
// if CleartextData.cb is not 0, then the called is getting back data
|
|
//
|
|
if (CleartextDataBuffer.cb != 0)
|
|
{
|
|
memcpy(CleartextData, CleartextDataBuffer.pb, CleartextDataBuffer.cb);
|
|
}
|
|
|
|
Return:
|
|
|
|
if (CleartextDataBuffer.pb != NULL)
|
|
{
|
|
MIDL_user_free(CleartextDataBuffer.pb);
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
//***************************************************************************************
|
|
//
|
|
// __ScHelperEncryptCredentials:
|
|
//
|
|
//***************************************************************************************
|
|
NTSTATUS WINAPI
|
|
__ScHelperEncryptCredentials(
|
|
IN PUNICODE_STRING pucPIN,
|
|
IN PCCERT_CONTEXT CertificateContext,
|
|
IN ScHelper_RandomCredBits* psch_rcb,
|
|
IN PBYTE pbLogonInfo,
|
|
IN PBYTE CleartextData,
|
|
IN ULONG CleartextDataSize,
|
|
OUT OPTIONAL PBYTE EncryptedData,
|
|
OUT PULONG EncryptedDataSize)
|
|
{
|
|
_ASSERTE(NULL != pbLogonInfo);
|
|
|
|
LogonInfo *pLI = (LogonInfo *)pbLogonInfo;
|
|
SCLOGON_PIPE *pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
CUnicodeString szPIN(pucPIN);
|
|
OUT_BUFFER2 EncryptedDataBuffer;
|
|
|
|
memset(&EncryptedDataBuffer, 0, sizeof(EncryptedDataBuffer));
|
|
|
|
//
|
|
// Make sure pin got initialized correctly in constructor
|
|
//
|
|
if (NULL != pucPIN)
|
|
{
|
|
if (!szPIN.Valid())
|
|
{
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make the call
|
|
//
|
|
__try
|
|
{
|
|
status = RPC_ScHelperEncryptCredentials(
|
|
pSCLogonPipe->hRPCBinding,
|
|
pSCLogonPipe->BindingContext,
|
|
(LPCWSTR)szPIN,
|
|
psch_rcb->bR1,
|
|
psch_rcb->bR2,
|
|
CleartextDataSize,
|
|
CleartextData,
|
|
EncryptedDataSize,
|
|
&EncryptedDataBuffer);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
DbgPrint("Exception occurred during RPC_ScHelperEncryptCredentials - %lx\n", _exception_code());
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
if (status != STATUS_BUFFER_TOO_SMALL)
|
|
{
|
|
DbgPrint("RPC_ScHelperEncryptCredentials failed - %lx\n", status);
|
|
}
|
|
goto Return;
|
|
}
|
|
|
|
//
|
|
// if EncryptedDataBuffer.cb is not 0, then the called is getting back data
|
|
//
|
|
if (EncryptedDataBuffer.cb != 0)
|
|
{
|
|
memcpy(EncryptedData, EncryptedDataBuffer.pb, EncryptedDataBuffer.cb);
|
|
}
|
|
|
|
Return:
|
|
|
|
if (EncryptedDataBuffer.pb != NULL)
|
|
{
|
|
MIDL_user_free(EncryptedDataBuffer.pb);
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
//***************************************************************************************
|
|
//
|
|
// __ScHelperSignMessage:
|
|
//
|
|
//***************************************************************************************
|
|
NTSTATUS WINAPI
|
|
__ScHelperSignMessage(
|
|
IN PUNICODE_STRING pucPIN,
|
|
IN OPTIONAL PBYTE pbLogonInfo,
|
|
IN OPTIONAL ULONG_PTR KerbHProv,
|
|
IN ULONG Algorithm,
|
|
IN PBYTE Buffer,
|
|
IN ULONG BufferLength,
|
|
OUT PBYTE Signature,
|
|
OUT PULONG SignatureLength
|
|
)
|
|
{
|
|
LogonInfo *pLI;
|
|
SCLOGON_PIPE *pSCLogonPipe;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
CUnicodeString szPIN(pucPIN);
|
|
OUT_BUFFER2 SignatureBuffer;
|
|
PKERB_PUBLIC_KEY_HPROV pKerbHProv;
|
|
handle_t hRPCBinding;
|
|
BINDING_CONTEXT BindingContext;
|
|
BOOL fBindingIsCertAndKey = FALSE;
|
|
|
|
//
|
|
// Decide which rpc binding to use
|
|
//
|
|
if (KerbHProv != NULL)
|
|
{
|
|
pKerbHProv = (PKERB_PUBLIC_KEY_HPROV) KerbHProv;
|
|
hRPCBinding = pKerbHProv->hRPCBinding;
|
|
BindingContext = pKerbHProv->hCertAndKey;
|
|
fBindingIsCertAndKey = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pLI = (LogonInfo *)pbLogonInfo;
|
|
pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
|
|
hRPCBinding = pSCLogonPipe->hRPCBinding;
|
|
BindingContext = pSCLogonPipe->BindingContext;
|
|
}
|
|
|
|
memset(&SignatureBuffer, 0, sizeof(SignatureBuffer));
|
|
|
|
//
|
|
// Make sure pin got initialized correctly in constructor
|
|
//
|
|
if (NULL != pucPIN)
|
|
{
|
|
if (!szPIN.Valid())
|
|
{
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make the call
|
|
//
|
|
__try
|
|
{
|
|
status = RPC_ScHelperSignMessage(
|
|
hRPCBinding,
|
|
BindingContext,
|
|
(LPCWSTR)szPIN,
|
|
fBindingIsCertAndKey,
|
|
Algorithm,
|
|
BufferLength,
|
|
Buffer,
|
|
SignatureLength,
|
|
&SignatureBuffer);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
DbgPrint("Exception occurred during RPC_ScHelperSignMessage - %lx\n", _exception_code());
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
DbgPrint("RPC_ScHelperSignMessage failed - %lx\n", status);
|
|
goto Return;
|
|
}
|
|
|
|
//
|
|
// if SignatureBuffer.cb is not 0, then the called is getting back data
|
|
//
|
|
if (SignatureBuffer.cb != 0)
|
|
{
|
|
memcpy(Signature, SignatureBuffer.pb, SignatureBuffer.cb);
|
|
}
|
|
|
|
Return:
|
|
|
|
if (SignatureBuffer.pb != NULL)
|
|
{
|
|
MIDL_user_free(SignatureBuffer.pb);
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
//***************************************************************************************
|
|
//
|
|
// __ScHelperVerifyMessage:
|
|
//
|
|
//***************************************************************************************
|
|
NTSTATUS WINAPI
|
|
__ScHelperVerifyMessage(
|
|
IN OPTIONAL PBYTE pbLogonInfo,
|
|
IN PCCERT_CONTEXT CertificateContext,
|
|
IN ULONG Algorithm,
|
|
IN PBYTE Buffer,
|
|
IN ULONG BufferLength,
|
|
IN PBYTE Signature,
|
|
IN ULONG SignatureLength
|
|
)
|
|
{
|
|
_ASSERTE(NULL != pbLogonInfo);
|
|
|
|
LogonInfo *pLI = (LogonInfo *)pbLogonInfo;
|
|
SCLOGON_PIPE *pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
__try
|
|
{
|
|
status = RPC_ScHelperVerifyMessage(
|
|
pSCLogonPipe->hRPCBinding,
|
|
pSCLogonPipe->BindingContext,
|
|
Algorithm,
|
|
BufferLength,
|
|
Buffer,
|
|
SignatureLength,
|
|
Signature);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
DbgPrint("Exception occurred during RPC_ScHelperVerifyMessage - %lx\n", _exception_code());
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
//***************************************************************************************
|
|
//
|
|
// __ScHelperSignPkcsMessage:
|
|
//
|
|
//***************************************************************************************
|
|
NTSTATUS WINAPI
|
|
__ScHelperSignPkcsMessage(
|
|
IN OPTIONAL PUNICODE_STRING pucPIN,
|
|
IN OPTIONAL PBYTE pbLogonInfo,
|
|
IN OPTIONAL ULONG_PTR KerbHProv,
|
|
IN PCCERT_CONTEXT Certificate,
|
|
IN PCRYPT_ALGORITHM_IDENTIFIER Algorithm,
|
|
IN DWORD dwSignMessageFlags,
|
|
IN PBYTE Buffer,
|
|
IN ULONG BufferLength,
|
|
OUT OPTIONAL PBYTE SignedBuffer,
|
|
OUT OPTIONAL PULONG SignedBufferLength
|
|
)
|
|
{
|
|
LogonInfo *pLI;
|
|
SCLOGON_PIPE *pSCLogonPipe;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
CUnicodeString szPIN(pucPIN);
|
|
OUT_BUFFER2 SignedBufferBuffer;
|
|
PKERB_PUBLIC_KEY_HPROV pKerbHProv;
|
|
handle_t hRPCBinding;
|
|
BINDING_CONTEXT BindingContext;
|
|
BOOL fBindingIsCertAndKey = FALSE;
|
|
|
|
//
|
|
// Decide which rpc binding to use
|
|
//
|
|
if (KerbHProv != NULL)
|
|
{
|
|
pKerbHProv = (PKERB_PUBLIC_KEY_HPROV) KerbHProv;
|
|
hRPCBinding = pKerbHProv->hRPCBinding;
|
|
BindingContext = pKerbHProv->hCertAndKey;
|
|
fBindingIsCertAndKey = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pLI = (LogonInfo *)pbLogonInfo;
|
|
pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
|
|
hRPCBinding = pSCLogonPipe->hRPCBinding;
|
|
BindingContext = pSCLogonPipe->BindingContext;
|
|
}
|
|
|
|
memset(&SignedBufferBuffer, 0, sizeof(SignedBufferBuffer));
|
|
|
|
//
|
|
// Make sure pin got initialized correctly in constructor
|
|
//
|
|
if (NULL != pucPIN)
|
|
{
|
|
if (!szPIN.Valid())
|
|
{
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make the call
|
|
//
|
|
__try
|
|
{
|
|
status = RPC_ScHelperSignPkcsMessage(
|
|
hRPCBinding,
|
|
BindingContext,
|
|
(LPCWSTR)szPIN,
|
|
fBindingIsCertAndKey,
|
|
Algorithm->pszObjId,
|
|
Algorithm->Parameters.cbData,
|
|
Algorithm->Parameters.pbData,
|
|
dwSignMessageFlags,
|
|
BufferLength,
|
|
Buffer,
|
|
SignedBufferLength,
|
|
&SignedBufferBuffer);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
DbgPrint("Exception occurred during RPC_ScHelperSignPkcsMessage - %lx\n", _exception_code());
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
if (status != STATUS_BUFFER_TOO_SMALL)
|
|
{
|
|
DbgPrint("RPC_ScHelperSignPkcsMessage failed - %lx\n", status);
|
|
}
|
|
goto Return;
|
|
}
|
|
|
|
//
|
|
// if SignedBufferBuffer.cb is not 0, then the called is getting back data
|
|
//
|
|
if (SignedBufferBuffer.cb != 0)
|
|
{
|
|
memcpy(SignedBuffer, SignedBufferBuffer.pb, SignedBufferBuffer.cb);
|
|
}
|
|
|
|
Return:
|
|
|
|
if (SignedBufferBuffer.pb != NULL)
|
|
{
|
|
MIDL_user_free(SignedBufferBuffer.pb);
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
//***************************************************************************************
|
|
//
|
|
// __ScHelperVerifyPkcsMessage:
|
|
//
|
|
//***************************************************************************************
|
|
/*NTSTATUS WINAPI
|
|
__ScHelperVerifyPkcsMessage(
|
|
IN OPTIONAL PBYTE pbLogonInfo,
|
|
IN OPTIONAL HCRYPTPROV Provider,
|
|
IN PBYTE Buffer,
|
|
IN ULONG BufferLength,
|
|
OUT OPTIONAL PBYTE DecodedBuffer,
|
|
OUT OPTIONAL PULONG DecodedBufferLength,
|
|
OUT OPTIONAL PCCERT_CONTEXT * CertificateContext
|
|
)
|
|
{
|
|
if (Provider != NULL)
|
|
{
|
|
return (ScHelperVerifyPkcsMessage(
|
|
pbLogonInfo,
|
|
Provider,
|
|
Buffer,
|
|
BufferLength,
|
|
DecodedBuffer,
|
|
DecodedBufferLength,
|
|
CertificateContext));
|
|
}
|
|
|
|
_ASSERTE(NULL != pbLogonInfo);
|
|
|
|
LogonInfo *pLI = (LogonInfo *)pbLogonInfo;
|
|
SCLOGON_PIPE *pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PCCERT_CONTEXT pCertCtx = NULL;
|
|
OUT_BUFFER2 DecodedBufferBuffer;
|
|
OUT_BUFFER1 CertBytes;
|
|
BOOL fCertificateContextRequested = (CertificateContext != NULL);
|
|
|
|
memset(&DecodedBufferBuffer, 0, sizeof(DecodedBufferBuffer));
|
|
memset(&CertBytes, 0, sizeof(CertBytes));
|
|
|
|
//
|
|
// Make the call
|
|
//
|
|
__try
|
|
{
|
|
status = RPC_ScHelperVerifyPkcsMessage(
|
|
pSCLogonPipe->hRPCBinding,
|
|
pSCLogonPipe->BindingContext,
|
|
BufferLength,
|
|
Buffer,
|
|
DecodedBufferLength,
|
|
&DecodedBufferBuffer,
|
|
fCertificateContextRequested,
|
|
&CertBytes);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
DbgPrint("Exception occurred during RPC_ScHelperVerifyPkcsMessage - %lx\n", _exception_code());
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
goto Return;
|
|
}
|
|
|
|
//
|
|
// Create the return CertContext based on the bytes returned
|
|
//
|
|
if (fCertificateContextRequested)
|
|
{
|
|
pCertCtx = CertCreateCertificateContext(
|
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
|
CertBytes.pb,
|
|
CertBytes.cb);
|
|
if (pCertCtx == NULL)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
goto Return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// if DecodedBufferBuffer.cb is not 0, then the called is getting back data
|
|
//
|
|
if (DecodedBufferBuffer.cb != 0)
|
|
{
|
|
memcpy(DecodedBuffer, DecodedBufferBuffer.pb, DecodedBufferBuffer.cb);
|
|
}
|
|
|
|
Return:
|
|
|
|
if (fCertificateContextRequested)
|
|
{
|
|
*CertificateContext = pCertCtx;
|
|
}
|
|
|
|
if (DecodedBufferBuffer.pb != NULL)
|
|
{
|
|
MIDL_user_free(DecodedBufferBuffer.pb);
|
|
}
|
|
|
|
if (CertBytes.pb != NULL)
|
|
{
|
|
MIDL_user_free(CertBytes.pb);
|
|
}
|
|
|
|
return (status);
|
|
}*/
|
|
|
|
|
|
|
|
//***************************************************************************************
|
|
//
|
|
// __ScHelperDecryptMessage:
|
|
//
|
|
//***************************************************************************************
|
|
NTSTATUS WINAPI
|
|
__ScHelperDecryptMessage(
|
|
IN PUNICODE_STRING pucPIN,
|
|
IN OPTIONAL PBYTE pbLogonInfo,
|
|
IN OPTIONAL ULONG_PTR KerbHProv,
|
|
IN PCCERT_CONTEXT CertificateContext,
|
|
IN PBYTE CipherText, // Supplies formatted CipherText
|
|
IN ULONG CipherLength, // Supplies the length of the CiperText
|
|
OUT PBYTE ClearText, // Receives decrypted message
|
|
IN OUT PULONG pClearLength // Supplies length of buffer, receives actual length
|
|
)
|
|
{
|
|
LogonInfo *pLI;
|
|
SCLOGON_PIPE *pSCLogonPipe;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
CUnicodeString szPIN(pucPIN);
|
|
OUT_BUFFER2 ClearTextBuffer;
|
|
PKERB_PUBLIC_KEY_HPROV pKerbHProv;
|
|
handle_t hRPCBinding;
|
|
BINDING_CONTEXT BindingContext;
|
|
BOOL fBindingIsCertAndKey = FALSE;
|
|
|
|
//
|
|
// Decide which rpc binding to use
|
|
//
|
|
if (KerbHProv != NULL)
|
|
{
|
|
pKerbHProv = (PKERB_PUBLIC_KEY_HPROV) KerbHProv;
|
|
hRPCBinding = pKerbHProv->hRPCBinding;
|
|
BindingContext = pKerbHProv->hCertAndKey;
|
|
fBindingIsCertAndKey = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pLI = (LogonInfo *)pbLogonInfo;
|
|
pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
|
|
hRPCBinding = pSCLogonPipe->hRPCBinding;
|
|
BindingContext = pSCLogonPipe->BindingContext;
|
|
}
|
|
|
|
memset(&ClearTextBuffer, 0, sizeof(ClearTextBuffer));
|
|
|
|
//
|
|
// Make sure pin got initialized correctly in constructor
|
|
//
|
|
if (NULL != pucPIN)
|
|
{
|
|
if (!szPIN.Valid())
|
|
{
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make the call
|
|
//
|
|
__try
|
|
{
|
|
status = RPC_ScHelperDecryptMessage(
|
|
hRPCBinding,
|
|
BindingContext,
|
|
(LPCWSTR)szPIN,
|
|
fBindingIsCertAndKey,
|
|
CipherLength,
|
|
CipherText,
|
|
pClearLength,
|
|
&ClearTextBuffer);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
DbgPrint("Exception occurred during RPC_ScHelperDecryptMessage - %lx\n", _exception_code());
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
if (status != STATUS_BUFFER_TOO_SMALL)
|
|
{
|
|
DbgPrint("RPC_ScHelperDecryptMessage failed - %lx\n", status);
|
|
}
|
|
goto Return;
|
|
}
|
|
|
|
//
|
|
// if ClearTextBuffer.cb is not 0, then the call is getting back data
|
|
//
|
|
if (ClearTextBuffer.cb != 0)
|
|
{
|
|
memcpy(ClearText, ClearTextBuffer.pb, ClearTextBuffer.cb);
|
|
}
|
|
|
|
Return:
|
|
|
|
if (ClearTextBuffer.pb != NULL)
|
|
{
|
|
MIDL_user_free(ClearTextBuffer.pb);
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************************
|
|
//
|
|
// __ScHelper_CryptAcquireCertificatePrivateKey:
|
|
//
|
|
//***************************************************************************************
|
|
NTSTATUS WINAPI
|
|
__ScHelper_CryptAcquireCertificatePrivateKey(
|
|
IN PCCERT_CONTEXT CertificateContext,
|
|
OUT ULONG_PTR *pKerbHProv,
|
|
OUT DWORD *pLastError
|
|
)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PKERB_PUBLIC_KEY_HPROV pProv = NULL;
|
|
BOOL fRPCBindingInitialized = FALSE;
|
|
CRYPT_KEY_PROV_INFO *pKeyProvInfo = NULL;
|
|
DWORD cbKeyProvInfo = 0;
|
|
HANDLE hThreadToken = INVALID_HANDLE_VALUE;
|
|
BOOL fImpersonatingAnonymous = FALSE;
|
|
HANDLE hNULL = NULL;
|
|
|
|
*pLastError = 0;
|
|
|
|
//
|
|
// If we are already impersonating, then we need to do things slightly
|
|
// differently... starting with getting the current thread token
|
|
//
|
|
if (!GetImpersonationToken(&hThreadToken))
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
goto Return;
|
|
}
|
|
|
|
//
|
|
// If we are impersonating, then revert to anonymous
|
|
//
|
|
if (hThreadToken != INVALID_HANDLE_VALUE)
|
|
{
|
|
if (!SetThreadToken(NULL, NULL))
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
goto Return;
|
|
}
|
|
|
|
fImpersonatingAnonymous = TRUE;
|
|
}
|
|
|
|
//
|
|
// Allocate the new KERB_PUBLIC_KEY_HPROV struct
|
|
//
|
|
pProv = (PKERB_PUBLIC_KEY_HPROV) MIDL_user_allocate(sizeof(KERB_PUBLIC_KEY_HPROV));
|
|
if (pProv == NULL)
|
|
{
|
|
*pLastError = ERROR_NOT_ENOUGH_MEMORY;
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Return;
|
|
}
|
|
pProv->hCertAndKey = NULL;
|
|
|
|
//
|
|
// Setup the RPC binding
|
|
//
|
|
status = _SetupRPCConnection(&(pProv->hRPCBinding), hThreadToken);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
goto Return;
|
|
}
|
|
fRPCBindingInitialized = TRUE;
|
|
|
|
//
|
|
// Get the key prov info from the cert context
|
|
//
|
|
if (!CertGetCertificateContextProperty(
|
|
CertificateContext,
|
|
CERT_KEY_PROV_INFO_PROP_ID,
|
|
NULL,
|
|
&cbKeyProvInfo))
|
|
{
|
|
*pLastError = GetLastError();
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Return;
|
|
}
|
|
|
|
pKeyProvInfo = (CRYPT_KEY_PROV_INFO *) MIDL_user_allocate(cbKeyProvInfo);
|
|
if (pKeyProvInfo == NULL)
|
|
{
|
|
*pLastError = ERROR_NOT_ENOUGH_MEMORY;
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Return;
|
|
}
|
|
|
|
if (!CertGetCertificateContextProperty(
|
|
CertificateContext,
|
|
CERT_KEY_PROV_INFO_PROP_ID,
|
|
pKeyProvInfo,
|
|
&cbKeyProvInfo))
|
|
{
|
|
*pLastError = GetLastError();
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Return;
|
|
}
|
|
|
|
//
|
|
// Create the hProv in the winlogon process
|
|
//
|
|
__try
|
|
{
|
|
status = RPC_ScHelper_CryptAcquireCertificatePrivateKey(
|
|
pProv->hRPCBinding,
|
|
CertificateContext->cbCertEncoded,
|
|
CertificateContext->pbCertEncoded,
|
|
pKeyProvInfo->pwszContainerName,
|
|
pKeyProvInfo->pwszProvName,
|
|
pKeyProvInfo->dwProvType,
|
|
pKeyProvInfo->dwFlags,
|
|
pKeyProvInfo->dwKeySpec,
|
|
&(pProv->hCertAndKey),
|
|
pLastError);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
DbgPrint("Exception occurred during RPC_ScHelper_CryptAcquireCertificatePrivateKey - %lx\n", _exception_code());
|
|
}
|
|
|
|
Return:
|
|
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
*pKerbHProv = (ULONG_PTR) pProv;
|
|
}
|
|
else
|
|
{
|
|
DbgPrint("RPC_ScHelper_CryptAcquireCertificatePrivateKey failed - %lx\n", status);
|
|
|
|
if (fRPCBindingInitialized)
|
|
{
|
|
_TeardownRPCConnection(&(pProv->hRPCBinding));
|
|
}
|
|
|
|
if (pProv != NULL)
|
|
{
|
|
MIDL_user_free(pProv);
|
|
}
|
|
}
|
|
|
|
if (pKeyProvInfo != NULL)
|
|
{
|
|
MIDL_user_free(pKeyProvInfo);
|
|
}
|
|
|
|
//
|
|
// Reset impersonation if needed
|
|
//
|
|
if (fImpersonatingAnonymous)
|
|
{
|
|
if (!SetThreadToken(NULL, hThreadToken))
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
DbgPrint("SetThreadToken failed, we are now in a BOGUS STATE!! - %lx\n", status);
|
|
}
|
|
}
|
|
|
|
if (hThreadToken != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(hThreadToken);
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************************
|
|
//
|
|
// __ScHelper_CryptSetProvParam:
|
|
//
|
|
//***************************************************************************************
|
|
NTSTATUS WINAPI
|
|
__ScHelper_CryptSetProvParam(
|
|
IN ULONG_PTR KerbHProv,
|
|
IN LPSTR pszPIN,
|
|
OUT DWORD *pLastError
|
|
)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PKERB_PUBLIC_KEY_HPROV pKerbHProv = (PKERB_PUBLIC_KEY_HPROV) KerbHProv;
|
|
HANDLE hThreadToken = INVALID_HANDLE_VALUE;
|
|
BOOL fImpersonatingAnonymous = FALSE;
|
|
HANDLE hNULL = NULL;
|
|
|
|
*pLastError = 0;
|
|
|
|
//
|
|
// If we are already impersonating, then we need to do things slightly
|
|
// differently... starting with getting the current thread token
|
|
//
|
|
if (!GetImpersonationToken(&hThreadToken))
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
goto Return;
|
|
}
|
|
|
|
//
|
|
// If we are impersonating, then revert to anonymous
|
|
//
|
|
if (hThreadToken != INVALID_HANDLE_VALUE)
|
|
{
|
|
if (!SetThreadToken(NULL, NULL))
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
goto Return;
|
|
}
|
|
|
|
fImpersonatingAnonymous = TRUE;
|
|
}
|
|
|
|
//
|
|
// Set the prov param on the hProv in the winlogon process
|
|
//
|
|
__try
|
|
{
|
|
status = RPC_ScHelper_CryptSetProvParam(
|
|
pKerbHProv->hRPCBinding,
|
|
pKerbHProv->hCertAndKey,
|
|
pszPIN,
|
|
pLastError);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
DbgPrint("Exception occurred during RPC_ScHelper_CryptSetProvParam - %lx\n", _exception_code());
|
|
goto Return;
|
|
}
|
|
|
|
Return:
|
|
|
|
//
|
|
// Reset impersonation if needed
|
|
//
|
|
if (fImpersonatingAnonymous)
|
|
{
|
|
if (!SetThreadToken(NULL, hThreadToken))
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
DbgPrint("SetThreadToken failed, we are now in a BOGUS STATE!! - %lx\n", status);
|
|
}
|
|
}
|
|
|
|
if (hThreadToken != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(hThreadToken);
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************************
|
|
//
|
|
// __ScHelper_CryptReleaseContext:
|
|
//
|
|
//***************************************************************************************
|
|
NTSTATUS WINAPI
|
|
__ScHelper_CryptReleaseContext(
|
|
IN ULONG_PTR KerbHProv
|
|
)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PKERB_PUBLIC_KEY_HPROV pKerbHProv = (PKERB_PUBLIC_KEY_HPROV) KerbHProv;
|
|
HANDLE hThreadToken = INVALID_HANDLE_VALUE;
|
|
BOOL fImpersonatingAnonymous = FALSE;
|
|
HANDLE hNULL = NULL;
|
|
|
|
//
|
|
// If we are already impersonating, then we need to do things slightly
|
|
// differently... starting with getting the current thread token
|
|
//
|
|
if (!GetImpersonationToken(&hThreadToken))
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
goto Return;
|
|
}
|
|
|
|
//
|
|
// If we are impersonating, then revert to anonymous
|
|
//
|
|
if (hThreadToken != INVALID_HANDLE_VALUE)
|
|
{
|
|
if (!SetThreadToken(NULL, NULL))
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
goto Return;
|
|
}
|
|
|
|
fImpersonatingAnonymous = TRUE;
|
|
}
|
|
|
|
//
|
|
// release hProv in the winlogon process
|
|
//
|
|
__try
|
|
{
|
|
status = RPC_ScHelper_CryptReleaseContext(
|
|
pKerbHProv->hRPCBinding,
|
|
&(pKerbHProv->hCertAndKey));
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
DbgPrint("Exception occurred during RPC_ScHelper_CryptReleaseContext - %lx\n", _exception_code());
|
|
goto Return;
|
|
}
|
|
|
|
Return:
|
|
|
|
_TeardownRPCConnection(&(pKerbHProv->hRPCBinding));
|
|
MIDL_user_free(pKerbHProv);
|
|
|
|
//
|
|
// Reset impersonation if needed
|
|
//
|
|
if (fImpersonatingAnonymous)
|
|
{
|
|
if (!SetThreadToken(NULL, hThreadToken))
|
|
{
|
|
status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
|
|
DbgPrint("SetThreadToken failed, we are now in a BOGUS STATE!! - %lx\n", status);
|
|
}
|
|
}
|
|
|
|
if (hThreadToken != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(hThreadToken);
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
|