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.
442 lines
10 KiB
442 lines
10 KiB
/*++
|
|
|
|
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);
|
|
|
|
}
|