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.
1137 lines
32 KiB
1137 lines
32 KiB
/*++
|
|
|
|
Copyright (c) 1987-1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
subauth.c
|
|
|
|
Abstract:
|
|
|
|
Interface to SubAuthentication Package.
|
|
|
|
Author:
|
|
|
|
Cliff Van Dyke (cliffv) 23-May-1994
|
|
|
|
Environment:
|
|
|
|
User mode only.
|
|
Contains NT-specific code.
|
|
Requires ANSI C extensions: slash-slash comments, long external names.
|
|
|
|
Revision History:
|
|
Chandana Surlu 21-Jul-96 Stolen from \\kernel\razzle3\src\security\msv1_0\subauth.c
|
|
|
|
--*/
|
|
|
|
#include <global.h>
|
|
|
|
#include "msp.h"
|
|
#include "nlp.h"
|
|
#include <winreg.h>
|
|
#include <kerberos.h>
|
|
|
|
//
|
|
// Prototype for subauthentication routines.
|
|
//
|
|
// the pre NT 5.0 Subauth routine
|
|
typedef NTSTATUS
|
|
(*PSUBAUTHENTICATION_ROUTINE)(
|
|
IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
|
|
IN PVOID LogonInformation,
|
|
IN ULONG Flags,
|
|
IN PUSER_ALL_INFORMATION UserAll,
|
|
OUT PULONG WhichFields,
|
|
OUT PULONG UserFlags,
|
|
OUT PBOOLEAN Authoritative,
|
|
OUT PLARGE_INTEGER LogoffTime,
|
|
OUT PLARGE_INTEGER KickoffTime
|
|
);
|
|
|
|
// the NT 5.0 Subauth routine
|
|
typedef NTSTATUS
|
|
(*PSUBAUTHENTICATION_ROUTINEEX)(
|
|
IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
|
|
IN PVOID LogonInformation,
|
|
IN ULONG Flags,
|
|
IN PUSER_ALL_INFORMATION UserAll,
|
|
IN SAM_HANDLE UserHandle,
|
|
IN OUT PMSV1_0_VALIDATION_INFO ValidationInfo,
|
|
OUT PULONG ActionsPerfomed
|
|
);
|
|
|
|
// the NT 5.0 Generic Subauth routine
|
|
typedef NTSTATUS
|
|
(*PSUBAUTHENTICATION_ROUTINEGENERIC)(
|
|
IN PVOID SubmitBuffer,
|
|
IN ULONG SubmitBufferLength,
|
|
OUT PULONG ReturnBufferLength,
|
|
OUT PVOID *ReturnBuffer
|
|
);
|
|
typedef enum _SUBAUTH_TYPE {
|
|
SubAuth = 1, // Pre NT 5.0 subAuth called using LogonUser
|
|
SubAuthEx, // NT 5.0 subAuth called during LogonUser
|
|
SubAuthGeneric // NT 5.0 subAuth called during LaCallAuthenticationPackage
|
|
} SUBAUTH_TYPE;
|
|
//
|
|
// Structure describing a loaded SubAuthentication DLL.
|
|
//
|
|
|
|
typedef struct _SUBAUTHENTICATION_DLL {
|
|
LIST_ENTRY Next;
|
|
ULONG DllNumber;
|
|
PSUBAUTHENTICATION_ROUTINE SubAuthenticationRoutine;
|
|
PSUBAUTHENTICATION_ROUTINEEX SubAuthenticationRoutineEx;
|
|
PSUBAUTHENTICATION_ROUTINEGENERIC SubAuthenticationRoutineGeneric;
|
|
} SUBAUTHENTICATION_DLL, *PSUBAUTHENTICATION_DLL;
|
|
|
|
//
|
|
// Global list of all loaded subauthentication DLLs
|
|
//
|
|
|
|
LIST_ENTRY SubAuthenticationDlls;
|
|
RTL_RESOURCE SubAuthenticationCritSect;
|
|
|
|
|
|
|
|
|
|
VOID
|
|
Msv1_0SubAuthenticationInitialization(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialization routine for this source file.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
RtlInitializeResource( &SubAuthenticationCritSect );
|
|
InitializeListHead( &SubAuthenticationDlls );
|
|
}
|
|
|
|
PSUBAUTHENTICATION_DLL
|
|
ReferenceSubAuth (
|
|
IN ULONG DllNumber,
|
|
OUT PNTSTATUS SubStatus)
|
|
{
|
|
LONG RegStatus;
|
|
|
|
PSUBAUTHENTICATION_DLL SubAuthenticationDll = NULL;
|
|
|
|
HKEY ParmHandle = NULL;
|
|
HINSTANCE DllHandle = NULL;
|
|
|
|
CHAR ValueName[sizeof(MSV1_0_SUBAUTHENTICATION_VALUE)+3];
|
|
CHAR DllName[MAXIMUM_FILENAME_LENGTH+1];
|
|
DWORD DllNameSize;
|
|
DWORD DllNameType;
|
|
PSUBAUTHENTICATION_ROUTINE SubAuthenticationRoutine = NULL;
|
|
PSUBAUTHENTICATION_ROUTINEEX SubAuthenticationRoutineEx = NULL;
|
|
PSUBAUTHENTICATION_ROUTINEGENERIC SubAuthenticationRoutineGeneric = NULL;
|
|
|
|
PLIST_ENTRY ListEntry;
|
|
|
|
*SubStatus = STATUS_SUCCESS;
|
|
DllName[0] = 0;
|
|
|
|
// See if the SubAuthentication Dll is already loaded.
|
|
//
|
|
|
|
RtlAcquireResourceShared(&SubAuthenticationCritSect, TRUE);
|
|
|
|
for ( ListEntry = SubAuthenticationDlls.Flink ;
|
|
ListEntry != &SubAuthenticationDlls ;
|
|
ListEntry = ListEntry->Flink) {
|
|
|
|
SubAuthenticationDll = CONTAINING_RECORD( ListEntry,
|
|
SUBAUTHENTICATION_DLL,
|
|
Next );
|
|
|
|
if ( SubAuthenticationDll->DllNumber == DllNumber ) {
|
|
break;
|
|
}
|
|
|
|
SubAuthenticationDll = NULL;
|
|
|
|
}
|
|
|
|
RtlReleaseResource(&SubAuthenticationCritSect);
|
|
|
|
//
|
|
// If the Dll is not already loaded,
|
|
// load it.
|
|
//
|
|
|
|
if ( SubAuthenticationDll != NULL ) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Build the name of the registry value.
|
|
//
|
|
|
|
RtlCopyMemory( ValueName,
|
|
MSV1_0_SUBAUTHENTICATION_VALUE,
|
|
sizeof(MSV1_0_SUBAUTHENTICATION_VALUE) );
|
|
|
|
*SubStatus = RtlIntegerToChar(
|
|
DllNumber & KERB_SUBAUTHENTICATION_MASK,
|
|
10, // Base
|
|
4, // Length of buffer
|
|
&ValueName[sizeof(MSV1_0_SUBAUTHENTICATION_VALUE)-1] );
|
|
|
|
if ( !NT_SUCCESS(*SubStatus) ) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Open the MSV1_0_SUBAUTHENTICATION_KEY registry key.
|
|
//
|
|
|
|
|
|
if ((DllNumber & KERB_SUBAUTHENTICATION_FLAG) == 0) {
|
|
RegStatus = RegOpenKeyExA(
|
|
HKEY_LOCAL_MACHINE,
|
|
MSV1_0_SUBAUTHENTICATION_KEY,
|
|
0, //Reserved
|
|
KEY_QUERY_VALUE,
|
|
&ParmHandle );
|
|
} else {
|
|
RegStatus = RegOpenKeyExA(
|
|
HKEY_LOCAL_MACHINE,
|
|
KERB_SUBAUTHENTICATION_KEY,
|
|
0, //Reserved
|
|
KEY_QUERY_VALUE,
|
|
&ParmHandle );
|
|
|
|
}
|
|
|
|
if ( RegStatus != ERROR_SUCCESS ) {
|
|
SspPrint((SSP_MISC, "Cannot open registry key %s %ld.\n",
|
|
MSV1_0_SUBAUTHENTICATION_KEY,
|
|
RegStatus ));
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// Get the registry value.
|
|
//
|
|
|
|
DllNameSize = sizeof(DllName);
|
|
|
|
RegStatus = RegQueryValueExA(
|
|
ParmHandle,
|
|
ValueName,
|
|
NULL, // Reserved
|
|
&DllNameType,
|
|
(LPBYTE) DllName,
|
|
&DllNameSize );
|
|
|
|
if ( RegStatus == ERROR_SUCCESS ) {
|
|
|
|
if ( DllNameType != REG_SZ ) {
|
|
SspPrint((SSP_MISC, "Registry value %s isn't REG_SZ.\n",
|
|
ValueName ));
|
|
*SubStatus = STATUS_DLL_NOT_FOUND;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Load the DLL
|
|
//
|
|
|
|
DllHandle = LoadLibraryA( DllName );
|
|
|
|
if ( DllHandle == NULL ) {
|
|
SspPrint((SSP_MISC, "MSV1_0: Cannot load dll %s %ld.\n",
|
|
DllName,
|
|
GetLastError() ));
|
|
*SubStatus = STATUS_DLL_NOT_FOUND;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Find the SubAuthenticationRoutine. For packages other than
|
|
// zero, this will be Msv1_0SubauthenticationRoutine. For packge
|
|
// zero it will be Msv1_0SubauthenticationFilter.
|
|
//
|
|
|
|
if ((DllNumber & KERB_SUBAUTHENTICATION_MASK) == 0)
|
|
{
|
|
SubAuthenticationRoutine = (PSUBAUTHENTICATION_ROUTINE)
|
|
GetProcAddress(DllHandle, "Msv1_0SubAuthenticationFilter");
|
|
}
|
|
else
|
|
{
|
|
SubAuthenticationRoutine = (PSUBAUTHENTICATION_ROUTINE)
|
|
GetProcAddress(DllHandle, "Msv1_0SubAuthenticationRoutine");
|
|
}
|
|
|
|
//
|
|
// Find the SubAuthenticationRoutine
|
|
//
|
|
|
|
SubAuthenticationRoutineEx = (PSUBAUTHENTICATION_ROUTINEEX)
|
|
GetProcAddress(DllHandle, "Msv1_0SubAuthenticationRoutineEx");
|
|
|
|
//
|
|
// Find the SubAuthenticationRoutineGeneric
|
|
//
|
|
|
|
SubAuthenticationRoutineGeneric = (PSUBAUTHENTICATION_ROUTINEGENERIC)
|
|
GetProcAddress(DllHandle, "Msv1_0SubAuthenticationRoutineGeneric");
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we didn't find the DLL or any routines, bail out now.
|
|
//
|
|
|
|
if ((DllHandle == NULL) ||
|
|
((SubAuthenticationRoutine == NULL) &&
|
|
(SubAuthenticationRoutineEx == NULL) &&
|
|
(SubAuthenticationRoutineGeneric == NULL))) {
|
|
|
|
SspPrint((SSP_MISC, "Cannot find any of the subauth entry points in %s %ld.\n",
|
|
DllName,
|
|
GetLastError() ));
|
|
*SubStatus = STATUS_PROCEDURE_NOT_FOUND;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Cache the address of the procedure.
|
|
//
|
|
|
|
SubAuthenticationDll =
|
|
I_NtLmAllocate(sizeof(SUBAUTHENTICATION_DLL));
|
|
|
|
if ( SubAuthenticationDll == NULL ) {
|
|
*SubStatus = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
SubAuthenticationDll->DllNumber = DllNumber;
|
|
SubAuthenticationDll->SubAuthenticationRoutine = SubAuthenticationRoutine;
|
|
SubAuthenticationDll->SubAuthenticationRoutineEx = SubAuthenticationRoutineEx;
|
|
SubAuthenticationDll->SubAuthenticationRoutineGeneric = SubAuthenticationRoutineGeneric;
|
|
|
|
RtlAcquireResourceExclusive(&SubAuthenticationCritSect, TRUE);
|
|
InsertHeadList( &SubAuthenticationDlls, &SubAuthenticationDll->Next );
|
|
RtlReleaseResource(&SubAuthenticationCritSect);
|
|
|
|
DllHandle = NULL;
|
|
|
|
//
|
|
// Cleanup up before returning.
|
|
//
|
|
|
|
Cleanup:
|
|
|
|
|
|
if ( ParmHandle != NULL ) {
|
|
RegCloseKey( ParmHandle );
|
|
}
|
|
|
|
if ( !NT_SUCCESS( *SubStatus) ) {
|
|
if ( DllHandle != NULL ) {
|
|
FreeLibrary( DllHandle );
|
|
}
|
|
}
|
|
|
|
return SubAuthenticationDll;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
Msv1_0SubAuthenticationPresent(
|
|
IN ULONG DllNumber
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns TRUE if there is a subauthentication package with the given number
|
|
|
|
Arguments:
|
|
|
|
DllNumber - the number of the DLL to check
|
|
|
|
Return Value:
|
|
|
|
TRUE if there is a subauthentication DLL, otherwise FALSE.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS SubStatus;
|
|
BOOLEAN Present;
|
|
|
|
if(ReferenceSubAuth( DllNumber, &SubStatus) != NULL) {
|
|
Present = TRUE;
|
|
} else {
|
|
Present = FALSE;
|
|
}
|
|
|
|
return Present;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
Msv1_0SubAuthenticationRoutineZero(
|
|
IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
|
|
IN PVOID LogonInformation,
|
|
IN ULONG Flags,
|
|
IN PUSER_ALL_INFORMATION UserAll,
|
|
OUT PULONG WhichFields,
|
|
OUT PULONG UserFlags,
|
|
OUT PBOOLEAN Authoritative,
|
|
OUT PLARGE_INTEGER LogoffTime,
|
|
OUT PLARGE_INTEGER KickoffTime
|
|
)
|
|
{
|
|
PNETLOGON_LOGON_IDENTITY_INFO LogonInfo;
|
|
ULONG DllNumber;
|
|
|
|
LogonInfo = (PNETLOGON_LOGON_IDENTITY_INFO) LogonInformation;
|
|
DllNumber = LogonInfo->ParameterControl >> MSV1_0_SUBAUTHENTICATION_DLL_SHIFT;
|
|
|
|
if( DllNumber != 0 ) {
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
return Msv1_0SubAuthenticationRoutine(
|
|
LogonLevel,
|
|
LogonInformation,
|
|
Flags,
|
|
UserAll,
|
|
WhichFields,
|
|
UserFlags,
|
|
Authoritative,
|
|
LogoffTime,
|
|
KickoffTime
|
|
);
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
Msv1_0SubAuthenticationRoutine(
|
|
IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
|
|
IN PVOID LogonInformation,
|
|
IN ULONG Flags,
|
|
IN PUSER_ALL_INFORMATION UserAll,
|
|
OUT PULONG WhichFields,
|
|
OUT PULONG UserFlags,
|
|
OUT PBOOLEAN Authoritative,
|
|
OUT PLARGE_INTEGER LogoffTime,
|
|
OUT PLARGE_INTEGER KickoffTime
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The subauthentication routine does client/server specific authentication
|
|
of a user. This stub routine loads the appropriate subauthentication
|
|
package DLL and calls out to that DLL to do the actuall validation.
|
|
|
|
Arguments:
|
|
|
|
LogonLevel -- Specifies the level of information given in
|
|
LogonInformation.
|
|
|
|
LogonInformation -- Specifies the description for the user
|
|
logging on. The LogonDomainName field should be ignored.
|
|
|
|
Flags - Flags describing the circumstances of the logon.
|
|
|
|
MSV1_0_PASSTHRU -- This is a PassThru authenication. (i.e., the
|
|
user isn't connecting to this machine.)
|
|
MSV1_0_GUEST_LOGON -- This is a retry of the logon using the GUEST
|
|
user account.
|
|
|
|
UserAll -- The description of the user as returned from SAM.
|
|
|
|
WhichFields -- Returns which fields from UserAllInfo are to be written
|
|
back to SAM. The fields will only be written if MSV returns success
|
|
to it's caller. Only the following bits are valid.
|
|
|
|
USER_ALL_PARAMETERS - Write UserAllInfo->Parameters back to SAM. If
|
|
the size of the buffer is changed, Msv1_0SubAuthenticationRoutine
|
|
must delete the old buffer using MIDL_user_free() and reallocate the
|
|
buffer using MIDL_user_allocate().
|
|
|
|
UserFlags -- Returns UserFlags to be returned from LsaLogonUser in the
|
|
LogonProfile. The following bits are currently defined:
|
|
|
|
|
|
LOGON_GUEST -- This was a guest logon
|
|
LOGON_NOENCRYPTION -- The caller didn't specify encrypted credentials
|
|
LOGON_GRACE_LOGON -- The caller's password has expired but logon
|
|
was allowed during a grace period following the expiration.
|
|
|
|
SubAuthentication packages should restrict themselves to returning
|
|
bits in the high order byte of UserFlags. However, this convention
|
|
isn't enforced giving the SubAuthentication package more flexibility.
|
|
|
|
Authoritative -- Returns whether the status returned is an
|
|
authoritative status which should be returned to the original
|
|
caller. If not, this logon request may be tried again on another
|
|
domain controller. This parameter is returned regardless of the
|
|
status code.
|
|
|
|
LogoffTime - Receives the time at which the user should logoff the
|
|
system. This time is specified as a GMT relative NT system time.
|
|
|
|
KickoffTime - Receives the time at which the user should be kicked
|
|
off the system. This time is specified as a GMT relative NT system
|
|
time. Specify, a full scale positive number if the user isn't to
|
|
be kicked off.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS: if there was no error.
|
|
|
|
STATUS_NO_SUCH_USER: The specified user has no account.
|
|
STATUS_WRONG_PASSWORD: The password was invalid.
|
|
|
|
STATUS_INVALID_INFO_CLASS: LogonLevel is invalid.
|
|
STATUS_ACCOUNT_LOCKED_OUT: The account is locked out
|
|
STATUS_ACCOUNT_DISABLED: The account is disabled
|
|
STATUS_ACCOUNT_EXPIRED: The account has expired.
|
|
STATUS_PASSWORD_MUST_CHANGE: Account is marked as Password must change
|
|
on next logon.
|
|
STATUS_PASSWORD_EXPIRED: The Password is expired.
|
|
STATUS_INVALID_LOGON_HOURS - The user is not authorized to logon at
|
|
this time.
|
|
STATUS_INVALID_WORKSTATION - The user is not authorized to logon to
|
|
the specified workstation.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
NTSTATUS SubStatus;
|
|
|
|
ULONG DllNumber;
|
|
PSUBAUTHENTICATION_DLL SubAuthenticationDll;
|
|
PSUBAUTHENTICATION_ROUTINE SubAuthenticationRoutine;
|
|
|
|
PNETLOGON_LOGON_IDENTITY_INFO LogonInfo;
|
|
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
|
|
LogonInfo = (PNETLOGON_LOGON_IDENTITY_INFO) LogonInformation;
|
|
|
|
DllNumber = LogonInfo->ParameterControl >> MSV1_0_SUBAUTHENTICATION_DLL_SHIFT;
|
|
*Authoritative = TRUE;
|
|
|
|
//
|
|
// Find the SubAuthentication Dll.
|
|
//
|
|
|
|
SubAuthenticationDll = ReferenceSubAuth ( DllNumber, &SubStatus);
|
|
|
|
//
|
|
// If this was package zero and we didn't find it, remember it for
|
|
// next time.
|
|
//
|
|
|
|
if ( (DllNumber == 0) && (SubAuthenticationDll == NULL) ) {
|
|
NlpSubAuthZeroExists = FALSE;
|
|
Status = STATUS_SUCCESS;
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
if (SubStatus != STATUS_SUCCESS)
|
|
{
|
|
SspPrint((SSP_MISC, "SubAuth Error value is %ld.\n", SubStatus));
|
|
Status = SubStatus;
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Leave the crit sect while calling the DLL
|
|
//
|
|
|
|
SubAuthenticationRoutine = SubAuthenticationDll->SubAuthenticationRoutine;
|
|
|
|
if (SubAuthenticationRoutine == NULL)
|
|
{
|
|
if( DllNumber == 0 ) {
|
|
|
|
//
|
|
// If this was package zero and we didn't find it, remember it for
|
|
// next time.
|
|
//
|
|
|
|
NlpSubAuthZeroExists = FALSE;
|
|
Status = STATUS_SUCCESS;
|
|
} else {
|
|
Status = STATUS_PROCEDURE_NOT_FOUND;
|
|
}
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Call the actual authentication routine.
|
|
//
|
|
|
|
Status = (*SubAuthenticationRoutine)(
|
|
LogonLevel,
|
|
LogonInformation,
|
|
Flags,
|
|
UserAll,
|
|
WhichFields,
|
|
UserFlags,
|
|
Authoritative,
|
|
LogoffTime,
|
|
KickoffTime );
|
|
|
|
//
|
|
// Cleanup up before returning.
|
|
//
|
|
|
|
Cleanup:
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
Msv1_0ExportSubAuthenticationRoutine(
|
|
IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
|
|
IN PVOID LogonInformation,
|
|
IN ULONG Flags,
|
|
IN ULONG DllNumber,
|
|
IN PUSER_ALL_INFORMATION UserAll,
|
|
OUT PULONG WhichFields,
|
|
OUT PULONG UserFlags,
|
|
OUT PBOOLEAN Authoritative,
|
|
OUT PLARGE_INTEGER LogoffTime,
|
|
OUT PLARGE_INTEGER KickoffTime
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The subauthentication routine does client/server specific authentication
|
|
of a user. This stub routine loads the appropriate subauthentication
|
|
package DLL and calls out to that DLL to do the actuall validation.
|
|
|
|
Arguments:
|
|
|
|
LogonLevel -- Specifies the level of information given in
|
|
LogonInformation.
|
|
|
|
LogonInformation -- Specifies the description for the user
|
|
logging on. The LogonDomainName field should be ignored.
|
|
|
|
Flags -- Flags describing the circumstances of the logon.
|
|
|
|
MSV1_0_PASSTHRU -- This is a PassThru authenication. (i.e., the
|
|
user isn't connecting to this machine.)
|
|
MSV1_0_GUEST_LOGON -- This is a retry of the logon using the GUEST
|
|
user account.
|
|
|
|
DllNumber - The number of the subauthentication DLL to call.
|
|
|
|
UserAll -- The description of the user as returned from SAM.
|
|
|
|
WhichFields -- Returns which fields from UserAllInfo are to be written
|
|
back to SAM. The fields will only be written if MSV returns success
|
|
to it's caller. Only the following bits are valid.
|
|
|
|
USER_ALL_PARAMETERS - Write UserAllInfo->Parameters back to SAM. If
|
|
the size of the buffer is changed, Msv1_0SubAuthenticationRoutine
|
|
must delete the old buffer using MIDL_user_free() and reallocate the
|
|
buffer using MIDL_user_allocate().
|
|
|
|
UserFlags -- Returns UserFlags to be returned from LsaLogonUser in the
|
|
LogonProfile. The following bits are currently defined:
|
|
|
|
|
|
LOGON_GUEST -- This was a guest logon
|
|
LOGON_NOENCRYPTION -- The caller didn't specify encrypted credentials
|
|
LOGON_GRACE_LOGON -- The caller's password has expired but logon
|
|
was allowed during a grace period following the expiration.
|
|
|
|
SubAuthentication packages should restrict themselves to returning
|
|
bits in the high order byte of UserFlags. However, this convention
|
|
isn't enforced giving the SubAuthentication package more flexibility.
|
|
|
|
Authoritative -- Returns whether the status returned is an
|
|
authoritative status which should be returned to the original
|
|
caller. If not, this logon request may be tried again on another
|
|
domain controller. This parameter is returned regardless of the
|
|
status code.
|
|
|
|
LogoffTime - Receives the time at which the user should logoff the
|
|
system. This time is specified as a GMT relative NT system time.
|
|
|
|
KickoffTime - Receives the time at which the user should be kicked
|
|
off the system. This time is specified as a GMT relative NT system
|
|
time. Specify, a full scale positive number if the user isn't to
|
|
be kicked off.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS: if there was no error.
|
|
|
|
STATUS_NO_SUCH_USER: The specified user has no account.
|
|
STATUS_WRONG_PASSWORD: The password was invalid.
|
|
|
|
STATUS_INVALID_INFO_CLASS: LogonLevel is invalid.
|
|
STATUS_ACCOUNT_LOCKED_OUT: The account is locked out
|
|
STATUS_ACCOUNT_DISABLED: The account is disabled
|
|
STATUS_ACCOUNT_EXPIRED: The account has expired.
|
|
STATUS_PASSWORD_MUST_CHANGE: Account is marked as Password must change
|
|
on next logon.
|
|
STATUS_PASSWORD_EXPIRED: The Password is expired.
|
|
STATUS_INVALID_LOGON_HOURS - The user is not authorized to logon at
|
|
this time.
|
|
STATUS_INVALID_WORKSTATION - The user is not authorized to logon to
|
|
the specified workstation.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
NTSTATUS SubStatus;
|
|
|
|
PSUBAUTHENTICATION_DLL SubAuthenticationDll;
|
|
PSUBAUTHENTICATION_ROUTINE SubAuthenticationRoutine;
|
|
|
|
PNETLOGON_LOGON_IDENTITY_INFO LogonInfo;
|
|
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
|
|
LogonInfo = (PNETLOGON_LOGON_IDENTITY_INFO) LogonInformation;
|
|
|
|
*Authoritative = TRUE;
|
|
|
|
//
|
|
// Find the SubAuthentication Dll.
|
|
//
|
|
|
|
SubAuthenticationDll = ReferenceSubAuth ( DllNumber, &SubStatus);
|
|
|
|
if (SubStatus != STATUS_SUCCESS)
|
|
{
|
|
SspPrint((SSP_MISC, "SubAuth Error value is %ld.\n", SubStatus));
|
|
Status = SubStatus;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Leave the crit sect while calling the DLL
|
|
//
|
|
|
|
SubAuthenticationRoutine = SubAuthenticationDll->SubAuthenticationRoutine;
|
|
|
|
if (SubAuthenticationRoutine == NULL)
|
|
{
|
|
Status = STATUS_PROCEDURE_NOT_FOUND;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Call the actual authentication routine.
|
|
//
|
|
|
|
Status = (*SubAuthenticationRoutine)(
|
|
LogonLevel,
|
|
LogonInformation,
|
|
Flags,
|
|
UserAll,
|
|
WhichFields,
|
|
UserFlags,
|
|
Authoritative,
|
|
LogoffTime,
|
|
KickoffTime );
|
|
|
|
//
|
|
// Cleanup up before returning.
|
|
//
|
|
|
|
Cleanup:
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
Msv1_0SubAuthenticationRoutineEx(
|
|
IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
|
|
IN PVOID LogonInformation,
|
|
IN ULONG Flags,
|
|
IN PUSER_ALL_INFORMATION UserAll,
|
|
IN SAM_HANDLE UserHandle,
|
|
IN OUT PMSV1_0_VALIDATION_INFO ValidationInfo,
|
|
OUT PULONG ActionsPerformed
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The subauthentication routine does client/server specific authentication
|
|
of a user. This stub routine loads the appropriate subauthentication
|
|
package DLL and calls out to that DLL to do the actuall validation.
|
|
|
|
Arguments:
|
|
|
|
LogonLevel -- Specifies the level of information given in
|
|
LogonInformation.
|
|
|
|
LogonInformation -- Specifies the description for the user
|
|
logging on. The LogonDomainName field should be ignored.
|
|
|
|
Flags - Flags describing the circumstances of the logon.
|
|
|
|
MSV1_0_PASSTHRU -- This is a PassThru authenication. (i.e., the
|
|
user isn't connecting to this machine.)
|
|
MSV1_0_GUEST_LOGON -- This is a retry of the logon using the GUEST
|
|
user account.
|
|
|
|
UserAll -- The description of the user as returned from SAM.
|
|
|
|
WhichFields -- Returns which fields from UserAllInfo are to be written
|
|
back to SAM. The fields will only be written if MSV returns success
|
|
to it's caller. Only the following bits are valid.
|
|
|
|
USER_ALL_PARAMETERS - Write UserAllInfo->Parameters back to SAM. If
|
|
the size of the buffer is changed, Msv1_0SubAuthenticationRoutine
|
|
must delete the old buffer using MIDL_user_free() and reallocate the
|
|
buffer using MIDL_user_allocate().
|
|
|
|
UserFlags -- Returns UserFlags to be returned from LsaLogonUser in the
|
|
LogonProfile. The following bits are currently defined:
|
|
|
|
|
|
LOGON_GUEST -- This was a guest logon
|
|
LOGON_NOENCRYPTION -- The caller didn't specify encrypted credentials
|
|
LOGON_GRACE_LOGON -- The caller's password has expired but logon
|
|
was allowed during a grace period following the expiration.
|
|
|
|
SubAuthentication packages should restrict themselves to returning
|
|
bits in the high order byte of UserFlags. However, this convention
|
|
isn't enforced giving the SubAuthentication package more flexibility.
|
|
|
|
Authoritative -- Returns whether the status returned is an
|
|
authoritative status which should be returned to the original
|
|
caller. If not, this logon request may be tried again on another
|
|
domain controller. This parameter is returned regardless of the
|
|
status code.
|
|
|
|
LogoffTime - Receives the time at which the user should logoff the
|
|
system. This time is specified as a GMT relative NT system time.
|
|
|
|
KickoffTime - Receives the time at which the user should be kicked
|
|
off the system. This time is specified as a GMT relative NT system
|
|
time. Specify, a full scale positive number if the user isn't to
|
|
be kicked off.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS: if there was no error.
|
|
|
|
STATUS_NO_SUCH_USER: The specified user has no account.
|
|
STATUS_WRONG_PASSWORD: The password was invalid.
|
|
|
|
STATUS_INVALID_INFO_CLASS: LogonLevel is invalid.
|
|
STATUS_ACCOUNT_LOCKED_OUT: The account is locked out
|
|
STATUS_ACCOUNT_DISABLED: The account is disabled
|
|
STATUS_ACCOUNT_EXPIRED: The account has expired.
|
|
STATUS_PASSWORD_MUST_CHANGE: Account is marked as Password must change
|
|
on next logon.
|
|
STATUS_PASSWORD_EXPIRED: The Password is expired.
|
|
STATUS_INVALID_LOGON_HOURS - The user is not authorized to logon at
|
|
this time.
|
|
STATUS_INVALID_WORKSTATION - The user is not authorized to logon to
|
|
the specified workstation.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
NTSTATUS SubStatus;
|
|
|
|
ULONG DllNumber;
|
|
PSUBAUTHENTICATION_DLL SubAuthenticationDll;
|
|
PSUBAUTHENTICATION_ROUTINEEX SubAuthenticationRoutineEx;
|
|
|
|
PNETLOGON_LOGON_IDENTITY_INFO LogonInfo;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
|
|
LogonInfo = (PNETLOGON_LOGON_IDENTITY_INFO) LogonInformation;
|
|
|
|
DllNumber = LogonInfo->ParameterControl >> MSV1_0_SUBAUTHENTICATION_DLL_SHIFT;
|
|
|
|
|
|
//
|
|
// Find the SubAuthentication Dll.
|
|
//
|
|
|
|
SubAuthenticationDll = ReferenceSubAuth (DllNumber, &SubStatus);;
|
|
|
|
|
|
if (SubStatus != STATUS_SUCCESS)
|
|
{
|
|
SspPrint((SSP_MISC, "SubAuth Error value is %ld.\n", SubStatus));
|
|
Status = SubStatus;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Leave the crit sect while calling the DLL
|
|
//
|
|
|
|
SubAuthenticationRoutineEx = SubAuthenticationDll->SubAuthenticationRoutineEx;
|
|
|
|
if (SubAuthenticationRoutineEx == NULL)
|
|
{
|
|
Status = STATUS_PROCEDURE_NOT_FOUND;
|
|
goto Cleanup;
|
|
}
|
|
//
|
|
// Call the actual authentication routine.
|
|
//
|
|
|
|
Status = (*SubAuthenticationRoutineEx)(
|
|
LogonLevel,
|
|
LogonInformation,
|
|
Flags,
|
|
UserAll,
|
|
UserHandle,
|
|
ValidationInfo,
|
|
ActionsPerformed
|
|
);
|
|
|
|
//
|
|
// Cleanup up before returning.
|
|
//
|
|
|
|
Cleanup:
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
MspNtSubAuth(
|
|
IN PLSA_CLIENT_REQUEST ClientRequest,
|
|
IN PVOID ProtocolSubmitBuffer,
|
|
IN PVOID ClientBufferBase,
|
|
IN ULONG SubmitBufferSize,
|
|
OUT PVOID *ProtocolReturnBuffer,
|
|
OUT PULONG ReturnBufferSize,
|
|
OUT PNTSTATUS ProtocolStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is the dispatch routine for LsaCallAuthenticationPackage()
|
|
with a message type of MsV1_0SubAuthInfo.
|
|
|
|
Arguments:
|
|
|
|
The arguments to this routine are identical to those of LsaApCallPackage.
|
|
Only the special attributes of these parameters as they apply to
|
|
this routine are mentioned here.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - Indicates the service completed successfully.
|
|
|
|
STATUS_QUOTA_EXCEEDED - This error indicates that the logon
|
|
could not be completed because the client does not have
|
|
sufficient quota to allocate the return buffer.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
NTSTATUS SubStatus = STATUS_SUCCESS;
|
|
PMSV1_0_SUBAUTH_REQUEST SubAuthRequest;
|
|
PMSV1_0_SUBAUTH_RESPONSE SubAuthResponse;
|
|
CLIENT_BUFFER_DESC ClientBufferDesc;
|
|
ULONG ReturnDataLength = 0;
|
|
PVOID ReturnDataBuffer = NULL;
|
|
|
|
PSUBAUTHENTICATION_DLL SubAuthenticationDll;
|
|
PSUBAUTHENTICATION_ROUTINEGENERIC SubAuthenticationRoutineGeneric;
|
|
|
|
NlpInitClientBuffer( &ClientBufferDesc, ClientRequest );
|
|
*ProtocolStatus = STATUS_SUCCESS;
|
|
|
|
//
|
|
// Ensure the specified Submit Buffer is of reasonable size and
|
|
// relocate all of the pointers to be relative to the LSA allocated
|
|
// buffer.
|
|
//
|
|
|
|
if ( SubmitBufferSize < sizeof(MSV1_0_SUBAUTH_REQUEST) ) {
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
SubAuthRequest = (PMSV1_0_SUBAUTH_REQUEST) ProtocolSubmitBuffer;
|
|
|
|
//
|
|
// Make sure the buffer fits in the supplied size
|
|
//
|
|
|
|
if (SubAuthRequest->SubAuthSubmitBuffer != NULL) {
|
|
if (SubAuthRequest->SubAuthSubmitBuffer + SubAuthRequest->SubAuthInfoLength >
|
|
(PUCHAR) ClientBufferBase + SubmitBufferSize) {
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Reset the pointers for the validation data
|
|
//
|
|
|
|
SubAuthRequest->SubAuthSubmitBuffer =
|
|
(PUCHAR) SubAuthRequest -
|
|
(ULONG_PTR) ClientBufferBase +
|
|
(ULONG_PTR) SubAuthRequest->SubAuthSubmitBuffer;
|
|
|
|
}
|
|
|
|
// If subauth package found, call the routine,
|
|
|
|
|
|
//
|
|
// Find the SubAuthentication Dll.
|
|
//
|
|
|
|
SubAuthenticationDll = ReferenceSubAuth (SubAuthRequest->SubAuthPackageId, &SubStatus);;
|
|
|
|
|
|
if (SubStatus != STATUS_SUCCESS)
|
|
{
|
|
SspPrint((SSP_MISC, "SubAuth Error value is %ld.\n", SubStatus));
|
|
Status = SubStatus;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Leave the crit sect while calling the DLL
|
|
//
|
|
|
|
SubAuthenticationRoutineGeneric = SubAuthenticationDll->SubAuthenticationRoutineGeneric;
|
|
|
|
if (SubAuthenticationRoutineGeneric == NULL)
|
|
{
|
|
Status = STATUS_PROCEDURE_NOT_FOUND;
|
|
goto Cleanup;
|
|
}
|
|
Status = (*SubAuthenticationRoutineGeneric)(
|
|
(PVOID) SubAuthRequest->SubAuthSubmitBuffer,
|
|
SubAuthRequest->SubAuthInfoLength,
|
|
&ReturnDataLength,
|
|
&ReturnDataBuffer);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Allocate a buffer to return to the caller.
|
|
//
|
|
|
|
*ReturnBufferSize = sizeof(MSV1_0_SUBAUTH_RESPONSE) +
|
|
ReturnDataLength;
|
|
|
|
Status = NlpAllocateClientBuffer( &ClientBufferDesc,
|
|
sizeof(MSV1_0_SUBAUTH_RESPONSE),
|
|
*ReturnBufferSize );
|
|
|
|
|
|
if ( !NT_SUCCESS( Status ) ) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
SubAuthResponse = (PMSV1_0_SUBAUTH_RESPONSE) ClientBufferDesc.MsvBuffer;
|
|
|
|
//
|
|
// Fill in the return buffer.
|
|
//
|
|
|
|
SubAuthResponse->MessageType = MsV1_0SubAuth;
|
|
SubAuthResponse->SubAuthInfoLength = ReturnDataLength;
|
|
|
|
if (ReturnDataLength > 0)
|
|
{
|
|
SubAuthResponse->SubAuthReturnBuffer = ClientBufferDesc.UserBuffer + sizeof(MSV1_0_SUBAUTH_RESPONSE);
|
|
|
|
if (ReturnDataBuffer)
|
|
{
|
|
RtlCopyMemory(
|
|
SubAuthResponse + 1,
|
|
ReturnDataBuffer,
|
|
ReturnDataLength
|
|
);
|
|
|
|
// Make relative pointers
|
|
SubAuthResponse->SubAuthReturnBuffer = (PUCHAR) sizeof(MSV1_0_SUBAUTH_RESPONSE);
|
|
}
|
|
else
|
|
{
|
|
SubAuthResponse->SubAuthReturnBuffer = NULL;
|
|
SubStatus = STATUS_NO_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SubAuthResponse->SubAuthReturnBuffer = 0;
|
|
}
|
|
|
|
|
|
//
|
|
// Flush the buffer to the client's address space.
|
|
//
|
|
|
|
Status = NlpFlushClientBuffer( &ClientBufferDesc,
|
|
ProtocolReturnBuffer );
|
|
|
|
|
|
Cleanup:
|
|
|
|
if (ReturnDataBuffer != NULL) {
|
|
MIDL_user_free(ReturnDataBuffer);
|
|
}
|
|
|
|
if ( !NT_SUCCESS(Status)) {
|
|
NlpFreeClientBuffer( &ClientBufferDesc );
|
|
}
|
|
|
|
*ProtocolStatus = SubStatus;
|
|
return(Status);
|
|
|
|
}
|