mirror of https://github.com/lianthony/NT4.0
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.
447 lines
12 KiB
447 lines
12 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:
|
|
|
|
--*/
|
|
|
|
#include "msp.h"
|
|
#include "nlp.h"
|
|
#include <winreg.h>
|
|
|
|
//
|
|
// Prototype for subauthentication 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
|
|
);
|
|
|
|
//
|
|
// Structure describing a loaded SubAuthentication DLL.
|
|
//
|
|
|
|
typedef struct _SUBAUTHENTICATION_DLL {
|
|
LIST_ENTRY Next;
|
|
ULONG DllNumber;
|
|
PSUBAUTHENTICATION_ROUTINE SubAuthenticationRoutine;
|
|
} SUBAUTHENTICATION_DLL, *PSUBAUTHENTICATION_DLL;
|
|
|
|
//
|
|
// Global list of all loaded subauthentication DLLs
|
|
//
|
|
|
|
LIST_ENTRY SubAuthenticationDlls;
|
|
CRITICAL_SECTION SubAuthenticationCritSect;
|
|
|
|
|
|
VOID
|
|
Msv1_0SubAuthenticationInitialization(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialization routine for this source file.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
InitializeCriticalSection( &SubAuthenticationCritSect );
|
|
InitializeListHead( &SubAuthenticationDlls );
|
|
}
|
|
|
|
|
|
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;
|
|
LONG RegStatus;
|
|
|
|
ULONG DllNumber;
|
|
PSUBAUTHENTICATION_DLL SubAuthenticationDll = NULL;
|
|
PSUBAUTHENTICATION_ROUTINE SubAuthenticationRoutine = NULL;
|
|
|
|
PNETLOGON_LOGON_IDENTITY_INFO LogonInfo;
|
|
BOOLEAN CritSectLocked = FALSE;
|
|
|
|
HKEY BaseHandle = NULL;
|
|
HKEY ParmHandle = NULL;
|
|
|
|
CHAR ValueName[sizeof(MSV1_0_SUBAUTHENTICATION_VALUE)+3];
|
|
CHAR DllName[MAXIMUM_FILENAME_LENGTH+1];
|
|
DWORD DllNameSize;
|
|
DWORD DllNameType;
|
|
HINSTANCE DllHandle = NULL;
|
|
|
|
PLIST_ENTRY ListEntry;
|
|
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
|
|
LogonInfo = (PNETLOGON_LOGON_IDENTITY_INFO) LogonInformation;
|
|
|
|
DllNumber = LogonInfo->ParameterControl >> MSV1_0_SUBAUTHENTICATION_DLL_SHIFT;
|
|
*Authoritative = TRUE;
|
|
|
|
EnterCriticalSection( &SubAuthenticationCritSect );
|
|
CritSectLocked = TRUE;
|
|
|
|
//
|
|
// See if the SubAuthentication Dll is already loaded.
|
|
//
|
|
|
|
SubAuthenticationDll = NULL;
|
|
for ( ListEntry = SubAuthenticationDlls.Flink ;
|
|
ListEntry != &SubAuthenticationDlls ;
|
|
ListEntry = ListEntry->Flink) {
|
|
|
|
SubAuthenticationDll = CONTAINING_RECORD( ListEntry,
|
|
SUBAUTHENTICATION_DLL,
|
|
Next );
|
|
|
|
if ( SubAuthenticationDll->DllNumber == DllNumber ) {
|
|
break;
|
|
}
|
|
|
|
SubAuthenticationDll = NULL;
|
|
|
|
}
|
|
|
|
//
|
|
// If the Dll is not already loaded,
|
|
// load it.
|
|
//
|
|
|
|
if ( SubAuthenticationDll == NULL ) {
|
|
|
|
|
|
//
|
|
// Open the registry
|
|
//
|
|
|
|
RegStatus = RegConnectRegistryW( NULL,
|
|
HKEY_LOCAL_MACHINE,
|
|
&BaseHandle);
|
|
|
|
if ( RegStatus != ERROR_SUCCESS ) {
|
|
KdPrint(( "MSV1_0: Cannot connect to registy %ld.\n", RegStatus ));
|
|
Status = STATUS_DLL_NOT_FOUND;
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Open the MSV1_0 registry key.
|
|
//
|
|
|
|
RegStatus = RegOpenKeyExA(
|
|
BaseHandle,
|
|
MSV1_0_SUBAUTHENTICATION_KEY,
|
|
0, //Reserved
|
|
KEY_QUERY_VALUE,
|
|
&ParmHandle );
|
|
|
|
if ( RegStatus != ERROR_SUCCESS ) {
|
|
KdPrint(( "MSV1_0: Cannot open registry key %s %ld.\n",
|
|
MSV1_0_SUBAUTHENTICATION_KEY,
|
|
RegStatus ));
|
|
Status = STATUS_DLL_NOT_FOUND;
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Build the name of the registry value.
|
|
//
|
|
|
|
RtlCopyMemory( ValueName,
|
|
MSV1_0_SUBAUTHENTICATION_VALUE,
|
|
sizeof(MSV1_0_SUBAUTHENTICATION_VALUE) );
|
|
|
|
Status = RtlIntegerToChar(
|
|
DllNumber,
|
|
10, // Base
|
|
4, // Length of buffer
|
|
&ValueName[sizeof(MSV1_0_SUBAUTHENTICATION_VALUE)-1] );
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Get the registry value.
|
|
//
|
|
|
|
DllNameSize = sizeof(DllName);
|
|
|
|
RegStatus = RegQueryValueExA(
|
|
ParmHandle,
|
|
ValueName,
|
|
NULL, // Reserved
|
|
&DllNameType,
|
|
DllName,
|
|
&DllNameSize );
|
|
|
|
if ( RegStatus != ERROR_SUCCESS ) {
|
|
KdPrint(( "MSV1_0: Cannot query registry value %s %ld.\n",
|
|
ValueName,
|
|
RegStatus ));
|
|
Status = STATUS_DLL_NOT_FOUND;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if ( DllNameType != REG_SZ ) {
|
|
KdPrint(( "MSV1_0: Registry value %s isn't REG_SZ.\n",
|
|
ValueName ));
|
|
Status = STATUS_DLL_NOT_FOUND;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Load the DLL
|
|
//
|
|
|
|
DllHandle = LoadLibraryA( DllName );
|
|
|
|
if ( DllHandle == NULL ) {
|
|
KdPrint(( "MSV1_0: Cannot load dll %s %ld.\n",
|
|
DllName,
|
|
GetLastError() ));
|
|
Status = 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 == 0) {
|
|
SubAuthenticationRoutine = (PSUBAUTHENTICATION_ROUTINE)
|
|
GetProcAddress(DllHandle, "Msv1_0SubAuthenticationFilter");
|
|
|
|
} else {
|
|
SubAuthenticationRoutine = (PSUBAUTHENTICATION_ROUTINE)
|
|
GetProcAddress(DllHandle, "Msv1_0SubAuthenticationRoutine");
|
|
|
|
}
|
|
|
|
if ( SubAuthenticationRoutine == NULL ) {
|
|
KdPrint(( "MSV1_0: Cannot find required entry point in %s %ld.\n",
|
|
DllName,
|
|
GetLastError() ));
|
|
Status = STATUS_PROCEDURE_NOT_FOUND;
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Cache the address of the procedure.
|
|
//
|
|
|
|
SubAuthenticationDll =
|
|
RtlAllocateHeap(MspHeap, 0, sizeof(SUBAUTHENTICATION_DLL));
|
|
|
|
if ( SubAuthenticationDll == NULL ) {
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
SubAuthenticationDll->DllNumber = DllNumber;
|
|
SubAuthenticationDll->SubAuthenticationRoutine = SubAuthenticationRoutine;
|
|
InsertHeadList( &SubAuthenticationDlls, &SubAuthenticationDll->Next );
|
|
|
|
DllHandle = NULL;
|
|
|
|
}
|
|
|
|
//
|
|
// Leave the crit sect while calling the DLL
|
|
//
|
|
|
|
SubAuthenticationRoutine = SubAuthenticationDll->SubAuthenticationRoutine;
|
|
LeaveCriticalSection( &SubAuthenticationCritSect );
|
|
CritSectLocked = FALSE;
|
|
|
|
|
|
//
|
|
// Call the actual authentication routine.
|
|
//
|
|
|
|
Status = (*SubAuthenticationRoutine)(
|
|
LogonLevel,
|
|
LogonInformation,
|
|
Flags,
|
|
UserAll,
|
|
WhichFields,
|
|
UserFlags,
|
|
Authoritative,
|
|
LogoffTime,
|
|
KickoffTime );
|
|
|
|
//
|
|
// Cleanup up before returning.
|
|
//
|
|
|
|
Cleanup:
|
|
|
|
//
|
|
// If this was package zero and we didn't find it, remember it for
|
|
// next time.
|
|
//
|
|
|
|
if (!NT_SUCCESS(Status) && (DllNumber == 0) && (SubAuthenticationDll == NULL)) {
|
|
NlpSubAuthZeroExists = FALSE;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
if ( BaseHandle != NULL ) {
|
|
RegCloseKey( BaseHandle );
|
|
}
|
|
|
|
if ( ParmHandle != NULL ) {
|
|
RegCloseKey( ParmHandle );
|
|
}
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
if ( DllHandle != NULL ) {
|
|
FreeLibrary( DllHandle );
|
|
}
|
|
}
|
|
|
|
if ( CritSectLocked ) {
|
|
LeaveCriticalSection( &SubAuthenticationCritSect );
|
|
}
|
|
|
|
return Status;
|
|
}
|