diff options
Diffstat (limited to 'private/lsa/msv1_0/subauth.c')
-rw-r--r-- | private/lsa/msv1_0/subauth.c | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/private/lsa/msv1_0/subauth.c b/private/lsa/msv1_0/subauth.c new file mode 100644 index 000000000..937056451 --- /dev/null +++ b/private/lsa/msv1_0/subauth.c @@ -0,0 +1,447 @@ +/*++ + +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; +} |