Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1446 lines
43 KiB

/*++
Copyright (c) 1987-1992 Microsoft Corporation
Module Name:
ssiapi.c
Abstract:
Authentication and replication API routines (client side).
Author:
Cliff Van Dyke (cliffv) 30-Jul-1991
Environment:
User mode only.
Contains NT-specific code.
Requires ANSI C extensions: slash-slash comments, long external names.
Revision History:
--*/
#include <nt.h> // LARGE_INTEGER definition
#include <ntrtl.h> // LARGE_INTEGER definition
#include <nturtl.h> // LARGE_INTEGER definition
#include <rpc.h> // Needed by logon.h
#include <logon_c.h> // includes lmcons.h, lmaccess.h, netlogon.h, ssi.h, windef.h
#include <debuglib.h> // IF_DEBUG()
#include <lmerr.h> // NERR_* defines
#include <netdebug.h> // NetpKdPrint
#include "..\server\ssiapi.h"
NTSTATUS
I_NetServerReqChallenge(
IN LPWSTR PrimaryName OPTIONAL,
IN LPWSTR ComputerName,
IN PNETLOGON_CREDENTIAL ClientChallenge,
OUT PNETLOGON_CREDENTIAL ServerChallenge
)
/*++
Routine Description:
This is the client side of I_NetServerReqChallenge.
I_NetLogonRequestChallenge is the first of two functions used by a client
to process an authentication with a domain controller (DC). (See
I_NetServerAuthenticate below.) It is called for
a BDC (or member server) authenticating with a PDC for replication
purposes.
This function passes a challenge to the PDC and the PDC passes a challenge
back to the caller.
Arguments:
PrimaryName -- Supplies the name of the PrimaryDomainController we wish to
authenticate with.
ComputerName -- Name of the BDC or member server making the call.
ClientChallenge -- 64 bit challenge supplied by the BDC or member server.
ServerChallenge -- Receives 64 bit challenge from the PDC.
Return Value:
The status of the operation.
--*/
{
NTSTATUS Status = 0;
//
// 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 = NetrServerReqChallenge(
PrimaryName,
ComputerName,
ClientChallenge,
ServerChallenge );
} RpcExcept( EXCEPTION_EXECUTE_HANDLER ) {
Status = I_RpcMapWin32Status(RpcExceptionCode());
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("I_NetServerReqChallenge rc = %lu 0x%lx\n",
Status, Status));
}
return Status;
}
NTSTATUS
I_NetServerAuthenticate(
IN LPWSTR PrimaryName OPTIONAL,
IN LPWSTR AccountName,
IN NETLOGON_SECURE_CHANNEL_TYPE AccountType,
IN LPWSTR ComputerName,
IN PNETLOGON_CREDENTIAL ClientCredential,
OUT PNETLOGON_CREDENTIAL ServerCredential
)
/*++
Routine Description:
This is the client side of I_NetServerAuthenticate
I_NetServerAuthenticate is the second of two functions used by a client
Netlogon service to authenticate with another Netlogon service.
(See I_NetServerReqChallenge above.) Both a SAM or UAS server authenticates
using this function.
This function passes a credential to the DC and the DC passes a credential
back to the caller.
Arguments:
PrimaryName -- Supplies the name of the DC we wish to authenticate with.
AccountName -- Name of the Account to authenticate with.
SecureChannelType -- The type of the account being accessed. This field
must be set to UasServerSecureChannel to indicate a call from
downlevel (LanMan 2.x and below) BDC or member server.
ComputerName -- Name of the BDC or member server making the call.
ClientCredential -- 64 bit credential supplied by the BDC or member server.
ServerCredential -- Receives 64 bit credential from the PDC.
Return Value:
The status of the operation.
--*/
{
NTSTATUS Status = 0;
//
// 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 = NetrServerAuthenticate(
PrimaryName,
AccountName,
AccountType,
ComputerName,
ClientCredential,
ServerCredential );
} RpcExcept( EXCEPTION_EXECUTE_HANDLER ) {
Status = I_RpcMapWin32Status(RpcExceptionCode());
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("I_NetServerAuthenticate rc = %lu 0x%lx\n",
Status, Status));
}
return Status;
}
NTSTATUS
I_NetServerAuthenticate2(
IN LPWSTR PrimaryName OPTIONAL,
IN LPWSTR AccountName,
IN NETLOGON_SECURE_CHANNEL_TYPE AccountType,
IN LPWSTR ComputerName,
IN PNETLOGON_CREDENTIAL ClientCredential,
OUT PNETLOGON_CREDENTIAL ServerCredential,
IN OUT PULONG NegotiatedFlags
)
/*++
Routine Description:
This is the client side of I_NetServerAuthenticate
I_NetServerAuthenticate is the second of two functions used by a client
Netlogon service to authenticate with another Netlogon service.
(See I_NetServerReqChallenge above.) Both a SAM or UAS server authenticates
using this function.
This function passes a credential to the DC and the DC passes a credential
back to the caller.
Arguments:
PrimaryName -- Supplies the name of the DC we wish to authenticate with.
AccountName -- Name of the Account to authenticate with.
SecureChannelType -- The type of the account being accessed. This field
must be set to UasServerSecureChannel to indicate a call from
downlevel (LanMan 2.x and below) BDC or member server.
ComputerName -- Name of the BDC or member server making the call.
ClientCredential -- 64 bit credential supplied by the BDC or member server.
ServerCredential -- Receives 64 bit credential from the PDC.
NegotiatedFlags -- Specifies flags indicating what features the BDC supports.
Returns a subset of those flags indicating what features the PDC supports.
The PDC/BDC should ignore any bits that it doesn't understand.
Return Value:
The status of the operation.
--*/
{
NTSTATUS Status = 0;
//
// 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 = NetrServerAuthenticate2(
PrimaryName,
AccountName,
AccountType,
ComputerName,
ClientCredential,
ServerCredential,
NegotiatedFlags );
} RpcExcept( EXCEPTION_EXECUTE_HANDLER ) {
Status = I_RpcMapWin32Status(RpcExceptionCode());
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("I_NetServerAuthenticate2 rc = %lu 0x%lx\n",
Status, Status));
}
return Status;
}
NTSTATUS
I_NetServerPasswordSet(
IN LPWSTR PrimaryName OPTIONAL,
IN LPWSTR AccountName,
IN NETLOGON_SECURE_CHANNEL_TYPE AccountType,
IN LPWSTR ComputerName,
IN PNETLOGON_AUTHENTICATOR Authenticator,
OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
IN PENCRYPTED_LM_OWF_PASSWORD UasNewPassword
)
/*++
Routine Description:
This function is used to change the password for the account being
used to maintain a secure channel. This function can only be called
by a server which has previously authenticated with a DC by calling
I_NetServerAuthenticate.
The call is made differently depending on the account type:
* A domain account password is changed from the PDC in the
trusting domain. The I_NetServerPasswordSet call is made to any
DC in the trusted domain.
* A server account password is changed from the specific server.
The I_NetServerPasswordSet call is made to the PDC in the domain
the server belongs to.
* A workstation account password is changed from the specific
workstation. The I_NetServerPasswordSet call is made to a DC in
the domain the server belongs to.
For domain accounts and workstation accounts, the server being called
may be a BDC in the specific domain. In that case, the BDC will
validate the request and pass it on to the PDC of the domain using
the server account secure channel. If the PDC of the domain is
currently not available, the BDC will return STATUS_NO_LOGON_SERVERS. Since
the UasNewPassword is passed encrypted by the session key, such a BDC
will decrypt the UasNewPassword using the original session key and
will re-encrypt it with the session key for its session to its PDC
before passing the request on.
This function uses RPC to contact the DC named by PrimaryName.
Arguments:
PrimaryName -- Name of the PDC to change the servers password
with. NULL indicates this call is a local call being made on
behalf of a UAS server by the XACT server.
AccountName -- Name of the account to change the password for.
AccountType -- The type of account being accessed. This field must
be set to UasServerAccount to indicate a call from a downlevel
ComputerName -- Name of the BDC or member making the call.
Authenticator -- supplied by the server.
ReturnAuthenticator -- Receives an authenticator returned by the PDC.
UasNewPassword -- The new password for the server. This
Password is generated by automatic means using
random number genertaor seeded with the current Time
It is assumed that the machine generated password
was used as key to encrypt STD text and "sesskey"
obtained via Challenge/Authenticate sequence was
used to further encrypt it before passing to this api.
i.e. UasNewPassword = E2(E1(STD_TXT, PW), SK)
Return Value:
NT status code.
--*/
{
NTSTATUS Status = 0;
//
// 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 = NetrServerPasswordSet(
PrimaryName,
AccountName,
AccountType,
ComputerName,
Authenticator,
ReturnAuthenticator,
UasNewPassword );
} RpcExcept( EXCEPTION_EXECUTE_HANDLER ) {
Status = I_RpcMapWin32Status(RpcExceptionCode());
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("I_NetServerPasswordSet rc = %lu 0x%lx\n",
Status, Status));
}
return Status;
}
NTSTATUS
I_NetDatabaseDeltas (
IN LPWSTR PrimaryName,
IN LPWSTR ComputerName,
IN PNETLOGON_AUTHENTICATOR Authenticator,
OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
IN DWORD DatabaseID,
IN OUT PNLPR_MODIFIED_COUNT DomainModifiedCount,
OUT PNETLOGON_DELTA_ENUM_ARRAY *DeltaArray,
IN DWORD PreferredMaximumLength
)
/*++
Routine Description:
This function is used by a SAM BDC or SAM member server to request
SAM-style account delta information from a SAM PDC. This function
can only be called by a server which has previously authenticated
with the PDC by calling I_NetServerAuthenticate. This function uses
RPC to contact the Netlogon service on the PDC.
This function returns a list of deltas. A delta describes an
individual domain, user or group and all of the field values for that
object. The PDC maintains a list of deltas not including all of the
field values for that object. Rather, the PDC retrieves the field
values from SAM and returns those values from this call. The PDC
optimizes the data returned on this call by only returning the field
values for a particular object once on a single invocation of this
function. This optimizes the typical case where multiple deltas
exist for a single object (e.g., an application modified many fields
of the same user during a short period of time using different calls
to the SAM service).
Arguments:
PrimaryName -- Name of the PDC to retrieve the deltas from.
ComputerName -- Name of the BDC or member server making the call.
Authenticator -- supplied by the server.
ReturnAuthenticator -- Receives an authenticator returned by the PDC.
DomainModifiedCount -- Specifies the DomainModifiedCount of the
last delta retrieved by the server. Returns the
DomainModifiedCount of the last delta returned from the PDC
on this call.
DeltaArray -- Receives a pointer to a buffer where the information
is placed. The information returned is an array of
NETLOGON_DELTA_ENUM structures.
PreferredMaximumLength - Preferred maximum length of returned
data (in 8-bit bytes). This is not a hard upper limit, but
serves as a guide to the server. Due to data conversion
between systems with different natural data sizes, the actual
amount of data returned may be greater than this value.
Return Value:
STATUS_SUCCESS -- The function completed successfully.
STATUS_SYNCHRONIZATION_REQUIRED -- The replicant is totally out of sync and
should call I_NetDatabaseSync to do a full synchronization with
the PDC.
STATUS_MORE_ENTRIES -- The replicant should call again to get more
data.
STATUS_ACCESS_DENIED -- The replicant should re-authenticate with
the PDC.
--*/
{
NTSTATUS Status = 0;
//
// 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.
//
*DeltaArray = NULL; // Force RPC to allocate
Status = NetrDatabaseDeltas(
PrimaryName,
ComputerName,
Authenticator,
ReturnAuthenticator,
DatabaseID,
DomainModifiedCount,
DeltaArray,
PreferredMaximumLength );
} RpcExcept( EXCEPTION_EXECUTE_HANDLER ) {
Status = I_RpcMapWin32Status(RpcExceptionCode());
} RpcEndExcept;
NetpKdPrint(("I_NetDatabaseDeltas rc = %lu 0x%lx\n", Status, Status));
return Status;
}
NTSTATUS
I_NetDatabaseSync (
IN LPWSTR PrimaryName,
IN LPWSTR ComputerName,
IN PNETLOGON_AUTHENTICATOR Authenticator,
OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
IN DWORD DatabaseID,
IN OUT PULONG SamSyncContext,
OUT PNETLOGON_DELTA_ENUM_ARRAY *DeltaArray,
IN DWORD PreferredMaximumLength
)
/*++
Routine Description:
This function is used by a SAM BDC or SAM member server to request
the entire SAM database from a SAM PDC in SAM-style format. This
function can only be called by a server which has previously
authenticated with the PDC by calling I_NetServerAuthenticate. This
function uses RPC to contact the Netlogon service on the PDC.
This function uses the find-first find-next model to return portions
of the SAM database at a time. The SAM database is returned as a
list of deltas like those returned from I_NetDatabaseDeltas. The
following deltas are returned for each domain:
* One AddOrChangeDomain delta, followed by
* One AddOrChangeGroup delta for each group, followed by,
* One AddOrChangeUser delta for each user, followed by
* One ChangeGroupMembership delta for each group
Arguments:
PrimaryName -- Name of the PDC to retrieve the deltas from.
ComputerName -- Name of the BDC or member server making the call.
Authenticator -- supplied by the server.
ReturnAuthenticator -- Receives an authenticator returned by the PDC.
SamSyncContext -- Specifies context needed to continue the
operation. The caller should treat this as an opaque
value. The value should be zero before the first call.
DeltaArray -- Receives a pointer to a buffer where the information
is placed. The information returned is an array of
NETLOGON_DELTA_ENUM structures.
PreferredMaximumLength - Preferred maximum length of returned
data (in 8-bit bytes). This is not a hard upper limit, but
serves as a guide to the server. Due to data conversion
between systems with different natural data sizes, the actual
amount of data returned may be greater than this value.
Return Value:
STATUS_SUCCESS -- The function completed successfully.
STATUS_SYNCHRONIZATION_REQUIRED -- The replicant is totally out of sync and
should call I_NetDatabaseSync to do a full synchronization with
the PDC.
STATUS_MORE_ENTRIES -- The replicant should call again to get more
data.
STATUS_ACCESS_DENIED -- The replicant should re-authenticate with
the PDC.
--*/
{
NTSTATUS Status = 0;
//
// 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.
//
*DeltaArray = NULL; // Force RPC to allocate
Status = NetrDatabaseSync(
PrimaryName,
ComputerName,
Authenticator,
ReturnAuthenticator,
DatabaseID,
SamSyncContext,
DeltaArray,
PreferredMaximumLength );
} RpcExcept( EXCEPTION_EXECUTE_HANDLER ) {
Status = I_RpcMapWin32Status(RpcExceptionCode());
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("I_NetDatabaseSync rc = %lu 0x%lx\n", Status, Status));
}
return Status;
}
NTSTATUS
I_NetDatabaseSync2 (
IN LPWSTR PrimaryName,
IN LPWSTR ComputerName,
IN PNETLOGON_AUTHENTICATOR Authenticator,
OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
IN DWORD DatabaseID,
IN SYNC_STATE RestartState,
IN OUT PULONG SamSyncContext,
OUT PNETLOGON_DELTA_ENUM_ARRAY *DeltaArray,
IN DWORD PreferredMaximumLength
)
/*++
Routine Description:
This function is used by a SAM BDC or SAM member server to request
the entire SAM database from a SAM PDC in SAM-style format. This
function can only be called by a server which has previously
authenticated with the PDC by calling I_NetServerAuthenticate. This
function uses RPC to contact the Netlogon service on the PDC.
This function uses the find-first find-next model to return portions
of the SAM database at a time. The SAM database is returned as a
list of deltas like those returned from I_NetDatabaseDeltas. The
following deltas are returned for each domain:
* One AddOrChangeDomain delta, followed by
* One AddOrChangeGroup delta for each group, followed by,
* One AddOrChangeUser delta for each user, followed by
* One ChangeGroupMembership delta for each group
Arguments:
PrimaryName -- Name of the PDC to retrieve the deltas from.
ComputerName -- Name of the BDC or member server making the call.
Authenticator -- supplied by the server.
ReturnAuthenticator -- Receives an authenticator returned by the PDC.
RestartState -- Specifies whether this is a restart of the full sync and how
to interpret SyncContext. This value should be NormalState unless this
is the restart of a full sync.
However, if the caller is continuing a full sync after a reboot,
the following values are used:
GroupState - SyncContext is the global group rid to continue with.
UserState - SyncContext is the user rid to continue with
GroupMemberState - SyncContext is the global group rid to continue with
AliasState - SyncContext should be zero to restart at first alias
AliasMemberState - SyncContext should be zero to restart at first alias
One cannot continue the LSA database in this way.
SamSyncContext -- Specifies context needed to continue the
operation. The caller should treat this as an opaque
value. The value should be zero before the first call.
DeltaArray -- Receives a pointer to a buffer where the information
is placed. The information returned is an array of
NETLOGON_DELTA_ENUM structures.
PreferredMaximumLength - Preferred maximum length of returned
data (in 8-bit bytes). This is not a hard upper limit, but
serves as a guide to the server. Due to data conversion
between systems with different natural data sizes, the actual
amount of data returned may be greater than this value.
Return Value:
STATUS_SUCCESS -- The function completed successfully.
STATUS_SYNCHRONIZATION_REQUIRED -- The replicant is totally out of sync and
should call I_NetDatabaseSync to do a full synchronization with
the PDC.
STATUS_MORE_ENTRIES -- The replicant should call again to get more
data.
STATUS_ACCESS_DENIED -- The replicant should re-authenticate with
the PDC.
--*/
{
NTSTATUS Status = 0;
//
// 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.
//
*DeltaArray = NULL; // Force RPC to allocate
Status = NetrDatabaseSync2(
PrimaryName,
ComputerName,
Authenticator,
ReturnAuthenticator,
DatabaseID,
RestartState,
SamSyncContext,
DeltaArray,
PreferredMaximumLength );
} RpcExcept( EXCEPTION_EXECUTE_HANDLER ) {
Status = I_RpcMapWin32Status(RpcExceptionCode());
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("I_NetDatabaseSync rc = %lu 0x%lx\n", Status, Status));
}
return Status;
}
NET_API_STATUS NET_API_FUNCTION
I_NetAccountDeltas (
IN LPWSTR PrimaryName,
IN LPWSTR ComputerName,
IN PNETLOGON_AUTHENTICATOR Authenticator,
OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
IN PUAS_INFO_0 RecordId,
IN DWORD Count,
IN DWORD Level,
OUT LPBYTE Buffer,
IN DWORD BufferSize,
OUT PULONG CountReturned,
OUT PULONG TotalEntries,
OUT PUAS_INFO_0 NextRecordId
)
/*++
Routine Description:
This function is used by a UAS BDC or UAS member server to request
UAS-style account change information. This function can only be
called by a server which has previously authenticated with the PDC by
calling I_NetServerAuthenticate.
This function is only called by the XACT server upon receipt of a
I_NetAccountDeltas XACT SMB from a UAS BDC or a UAS member server.
As such, many of the parameters are opaque since the XACT server
doesn't need to interpret any of that data. This function uses RPC
to contact the Netlogon service.
The LanMan 3.0 SSI Functional Specification describes the operation
of this function.
Arguments:
PrimaryName -- Must be NULL to indicate this call is a local call
being made on behalf of a UAS server by the XACT server.
ComputerName -- Name of the BDC or member making the call.
Authenticator -- supplied by the server.
ReturnAuthenticator -- Receives an authenticator returned by the PDC.
RecordId -- Supplies an opaque buffer indicating the last record
received from a previous call to this function.
Count -- Supplies the number of Delta records requested.
Level -- Reserved. Must be zero.
Buffer -- Returns opaque data representing the information to be
returned.
BufferSize -- Size of buffer in bytes.
CountReturned -- Returns the number of records returned in buffer.
TotalEntries -- Returns the total number of records available.
NextRecordId -- Returns an opaque buffer identifying the last
record received by this function.
Return Value:
Status code
--*/
{
NET_API_STATUS NetStatus;
//
// 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 = NetrAccountDeltas (
PrimaryName,
ComputerName,
Authenticator,
ReturnAuthenticator,
RecordId,
Count,
Level,
Buffer,
BufferSize,
CountReturned,
TotalEntries,
NextRecordId );
} RpcExcept( EXCEPTION_EXECUTE_HANDLER ) {
NetStatus = RpcExceptionCode();
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("I_NetAccountDeltas rc = %lu 0x%lx\n",
NetStatus, NetStatus));
}
return NetStatus;
}
NET_API_STATUS NET_API_FUNCTION
I_NetAccountSync (
IN LPWSTR PrimaryName,
IN LPWSTR ComputerName,
IN PNETLOGON_AUTHENTICATOR Authenticator,
OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
IN DWORD Reference,
IN DWORD Level,
OUT LPBYTE Buffer,
IN DWORD BufferSize,
OUT PULONG CountReturned,
OUT PULONG TotalEntries,
OUT PULONG NextReference,
OUT PUAS_INFO_0 LastRecordId
)
/*++
Routine Description:
This function is used by a UAS BDC or UAS member server to request
the entire user accounts database. This function can only be called
by a server which has previously authenticated with the PDC by
calling I_NetServerAuthenticate.
This function is only called by the XACT server upon receipt of a
I_NetAccountSync XACT SMB from a UAS BDC or a UAS member server. As
such, many of the parameters are opaque since the XACT server doesn't
need to interpret any of that data. This function uses RPC to
contact the Netlogon service.
The LanMan 3.0 SSI Functional Specification describes the operation
of this function.
"Reference" and "NextReference" are treated as below.
1. "Reference" should hold either 0 or value of "NextReference"
from previous call to this API.
2. Send the modals and ALL group records in the first call. The API
expects the bufffer to be large enough to hold this info (worst
case size would be
MAXGROUP * (sizeof(struct group_info_1) + MAXCOMMENTSZ)
+ sizeof(struct user_modals_info_0)
which, for now, will be 256 * (26 + 49) + 16 = 19216 bytes
Arguments:
PrimaryName -- Must be NULL to indicate this call is a local call
being made on behalf of a UAS server by the XACT server.
ComputerName -- Name of the BDC or member making the call.
Authenticator -- supplied by the server.
ReturnAuthenticator -- Receives an authenticator returned by the PDC.
Reference -- Supplies find-first find-next handle returned by the
previous call to this function or 0 if it is the first call.
Level -- Reserved. Must be zero.
Buffer -- Returns opaque data representing the information to be
returned.
BufferLen -- Length of buffer in bytes.
CountReturned -- Returns the number of records returned in buffer.
TotalEntries -- Returns the total number of records available.
NextReference -- Returns a find-first find-next handle to be
provided on the next call.
LastRecordId -- Returns an opaque buffer identifying the last
record received by this function.
Return Value:
Status code.
--*/
{
NET_API_STATUS NetStatus;
//
// 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 = NetrAccountSync (
PrimaryName,
ComputerName,
Authenticator,
ReturnAuthenticator,
Reference,
Level,
Buffer,
BufferSize,
CountReturned,
TotalEntries,
NextReference,
LastRecordId );
} RpcExcept( EXCEPTION_EXECUTE_HANDLER ) {
NetStatus = RpcExceptionCode();
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("I_NetAccountSync rc = %lu 0x%lx\n",
NetStatus, NetStatus));
}
return NetStatus;
}
NET_API_STATUS NET_API_FUNCTION
I_NetLogonControl(
IN LPCWSTR ServerName OPTIONAL,
IN DWORD FunctionCode,
IN DWORD QueryLevel,
OUT LPBYTE *QueryInformation
)
/*++
Routine Description:
This function controls various aspects of the Netlogon service. It
can be used to request that a BDC ensure that its copy of the SAM
database is brought up to date. It can, also, be used to determine
if a BDC currently has a secure channel open to the PDC.
Only an Admin, Account Operator or Server Operator may call this
function.
Arguments:
ServerName - The name of the remote server.
FunctionCode - Defines the operation to be performed. The valid
values are:
FunctionCode Values
NETLOGON_CONTROL_QUERY - No operation. Merely returns the
information requested.
NETLOGON_CONTROL_REPLICATE: Forces the SAM database on a BDC
to be brought in sync with the copy on the PDC. This
operation does NOT imply a full synchronize. The
Netlogon service will merely replicate any outstanding
differences if possible.
NETLOGON_CONTROL_SYNCHRONIZE: Forces a BDC to get a
completely new copy of the SAM database from the PDC.
This operation will perform a full synchronize.
NETLOGON_CONTROL_PDC_REPLICATE: Forces a PDC to ask each BDC
to replicate now.
QueryLevel - Indicates what information should be returned from
the Netlogon Service. Must be 1.
QueryInformation - Returns a pointer to a buffer which contains the
requested information. The buffer must be freed using
NetApiBufferFree.
Return Value:
NERR_Success: the operation was successful
ERROR_NOT_SUPPORTED: Function code is not valid on the specified
server. (e.g. NETLOGON_CONTROL_REPLICATE was passed to a PDC).
--*/
{
NET_API_STATUS NetStatus;
NETLOGON_CONTROL_QUERY_INFORMATION RpcQueryInformation;
//
// 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.
//
RpcQueryInformation.NetlogonInfo1 = NULL; // Force RPC to allocate
NetStatus = NetrLogonControl (
(LPWSTR) ServerName OPTIONAL,
FunctionCode,
QueryLevel,
&RpcQueryInformation );
*QueryInformation = (LPBYTE) RpcQueryInformation.NetlogonInfo1;
} RpcExcept( EXCEPTION_EXECUTE_HANDLER ) {
NetStatus = RpcExceptionCode();
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("I_NetLogonControl rc = %lu 0x%lx\n",
NetStatus, NetStatus));
}
return NetStatus;
}
NET_API_STATUS NET_API_FUNCTION
I_NetLogonControl2(
IN LPCWSTR ServerName OPTIONAL,
IN DWORD FunctionCode,
IN DWORD QueryLevel,
IN LPBYTE InputData,
OUT LPBYTE *QueryInformation
)
/*++
Routine Description:
This is similar to the I_NetLogonControl function but it accepts
more generic input data according to the function code specified.
This function controls various aspects of the Netlogon service. It
can be used to request that a BDC ensure that its copy of the SAM
database is brought up to date. It can, also, be used to determine
if a BDC currently has a secure channel open to the PDC.
Only an Admin, Account Operator or Server Operator may call this
function.
Arguments:
ServerName - The name of the remote server.
FunctionCode - Defines the operation to be performed. The valid
values are:
FunctionCode Values
NETLOGON_CONTROL_QUERY - No operation. Merely returns the
information requested.
NETLOGON_CONTROL_REPLICATE: Forces the SAM database on a BDC
to be brought in sync with the copy on the PDC. This
operation does NOT imply a full synchronize. The
Netlogon service will merely replicate any outstanding
differences if possible.
NETLOGON_CONTROL_SYNCHRONIZE: Forces a BDC to get a
completely new copy of the SAM database from the PDC.
This operation will perform a full synchronize.
NETLOGON_CONTROL_PDC_REPLICATE: Forces a PDC to ask each BDC
to replicate now.
NETLOGON_CONTROL_REDISCOVER: Forces a DC to rediscover the
specified trusted domain DC.
NETLOGON_CONTROL_TC_QUERY: Query the status of the specified
trusted domain secure channel.
QueryLevel - Indicates what information should be returned from
the Netlogon Service. Must be 1.
InputData - According to the function code specified this parameter
will carry input data. NETLOGON_CONTROL_REDISCOVER and
NETLOGON_CONTROL_TC_QUERY function code specify the trusted
domain name (LPWSTR type) here.
QueryInformation - Returns a pointer to a buffer which contains the
requested information. The buffer must be freed using
NetApiBufferFree.
Return Value:
NERR_Success: the operation was successful
ERROR_NOT_SUPPORTED: Function code is not valid on the specified
server. (e.g. NETLOGON_CONTROL_REPLICATE was passed to a PDC).
--*/
{
NET_API_STATUS NetStatus;
NETLOGON_CONTROL_QUERY_INFORMATION RpcQueryInformation;
//
// 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.
//
// Use new Control2Ex if either QueryLevel or FunctionCode is new
//
RpcQueryInformation.NetlogonInfo1 = NULL; // Force RPC to allocate
switch ( FunctionCode ) {
case NETLOGON_CONTROL_QUERY:
case NETLOGON_CONTROL_REPLICATE:
case NETLOGON_CONTROL_SYNCHRONIZE:
case NETLOGON_CONTROL_PDC_REPLICATE:
case NETLOGON_CONTROL_REDISCOVER:
case NETLOGON_CONTROL_TC_QUERY:
case NETLOGON_CONTROL_TRANSPORT_NOTIFY:
case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
case NETLOGON_CONTROL_TRUNCATE_LOG:
case NETLOGON_CONTROL_SET_DBFLAG:
case NETLOGON_CONTROL_BREAKPOINT:
if ( QueryLevel >= 1 && QueryLevel <= 3 ) {
NetStatus = NetrLogonControl2 (
(LPWSTR) ServerName OPTIONAL,
FunctionCode,
QueryLevel,
(PNETLOGON_CONTROL_DATA_INFORMATION)InputData,
&RpcQueryInformation );
} else if ( QueryLevel == 4 ) {
NetStatus = NetrLogonControl2Ex (
(LPWSTR) ServerName OPTIONAL,
FunctionCode,
QueryLevel,
(PNETLOGON_CONTROL_DATA_INFORMATION)InputData,
&RpcQueryInformation );
} else {
NetStatus = ERROR_INVALID_LEVEL;
}
break;
case NETLOGON_CONTROL_FIND_USER:
case NETLOGON_CONTROL_UNLOAD_NETLOGON_DLL:
if ( QueryLevel >= 1 && QueryLevel <= 4 ) {
NetStatus = NetrLogonControl2Ex (
(LPWSTR) ServerName OPTIONAL,
FunctionCode,
QueryLevel,
(PNETLOGON_CONTROL_DATA_INFORMATION)InputData,
&RpcQueryInformation );
} else {
NetStatus = ERROR_INVALID_LEVEL;
}
break;
default:
NetStatus = ERROR_INVALID_LEVEL;
}
*QueryInformation = (LPBYTE) RpcQueryInformation.NetlogonInfo1;
} RpcExcept( EXCEPTION_EXECUTE_HANDLER ) {
NetStatus = RpcExceptionCode();
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("I_NetLogonControl rc = %lu 0x%lx\n",
NetStatus, NetStatus));
}
return NetStatus;
}
NTSTATUS
I_NetDatabaseRedo(
IN LPWSTR PrimaryName,
IN LPWSTR ComputerName,
IN PNETLOGON_AUTHENTICATOR Authenticator,
OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
IN LPBYTE ChangeLogEntry,
IN DWORD ChangeLogEntrySize,
OUT PNETLOGON_DELTA_ENUM_ARRAY *DeltaArray
)
/*++
Routine Description:
This function is used by a SAM BDC to request infomation about a single
account. This function can only be called by a server which has previously
authenticated with the PDC by calling I_NetServerAuthenticate. This
function uses RPC to contact the Netlogon service on the PDC.
Arguments:
PrimaryName -- Name of the PDC to retrieve the delta from.
ComputerName -- Name of the BDC making the call.
Authenticator -- supplied by the server.
ReturnAuthenticator -- Receives an authenticator returned by the PDC.
ChangeLogEntry -- A description of the account to be queried.
ChangeLogEntrySize -- Size (in bytes) of the ChangeLogEntry.
DeltaArray -- Receives a pointer to a buffer where the information
is placed. The information returned is an array of
NETLOGON_DELTA_ENUM structures.
Return Value:
STATUS_SUCCESS -- The function completed successfully.
STATUS_ACCESS_DENIED -- The replicant should re-authenticate with
the PDC.
--*/
{
NTSTATUS Status = 0;
//
// 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.
//
*DeltaArray = NULL; // Force RPC to allocate
Status = NetrDatabaseRedo(
PrimaryName,
ComputerName,
Authenticator,
ReturnAuthenticator,
ChangeLogEntry,
ChangeLogEntrySize,
DeltaArray );
} RpcExcept( EXCEPTION_EXECUTE_HANDLER ) {
Status = I_RpcMapWin32Status(RpcExceptionCode());
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("I_NetDatabaseSync rc = %lu 0x%lx\n", Status, Status));
}
return Status;
}
NTSTATUS
NetEnumerateTrustedDomains (
IN LPWSTR ServerName OPTIONAL,
OUT LPWSTR *DomainNames
)
/*++
Routine Description:
This API returns the names of the domains trusted by the domain ServerName is a member of.
ServerName must be an NT workstation or NT non-DC server.
The returned list does not include the domain ServerName is directly a member of.
Netlogon implements this API by calling LsaEnumerateTrustedDomains on a DC in the
domain ServerName is a member of. However, Netlogon returns cached information if
it has been less than 5 minutes since the last call was made or if no DC is available.
Netlogon's cache of Trusted domain names is maintained in the registry across reboots.
As such, the list is available upon boot even if no DC is available.
Arguments:
ServerName - name of remote server (null for local). ServerName must be an NT workstation
or NT non-DC server.
DomainNames - Returns an allocated buffer containing the list of trusted domains in
MULTI-SZ format (i.e., each string is terminated by a zero character, the next string
immediately follows, the sequence is terminated by zero length domain name). The
buffer should be freed using NetApiBufferFree.
Return Value:
ERROR_SUCCESS - Success.
STATUS_NOT_SUPPORTED - ServerName is not an NT workstation or NT non-DC server.
STATUS_NO_LOGON_SERVERS - No DC could be found and no cached information is available.
STATUS_NO_TRUST_LSA_SECRET - The client side of the trust relationship is
broken and no cached information is available.
STATUS_NO_TRUST_SAM_ACCOUNT - The server side of the trust relationship is
broken or the password is broken and no cached information is available.
--*/
{
NTSTATUS Status = 0;
DOMAIN_NAME_BUFFER DomainNameBuffer;
//
// 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.
//
DomainNameBuffer.DomainNameByteCount = 0;
DomainNameBuffer.DomainNames = NULL; // Force RPC to allocate
Status = NetrEnumerateTrustedDomains(
ServerName,
&DomainNameBuffer );
if ( NT_SUCCESS(Status) ) {
*DomainNames = (LPWSTR) DomainNameBuffer.DomainNames;
}
} RpcExcept( EXCEPTION_EXECUTE_HANDLER ) {
Status = I_RpcMapWin32Status(RpcExceptionCode());
} RpcEndExcept;
IF_DEBUG( LOGON ) {
NetpKdPrint(("NetEnumerateDomainNames rc = %lu 0x%lx\n", Status, Status));
}
return Status;
}