windows-nt/Source/XPSP1/NT/ds/security/protocols/pwdssp/pwdssp.c
2020-09-26 16:20:57 +08:00

1348 lines
33 KiB
C

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1997.
//
// File: pwdssp.c
//
// Contents:
//
// Classes:
//
// Functions:
//
// History: 9-07-97 RichardW Created
//
//----------------------------------------------------------------------------
#include "pwdsspp.h"
typedef struct _PWD_CRED {
DWORD Ref;
} PWD_CRED, * PPWD_CRED;
typedef struct _PWD_CONTEXT {
DWORD Tag;
HANDLE Token;
} PWD_CONTEXT, *PPWD_CONTEXT ;
PWD_CRED PwdGlobalAnsi;
PWD_CRED PwdGlobalUnicode;
#define CONTEXT_TAG 'txtC'
#define ANONYMOUS_TOKEN ((HANDLE) 1)
SecPkgInfoA PwdInfoA = { SECPKG_FLAG_CONNECTION |
SECPKG_FLAG_ACCEPT_WIN32_NAME,
1,
(WORD) -1,
768,
PWDSSP_NAME_A,
"Microsoft Clear Text Password Security Provider" };
SecPkgInfoW PwdInfoW = { SECPKG_FLAG_CONNECTION |
SECPKG_FLAG_ACCEPT_WIN32_NAME,
1,
(WORD) -1,
768,
PWDSSP_NAME_W,
L"Microsoft Clear Text Password Security Provider" };
SecurityFunctionTableA PwdTableA = {
SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
EnumerateSecurityPackagesA,
NULL,
AcquireCredentialsHandleA,
FreeCredentialsHandle,
NULL,
InitializeSecurityContextA,
AcceptSecurityContext,
CompleteAuthToken,
DeleteSecurityContext,
ApplyControlToken,
QueryContextAttributesA,
ImpersonateSecurityContext,
RevertSecurityContext,
MakeSignature,
VerifySignature,
FreeContextBuffer,
QuerySecurityPackageInfoA,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
QuerySecurityContextToken
};
SecurityFunctionTableW PwdTableW = {
SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
EnumerateSecurityPackagesW,
NULL,
AcquireCredentialsHandleW,
FreeCredentialsHandle,
NULL,
InitializeSecurityContextW,
AcceptSecurityContext,
CompleteAuthToken,
DeleteSecurityContext,
ApplyControlToken,
QueryContextAttributesW,
ImpersonateSecurityContext,
RevertSecurityContext,
MakeSignature,
VerifySignature,
FreeContextBuffer,
QuerySecurityPackageInfoW,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
QuerySecurityContextToken
};
//#define PwdAlloc(x) LsaIAllocateHeap(x)
//#define PwdFree(x) LsaIFreeHeap(x)
#define PwdAlloc(x) LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT,x)
#define PwdFree(x) LocalFree(x)
NTSTATUS
VerifyCredentials(
IN PWSTR UserName,
IN PWSTR DomainName,
IN PWSTR Password,
IN ULONG VerifyFlags
);
UNICODE_STRING AuthenticationPackage;
//+---------------------------------------------------------------------------
//
// Function: DllMain
//
// Synopsis: Entry point
//
// Arguments: [hInstance] --
// [dwReason] --
// [lpReserved] --
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL
WINAPI
DllMain(
HINSTANCE hInstance,
DWORD dwReason,
LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls( hInstance );
RtlInitUnicodeString(&AuthenticationPackage, MICROSOFT_KERBEROS_NAME_W);
if ( !CacheInitialize() ) {
return FALSE;
}
}
return(TRUE);
}
//+---------------------------------------------------------------------------
//
// Function: PwdpParseBuffers
//
// Synopsis: Parse out right buffer descriptor
//
// Arguments: [pMessage] --
// [pToken] --
// [pEmpty] --
//
// Notes:
//
//----------------------------------------------------------------------------
VOID
PwdpParseBuffers(
PSecBufferDesc pMessage,
PSecBuffer * pToken,
PSecBuffer * pEmpty)
{
ULONG i;
PSecBuffer pFirstBlank = NULL;
PSecBuffer pWholeMessage = NULL;
for (i = 0 ; i < pMessage->cBuffers ; i++ )
{
if ( (pMessage->pBuffers[i].BufferType & (~SECBUFFER_ATTRMASK)) == SECBUFFER_TOKEN )
{
pWholeMessage = &pMessage->pBuffers[i];
if (pFirstBlank)
{
break;
}
}
else if ( (pMessage->pBuffers[i].BufferType & (~SECBUFFER_ATTRMASK)) == SECBUFFER_EMPTY )
{
pFirstBlank = &pMessage->pBuffers[i];
if (pWholeMessage)
{
break;
}
}
}
if (pToken)
{
*pToken = pWholeMessage;
}
if (pEmpty)
{
*pEmpty = pFirstBlank;
}
}
//+---------------------------------------------------------------------------
//
// Function: AcquireCredentialsHandleW
//
// Synopsis: Get the credential handle
//
// Arguments: [pszPrincipal] --
// [pszPackageName] --
// [fCredentialUse] --
// [pvLogonId] --
// [pAuthData] --
// [pGetKeyFn] --
// [GetKey] --
// [pvGetKeyArgument] --
// [GetKey] --
// [phCredential] --
// [PTimeStamp] --
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS
SEC_ENTRY
AcquireCredentialsHandleW(
SEC_WCHAR SEC_FAR * pszPrincipal, // Name of principal
SEC_WCHAR SEC_FAR * pszPackageName, // Name of package
unsigned long fCredentialUse, // Flags indicating use
void SEC_FAR * pvLogonId, // Pointer to logon ID
void SEC_FAR * pAuthData, // Package specific data
SEC_GET_KEY_FN pGetKeyFn, // Pointer to GetKey() func
void SEC_FAR * pvGetKeyArgument, // Value to pass to GetKey()
PCredHandle phCredential, // (out) Cred Handle
PTimeStamp ptsExpiry // (out) Lifetime (optional)
)
{
if (_wcsicmp(pszPackageName, PWDSSP_NAME_W))
{
return( SEC_E_SECPKG_NOT_FOUND );
}
if ( fCredentialUse & SECPKG_CRED_OUTBOUND )
{
return( SEC_E_NO_CREDENTIALS );
}
InterlockedIncrement( &PwdGlobalUnicode.Ref );
phCredential->dwUpper = (ULONG_PTR) &PwdGlobalUnicode ;
if ( ptsExpiry )
{
ptsExpiry->LowPart = (DWORD) 0xFFFFFFFF;
ptsExpiry->HighPart = (DWORD) 0x7FFFFFFF;
}
return( SEC_E_OK );
}
//+---------------------------------------------------------------------------
//
// Function: AcquireCredentialsHandleA
//
// Synopsis: ANSI entry
//
// Arguments: [pszPrincipal] --
// [pszPackageName] --
// [fCredentialUse] --
// [pvLogonId] --
// [pAuthData] --
// [pGetKeyFn] --
// [GetKey] --
// [pvGetKeyArgument] --
// [GetKey] --
// [phCredential] --
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY
AcquireCredentialsHandleA(
SEC_CHAR SEC_FAR * pszPrincipal, // Name of principal
SEC_CHAR SEC_FAR * pszPackageName, // Name of package
unsigned long fCredentialUse, // Flags indicating use
void SEC_FAR * pvLogonId, // Pointer to logon ID
void SEC_FAR * pAuthData, // Package specific data
SEC_GET_KEY_FN pGetKeyFn, // Pointer to GetKey() func
void SEC_FAR * pvGetKeyArgument, // Value to pass to GetKey()
PCredHandle phCredential, // (out) Cred Handle
PTimeStamp ptsExpiry // (out) Lifetime (optional)
)
{
if (_stricmp(pszPackageName, PWDSSP_NAME_A))
{
return( SEC_E_SECPKG_NOT_FOUND );
}
if ( fCredentialUse & SECPKG_CRED_OUTBOUND )
{
return( SEC_E_NO_CREDENTIALS );
}
InterlockedIncrement( &PwdGlobalAnsi.Ref );
phCredential->dwUpper = (ULONG_PTR) &PwdGlobalAnsi ;
if ( ptsExpiry )
{
ptsExpiry->LowPart = (DWORD) 0xFFFFFFFF;
ptsExpiry->HighPart = (DWORD) 0x7FFFFFFF;
}
return(SEC_E_OK);
}
//+---------------------------------------------------------------------------
//
// Function: FreeCredentialHandle
//
// Synopsis: Free a credential handle
//
// Arguments: [free] --
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS
SEC_ENTRY
FreeCredentialsHandle(
PCredHandle phCredential // Handle to free
)
{
PPWD_CRED Cred;
if ( (phCredential->dwUpper != (ULONG_PTR) &PwdGlobalAnsi ) &&
(phCredential->dwUpper != (ULONG_PTR) &PwdGlobalUnicode ) )
{
return( SEC_E_INVALID_HANDLE );
}
Cred = (PPWD_CRED) phCredential->dwUpper ;
InterlockedDecrement( &Cred->Ref );
return( SEC_E_OK );
}
//+---------------------------------------------------------------------------
//
// Function: InitializeSecurityContextW
//
// Synopsis: Initialize a security context (outbound) NOT SUPPORTED
//
// Arguments: [phCredential] --
// [phContext] --
// [pszTargetName] --
// [fContextReq] --
// [Reserved1] --
// [Reserved] --
// [TargetDataRep] --
// [pInput] --
// [Reserved2] --
// [Reserved] --
// [phNewContext] --
// [pOutput] --
// [pfContextAttr] --
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS
SEC_ENTRY
InitializeSecurityContextW(
PCredHandle phCredential, // Cred to base context
PCtxtHandle phContext, // Existing context (OPT)
SEC_WCHAR SEC_FAR * pszTargetName, // Name of target
unsigned long fContextReq, // Context Requirements
unsigned long Reserved1, // Reserved, MBZ
unsigned long TargetDataRep, // Data rep of target
PSecBufferDesc pInput, // Input Buffers
unsigned long Reserved2, // Reserved, MBZ
PCtxtHandle phNewContext, // (out) New Context handle
PSecBufferDesc pOutput, // (inout) Output Buffers
unsigned long SEC_FAR * pfContextAttr, // (out) Context attrs
PTimeStamp ptsExpiry // (out) Life span (OPT)
)
{
return( SEC_E_UNSUPPORTED_FUNCTION );
}
//+---------------------------------------------------------------------------
//
// Function: InitializeSecurityContextA
//
// Synopsis: NOT SUPPORTED
//
// Arguments: [phCredential] --
// [phContext] --
// [pszTargetName] --
// [fContextReq] --
// [Reserved1] --
// [TargetDataRep] --
// [pInput] --
// [Reserved2] --
// [phNewContext] --
// [pOutput] --
// [pfContextAttr] --
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS
SEC_ENTRY
InitializeSecurityContextA(
PCredHandle phCredential, // Cred to base context
PCtxtHandle phContext, // Existing context (OPT)
SEC_CHAR SEC_FAR * pszTargetName, // Name of target
unsigned long fContextReq, // Context Requirements
unsigned long Reserved1, // Reserved, MBZ
unsigned long TargetDataRep, // Data rep of target
PSecBufferDesc pInput, // Input Buffers
unsigned long Reserved2, // Reserved, MBZ
PCtxtHandle phNewContext, // (out) New Context handle
PSecBufferDesc pOutput, // (inout) Output Buffers
unsigned long SEC_FAR * pfContextAttr, // (out) Context attrs
PTimeStamp ptsExpiry // (out) Life span (OPT)
)
{
return( SEC_E_UNSUPPORTED_FUNCTION );
}
PSEC_WINNT_AUTH_IDENTITY_A
PwdpMakeAnsiCopy(
PSEC_WINNT_AUTH_IDENTITY_A Ansi
)
{
PSEC_WINNT_AUTH_IDENTITY_A New ;
New = PwdAlloc( sizeof( SEC_WINNT_AUTH_IDENTITY_A ) +
Ansi->UserLength + 1 +
Ansi->DomainLength + 1 +
Ansi->PasswordLength + 1 );
if ( New )
{
New->User = (PSTR) (New + 1);
CopyMemory( New->User, Ansi->User, Ansi->UserLength );
New->User[ Ansi->UserLength ] = '\0';
New->Domain = New->User + Ansi->UserLength + 1 ;
CopyMemory( New->Domain, Ansi->Domain, Ansi->DomainLength );
New->Domain[ Ansi->DomainLength ] = '\0';
New->Password = New->Domain + Ansi->DomainLength + 1 ;
CopyMemory( New->Password, Ansi->Password, Ansi->PasswordLength );
New->Password[ Ansi->PasswordLength ] = '\0';
}
return( New );
}
PSEC_WINNT_AUTH_IDENTITY_W
PwdpMakeWideCopy(
PSEC_WINNT_AUTH_IDENTITY_W Wide,
BOOLEAN ValidateOnly
)
{
PSEC_WINNT_AUTH_IDENTITY_W New ;
ULONG FlatUserLength ;
PWSTR FlatUser = NULL;
WCHAR FlatDomain[ DNLEN + 2 ];
SEC_WINNT_AUTH_IDENTITY_W Local ;
if ( (Wide->Domain == NULL) )
{
if( ValidateOnly )
{
ULONG Index;
Local = *Wide ;
FlatUserLength = wcslen( Wide->User );
for( Index = 0 ; Index < FlatUserLength ; Index++ )
{
if( Wide->User[ Index ] == '\\' )
{
Local.Domain = Wide->User;
Local.DomainLength = Index;
Local.User = &(Wide->User[Index+1]);
Local.UserLength = FlatUserLength - Index - 1;
break;
}
}
} else {
FlatUserLength = wcslen( Wide->User ) + 1;
if ( FlatUserLength < UNLEN+2 )
{
FlatUserLength = UNLEN + 2;
}
FlatUser = PwdAlloc(FlatUserLength * sizeof( WCHAR ));
if ( FlatUser == NULL )
{
return NULL ;
}
if ( ! PwdCrackName( Wide->User,
FlatDomain,
FlatUser ) )
{
PwdFree( FlatUser );
SetLastError( ERROR_NO_SUCH_USER );
return NULL ;
}
Local = *Wide ;
Local.User = FlatUser ;
Local.Domain = FlatDomain ;
Local.UserLength = wcslen( FlatUser );
Local.DomainLength = wcslen( FlatDomain );
}
Wide = &Local ;
}
New = PwdAlloc( sizeof( SEC_WINNT_AUTH_IDENTITY_W ) +
(Wide->UserLength + 1) * sizeof(WCHAR) +
(Wide->DomainLength + 1) * sizeof(WCHAR) +
(Wide->PasswordLength + 1) * sizeof(WCHAR) );
if ( New )
{
New->User = (PWSTR) (New + 1);
CopyMemory( New->User, Wide->User, Wide->UserLength * 2 );
New->User[ Wide->UserLength ] = L'\0';
New->UserLength = Wide->UserLength;
New->Domain = New->User + Wide->UserLength + 1 ;
CopyMemory( New->Domain, Wide->Domain, Wide->DomainLength * 2 );
New->Domain[ Wide->DomainLength ] = L'\0';
New->DomainLength = Wide->DomainLength;
New->Password = New->Domain + Wide->DomainLength + 1 ;
CopyMemory( New->Password, Wide->Password, Wide->PasswordLength * 2);
New->Password[ Wide->PasswordLength ] = '\0';
New->PasswordLength = Wide->PasswordLength;
}
if ( Wide == &Local )
{
if( FlatUser != NULL )
{
PwdFree( FlatUser );
}
}
return( New );
}
//+---------------------------------------------------------------------------
//
// Function: AcceptSecurityContext
//
// Synopsis: Server side accept security context
//
// Arguments: [phCredential] --
// [phContext] --
// [pInput] --
// [fContextReq] --
// [TargetDataRep] --
// [phNewContext] --
// [pOutput] --
// [pfContextAttr] --
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS
SEC_ENTRY
AcceptSecurityContext(
PCredHandle phCredential, // Cred to base context
PCtxtHandle phContext, // Existing context (OPT)
PSecBufferDesc pInput, // Input buffer
unsigned long fContextReq, // Context Requirements
unsigned long TargetDataRep, // Target Data Rep
PCtxtHandle phNewContext, // (out) New context handle
PSecBufferDesc pOutput, // (inout) Output buffers
unsigned long SEC_FAR * pfContextAttr, // (out) Context attributes
PTimeStamp ptsExpiry // (out) Life span (OPT)
)
{
PPWD_CONTEXT Context ;
PSecBuffer Buffer ;
DWORD Type;
PSEC_WINNT_AUTH_IDENTITY_W Unknown ;
PSEC_WINNT_AUTH_IDENTITY_A Ansi;
PSEC_WINNT_AUTH_IDENTITY_W Unicode;
HANDLE Token;
BOOL Ret;
if ( phCredential->dwUpper == (ULONG_PTR) &PwdGlobalAnsi )
{
Type = 1;
}
else
{
if ( phCredential->dwUpper == (ULONG_PTR) &PwdGlobalUnicode )
{
Type = 2;
}
else
{
return( SEC_E_INVALID_HANDLE );
}
}
PwdpParseBuffers( pInput, &Buffer, NULL );
if ( !Buffer )
{
return( SEC_E_INVALID_TOKEN );
}
Unknown = (PSEC_WINNT_AUTH_IDENTITY_W) Buffer->pvBuffer ;
if ( Unknown->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE )
{
Type = 2 ;
}
if ( Type == 1 )
{
//
// ANSI:
//
Ansi = PwdpMakeAnsiCopy( (PSEC_WINNT_AUTH_IDENTITY_A) Buffer->pvBuffer);
if ( Ansi )
{
Ret = LogonUserA( Ansi->User, Ansi->Domain, Ansi->Password,
LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT,
&Token ) ;
PwdFree( Ansi );
}
else
{
Ret = FALSE ;
}
}
else
{
BOOLEAN ValidateOnly = ((fContextReq & ASC_REQ_ALLOW_NON_USER_LOGONS) != 0);
Unicode = PwdpMakeWideCopy(
(PSEC_WINNT_AUTH_IDENTITY_W) Buffer->pvBuffer,
ValidateOnly
);
if ( Unicode )
{
if( ValidateOnly )
{
PVOID DsContext = THSave();
NTSTATUS Status;
Status = VerifyCredentials(
Unicode->User,
Unicode->Domain,
Unicode->Password,
0
);
THRestore( DsContext );
if( NT_SUCCESS(Status) )
{
Ret = TRUE;
Token = ANONYMOUS_TOKEN ;
} else {
Ret = FALSE;
}
} else {
Ret = LogonUserW(
Unicode->User,
Unicode->Domain,
Unicode->Password,
LOGON32_LOGON_NETWORK,
LOGON32_PROVIDER_DEFAULT,
&Token
);
}
PwdFree( Unicode );
}
else
{
Ret = FALSE ;
if ( GetLastError() == ERROR_NO_SUCH_USER )
{
Unicode = (PSEC_WINNT_AUTH_IDENTITY_W) Buffer->pvBuffer ;
__try
{
if ( Unicode->PasswordLength == 0 )
{
Ret = TRUE ;
Token = ANONYMOUS_TOKEN ;
}
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
NOTHING ;
}
}
}
}
if ( Ret )
{
Context = (PPWD_CONTEXT) PwdAlloc( sizeof( PWD_CONTEXT ) );
if ( Context )
{
Context->Tag = CONTEXT_TAG ;
Context->Token = Token ;
phNewContext->dwUpper = (ULONG_PTR) Context ;
return( SEC_E_OK );
}
if ( Token != ANONYMOUS_TOKEN )
{
CloseHandle( Token );
}
return( SEC_E_INSUFFICIENT_MEMORY );
}
return( SEC_E_INVALID_TOKEN );
}
//+---------------------------------------------------------------------------
//
// Function: DeleteSecurityContext
//
// Synopsis: Deletes a security context
//
// Arguments: [phContext] --
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS
SEC_ENTRY
DeleteSecurityContext(
PCtxtHandle phContext )
{
PPWD_CONTEXT Context;
Context = (PPWD_CONTEXT) phContext->dwUpper ;
#if DBG
// What is the appropriate assert model? This dll does not seem to
// nt specific, win32 does not provide a model, and the crt requires
// NDEBUG to set, which is not always the case.
if (!Context) {
OutputDebugStringA("[PWDSSP]: !!Error!! - Context is NULL\n");
DebugBreak();
}
#endif
if ( Context->Tag == CONTEXT_TAG )
{
if ( Context->Token != ANONYMOUS_TOKEN )
{
CloseHandle( Context->Token );
}
PwdFree( Context );
return( SEC_E_OK );
}
return( SEC_E_INVALID_HANDLE );
}
//+---------------------------------------------------------------------------
//
// Function: ImpersonateSecurityContext
//
// Synopsis: Impersonate the security context
//
// Arguments: [impersonate] --
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS
SEC_ENTRY
ImpersonateSecurityContext(
PCtxtHandle phContext // Context to impersonate
)
{
PPWD_CONTEXT Context;
HANDLE hThread;
NTSTATUS Status ;
Context = (PPWD_CONTEXT) phContext->dwUpper ;
if ( Context->Tag == CONTEXT_TAG )
{
if ( Context->Token != ANONYMOUS_TOKEN )
{
hThread = GetCurrentThread();
SetThreadToken( &hThread, Context->Token );
Status = SEC_E_OK ;
}
else
{
Status = NtImpersonateAnonymousToken(
NtCurrentThread() );
}
return( Status );
}
return( SEC_E_INVALID_HANDLE );
}
//+---------------------------------------------------------------------------
//
// Function: RevertSecurityContext
//
// Synopsis: Revert the security context
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS
SEC_ENTRY
RevertSecurityContext(
PCtxtHandle phContext // Context from which to re
)
{
PPWD_CONTEXT Context;
Context = (PPWD_CONTEXT) phContext->dwUpper ;
if ( Context->Tag == CONTEXT_TAG )
{
RevertToSelf();
return( SEC_E_OK );
}
return( SEC_E_INVALID_HANDLE );
}
SECURITY_STATUS
SEC_ENTRY
QueryContextAttributesA(
PCtxtHandle phContext, // Context to query
unsigned long ulAttribute, // Attribute to query
void SEC_FAR * pBuffer // Buffer for attributes
)
{
return( SEC_E_UNSUPPORTED_FUNCTION );
}
SECURITY_STATUS
SEC_ENTRY
QueryContextAttributesW(
PCtxtHandle phContext, // Context to query
unsigned long ulAttribute, // Attribute to query
void SEC_FAR * pBuffer // Buffer for attributes
)
{
return( SEC_E_UNSUPPORTED_FUNCTION );
}
//+---------------------------------------------------------------------------
//
// Function: PwdpCopyInfoW
//
// Synopsis: Helper - copy package info around
//
// Arguments: [ppPackageInfo] --
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS
PwdpCopyInfoW(
PSecPkgInfoW * ppPackageInfo)
{
DWORD cbTotal;
PSecPkgInfoW pInfo;
PWSTR pszCopy;
cbTotal = sizeof(SecPkgInfoW) +
(wcslen(PwdInfoW.Name) + wcslen(PwdInfoW.Comment) + 2) * 2;
pInfo = PwdAlloc( cbTotal );
if (pInfo)
{
*pInfo = PwdInfoW;
pszCopy = (PWSTR) (pInfo + 1);
pInfo->Name = pszCopy;
wcscpy(pszCopy, PwdInfoW.Name);
pszCopy += wcslen(PwdInfoW.Name) + 1;
pInfo->Comment = pszCopy;
wcscpy(pszCopy, PwdInfoW.Comment);
*ppPackageInfo = pInfo;
return(SEC_E_OK);
}
return(SEC_E_INSUFFICIENT_MEMORY);
}
//+---------------------------------------------------------------------------
//
// Function: PwdpCopyInfoA
//
// Synopsis: copy ansi package info around
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS
PwdpCopyInfoA(
PSecPkgInfoA * ppPackageInfo)
{
DWORD cbTotal;
PSecPkgInfoA pInfo;
PSTR pszCopy;
cbTotal = sizeof(SecPkgInfoA) +
(strlen(PwdInfoA.Name) + strlen(PwdInfoA.Comment) + 2) * 2;
pInfo = PwdAlloc( cbTotal );
if (pInfo)
{
*pInfo = PwdInfoA;
pszCopy = (PSTR) (pInfo + 1);
pInfo->Name = pszCopy;
strcpy(pszCopy, PwdInfoA.Name);
pszCopy += strlen(PwdInfoA.Name) + 1;
pInfo->Comment = pszCopy;
strcpy(pszCopy, PwdInfoA.Comment);
*ppPackageInfo = pInfo;
return(SEC_E_OK);
}
return(SEC_E_INSUFFICIENT_MEMORY);
}
//+---------------------------------------------------------------------------
//
// Function: EnumerateSecurityPackagesW
//
// Synopsis: Enumerate packages in this DLL
//
// Arguments: [pcPackages] --
// [info] --
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS
SEC_ENTRY
EnumerateSecurityPackagesW(
unsigned long SEC_FAR * pcPackages, // Receives num. packages
PSecPkgInfoW SEC_FAR * ppPackageInfo // Receives array of info
)
{
SECURITY_STATUS scRet;
*ppPackageInfo = NULL;
scRet = PwdpCopyInfoW(ppPackageInfo);
if (SUCCEEDED(scRet))
{
*pcPackages = 1;
return(scRet);
}
*pcPackages = 0;
return(scRet);
}
//+---------------------------------------------------------------------------
//
// Function: EnumerateSecurityPackagesA
//
// Synopsis: Enumerate
//
// Arguments: [pcPackages] --
// [info] --
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY
EnumerateSecurityPackagesA(
unsigned long SEC_FAR * pcPackages, // Receives num. packages
PSecPkgInfoA SEC_FAR * ppPackageInfo // Receives array of info
)
{
SECURITY_STATUS scRet;
*ppPackageInfo = NULL;
scRet = PwdpCopyInfoA(ppPackageInfo);
if (SUCCEEDED(scRet))
{
*pcPackages = 1;
return(scRet);
}
*pcPackages = 0;
return(scRet);
}
//+---------------------------------------------------------------------------
//
// Function: QuerySecurityPackageInfoW
//
// Synopsis: Query individual package info
//
// Arguments: [pszPackageName] --
// [info] --
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY
QuerySecurityPackageInfoW(
SEC_WCHAR SEC_FAR * pszPackageName, // Name of package
PSecPkgInfoW * ppPackageInfo // Receives package info
)
{
if (_wcsicmp(pszPackageName, PWDSSP_NAME_W))
{
return(SEC_E_SECPKG_NOT_FOUND);
}
return(PwdpCopyInfoW(ppPackageInfo));
}
//+---------------------------------------------------------------------------
//
// Function: QuerySecurityPackageInfoA
//
// Synopsis: Same, ansi
//
// Arguments: [pszPackageName] --
// [info] --
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY
QuerySecurityPackageInfoA(
SEC_CHAR SEC_FAR * pszPackageName, // Name of package
PSecPkgInfoA * ppPackageInfo // Receives package info
)
{
if (_stricmp(pszPackageName, PWDSSP_NAME_A))
{
return(SEC_E_SECPKG_NOT_FOUND);
}
return(PwdpCopyInfoA(ppPackageInfo));
}
SECURITY_STATUS
SEC_ENTRY
MakeSignature(PCtxtHandle phContext,
DWORD fQOP,
PSecBufferDesc pMessage,
ULONG MessageSeqNo)
{
return(SEC_E_UNSUPPORTED_FUNCTION);
}
SECURITY_STATUS SEC_ENTRY
VerifySignature(PCtxtHandle phContext,
PSecBufferDesc pMessage,
ULONG MessageSeqNo,
DWORD * pfQOP)
{
return(SEC_E_UNSUPPORTED_FUNCTION);
}
SECURITY_STATUS
SEC_ENTRY
SealMessage(PCtxtHandle phContext,
DWORD fQOP,
PSecBufferDesc pMessage,
ULONG MessageSeqNo)
{
return(SEC_E_UNSUPPORTED_FUNCTION);
}
SECURITY_STATUS SEC_ENTRY
UnsealMessage(PCtxtHandle phContext,
PSecBufferDesc pMessage,
ULONG MessageSeqNo,
DWORD * pfQOP)
{
return(SEC_E_UNSUPPORTED_FUNCTION);
}
SECURITY_STATUS SEC_ENTRY
ApplyControlToken(
PCtxtHandle phContext, // Context to modify
PSecBufferDesc pInput // Input token to apply
)
{
return( SEC_E_UNSUPPORTED_FUNCTION );
}
SECURITY_STATUS
SEC_ENTRY
FreeContextBuffer(
PVOID p)
{
if( p != NULL )
{
PwdFree( p );
}
return( SEC_E_OK );
}
SECURITY_STATUS
SEC_ENTRY
QuerySecurityContextToken(
PCtxtHandle phContext,
PHANDLE Token)
{
PPWD_CONTEXT Context;
Context = (PPWD_CONTEXT) phContext->dwUpper ;
if ( Context->Tag == CONTEXT_TAG )
{
*Token = Context->Token ;
return( SEC_E_OK );
}
return( SEC_E_INVALID_HANDLE );
}
SECURITY_STATUS SEC_ENTRY
CompleteAuthToken(
PCtxtHandle phContext, // Context to complete
PSecBufferDesc pToken // Token to complete
)
{
return( SEC_E_UNSUPPORTED_FUNCTION );
}
PSecurityFunctionTableA
SEC_ENTRY
InitSecurityInterfaceA( VOID )
{
return( &PwdTableA );
}
PSecurityFunctionTableW
SEC_ENTRY
InitSecurityInterfaceW( VOID )
{
return( &PwdTableW );
}
NTSTATUS
VerifyCredentials(
IN PWSTR UserName,
IN PWSTR DomainName,
IN PWSTR Password,
IN ULONG VerifyFlags
)
{
PKERB_VERIFY_CREDENTIALS_REQUEST pVerifyRequest;
KERB_VERIFY_CREDENTIALS_REQUEST VerifyRequest;
ULONG cbVerifyRequest;
PVOID pResponse = NULL;
ULONG cbResponse;
USHORT cbUserName;
USHORT cbDomainName;
USHORT cbPassword;
NTSTATUS ProtocolStatus = STATUS_LOGON_FAILURE;
NTSTATUS Status;
cbUserName = (USHORT)(lstrlenW(UserName) * sizeof(WCHAR)) ;
cbDomainName = (USHORT)(lstrlenW(DomainName) * sizeof(WCHAR)) ;
cbPassword = (USHORT)(lstrlenW(Password) * sizeof(WCHAR)) ;
cbVerifyRequest = sizeof(VerifyRequest) +
cbUserName +
cbDomainName +
cbPassword ;
pVerifyRequest = &VerifyRequest;
ZeroMemory( &VerifyRequest, sizeof(VerifyRequest) );
pVerifyRequest->MessageType = KerbVerifyCredentialsMessage ;
//
// do the length, buffers, copy, marshall dance.
//
pVerifyRequest->UserName.Length = cbUserName;
pVerifyRequest->UserName.MaximumLength = cbUserName;
pVerifyRequest->UserName.Buffer = UserName;
pVerifyRequest->DomainName.Length = cbDomainName;
pVerifyRequest->DomainName.MaximumLength = cbDomainName;
pVerifyRequest->DomainName.Buffer = DomainName;
pVerifyRequest->Password.Length = cbPassword;
pVerifyRequest->Password.MaximumLength = cbPassword;
pVerifyRequest->Password.Buffer = Password;
pVerifyRequest->VerifyFlags = VerifyFlags;
Status = I_LsaICallPackage(
&AuthenticationPackage,
pVerifyRequest,
cbVerifyRequest,
&pResponse,
&cbResponse,
&ProtocolStatus
);
if(!NT_SUCCESS(Status))
{
goto Cleanup;
}
Status = ProtocolStatus;
Cleanup:
return Status;
}