443 lines
10 KiB
C
443 lines
10 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
auproc.c
|
||
|
||
Abstract:
|
||
|
||
This module provides logon process context management services within the
|
||
LSA subsystem.
|
||
|
||
Author:
|
||
|
||
Jim Kelly (JimK) 11-March-1991
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "lsasrvp.h"
|
||
#include "ausrvp.h"
|
||
#include "adtp.h"
|
||
|
||
|
||
|
||
|
||
NTSTATUS
|
||
LsapValidLogonProcess(
|
||
IN PCLIENT_ID ClientId,
|
||
IN PLSAP_AU_REGISTER_CONNECT_INFO ConnectInfo,
|
||
OUT PLSAP_LOGON_PROCESS *LogonProcessContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function checks to see if a calling process qualifies as a logon
|
||
process. If so, a logon process context is created for the caller and
|
||
returned.
|
||
|
||
A logon process must hold the SeTcbPrivilege privilege. Since there
|
||
is no way to impersonate a connection requestor (that would be way
|
||
too easy), we have to open the client thread and then open that thread's
|
||
token.
|
||
|
||
If the ConnectInfo message is all zeros, then the client is asking
|
||
for an untrusted connection and the privilege check is omitted.
|
||
|
||
Arguments:
|
||
|
||
ClientId - Pointer to the client Id of the sender of the logon
|
||
message. This is used to locate and open the calling thread or
|
||
process.
|
||
|
||
ConnectInfo - Authentication port information.
|
||
|
||
LogonProcessContext - If the caller is a legitimate logon process,
|
||
this receives a pointer to new logon process context block.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - Indicates the caller is a legitimate logon process
|
||
and a logon process context block is being returned.
|
||
|
||
any other value - Indicates the caller is NOT a legitimate logon
|
||
process and a logon process context block is NOT being returned.
|
||
The value returned indicates the reason why the client is not
|
||
acceptable.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NTSTATUS Status, TempStatus;
|
||
BOOLEAN PrivilegeHeld;
|
||
HANDLE ClientThread, ClientProcess, ClientToken;
|
||
PRIVILEGE_SET Privilege;
|
||
OBJECT_ATTRIBUTES NullAttributes;
|
||
UNICODE_STRING Unicode;
|
||
STRING Ansi;
|
||
LSAP_AU_REGISTER_CONNECT_INFO NullConnectInfo;
|
||
|
||
RtlZeroMemory(
|
||
&NullConnectInfo,
|
||
sizeof(NullConnectInfo)
|
||
);
|
||
|
||
|
||
InitializeObjectAttributes( &NullAttributes, NULL, 0, NULL, NULL );
|
||
|
||
//
|
||
// Open the client process. This is needed to:
|
||
//
|
||
// 1) Access the client's virtual memory (to copy arguments),
|
||
// 2) Duplicate token handles into the process,
|
||
// 3) Open the process's token to see if it qualifies as
|
||
// a logon process.
|
||
//
|
||
|
||
Status = NtOpenProcess(
|
||
&ClientProcess,
|
||
PROCESS_QUERY_INFORMATION | // To open primary token
|
||
PROCESS_VM_OPERATION | // To allocate memory
|
||
PROCESS_VM_READ | // To read memory
|
||
PROCESS_VM_WRITE | // To write memory
|
||
PROCESS_DUP_HANDLE, // To duplicate a handle into
|
||
&NullAttributes,
|
||
ClientId
|
||
);
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
return Status;
|
||
}
|
||
|
||
|
||
//
|
||
// If the connect message is all zeros, setup an untrusted connection.
|
||
//
|
||
|
||
if (RtlCompareMemory(
|
||
&NullConnectInfo,
|
||
ConnectInfo,
|
||
sizeof(NullConnectInfo)) == sizeof(NullConnectInfo)) {
|
||
|
||
//
|
||
// Allocate a mostly empty fill in a new logon process context.
|
||
//
|
||
|
||
(*LogonProcessContext) =
|
||
LsapAllocateLsaHeap( (ULONG)sizeof(LSAP_LOGON_PROCESS) );
|
||
if ( (*LogonProcessContext) == NULL ) {
|
||
TempStatus = NtClose( ClientProcess );
|
||
ASSERT( NT_SUCCESS(TempStatus) );
|
||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||
}
|
||
|
||
RtlZeroMemory(
|
||
*LogonProcessContext,
|
||
sizeof(LSAP_LOGON_PROCESS)
|
||
);
|
||
|
||
//
|
||
// Save the handle to the client process.
|
||
// The CommPort field of LogonProcessContext will be filled in
|
||
// when the connection is accepted.
|
||
//
|
||
|
||
(*LogonProcessContext)->ClientProcess = ClientProcess;
|
||
|
||
|
||
(*LogonProcessContext)->TrustedClient = FALSE;
|
||
|
||
return(STATUS_SUCCESS);
|
||
|
||
|
||
}
|
||
|
||
|
||
//
|
||
// Open the client thread and that thread's token
|
||
//
|
||
|
||
|
||
Status = NtOpenThread(
|
||
&ClientThread,
|
||
THREAD_QUERY_INFORMATION,
|
||
&NullAttributes,
|
||
ClientId
|
||
);
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
TempStatus = NtClose( ClientProcess );
|
||
ASSERT( NT_SUCCESS(TempStatus) );
|
||
return Status;
|
||
}
|
||
|
||
Status = NtOpenThreadToken(
|
||
ClientThread,
|
||
TOKEN_QUERY,
|
||
TRUE,
|
||
&ClientToken
|
||
);
|
||
|
||
TempStatus = NtClose( ClientThread );
|
||
ASSERT( NT_SUCCESS(TempStatus) );
|
||
|
||
//
|
||
// Make sure we succeeded in opening the token
|
||
//
|
||
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
if ( Status != STATUS_NO_TOKEN ) {
|
||
TempStatus = NtClose( ClientProcess );
|
||
ASSERT( NT_SUCCESS(TempStatus) );
|
||
return Status;
|
||
|
||
} else {
|
||
|
||
//
|
||
// The thread isn't impersonating...open the process's token.
|
||
//
|
||
|
||
Status = NtOpenProcessToken(
|
||
ClientProcess,
|
||
TOKEN_QUERY,
|
||
&ClientToken
|
||
);
|
||
|
||
|
||
//
|
||
// Make sure we succeeded in opening the token
|
||
//
|
||
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
TempStatus = NtClose( ClientProcess );
|
||
ASSERT( NT_SUCCESS(TempStatus) );
|
||
return Status;
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// OK, we have a token open
|
||
//
|
||
|
||
|
||
|
||
//
|
||
// Check for the privilege to execute this service.
|
||
//
|
||
|
||
Privilege.PrivilegeCount = 1;
|
||
Privilege.Control = PRIVILEGE_SET_ALL_NECESSARY;
|
||
Privilege.Privilege[0].Luid = LsapTcbPrivilege;
|
||
Privilege.Privilege[0].Attributes = 0;
|
||
|
||
Status = NtPrivilegeCheck(
|
||
ClientToken,
|
||
&Privilege,
|
||
&PrivilegeHeld
|
||
);
|
||
ASSERT( NT_SUCCESS(Status) );
|
||
|
||
|
||
//
|
||
// Generate any necessary audits
|
||
//
|
||
|
||
TempStatus = NtPrivilegedServiceAuditAlarm (
|
||
&LsapLsaAuName,
|
||
&LsapRegisterLogonServiceName,
|
||
ClientToken,
|
||
&Privilege,
|
||
PrivilegeHeld
|
||
);
|
||
// ASSERT( NT_SUCCESS(TempStatus) );
|
||
|
||
TempStatus = NtClose( ClientToken );
|
||
ASSERT( NT_SUCCESS(TempStatus) );
|
||
|
||
if ( !PrivilegeHeld ) {
|
||
TempStatus = NtClose( ClientProcess );
|
||
ASSERT( NT_SUCCESS(TempStatus) );
|
||
return STATUS_PRIVILEGE_NOT_HELD;
|
||
}
|
||
|
||
|
||
//
|
||
// Convert the LogonProcessName to Unicode.
|
||
//
|
||
|
||
Ansi.Buffer = ConnectInfo->LogonProcessName;
|
||
Ansi.Length = Ansi.MaximumLength =
|
||
(USHORT) ConnectInfo->LogonProcessNameLength;
|
||
Status = RtlAnsiStringToUnicodeString( &Unicode, &Ansi, TRUE );
|
||
|
||
if ( !NT_SUCCESS( Status )) {
|
||
TempStatus = NtClose( ClientProcess );
|
||
ASSERT( NT_SUCCESS(TempStatus) );
|
||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
//
|
||
// Allocate and fill in a new logon process context.
|
||
//
|
||
|
||
(*LogonProcessContext) =
|
||
LsapAllocateLsaHeap( (ULONG)sizeof(LSAP_LOGON_PROCESS) +
|
||
Unicode.Length );
|
||
if ( (*LogonProcessContext) == NULL ) {
|
||
RtlFreeUnicodeString( &Unicode );
|
||
TempStatus = NtClose( ClientProcess );
|
||
ASSERT( NT_SUCCESS(TempStatus) );
|
||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||
}
|
||
|
||
//
|
||
// Save the handle to the client process.
|
||
// The CommPort field of LogonProcessContext will be filled in
|
||
// when the connection is accepted.
|
||
//
|
||
|
||
(*LogonProcessContext)->ClientProcess = ClientProcess;
|
||
|
||
|
||
//
|
||
// Save the LogonProcessName in the context
|
||
//
|
||
|
||
RtlCopyMemory( (*LogonProcessContext)->LogonProcessName,
|
||
Unicode.Buffer,
|
||
Unicode.Length );
|
||
(*LogonProcessContext)->LogonProcessName[Unicode.Length/sizeof(WCHAR)] = L'\0';
|
||
|
||
//
|
||
// Set the contex to be trusted.
|
||
//
|
||
|
||
(*LogonProcessContext)->TrustedClient = TRUE;
|
||
|
||
//
|
||
// Audit the registration of the logon process
|
||
//
|
||
|
||
LsapAdtAuditLogonProcessRegistration( ConnectInfo );
|
||
RtlFreeUnicodeString( &Unicode );
|
||
|
||
|
||
|
||
return(STATUS_SUCCESS);
|
||
}
|
||
|
||
NTSTATUS
|
||
LsapAuApiDeregisterLogonProcess(
|
||
IN OUT PLSAP_CLIENT_REQUEST ClientRequest,
|
||
IN BOOLEAN TrustedClient
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function doesn't do anything. All the interesting
|
||
things are done as a result of dereferencing the client's
|
||
context, and that is done in auloop.c
|
||
|
||
|
||
|
||
Arguments:
|
||
|
||
ClientRequest - Represents the client's LPC request message and context.
|
||
The request message contains a LSAP_AU_API_MESSAGE message
|
||
block.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - Indicates the service completed successfully.
|
||
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
return(STATUS_SUCCESS);
|
||
|
||
}
|
||
|
||
|
||
|
||
NTSTATUS
|
||
LsapAuRundownLogonProcess(
|
||
PLSAP_LOGON_PROCESS Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function performs Logon process rundown.
|
||
It is to be called if a logon process exits without deregistering.
|
||
|
||
This function deletes the logon process context specified
|
||
by the caller.
|
||
|
||
|
||
Arguments:
|
||
|
||
Context - The context of the logon process to run-down.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - Indicates the service completed successfully.
|
||
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NTSTATUS Status;
|
||
|
||
|
||
//
|
||
// Close the client process and the communication port used
|
||
// to talk with this client.
|
||
//
|
||
|
||
Status = NtClose( Context->ClientProcess );
|
||
#if DBG
|
||
if (!NT_SUCCESS(Status)) {
|
||
DbgPrint("LsaSrv: Auproc.c - Close of logon process failed, 0x%lx\n", Status);
|
||
}
|
||
#endif //DBG
|
||
ASSERT(NT_SUCCESS(Status));
|
||
|
||
Status = NtClose( Context->CommPort );
|
||
#if DBG
|
||
if (!NT_SUCCESS(Status)) {
|
||
DbgPrint("LsaSrv: Auproc.c - Close of comm port failed, 0x%lx\n", Status);
|
||
}
|
||
#endif //DBG
|
||
ASSERT(NT_SUCCESS(Status));
|
||
|
||
|
||
//
|
||
// And free the client's context block.
|
||
//
|
||
|
||
LsapFreeLsaHeap( Context );
|
||
|
||
return(Status);
|
||
|
||
}
|