918 lines
24 KiB
C
918 lines
24 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
austub.c
|
||
|
||
Abstract:
|
||
|
||
Local Security Authority AUTHENTICATION service client stubs.
|
||
|
||
Author:
|
||
|
||
Jim Kelly (JimK) 20-Feb-1991
|
||
|
||
Environment: Kernel or User Modes
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "lsadllp.h"
|
||
#include <string.h>
|
||
#include <zwapi.h>
|
||
|
||
#ifdef _NTSYSTEM_
|
||
//
|
||
// Unfortunately the security header files are just not at all constructed
|
||
// in a manner compatible with kernelmode. For some reason they are totally
|
||
// reliant on usermode header definitions. Just assume the text and const
|
||
// pragma's will work. If they don't work on an architecture, they can be
|
||
// fixed.
|
||
//
|
||
#pragma alloc_text(PAGE,LsaFreeReturnBuffer)
|
||
#pragma alloc_text(PAGE,LsaRegisterLogonProcess)
|
||
#pragma alloc_text(PAGE,LsaConnectUntrusted)
|
||
#pragma alloc_text(PAGE,LsaLookupAuthenticationPackage)
|
||
#pragma alloc_text(PAGE,LsaLogonUser)
|
||
#pragma alloc_text(PAGE,LsaCallAuthenticationPackage)
|
||
#pragma alloc_text(PAGE,LsaDeregisterLogonProcess)
|
||
//#pragma const_seg("PAGECONST")
|
||
#endif //_NTSYSTEM_
|
||
|
||
const WCHAR LsapEvent[] = L"\\SECURITY\\LSA_AUTHENTICATION_INITIALIZED";
|
||
const WCHAR LsapPort[] = L"\\LsaAuthenticationPort";
|
||
|
||
|
||
NTSTATUS
|
||
LsaFreeReturnBuffer (
|
||
IN PVOID Buffer
|
||
)
|
||
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Some of the LSA authentication services allocate memory buffers to
|
||
hold returned information. This service is used to free those buffers
|
||
when no longer needed.
|
||
|
||
Arguments:
|
||
|
||
Buffer - Supplies a pointer to the return buffer to be freed.
|
||
|
||
Return Status:
|
||
|
||
STATUS_SUCCESS - Indicates the service completed successfully.
|
||
|
||
Others - returned by NtFreeVirtualMemory().
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NTSTATUS Status;
|
||
ULONG_PTR Length;
|
||
|
||
Length = 0;
|
||
Status = ZwFreeVirtualMemory(
|
||
NtCurrentProcess(),
|
||
&Buffer,
|
||
&Length,
|
||
MEM_RELEASE
|
||
);
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
LsaRegisterLogonProcess(
|
||
IN PSTRING LogonProcessName,
|
||
OUT PHANDLE LsaHandle,
|
||
OUT PLSA_OPERATIONAL_MODE SecurityMode
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This service connects to the LSA server and verifies that the caller
|
||
is a legitimate logon process. this is done by ensuring the caller has
|
||
the SeTcbPrivilege privilege. It also opens the caller's process for
|
||
PROCESS_DUP_HANDLE access in anticipation of future LSA authentication
|
||
calls.
|
||
|
||
Arguments:
|
||
|
||
LogonProcessName - Provides a name string that identifies the logon
|
||
process. This should be a printable name suitable for display to
|
||
administrators. For example, "User32LogonProces" might be used
|
||
for the windows logon process name. No check is made to determine
|
||
whether the name is already in use. This name must NOT be longer
|
||
than 127 bytes long.
|
||
|
||
LsaHandle - Receives a handle which must be provided in future
|
||
authenticaiton services.
|
||
|
||
SecurityMode - The security mode the system is running under. This
|
||
value typically influences the logon user interface. For example,
|
||
a system running with password control will prompt for username
|
||
and passwords before bringing up the UI shell. One running without
|
||
password control would typically automatically bring up the UI shell
|
||
at system initialization.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - The call completed successfully.
|
||
|
||
STATUS_PRIVILEGE_NOT_HELD - Indicates the caller does not have the
|
||
privilege necessary to act as a logon process. The SeTcbPrivilege
|
||
privilege is needed.
|
||
|
||
|
||
STATUS_NAME_TOO_LONG - The logon process name provided is too long.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status, IgnoreStatus;
|
||
UNICODE_STRING PortName, EventName;
|
||
LSAP_AU_REGISTER_CONNECT_INFO ConnectInfo;
|
||
ULONG ConnectInfoLength;
|
||
SECURITY_QUALITY_OF_SERVICE DynamicQos;
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
HANDLE EventHandle;
|
||
|
||
|
||
//
|
||
// Validate input parameters
|
||
//
|
||
|
||
if (LogonProcessName->Length > LSAP_MAX_LOGON_PROC_NAME_LENGTH) {
|
||
return STATUS_NAME_TOO_LONG;
|
||
}
|
||
|
||
|
||
//
|
||
// Wait for LSA to initialize...
|
||
//
|
||
|
||
|
||
RtlInitUnicodeString( &EventName, LsapEvent );
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&EventName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
0,
|
||
NULL
|
||
);
|
||
|
||
Status = NtOpenEvent( &EventHandle, SYNCHRONIZE, &ObjectAttributes );
|
||
if (!NT_SUCCESS(Status)) {
|
||
return(Status);
|
||
}
|
||
|
||
Status = NtWaitForSingleObject( EventHandle, TRUE, NULL);
|
||
IgnoreStatus = NtClose( EventHandle );
|
||
if (!NT_SUCCESS(Status)) {
|
||
return(Status);
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// Set up the security quality of service parameters to use over the
|
||
// port. Use the most efficient (least overhead) - which is dynamic
|
||
// rather than static tracking.
|
||
//
|
||
|
||
DynamicQos.Length = sizeof( DynamicQos );
|
||
DynamicQos.ImpersonationLevel = SecurityImpersonation;
|
||
DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
|
||
DynamicQos.EffectiveOnly = TRUE;
|
||
|
||
|
||
|
||
|
||
//
|
||
// Set up the connection information to contain the logon process
|
||
// name.
|
||
//
|
||
|
||
ConnectInfoLength = sizeof(LSAP_AU_REGISTER_CONNECT_INFO);
|
||
strncpy(
|
||
ConnectInfo.LogonProcessName,
|
||
LogonProcessName->Buffer,
|
||
LogonProcessName->Length
|
||
);
|
||
ConnectInfo.LogonProcessNameLength = LogonProcessName->Length;
|
||
ConnectInfo.LogonProcessName[ConnectInfo.LogonProcessNameLength] = '\0';
|
||
|
||
|
||
//
|
||
// Connect to the LSA server
|
||
//
|
||
|
||
*LsaHandle = NULL;
|
||
RtlInitUnicodeString(&PortName,LsapPort);
|
||
Status = ZwConnectPort(
|
||
LsaHandle,
|
||
&PortName,
|
||
&DynamicQos,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
&ConnectInfo,
|
||
&ConnectInfoLength
|
||
);
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
//DbgPrint("LSA AU: Logon Process Register failed %lx\n",Status);
|
||
return Status;
|
||
}
|
||
|
||
if ( !NT_SUCCESS(ConnectInfo.CompletionStatus) ) {
|
||
//DbgPrint("LSA AU: Logon Process Register rejected %lx\n",ConnectInfo.CompletionStatus);
|
||
if ( LsaHandle && *LsaHandle != NULL ) {
|
||
ZwClose( *LsaHandle );
|
||
*LsaHandle = NULL;
|
||
}
|
||
}
|
||
|
||
(*SecurityMode) = ConnectInfo.SecurityMode;
|
||
|
||
return ConnectInfo.CompletionStatus;
|
||
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
LsaConnectUntrusted(
|
||
OUT PHANDLE LsaHandle
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This service connects to the LSA server and sets up an untrusted
|
||
connection. It does not check anything about the caller.
|
||
|
||
Arguments:
|
||
|
||
|
||
LsaHandle - Receives a handle which must be provided in future
|
||
authenticaiton services.
|
||
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - The call completed successfully.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status, IgnoreStatus;
|
||
UNICODE_STRING PortName, EventName;
|
||
LSAP_AU_REGISTER_CONNECT_INFO ConnectInfo;
|
||
ULONG ConnectInfoLength;
|
||
SECURITY_QUALITY_OF_SERVICE DynamicQos;
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
HANDLE EventHandle;
|
||
|
||
|
||
|
||
//
|
||
// Wait for LSA to initialize...
|
||
//
|
||
|
||
|
||
RtlInitUnicodeString( &EventName, LsapEvent );
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&EventName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
0,
|
||
NULL
|
||
);
|
||
|
||
Status = NtOpenEvent( &EventHandle, SYNCHRONIZE, &ObjectAttributes );
|
||
if (!NT_SUCCESS(Status)) {
|
||
return(Status);
|
||
}
|
||
|
||
Status = NtWaitForSingleObject( EventHandle, TRUE, NULL);
|
||
IgnoreStatus = NtClose( EventHandle );
|
||
if (!NT_SUCCESS(Status)) {
|
||
return(Status);
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// Set up the security quality of service parameters to use over the
|
||
// port. Use the most efficient (least overhead) - which is dynamic
|
||
// rather than static tracking.
|
||
//
|
||
|
||
DynamicQos.ImpersonationLevel = SecurityImpersonation;
|
||
DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
|
||
DynamicQos.EffectiveOnly = TRUE;
|
||
|
||
|
||
|
||
|
||
//
|
||
// Set up the connection information to contain the logon process
|
||
// name.
|
||
//
|
||
|
||
ConnectInfoLength = sizeof(LSAP_AU_REGISTER_CONNECT_INFO);
|
||
RtlZeroMemory(
|
||
&ConnectInfo,
|
||
ConnectInfoLength
|
||
);
|
||
|
||
|
||
//
|
||
// Connect to the LSA server
|
||
//
|
||
|
||
RtlInitUnicodeString(&PortName,LsapPort);
|
||
Status = ZwConnectPort(
|
||
LsaHandle,
|
||
&PortName,
|
||
&DynamicQos,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
&ConnectInfo,
|
||
&ConnectInfoLength
|
||
);
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
//DbgPrint("LSA AU: Logon Process Register failed %lx\n",Status);
|
||
return Status;
|
||
}
|
||
|
||
if ( !NT_SUCCESS(ConnectInfo.CompletionStatus) ) {
|
||
//DbgPrint("LSA AU: Logon Process Register rejected %lx\n",ConnectInfo.CompletionStatus);
|
||
;
|
||
}
|
||
|
||
return ConnectInfo.CompletionStatus;
|
||
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
LsaLookupAuthenticationPackage (
|
||
IN HANDLE LsaHandle,
|
||
IN PSTRING PackageName,
|
||
OUT PULONG AuthenticationPackage
|
||
)
|
||
|
||
/*++
|
||
|
||
Arguments:
|
||
|
||
LsaHandle - Supplies a handle obtained in a previous call to
|
||
LsaRegisterLogonProcess.
|
||
|
||
PackageName - Supplies a string which identifies the
|
||
Authentication Package. "MSV1.0" is the standard NT
|
||
authentication package name. The package name must not
|
||
exceed 127 bytes in length.
|
||
|
||
AuthenticationPackage - Receives an ID used to reference the
|
||
authentication package in subsequent authentication services.
|
||
|
||
Return Status:
|
||
|
||
STATUS_SUCCESS - Indicates the service completed successfully.
|
||
|
||
STATUS_NO_SUCH_PACKAGE - The specified authentication package is
|
||
unknown to the LSA.
|
||
|
||
STATUS_NAME_TOO_LONG - The authentication package name provided is too
|
||
long.
|
||
|
||
|
||
|
||
Routine Description:
|
||
|
||
This service is used to obtain the ID of an authentication package.
|
||
This ID may then be used in subsequent authentication services.
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NTSTATUS Status;
|
||
LSAP_AU_API_MESSAGE Message = {0};
|
||
PLSAP_LOOKUP_PACKAGE_ARGS Arguments;
|
||
|
||
//
|
||
// Validate input parameters
|
||
//
|
||
|
||
if (PackageName->Length > LSAP_MAX_PACKAGE_NAME_LENGTH) {
|
||
return STATUS_NAME_TOO_LONG;
|
||
}
|
||
|
||
|
||
|
||
Arguments = &Message.Arguments.LookupPackage;
|
||
|
||
//
|
||
// Set arguments
|
||
//
|
||
|
||
strncpy(Arguments->PackageName, PackageName->Buffer, PackageName->Length);
|
||
Arguments->PackageNameLength = PackageName->Length;
|
||
Arguments->PackageName[Arguments->PackageNameLength] = '\0';
|
||
|
||
|
||
|
||
//
|
||
// Call the Local Security Authority Server.
|
||
//
|
||
|
||
Message.ApiNumber = LsapAuLookupPackageApi;
|
||
Message.PortMessage.u1.s1.DataLength = sizeof(*Arguments) + 8;
|
||
Message.PortMessage.u1.s1.TotalLength = sizeof(Message);
|
||
Message.PortMessage.u2.ZeroInit = 0L;
|
||
|
||
Status = ZwRequestWaitReplyPort(
|
||
LsaHandle,
|
||
(PPORT_MESSAGE) &Message,
|
||
(PPORT_MESSAGE) &Message
|
||
);
|
||
|
||
//
|
||
// Return the authentication package ID.
|
||
// If the call failed for any reason, this will be garbage,
|
||
// but who cares.
|
||
//
|
||
|
||
(*AuthenticationPackage) = Arguments->AuthenticationPackage;
|
||
|
||
|
||
if ( NT_SUCCESS(Status) ) {
|
||
Status = Message.ReturnedStatus;
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
//DbgPrint("LSA AU: Package Lookup Failed %lx\n",Status);
|
||
;
|
||
}
|
||
} else {
|
||
#if DBG
|
||
DbgPrint("LSA AU: Package Lookup NtRequestWaitReply Failed %lx\n",Status);
|
||
#else
|
||
;
|
||
#endif
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
LsaLogonUser (
|
||
IN HANDLE LsaHandle,
|
||
IN PSTRING OriginName,
|
||
IN SECURITY_LOGON_TYPE LogonType,
|
||
IN ULONG AuthenticationPackage,
|
||
IN PVOID AuthenticationInformation,
|
||
IN ULONG AuthenticationInformationLength,
|
||
IN PTOKEN_GROUPS LocalGroups OPTIONAL,
|
||
IN PTOKEN_SOURCE SourceContext,
|
||
OUT PVOID *ProfileBuffer,
|
||
OUT PULONG ProfileBufferLength,
|
||
OUT PLUID LogonId,
|
||
OUT PHANDLE Token,
|
||
OUT PQUOTA_LIMITS Quotas,
|
||
OUT PNTSTATUS SubStatus
|
||
)
|
||
|
||
/*++
|
||
|
||
Arguments:
|
||
|
||
LsaHandle - Supplies a handle obtained in a previous call to
|
||
LsaRegisterLogonProcess.
|
||
|
||
OriginName - Supplies a string which identifies the origin of the
|
||
logon attempt. For example, "TTY1" specify terminal 1, or
|
||
"LAN Manager - remote node JAZZ" might indicate a network
|
||
logon attempt via LAN Manager from a remote node called
|
||
"JAZZ".
|
||
|
||
LogonType - Identifies the type of logon being attempted. If the
|
||
type is Interactive or Batch then a PrimaryToken will be
|
||
generated to represent this new user. If the type is Network
|
||
then an impersonation token will be generated.
|
||
|
||
AuthenticationPackage - Supplies the ID of the authentication
|
||
package to use for the logon attempt. The standard
|
||
authentication package name for NT is called "MSV1.0".
|
||
|
||
AuthenticationInformation - Supplies the authentication
|
||
information specific to the authentication package. It is
|
||
expected to include identification and authentication
|
||
information such as user name and password.
|
||
|
||
AuthenticationInformationLength - Indicates the length of the
|
||
authentication information buffer.
|
||
|
||
LocalGroups - Optionally supplies a list of additional group
|
||
identifiers to add to the authenticated user's token. The
|
||
WORLD group will always be included in the token. A group
|
||
identifying the logon type (INTERACTIVE, NETWORK, BATCH) will
|
||
also automatically be included in the token.
|
||
|
||
SourceContext - Supplies information identifying the source
|
||
component (e.g., session manager) and context that may be
|
||
useful to that component. This information will be included
|
||
in the token and may later be retrieved.
|
||
|
||
ProfileBuffer - Receives a pointer to any returned profile and
|
||
accounting information about the logged on user's account.
|
||
This information is authentication package specific and
|
||
provides such information as the logon shell, home directory
|
||
and so forth. For an authentication package value of
|
||
"MSV1.0", a MSV1_0_PROFILE_DATA data structure is returned.
|
||
|
||
This buffer is allocated by this service and must be freed
|
||
using LsaFreeReturnBuffer() when no longer needed.
|
||
|
||
ProfileBufferLength - Receives the length (in bytes) of the
|
||
returned profile buffer.
|
||
|
||
LogonId - Points to a buffer which receives a LUID that uniquely
|
||
identifies this logon session. This LUID was assigned by the
|
||
domain controller which authenticated the logon information.
|
||
|
||
Token - Receives a handle to the new token created for this
|
||
authentication.
|
||
|
||
Quotas - When a primary token is returned, this parameter will be
|
||
filled in with process quota limits that are to be assigned
|
||
to the newly logged on user's initial process.
|
||
|
||
SubStatus - If the logon failed due to account restrictions, this
|
||
out parameter will receive an indication as to why the logon
|
||
failed. This value will only be set to a meaningful value if
|
||
the user has a legitimate account, but may not currently
|
||
logon for some reason. The substatus values for
|
||
authentication package "MSV1.0" are:
|
||
|
||
STATUS_INVALID_LOGON_HOURS
|
||
|
||
STATUS_INVALID_WORKSTATION
|
||
|
||
STATUS_PASSWORD_EXPIRED
|
||
|
||
STATUS_ACCOUNT_DISABLED
|
||
|
||
Return Status:
|
||
|
||
STATUS_SUCCESS - Indicates the service completed successfully.
|
||
|
||
STATUS_QUOTA_EXCEEDED - Indicates the caller does not have
|
||
enough quota to allocate the profile data being returned by
|
||
the authentication package.
|
||
|
||
STATUS_NO_LOGON_SERVERS - Indicates that no domain controllers
|
||
are currently able to service the authentication request.
|
||
|
||
STATUS_LOGON_FAILURE - Indicates the logon attempt failed. No
|
||
indication as to the reason for failure is given, but typical
|
||
reasons include mispelled usernames, mispelled passwords.
|
||
|
||
STATUS_ACCOUNT_RESTRICTION - Indicates the user account and
|
||
password were legitimate, but that the user account has some
|
||
restriction preventing successful logon at this time.
|
||
|
||
STATUS_NO_SUCH_PACKAGE - The specified authentication package is
|
||
unknown to the LSA.
|
||
|
||
STATUS_BAD_VALIDATION_CLASS - The authentication information
|
||
provided is not a validation class known to the specified
|
||
authentication package.
|
||
|
||
Routine Description:
|
||
|
||
This routine is used to authenticate a user logon attempt. This is
|
||
used only for user's initial logon, necessary to gain access to NT
|
||
OS/2. Subsequent (supplementary) authentication requests must be done
|
||
using LsaCallAuthenticationPackage(). This service will cause a logon
|
||
session to be created to represent the new logon. It will also return
|
||
a token representing the newly logged on user.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NTSTATUS Status;
|
||
LSAP_AU_API_MESSAGE Message = {0};
|
||
PLSAP_LOGON_USER_ARGS Arguments;
|
||
|
||
Arguments = &Message.Arguments.LogonUser;
|
||
|
||
//
|
||
// Set arguments
|
||
//
|
||
|
||
Arguments->AuthenticationPackage = AuthenticationPackage;
|
||
Arguments->AuthenticationInformation = AuthenticationInformation;
|
||
Arguments->AuthenticationInformationLength = AuthenticationInformationLength;
|
||
Arguments->OriginName = (*OriginName);
|
||
Arguments->LogonType = LogonType;
|
||
Arguments->SourceContext = (*SourceContext);
|
||
|
||
Arguments->LocalGroups = LocalGroups;
|
||
if ( ARGUMENT_PRESENT(LocalGroups) ) {
|
||
Arguments->LocalGroupsCount = LocalGroups->GroupCount;
|
||
} else {
|
||
Arguments->LocalGroupsCount = 0;
|
||
}
|
||
|
||
|
||
//
|
||
// Call the Local Security Authority Server.
|
||
//
|
||
|
||
Message.ApiNumber = LsapAuLogonUserApi;
|
||
Message.PortMessage.u1.s1.DataLength = sizeof(*Arguments) + 8;
|
||
Message.PortMessage.u1.s1.TotalLength = sizeof(Message);
|
||
Message.PortMessage.u2.ZeroInit = 0L;
|
||
|
||
Status = ZwRequestWaitReplyPort(
|
||
LsaHandle,
|
||
(PPORT_MESSAGE) &Message,
|
||
(PPORT_MESSAGE) &Message
|
||
);
|
||
|
||
//
|
||
// We may be returning bogus return values here, but it doesn't
|
||
// matter. They will just be ignored if an error occured.
|
||
//
|
||
|
||
(*SubStatus) = Arguments->SubStatus;
|
||
|
||
if ( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = Message.ReturnedStatus ;
|
||
|
||
// Don't not clear the ProfileBuffer even in case of error, cause
|
||
// subauth packages need the ProfileBuffer.
|
||
*ProfileBuffer = Arguments->ProfileBuffer ;
|
||
*ProfileBufferLength = Arguments->ProfileBufferLength ;
|
||
|
||
if ( NT_SUCCESS( Status ) )
|
||
{
|
||
*LogonId = Arguments->LogonId ;
|
||
*Token = Arguments->Token ;
|
||
*Quotas = Arguments->Quotas ;
|
||
} else {
|
||
*Token = NULL;
|
||
}
|
||
|
||
} else {
|
||
|
||
*ProfileBuffer = NULL ;
|
||
*Token = NULL ;
|
||
}
|
||
|
||
return Status;
|
||
|
||
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
LsaCallAuthenticationPackage (
|
||
IN HANDLE LsaHandle,
|
||
IN ULONG AuthenticationPackage,
|
||
IN PVOID ProtocolSubmitBuffer,
|
||
IN ULONG SubmitBufferLength,
|
||
OUT PVOID *ProtocolReturnBuffer OPTIONAL,
|
||
OUT PULONG ReturnBufferLength OPTIONAL,
|
||
OUT PNTSTATUS ProtocolStatus OPTIONAL
|
||
)
|
||
|
||
/*++
|
||
|
||
Arguments:
|
||
|
||
LsaHandle - Supplies a handle obtained in a previous call to
|
||
LsaRegisterLogonProcess.
|
||
|
||
AuthenticationPackage - Supplies the ID of the authentication
|
||
package to use for the logon attempt. The standard
|
||
authentication package name for NT is called "MSV1.0".
|
||
|
||
ProtocolSubmitBuffer - Supplies a protocol message specific to
|
||
the authentication package.
|
||
|
||
SubmitBufferLength - Indicates the length of the submitted
|
||
protocol message buffer.
|
||
|
||
ProtocolReturnBuffer - Receives a pointer to a returned protocol
|
||
message whose format and semantics are specific to the
|
||
authentication package.
|
||
|
||
This buffer is allocated by this service and must be freed
|
||
using LsaFreeReturnBuffer() when no longer needed.
|
||
|
||
ReturnBufferLength - Receives the length (in bytes) of the
|
||
returned profile buffer.
|
||
|
||
ProtocolStatus - Assuming the services completion is
|
||
STATUS_SUCCESS, this parameter will receive completion status
|
||
returned by the specified authentication package. The list
|
||
of status values that may be returned are authentication
|
||
package specific.
|
||
|
||
Return Status:
|
||
|
||
STATUS_SUCCESS - The call was made to the authentication package.
|
||
The ProtocolStatus parameter must be checked to see what the
|
||
completion status from the authentication package is.
|
||
|
||
STATUS_QUOTA_EXCEEDED - This error indicates that the call could
|
||
not be completed because the client does not have sufficient
|
||
quota to allocate the return buffer.
|
||
|
||
STATUS_NO_SUCH_PACKAGE - The specified authentication package is
|
||
unknown to the LSA.
|
||
|
||
Routine Description:
|
||
|
||
This routine is used when a logon process needs to communicate with an
|
||
authentication package. There are several reasons why a logon process
|
||
may want to do this. Some examples are:
|
||
|
||
o To implement multi-message authentication protocols (such as
|
||
the LAN Manager Challenge-response protocol.
|
||
|
||
o To notify the authentication package of interesting state
|
||
change information, such as LAN Manager notifying the MSV1.0
|
||
package that a previously unreachable domain controller is
|
||
now reachable. In this example, the authentication package
|
||
would re-logon any users logged on to that domain controller.
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NTSTATUS Status;
|
||
LSAP_AU_API_MESSAGE Message = {0};
|
||
PLSAP_CALL_PACKAGE_ARGS Arguments;
|
||
|
||
|
||
|
||
Arguments = &Message.Arguments.CallPackage;
|
||
|
||
//
|
||
// Set arguments
|
||
//
|
||
|
||
Arguments->AuthenticationPackage = AuthenticationPackage;
|
||
Arguments->ProtocolSubmitBuffer = ProtocolSubmitBuffer;
|
||
Arguments->SubmitBufferLength = SubmitBufferLength;
|
||
|
||
|
||
|
||
//
|
||
// Call the Local Security Authority Server.
|
||
//
|
||
|
||
Message.ApiNumber = LsapAuCallPackageApi;
|
||
Message.PortMessage.u1.s1.DataLength = sizeof(*Arguments) + 8;
|
||
Message.PortMessage.u1.s1.TotalLength = sizeof(Message);
|
||
Message.PortMessage.u2.ZeroInit = 0L;
|
||
|
||
Status = ZwRequestWaitReplyPort(
|
||
LsaHandle,
|
||
(PPORT_MESSAGE) &Message,
|
||
(PPORT_MESSAGE) &Message
|
||
);
|
||
|
||
//
|
||
// We may be returning bogus return values here, but it doesn't
|
||
// matter. They will just be ignored if an error occured.
|
||
//
|
||
|
||
if ( ProtocolReturnBuffer )
|
||
{
|
||
(*ProtocolReturnBuffer) = Arguments->ProtocolReturnBuffer;
|
||
}
|
||
|
||
if ( ReturnBufferLength )
|
||
{
|
||
(*ReturnBufferLength) = Arguments->ReturnBufferLength;
|
||
}
|
||
|
||
if ( ProtocolStatus )
|
||
{
|
||
(*ProtocolStatus) = Arguments->ProtocolStatus;
|
||
}
|
||
|
||
|
||
if ( NT_SUCCESS(Status) ) {
|
||
Status = Message.ReturnedStatus;
|
||
#if DBG
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
DbgPrint("LSA AU: Call Package Failed %lx\n",Status);
|
||
}
|
||
} else {
|
||
DbgPrint("LSA AU: Call Package Failed %lx\n",Status);
|
||
#endif //DBG
|
||
}
|
||
|
||
|
||
|
||
return Status;
|
||
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
LsaDeregisterLogonProcess (
|
||
IN HANDLE LsaHandle
|
||
)
|
||
|
||
/*++
|
||
|
||
This function deletes the caller's logon process context.
|
||
|
||
|
||
--- WARNING ---
|
||
|
||
Logon Processes are part of the Trusted Computer Base, and,
|
||
as such, are expected to be debugged to a high degree. If
|
||
a logon process deregisters, we will believe it. This
|
||
allows us to re-use the old Logon Process context value.
|
||
If the Logon process accidently uses its context value
|
||
after freeing it, strange things may happen. LIkewise,
|
||
if a client calls to release a context that has already
|
||
been released, then LSA may grind to a halt.
|
||
|
||
|
||
|
||
Arguments:
|
||
|
||
LsaHandle - Supplies a handle obtained in a previous call to
|
||
LsaRegisterLogonProcess.
|
||
|
||
|
||
Return Status:
|
||
|
||
STATUS_SUCCESS - Indicates the service completed successfully.
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NTSTATUS Status;
|
||
LSAP_AU_API_MESSAGE Message = {0};
|
||
NTSTATUS TempStatus;
|
||
|
||
//
|
||
// Call the Local Security Authority Server.
|
||
//
|
||
|
||
Message.ApiNumber = LsapAuDeregisterLogonProcessApi;
|
||
Message.PortMessage.u1.s1.DataLength = 8;
|
||
Message.PortMessage.u1.s1.TotalLength = sizeof(Message);
|
||
Message.PortMessage.u2.ZeroInit = 0L;
|
||
|
||
Status = ZwRequestWaitReplyPort(
|
||
LsaHandle,
|
||
(PPORT_MESSAGE) &Message,
|
||
(PPORT_MESSAGE) &Message
|
||
);
|
||
|
||
TempStatus = ZwClose(LsaHandle);
|
||
ASSERT(NT_SUCCESS(TempStatus));
|
||
|
||
if ( NT_SUCCESS(Status) ) {
|
||
Status = Message.ReturnedStatus;
|
||
#if DBG
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
DbgPrint("LSA AU: DeRregisterLogonProcess Failed 0x%lx\n",Status);
|
||
}
|
||
} else {
|
||
DbgPrint("LSA AU: Package Lookup NtRequestWaitReply Failed 0x%lx\n",Status);
|
||
#endif
|
||
}
|
||
|
||
return Status;
|
||
}
|