NT4/private/lsa/server/auproc.c
2020-09-30 17:12:29 +02:00

443 lines
10 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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);
}