windows-nt/Source/XPSP1/NT/ds/netapi/svcdlls/logonsrv/client/logonapi.c

769 lines
22 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1991-92 Microsoft Corporation
Module Name:
logonapi.c
Abstract:
This module contains the Netlogon API RPC client stubs.
Author:
Cliff Van Dyke (CliffV) 27-Jun-1991
[Environment:]
User Mode - Win32
Revision History:
27-Jun-1991 CliffV
Created
--*/
//
// INCLUDES
//
#include <nt.h>
#include <ntrtl.h>
#include <rpc.h>
#include <ntrpcp.h> // needed by rpcasync.h
#include <rpcasync.h> // I_RpcExceptionFilter
#include <logon_c.h>// includes lmcons.h, lmaccess.h, netlogon.h, ssi.h, windef.h
#include <crypt.h> // Encryption routines.
#include <debuglib.h> // IF_DEBUG()
#include <lmerr.h> // NERR_ and ERROR_ equates.
#include <netdebug.h> // NetpKdPrint
NET_API_STATUS NET_API_FUNCTION
I_NetLogonUasLogon (
IN LPWSTR UserName,
IN LPWSTR Workstation,
OUT PNETLOGON_VALIDATION_UAS_INFO *ValidationInformation
)
/*++
Routine Description:
This function is called by the XACT server when processing a
I_NetWkstaUserLogon XACT SMB. This feature allows a UAS client to
logon to a SAM domain controller.
Arguments:
UserName -- Account name of the user logging on.
Workstation -- The workstation from which the user is logging on.
ValidationInformation -- Returns the requested validation
information.
Return Value:
NERR_SUCCESS if there was no error. Otherwise, the error code is
returned.
--*/
{
NET_API_STATUS NetStatus;
LPWSTR ServerName = NULL; // Not supported remotely
//
// Do the RPC call with an exception handler since RPC will raise an
// exception if anything fails. It is up to us to figure out what
// to do once the exception is raised.
//
RpcTryExcept {
*ValidationInformation = NULL; // Force RPC to allocate
//
// Call RPC version of the API.
//
NetStatus = NetrLogonUasLogon(
(LPWSTR) ServerName,
UserName,
Workstation,
ValidationInformation );
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
NetStatus = RpcExceptionCode();
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("NetrLogonUasLogon rc = %lu 0x%lx\n",
NetStatus, NetStatus));
}
return NetStatus;
}
NET_API_STATUS
I_NetLogonUasLogoff (
IN LPWSTR UserName,
IN LPWSTR Workstation,
OUT PNETLOGON_LOGOFF_UAS_INFO LogoffInformation
)
/*++
Routine Description:
This function is called by the XACT server when processing a
I_NetWkstaUserLogoff XACT SMB. This feature allows a UAS client to
logoff from a SAM domain controller. The request is authenticated,
the entry is removed for this user from the logon session table
maintained by the Netlogon service for NetLogonEnum, and logoff
information is returned to the caller.
The server portion of I_NetLogonUasLogoff (in the Netlogon service)
compares the user name and workstation name specified in the
LogonInformation with the user name and workstation name from the
impersonation token. If they don't match, I_NetLogonUasLogoff fails
indicating the access is denied.
Group SECURITY_LOCAL is refused access to this function. Membership
in SECURITY_LOCAL implies that this call was made locally and not
through the XACT server.
The Netlogon service cannot be sure that this function was called by
the XACT server. Therefore, the Netlogon service will not simply
delete the entry from the logon session table. Rather, the logon
session table entry will be marked invisible outside of the Netlogon
service (i.e., it will not be returned by NetLogonEnum) until a valid
LOGON_WKSTINFO_RESPONSE is received for the entry. The Netlogon
service will immediately interrogate the client (as described above
for LOGON_WKSTINFO_RESPONSE) and temporarily increase the
interrogation frequency to at least once a minute. The logon session
table entry will reappear as soon as a function of interrogation if
this isn't a true logoff request.
Arguments:
UserName -- Account name of the user logging off.
Workstation -- The workstation from which the user is logging
off.
LogoffInformation -- Returns the requested logoff information.
Return Value:
The Net status code.
--*/
{
NET_API_STATUS NetStatus;
LPWSTR ServerName = NULL; // Not supported remotely
//
// Do the RPC call with an exception handler since RPC will raise an
// exception if anything fails. It is up to us to figure out what
// to do once the exception is raised.
//
RpcTryExcept {
//
// Call RPC version of the API.
//
NetStatus = NetrLogonUasLogoff(
(LPWSTR) ServerName,
UserName,
Workstation,
LogoffInformation );
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
NetStatus = RpcExceptionCode();
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("NetrLogonUasLogoff rc = %lu 0x%lx\n",
NetStatus, NetStatus));
}
return NetStatus;
}
NTSTATUS
I_NetLogonSamLogon (
IN LPWSTR LogonServer OPTIONAL,
IN LPWSTR ComputerName OPTIONAL,
IN PNETLOGON_AUTHENTICATOR Authenticator OPTIONAL,
OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator OPTIONAL,
IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
IN LPBYTE LogonInformation,
IN NETLOGON_VALIDATION_INFO_CLASS ValidationLevel,
OUT LPBYTE * ValidationInformation,
OUT PBOOLEAN Authoritative
)
/*++
Routine Description:
This function is called by an NT client to process an interactive or
network logon. This function passes a domain name, user name and
credentials to the Netlogon service and returns information needed to
build a token. It is called in three instances:
* It is called by the LSA's MSV1_0 authentication package for any
NT system that has LanMan installed. The MSV1_0 authentication
package calls SAM directly if LanMan is not installed. In this
case, this function is a local function and requires the caller
to have SE_TCB privilege. The local Netlogon service will
either handle this request directly (validating the request with
the local SAM database) or will forward this request to the
appropriate domain controller as documented in sections 2.4 and
2.5.
* It is called by a Netlogon service on a workstation to a DC in
the Primary Domain of the workstation as documented in section
2.4. In this case, this function uses a secure channel set up
between the two Netlogon services.
* It is called by a Netlogon service on a DC to a DC in a trusted
domain as documented in section 2.5. In this case, this
function uses a secure channel set up between the two Netlogon
services.
The Netlogon service validates the specified credentials. If they
are valid, adds an entry for this LogonId, UserName, and Workstation
into the logon session table. The entry is added to the logon
session table only in the domain defining the specified user's
account.
This service is also used to process a re-logon request.
Arguments:
LogonServer -- Supplies the name of the logon server to process
this logon request. This field should be null to indicate
this is a call from the MSV1_0 authentication package to the
local Netlogon service.
ComputerName -- Name of the machine making the call. This field
should be null to indicate this is a call from the MSV1_0
authentication package to the local Netlogon service.
Authenticator -- supplied by the client. This field should be
null to indicate this is a call from the MSV1_0
authentication package to the local Netlogon service.
ReturnAuthenticator -- Receives an authenticator returned by the
server. This field should be null to indicate this is a call
from the MSV1_0 authentication package to the local Netlogon
service.
LogonLevel -- Specifies the level of information given in
LogonInformation.
LogonInformation -- Specifies the description for the user
logging on.
ValidationLevel -- Specifies the level of information returned in
ValidationInformation. Must be NetlogonValidationSamInformation.
ValidationInformation -- Returns the requested validation
information.
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.
Return Value:
STATUS_SUCCESS: if there was no error.
STATUS_NO_LOGON_SERVERS -- Either Pass-thru authentication or
Trusted Domain Authentication could not contact the requested
Domain Controller.
STATUS_INVALID_INFO_CLASS -- Either LogonLevel or ValidationLevel is
invalid.
STATUS_INVALID_PARAMETER -- Another Parameter is invalid.
STATUS_ACCESS_DENIED -- The caller does not have access to call this
API.
STATUS_NO_SUCH_USER -- Indicates that the user specified in
LogonInformation does not exist. This status should not be returned
to the originally caller. It should be mapped to STATUS_LOGON_FAILURE.
STATUS_WRONG_PASSWORD -- Indicates that the password information in
LogonInformation was incorrect. This status should not be returned
to the originally caller. It should be mapped to STATUS_LOGON_FAILURE.
STATUS_INVALID_LOGON_HOURES -- The user is not authorized to logon
at this time.
STATUS_INVALID_WORKSTATION -- The user is not authorized to logon
from the specified workstation.
STATUS_PASSWORD_EXPIRED -- The password for the user has expired.
STATUS_ACCOUNT_DISABLED -- The user's account has been disabled.
.
.
.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
NETLOGON_LEVEL RpcLogonInformation;
NETLOGON_VALIDATION RpcValidationInformation;
//
// Do the RPC call with an exception handler since RPC will raise an
// exception if anything fails. It is up to us to figure out what
// to do once the exception is raised.
//
RpcTryExcept {
//
// Call RPC version of the API.
//
RpcLogonInformation.LogonInteractive =
(PNETLOGON_INTERACTIVE_INFO) LogonInformation;
RpcValidationInformation.ValidationSam = NULL;
Status = NetrLogonSamLogon(
LogonServer,
ComputerName,
Authenticator,
ReturnAuthenticator,
LogonLevel,
&RpcLogonInformation,
ValidationLevel,
&RpcValidationInformation,
Authoritative );
*ValidationInformation = (LPBYTE)
RpcValidationInformation.ValidationSam;
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
*Authoritative = TRUE;
Status = I_RpcMapWin32Status(RpcExceptionCode());
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("I_NetLogonSamLogon rc = %lu 0x%lx\n", Status, Status));
}
return Status;
}
NTSTATUS
I_NetLogonSamLogonWithFlags (
IN LPWSTR LogonServer OPTIONAL,
IN LPWSTR ComputerName OPTIONAL,
IN PNETLOGON_AUTHENTICATOR Authenticator OPTIONAL,
OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator OPTIONAL,
IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
IN LPBYTE LogonInformation,
IN NETLOGON_VALIDATION_INFO_CLASS ValidationLevel,
OUT LPBYTE * ValidationInformation,
OUT PBOOLEAN Authoritative,
IN OUT PULONG ExtraFlags
)
/*++
Routine Description:
Flag version of I_NetLogonSamLogon.
Arguments:
Same as I_NetLogonSamLogon except:
* ExtraFlags - Passes and returns a DWORD. For later expansion.
Return Value:
Same as I_NetLogonSamLogon.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
NETLOGON_LEVEL RpcLogonInformation;
NETLOGON_VALIDATION RpcValidationInformation;
//
// Do the RPC call with an exception handler since RPC will raise an
// exception if anything fails. It is up to us to figure out what
// to do once the exception is raised.
//
RpcTryExcept {
//
// Call RPC version of the API.
//
RpcLogonInformation.LogonInteractive =
(PNETLOGON_INTERACTIVE_INFO) LogonInformation;
RpcValidationInformation.ValidationSam = NULL;
Status = NetrLogonSamLogonWithFlags(
LogonServer,
ComputerName,
Authenticator,
ReturnAuthenticator,
LogonLevel,
&RpcLogonInformation,
ValidationLevel,
&RpcValidationInformation,
Authoritative,
ExtraFlags );
*ValidationInformation = (LPBYTE)
RpcValidationInformation.ValidationSam;
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
*Authoritative = TRUE;
Status = I_RpcMapWin32Status(RpcExceptionCode());
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("I_NetLogonSamLogonWithFlags rc = %lu 0x%lx\n", Status, Status));
}
return Status;
}
NTSTATUS
I_NetLogonSamLogonEx (
IN PVOID ContextHandle,
IN LPWSTR LogonServer OPTIONAL,
IN LPWSTR ComputerName OPTIONAL,
IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
IN LPBYTE LogonInformation,
IN NETLOGON_VALIDATION_INFO_CLASS ValidationLevel,
OUT LPBYTE * ValidationInformation,
OUT PBOOLEAN Authoritative,
IN OUT PULONG ExtraFlags,
OUT PBOOLEAN RpcFailed
)
/*++
Routine Description:
Concurrent API version of I_NetLogonSamLogon.
Arguments:
Same as I_NetLogonSamLogon except:
* No authenticator parameters.
* Context Handle parameter
* ExtraFlags - Passes and returns a DWORD. For later expansion.
Return Value:
Same as I_NetLogonSamLogon.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
NETLOGON_LEVEL RpcLogonInformation;
NETLOGON_VALIDATION RpcValidationInformation;
*RpcFailed = FALSE;
//
// Do the RPC call with an exception handler since RPC will raise an
// exception if anything fails. It is up to us to figure out what
// to do once the exception is raised.
//
RpcTryExcept {
//
// Call RPC version of the API.
//
RpcLogonInformation.LogonInteractive =
(PNETLOGON_INTERACTIVE_INFO) LogonInformation;
RpcValidationInformation.ValidationSam = NULL;
Status = NetrLogonSamLogonEx(
ContextHandle,
LogonServer,
ComputerName,
LogonLevel,
&RpcLogonInformation,
ValidationLevel,
&RpcValidationInformation,
Authoritative,
ExtraFlags );
*ValidationInformation = (LPBYTE)
RpcValidationInformation.ValidationSam;
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
*Authoritative = TRUE;
*RpcFailed = TRUE;
Status = I_RpcMapWin32Status(RpcExceptionCode());
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("I_NetLogonSamLogonEx rc = %lu 0x%lx\n", Status, Status));
}
return Status;
}
NTSTATUS NET_API_FUNCTION
I_NetLogonSamLogoff (
IN LPWSTR LogonServer OPTIONAL,
IN LPWSTR ComputerName OPTIONAL,
IN PNETLOGON_AUTHENTICATOR Authenticator OPTIONAL,
OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator OPTIONAL,
IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
IN LPBYTE LogonInformation
)
/*++
Routine Description:
This function is called by an NT client to process an interactive
logoff. It is not called for the network logoff case since the
Netlogon service does not maintain any context for network logons.
This function does the following. It authenticates the request. It
updates the logon statistics in the SAM database on whichever machine
or domain defines this user account. It updates the logon session
table in the primary domain of the machine making the request. And
it returns logoff information to the caller.
This function is called in same scenarios that I_NetLogonSamLogon is
called:
* It is called by the LSA's MSV1_0 authentication package to
support LsaApLogonTerminated. In this case, this function is a
local function and requires the caller to have SE_TCB privilege.
The local Netlogon service will either handle this request
directly (if LogonDomainName indicates this request was
validated locally) or will forward this request to the
appropriate domain controller as documented in sections 2.4 and
2.5.
* It is called by a Netlogon service on a workstation to a DC in
the Primary Domain of the workstation as documented in section
2.4. In this case, this function uses a secure channel set up
between the two Netlogon services.
* It is called by a Netlogon service on a DC to a DC in a trusted
domain as documented in section 2.5. In this case, this
function uses a secure channel set up between the two Netlogon
services.
When this function is a remote function, it is sent to the DC over a
NULL session.
Arguments:
LogonServer -- Supplies the name of the logon server which logged
this user on. This field should be null to indicate this is
a call from the MSV1_0 authentication package to the local
Netlogon service.
ComputerName -- Name of the machine making the call. This field
should be null to indicate this is a call from the MSV1_0
authentication package to the local Netlogon service.
Authenticator -- supplied by the client. This field should be
null to indicate this is a call from the MSV1_0
authentication package to the local Netlogon service.
ReturnAuthenticator -- Receives an authenticator returned by the
server. This field should be null to indicate this is a call
from the MSV1_0 authentication package to the local Netlogon
service.
LogonLevel -- Specifies the level of information given in
LogonInformation.
LogonInformation -- Specifies the logon domain name, logon Id,
user name and workstation name of the user logging off.
Return Value:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
NETLOGON_LEVEL RpcLogonInformation;
//
// Do the RPC call with an exception handler since RPC will raise an
// exception if anything fails. It is up to us to figure out what
// to do once the exception is raised.
//
RpcTryExcept {
//
// Call RPC version of the API.
//
RpcLogonInformation.LogonInteractive =
(PNETLOGON_INTERACTIVE_INFO) LogonInformation;
Status = NetrLogonSamLogoff(
LogonServer,
ComputerName,
Authenticator,
ReturnAuthenticator,
LogonLevel,
&RpcLogonInformation );
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
Status = I_RpcMapWin32Status(RpcExceptionCode());
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("I_NetLogonSamLogoff rc = %lu 0x%lx\n", Status, Status));
}
return Status;
}
NTSTATUS NET_API_FUNCTION
I_NetLogonSendToSam (
IN LPWSTR PrimaryName OPTIONAL,
IN LPWSTR ComputerName,
IN PNETLOGON_AUTHENTICATOR Authenticator,
OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
IN LPBYTE OpaqueBuffer,
IN ULONG OpaqueBufferSize
)
/*++
Routine Description:
This function sends an opaque buffer from SAM on a BDC to SAM on the PDC.
The original use of this routine will be to allow the BDC to forward user
account password changes to the PDC.
Arguments:
PrimaryName -- Computer name of the PDC to remote the call to.
ComputerName -- Name of the machine making the call.
Authenticator -- supplied by the client.
ReturnAuthenticator -- Receives an authenticator returned by the
server.
OpaqueBuffer - Buffer to be passed to the SAM service on the PDC.
The buffer will be encrypted on the wire.
OpaqueBufferSize - Size (in bytes) of OpaqueBuffer.
Return Value:
STATUS_SUCCESS: Message successfully sent to PDC
STATUS_NO_MEMORY: There is not enough memory to complete the operation
STATUS_NO_SUCH_DOMAIN: DomainName does not correspond to a hosted domain
STATUS_NO_LOGON_SERVERS: PDC is not currently available
STATUS_NOT_SUPPORTED: PDC does not support this operation
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
//
// Do the RPC call with an exception handler since RPC will raise an
// exception if anything fails. It is up to us to figure out what
// to do once the exception is raised.
//
RpcTryExcept {
//
// Call RPC version of the API.
//
Status = NetrLogonSendToSam(
PrimaryName,
ComputerName,
Authenticator,
ReturnAuthenticator,
OpaqueBuffer,
OpaqueBufferSize );
} RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
Status = I_RpcMapWin32Status(RpcExceptionCode());
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("I_NetLogonSendToSam rc = %lu 0x%lx\n", Status, Status));
}
return Status;
}