1111 lines
28 KiB
C
1111 lines
28 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
ApiLogon.c
|
||
|
||
Abstract:
|
||
|
||
This module contains individual API handlers for the NetLogon APIs.
|
||
|
||
SUPPORTED : NetGetDCName, NetLogonEnum, NetServerAuthenticate,
|
||
NetServerPasswordSet, NetServerReqChallenge,
|
||
NetWkstaUserLogoff, NetWkstaUserLogon.
|
||
|
||
SEE ALSO : NetAccountDeltas, NetAccountSync - in ApiAcct.c.
|
||
|
||
Author:
|
||
|
||
Shanku Niyogi (w-shanku) 04-Apr-1991
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
//
|
||
// Logon APIs are Unicode only.
|
||
//
|
||
|
||
#ifndef UNICODE
|
||
#define UNICODE
|
||
#endif
|
||
|
||
#include "xactsrvp.h"
|
||
#include <netlibnt.h>
|
||
|
||
#include <crypt.h> // must be included before <logonmsv.h>
|
||
#include <ntsam.h> // must be included before <logonmsv.h>
|
||
#include <logonmsv.h> // must be included before <ssi.h>
|
||
#include <ssi.h> // I_NetAccountDeltas and I_NetAccountSync prototypes
|
||
|
||
//
|
||
// Declaration of descriptor strings.
|
||
//
|
||
|
||
STATIC const LPDESC Desc16_user_logon_info_0 = REM16_user_logon_info_0;
|
||
STATIC const LPDESC Desc32_user_logon_info_0 = REM32_user_logon_info_0;
|
||
STATIC const LPDESC Desc16_user_logon_info_1 = REM16_user_logon_info_1;
|
||
STATIC const LPDESC Desc32_user_logon_info_1 = REM32_user_logon_info_1;
|
||
STATIC const LPDESC Desc16_user_logon_info_2 = REM16_user_logon_info_2;
|
||
STATIC const LPDESC Desc32_user_logon_info_2 = REM32_user_logon_info_2;
|
||
STATIC const LPDESC Desc16_user_logoff_info_1 = REM16_user_logoff_info_1;
|
||
STATIC const LPDESC Desc32_user_logoff_info_1 = REM32_user_logoff_info_1;
|
||
|
||
|
||
NTSTATUS
|
||
XsNetGetDCName (
|
||
API_HANDLER_PARAMETERS
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles a call to NetGetDCName.
|
||
|
||
Arguments:
|
||
|
||
API_HANDLER_PARAMETERS - Information about the API call. See
|
||
XsTypes.h for details.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - STATUS_SUCCESS or reason for failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
NET_API_STATUS status;
|
||
|
||
PXS_NET_GET_DC_NAME parameters = Parameters;
|
||
LPTSTR nativeDomain = NULL; // Native parameters
|
||
LPTSTR dcName = NULL;
|
||
|
||
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
||
|
||
try {
|
||
//
|
||
// Translate parameters, check for errors.
|
||
//
|
||
|
||
XsConvertTextParameter(
|
||
nativeDomain,
|
||
(LPSTR)XsSmbGetPointer( ¶meters->Domain )
|
||
);
|
||
|
||
//
|
||
// Make the local call.
|
||
//
|
||
|
||
status = NetGetDCName(
|
||
NULL,
|
||
nativeDomain,
|
||
(LPBYTE *)&dcName
|
||
);
|
||
|
||
if ( !XsApiSuccess( status )) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetGetDCName: NetGetDCName failed: %X\n",
|
||
status ));
|
||
}
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Put string into buffer. Convert from Unicode if necessary.
|
||
//
|
||
|
||
if ( (DWORD)SmbGetUshort( ¶meters->BufLen ) <= NetpUnicodeToDBCSLen( dcName )) {
|
||
|
||
status = NERR_BufTooSmall;
|
||
|
||
} else {
|
||
|
||
NetpCopyWStrToStrDBCS( (LPSTR)XsSmbGetPointer( ¶meters->Buffer ), dcName );
|
||
|
||
}
|
||
|
||
|
||
IF_DEBUG(LOGON) {
|
||
NetpKdPrint(( "Name is %ws\n", dcName ));
|
||
}
|
||
|
||
cleanup:
|
||
;
|
||
} except ( EXCEPTION_EXECUTE_HANDLER ) {
|
||
status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
||
}
|
||
|
||
|
||
//
|
||
// Set return data count.
|
||
//
|
||
|
||
if ( status == NERR_Success ) {
|
||
SmbPutUshort( ¶meters->BufLen, (USHORT)( STRLEN( dcName ) + 1 ));
|
||
} else {
|
||
SmbPutUshort( ¶meters->BufLen, 0 );
|
||
}
|
||
|
||
|
||
Header->Status = (WORD)status;
|
||
NetpMemoryFree( nativeDomain );
|
||
NetApiBufferFree( dcName );
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // XsNetGetDCName
|
||
|
||
|
||
NTSTATUS
|
||
XsNetLogonEnum (
|
||
API_HANDLER_PARAMETERS
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles a call to NetLogonEnum.
|
||
|
||
Arguments:
|
||
|
||
API_HANDLER_PARAMETERS - Information about the API call. See
|
||
XsTypes.h for details.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - STATUS_SUCCESS or reason for failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
NET_API_STATUS status;
|
||
|
||
PXS_NET_LOGON_ENUM parameters = Parameters;
|
||
LPVOID outBuffer= NULL;
|
||
DWORD entriesRead = 0;
|
||
DWORD totalEntries = 0;
|
||
|
||
DWORD entriesFilled = 0;
|
||
DWORD bytesRequired = 0;
|
||
LPDESC nativeStructureDesc;
|
||
|
||
API_HANDLER_PARAMETERS_REFERENCE;
|
||
|
||
IF_DEBUG(LOGON) {
|
||
NetpKdPrint(( "XsNetLogonEnum: header at %lx, params at %lx, "
|
||
"level %ld, buf size %ld\n",
|
||
Header, parameters, SmbGetUshort( ¶meters->Level ),
|
||
SmbGetUshort( ¶meters->BufLen )));
|
||
}
|
||
|
||
try {
|
||
//
|
||
// Check for errors.
|
||
//
|
||
|
||
if (( SmbGetUshort( ¶meters->Level ) != 0 )
|
||
&& ( SmbGetUshort( ¶meters->Level ) != 2 )) {
|
||
|
||
Header->Status = ERROR_INVALID_LEVEL;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Make the local call.
|
||
//
|
||
|
||
#ifdef LOGON_ENUM_SUPPORTED
|
||
status = NetLogonEnum(
|
||
NULL,
|
||
(DWORD)SmbGetUshort( ¶meters->Level ),
|
||
(LPBYTE *)&outBuffer,
|
||
XsNativeBufferSize( SmbGetUshort( ¶meters->BufLen )),
|
||
&entriesRead,
|
||
&totalEntries,
|
||
NULL
|
||
);
|
||
#else // LOGON_ENUM_SUPPORTED
|
||
status = NERR_InvalidAPI;
|
||
#endif // LOGON_ENUM_SUPPORTED
|
||
|
||
if ( !XsApiSuccess( status )) {
|
||
IF_DEBUG(API_ERRORS) {
|
||
NetpKdPrint(( "XsNetLogonEnum: NetLogonEnum failed: "
|
||
"%X\n", status ));
|
||
}
|
||
Header->Status = (WORD)status;
|
||
goto cleanup;
|
||
}
|
||
|
||
IF_DEBUG(LOGON) {
|
||
NetpKdPrint(( "XsNetLogonEnum: received %ld entries at %lx\n",
|
||
entriesRead, outBuffer ));
|
||
}
|
||
|
||
//
|
||
// Use the requested level to determine the format of the
|
||
// data structure.
|
||
//
|
||
|
||
switch ( SmbGetUshort( ¶meters->Level ) ) {
|
||
|
||
case 0:
|
||
|
||
nativeStructureDesc = Desc32_user_logon_info_0;
|
||
StructureDesc = Desc16_user_logon_info_0;
|
||
break;
|
||
|
||
case 2:
|
||
|
||
nativeStructureDesc = Desc32_user_logon_info_2;
|
||
StructureDesc = Desc16_user_logon_info_2;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Do the actual conversion from the 32-bit structures to 16-bit
|
||
// structures.
|
||
//
|
||
|
||
XsFillEnumBuffer(
|
||
outBuffer,
|
||
entriesRead,
|
||
nativeStructureDesc,
|
||
(LPVOID)XsSmbGetPointer( ¶meters->Buffer ),
|
||
(LPVOID)XsSmbGetPointer( ¶meters->Buffer ),
|
||
SmbGetUshort( ¶meters->BufLen ),
|
||
StructureDesc,
|
||
NULL, // verify function
|
||
&bytesRequired,
|
||
&entriesFilled,
|
||
NULL
|
||
);
|
||
|
||
IF_DEBUG(LOGON) {
|
||
NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR,"
|
||
" Entries %ld of %ld\n",
|
||
outBuffer, SmbGetUlong( ¶meters->Buffer ),
|
||
bytesRequired, entriesFilled, totalEntries ));
|
||
}
|
||
|
||
//
|
||
// If all the entries could not be filled, return ERROR_MORE_DATA,
|
||
// and return the buffer as is. Otherwise, the data needs to be
|
||
// packed so that we don't send too much useless data.
|
||
//
|
||
|
||
if ( entriesFilled < totalEntries ) {
|
||
|
||
Header->Status = ERROR_MORE_DATA;
|
||
|
||
} else {
|
||
|
||
Header->Converter = XsPackReturnData(
|
||
(LPVOID)XsSmbGetPointer( ¶meters->Buffer ),
|
||
SmbGetUshort( ¶meters->BufLen ),
|
||
StructureDesc,
|
||
entriesFilled
|
||
);
|
||
|
||
}
|
||
|
||
//
|
||
// Set up the response parameters.
|
||
//
|
||
|
||
SmbPutUshort( ¶meters->EntriesRead, (WORD)entriesFilled );
|
||
SmbPutUshort( ¶meters->TotalAvail, (WORD)totalEntries );
|
||
|
||
cleanup:
|
||
;
|
||
} except ( EXCEPTION_EXECUTE_HANDLER ) {
|
||
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
||
}
|
||
|
||
NetApiBufferFree( outBuffer );
|
||
|
||
//
|
||
// Determine return buffer size.
|
||
//
|
||
|
||
XsSetDataCount(
|
||
¶meters->BufLen,
|
||
StructureDesc,
|
||
Header->Converter,
|
||
entriesFilled,
|
||
Header->Status
|
||
);
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // XsNetLogonEnum
|
||
|
||
|
||
NTSTATUS
|
||
XsNetServerAuthenticate (
|
||
API_HANDLER_PARAMETERS
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles a call to NetServerAuthenticate.
|
||
|
||
Arguments:
|
||
|
||
API_HANDLER_PARAMETERS - Information about the API call. See
|
||
XsTypes.h for details.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - STATUS_SUCCESS or reason for failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
PXS_NET_SERVER_AUTHENTICATE parameters = Parameters;
|
||
NET_API_STATUS status; // Native parameters
|
||
LPTSTR nativeRequestor = NULL;
|
||
NETLOGON_CREDENTIAL inCredential = {0};
|
||
NETLOGON_CREDENTIAL outCredential = {0};
|
||
WCHAR AccountName[MAX_PATH+1];
|
||
|
||
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
||
|
||
try {
|
||
//
|
||
// Translate parameters, check for errors.
|
||
//
|
||
|
||
XsConvertTextParameter(
|
||
nativeRequestor,
|
||
(LPSTR)XsSmbGetPointer( ¶meters->Requestor )
|
||
);
|
||
|
||
//
|
||
// Copy the source credential, and zero out the destination
|
||
// credential.
|
||
//
|
||
|
||
RtlCopyMemory(
|
||
&inCredential,
|
||
(PVOID)XsSmbGetPointer( ¶meters->Caller ),
|
||
sizeof(NETLOGON_CREDENTIAL)
|
||
);
|
||
|
||
RtlZeroMemory(
|
||
&outCredential,
|
||
sizeof(NETLOGON_CREDENTIAL)
|
||
);
|
||
|
||
//
|
||
// Build the account name.
|
||
//
|
||
|
||
NetpNCopyTStrToWStr( AccountName, nativeRequestor, MAX_PATH );
|
||
|
||
//
|
||
// Make the local call.
|
||
//
|
||
|
||
status = NetpNtStatusToApiStatus(
|
||
I_NetServerAuthenticate(
|
||
NULL,
|
||
AccountName,
|
||
UasServerSecureChannel,
|
||
nativeRequestor,
|
||
&inCredential,
|
||
&outCredential
|
||
));
|
||
|
||
if ( !XsApiSuccess( status )) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetServerAuthenticate: I_NetServerAuthenticate "
|
||
"failed: %X\n", status ));
|
||
}
|
||
Header->Status = (WORD)status;
|
||
goto cleanup;
|
||
}
|
||
|
||
cleanup:
|
||
|
||
//
|
||
// Set the return credential.
|
||
//
|
||
|
||
RtlCopyMemory(
|
||
parameters->Primary,
|
||
&outCredential,
|
||
sizeof(NETLOGON_CREDENTIAL)
|
||
);
|
||
|
||
} except ( EXCEPTION_EXECUTE_HANDLER ) {
|
||
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
||
}
|
||
|
||
NetpMemoryFree( nativeRequestor );
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // XsNetServerAuthenticate
|
||
|
||
|
||
NTSTATUS
|
||
XsNetServerPasswordSet (
|
||
API_HANDLER_PARAMETERS
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles a call to NetGetDCName.
|
||
|
||
Arguments:
|
||
|
||
API_HANDLER_PARAMETERS - Information about the API call. See
|
||
XsTypes.h for details.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - STATUS_SUCCESS or reason for failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
PXS_NET_SERVER_PASSWORD_SET parameters = Parameters;
|
||
NET_API_STATUS status; // Native parameters
|
||
LPTSTR nativeRequestor = NULL;
|
||
NETLOGON_AUTHENTICATOR authIn = {0};
|
||
NETLOGON_AUTHENTICATOR authOut = {0};
|
||
ENCRYPTED_LM_OWF_PASSWORD password;
|
||
WCHAR AccountName[MAX_PATH+1];
|
||
|
||
LPBYTE structure = NULL; // Conversion variables
|
||
|
||
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
||
|
||
try {
|
||
//
|
||
// Translate parameters, check for errors.
|
||
//
|
||
|
||
XsConvertTextParameter(
|
||
nativeRequestor,
|
||
(LPSTR)XsSmbGetPointer( ¶meters->Requestor )
|
||
);
|
||
|
||
//
|
||
// Copy the source authenticator and password, and zero out the
|
||
// destination authenticator.
|
||
//
|
||
|
||
structure = (LPBYTE)XsSmbGetPointer( ¶meters->Authenticator );
|
||
RtlCopyMemory(
|
||
&authIn.Credential,
|
||
structure,
|
||
sizeof(NETLOGON_CREDENTIAL)
|
||
);
|
||
structure += sizeof(NETLOGON_CREDENTIAL);
|
||
authIn.timestamp = SmbGetUlong( structure );
|
||
|
||
RtlCopyMemory(
|
||
&password,
|
||
parameters->Password,
|
||
sizeof(ENCRYPTED_LM_OWF_PASSWORD)
|
||
);
|
||
|
||
RtlZeroMemory(
|
||
&authOut,
|
||
sizeof(NETLOGON_CREDENTIAL)
|
||
);
|
||
|
||
|
||
//
|
||
// Build the account name.
|
||
//
|
||
if( STRLEN( nativeRequestor ) >= MAX_PATH )
|
||
{
|
||
Header->Status = NERR_PasswordTooShort;
|
||
goto cleanup;
|
||
}
|
||
|
||
// Make sure its NULL terminated
|
||
AccountName[MAX_PATH] = L'\0';
|
||
NetpNCopyTStrToWStr( AccountName, nativeRequestor, MAX_PATH );
|
||
|
||
//
|
||
// Make the local call.
|
||
//
|
||
|
||
status = NetpNtStatusToApiStatus(
|
||
I_NetServerPasswordSet(
|
||
NULL,
|
||
AccountName,
|
||
UasServerSecureChannel,
|
||
nativeRequestor,
|
||
&authIn,
|
||
&authOut,
|
||
&password
|
||
));
|
||
|
||
if ( !XsApiSuccess( status )) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetServerPasswordSet: "
|
||
"I_NetServerPasswordSet failed: %X\n",
|
||
status ));
|
||
}
|
||
|
||
//
|
||
// !!! When protocol level is available in the header information,
|
||
// we can check it. Right now, we ignore this code.
|
||
//
|
||
// For clients older than LanMan 2.1, return a different error code.
|
||
// LANMAN 2.1 Protocol Level is 6.
|
||
//
|
||
|
||
#if 0
|
||
if ( status == NERR_TimeDiffAtDC && Header->ProtocolLevel < 6 ) {
|
||
status = NERR_SyncRequired;
|
||
}
|
||
#endif
|
||
|
||
Header->Status = (WORD)status;
|
||
goto cleanup;
|
||
}
|
||
|
||
cleanup:
|
||
|
||
//
|
||
// Fill in 16 bit return structures.
|
||
//
|
||
|
||
structure = parameters->RetAuth;
|
||
RtlCopyMemory(
|
||
structure,
|
||
&authOut.Credential,
|
||
sizeof(NETLOGON_CREDENTIAL)
|
||
);
|
||
structure += sizeof(NETLOGON_CREDENTIAL);
|
||
SmbPutUlong( (LPDWORD)structure, authOut.timestamp );
|
||
|
||
} except ( EXCEPTION_EXECUTE_HANDLER ) {
|
||
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
||
}
|
||
|
||
NetpMemoryFree( nativeRequestor );
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // XsNetServerPasswordSet
|
||
|
||
|
||
NTSTATUS
|
||
XsNetServerReqChallenge (
|
||
API_HANDLER_PARAMETERS
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles a call to NetGetDCName.
|
||
|
||
Arguments:
|
||
|
||
API_HANDLER_PARAMETERS - Information about the API call. See
|
||
XsTypes.h for details.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - STATUS_SUCCESS or reason for failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
PXS_NET_SERVER_REQ_CHALLENGE parameters = Parameters;
|
||
NET_API_STATUS status; // Native parameters
|
||
LPTSTR nativeRequestor = NULL;
|
||
NETLOGON_CREDENTIAL inChallenge = {0};
|
||
NETLOGON_CREDENTIAL outChallenge = {0};
|
||
|
||
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
||
|
||
try {
|
||
//
|
||
// Translate parameters, check for errors.
|
||
//
|
||
|
||
XsConvertTextParameter(
|
||
nativeRequestor,
|
||
(LPSTR)XsSmbGetPointer( ¶meters->Requestor )
|
||
);
|
||
|
||
//
|
||
// Copy the source challenge, and zero out the destination
|
||
// challenge.
|
||
//
|
||
|
||
RtlCopyMemory(
|
||
&inChallenge,
|
||
(PVOID)XsSmbGetPointer( ¶meters->Caller ),
|
||
sizeof(NETLOGON_CREDENTIAL)
|
||
);
|
||
|
||
RtlZeroMemory(
|
||
&outChallenge,
|
||
sizeof(NETLOGON_CREDENTIAL)
|
||
);
|
||
|
||
|
||
//
|
||
// Make the local call.
|
||
//
|
||
|
||
status = NetpNtStatusToApiStatus(
|
||
I_NetServerReqChallenge(
|
||
NULL,
|
||
nativeRequestor,
|
||
&inChallenge,
|
||
&outChallenge
|
||
));
|
||
|
||
if ( !XsApiSuccess( status )) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetServerReqChallenge: "
|
||
"I_NetServerReqChallenge failed: %X\n",
|
||
status ));
|
||
}
|
||
Header->Status = (WORD)status;
|
||
goto cleanup;
|
||
}
|
||
|
||
cleanup:
|
||
|
||
//
|
||
// Set the return credential.
|
||
//
|
||
|
||
RtlCopyMemory(
|
||
parameters->Primary,
|
||
&outChallenge,
|
||
sizeof(NETLOGON_CREDENTIAL)
|
||
);
|
||
} except ( EXCEPTION_EXECUTE_HANDLER ) {
|
||
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
||
}
|
||
|
||
NetpMemoryFree( nativeRequestor );
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // XsNetServerReqChallenge
|
||
|
||
|
||
NTSTATUS
|
||
XsNetWkstaUserLogoff (
|
||
API_HANDLER_PARAMETERS
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This temporary routine just returns STATUS_NOT_IMPLEMENTED.
|
||
|
||
Arguments:
|
||
|
||
API_HANDLER_PARAMETERS - information about the API call. See
|
||
XsTypes.h for details.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - STATUS_SUCCESS or reason for failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
NET_API_STATUS status;
|
||
|
||
PXS_NET_WKSTA_USER_LOGOFF parameters = Parameters;
|
||
LPWSTR machineName = NULL; // Native parameters
|
||
LPWSTR userName = NULL;
|
||
NETLOGON_LOGOFF_UAS_INFORMATION buffer;
|
||
|
||
LPBYTE stringLocation = NULL; // Conversion variables
|
||
DWORD bytesRequired = 0;
|
||
PWKSTA_16_USER_LOGOFF_REQUEST_1 usrLogoffReq =
|
||
(PWKSTA_16_USER_LOGOFF_REQUEST_1)parameters->InBuf;
|
||
PUSER_16_LOGOFF_INFO_1 logoffInfo;
|
||
|
||
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
||
|
||
try {
|
||
//
|
||
// Translate parameters, check for errors.
|
||
//
|
||
|
||
XsConvertUnicodeTextParameter(
|
||
userName,
|
||
(LPSTR)( usrLogoffReq->wlreq1_name )
|
||
);
|
||
|
||
XsConvertUnicodeTextParameter(
|
||
machineName,
|
||
(LPSTR)( usrLogoffReq->wlreq1_workstation )
|
||
);
|
||
|
||
if ( SmbGetUshort( ¶meters->Level ) != 1 ) {
|
||
|
||
Header->Status = ERROR_INVALID_LEVEL;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Make sure the workstation name in the logon request is the
|
||
// name of the workstation from which the request came.
|
||
//
|
||
|
||
if ( wcscmp( machineName, Header->ClientMachineName ) ) {
|
||
|
||
Header->Status = (WORD)ERROR_ACCESS_DENIED;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Make the local call.
|
||
//
|
||
|
||
status = I_NetLogonUasLogoff(
|
||
userName,
|
||
machineName,
|
||
&buffer
|
||
);
|
||
|
||
if ( !XsApiSuccess(status)) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetWkstaUserLogoff: I_NetLogonUasLogoff "
|
||
"failed: %X\n", status ));
|
||
}
|
||
Header->Status = (WORD)status;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Convert the structure returned by the 32-bit call to a 16-bit
|
||
// structure. The last possible location for variable data is
|
||
// calculated from buffer location and length.
|
||
//
|
||
|
||
stringLocation = (LPBYTE)( XsSmbGetPointer( ¶meters->OutBuf )
|
||
+ SmbGetUshort( ¶meters->OutBufLen ) );
|
||
|
||
status = RapConvertSingleEntry(
|
||
(LPBYTE)&buffer,
|
||
Desc32_user_logoff_info_1,
|
||
FALSE,
|
||
(LPBYTE)XsSmbGetPointer( ¶meters->OutBuf ),
|
||
(LPBYTE)XsSmbGetPointer( ¶meters->OutBuf ),
|
||
Desc16_user_logoff_info_1,
|
||
TRUE,
|
||
&stringLocation,
|
||
&bytesRequired,
|
||
Response,
|
||
NativeToRap
|
||
);
|
||
|
||
if ( status != NERR_Success ) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetWkstaUserLogoff: RapConvertSingleEntry "
|
||
"failed: %X\n", status ));
|
||
}
|
||
|
||
Header->Status = NERR_InternalError;
|
||
goto cleanup;
|
||
}
|
||
|
||
IF_DEBUG(LOGON) {
|
||
NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR\n",
|
||
&buffer, SmbGetUlong( ¶meters->OutBuf ),
|
||
bytesRequired ));
|
||
}
|
||
|
||
//
|
||
// Determine return code based on the size of the buffer.
|
||
// The user_logoff_info_1 structure has no variable data to pack,
|
||
// but we do need to fill in the code field of the return structure.
|
||
//
|
||
|
||
if ( !XsCheckBufferSize(
|
||
SmbGetUshort( ¶meters->OutBufLen ),
|
||
Desc16_user_logoff_info_1,
|
||
FALSE // not in native format
|
||
)) {
|
||
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetWkstaUserLogoff: Buffer too small.\n" ));
|
||
}
|
||
Header->Status = NERR_BufTooSmall;
|
||
|
||
} else if ( bytesRequired > (DWORD)SmbGetUshort( ¶meters->OutBufLen )) {
|
||
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetWkstaUserLogoff: More data available.\n" ));
|
||
}
|
||
Header->Status = ERROR_MORE_DATA;
|
||
}
|
||
|
||
if ( SmbGetUshort( ¶meters->OutBufLen ) > sizeof(WORD)) {
|
||
|
||
logoffInfo = (PUSER_16_LOGOFF_INFO_1)XsSmbGetPointer(
|
||
¶meters->OutBuf );
|
||
SmbPutUshort( &logoffInfo->usrlogf1_code, VALID_LOGOFF );
|
||
}
|
||
|
||
//
|
||
// Set up the response parameters.
|
||
//
|
||
|
||
SmbPutUshort( ¶meters->TotalAvail, (WORD)bytesRequired );
|
||
|
||
cleanup:
|
||
;
|
||
} except ( EXCEPTION_EXECUTE_HANDLER ) {
|
||
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
||
}
|
||
|
||
|
||
NetpMemoryFree( userName );
|
||
NetpMemoryFree( machineName );
|
||
|
||
//
|
||
// Determine return buffer size.
|
||
//
|
||
|
||
XsSetDataCount(
|
||
¶meters->OutBufLen,
|
||
Desc16_user_logoff_info_1,
|
||
Header->Converter,
|
||
1,
|
||
Header->Status
|
||
);
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // XsNetWkstaUserLogoff
|
||
|
||
|
||
NTSTATUS
|
||
XsNetWkstaUserLogon (
|
||
API_HANDLER_PARAMETERS
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles a call to NetWkstaUserLogon.
|
||
|
||
Arguments:
|
||
|
||
API_HANDLER_PARAMETERS - information about the API call. See
|
||
XsTypes.h for details.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - STATUS_SUCCESS or reason for failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
NET_API_STATUS status;
|
||
PXS_NET_WKSTA_USER_LOGON parameters = Parameters;
|
||
LPWSTR machineName = NULL; // Native parameters
|
||
LPWSTR userName = NULL;
|
||
PNETLOGON_VALIDATION_UAS_INFO buffer = NULL;
|
||
|
||
LPBYTE stringLocation = NULL; // Conversion variables
|
||
DWORD bytesRequired = 0;
|
||
PWKSTA_16_USER_LOGON_REQUEST_1 usrLogonReq =
|
||
(PWKSTA_16_USER_LOGON_REQUEST_1)parameters->InBuf;
|
||
PUSER_16_LOGON_INFO_1 logonInfo;
|
||
|
||
|
||
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
||
|
||
try {
|
||
//
|
||
// Translate parameters, check for errors.
|
||
//
|
||
|
||
XsConvertUnicodeTextParameter(
|
||
userName,
|
||
(LPSTR)( usrLogonReq->wlreq1_name )
|
||
);
|
||
|
||
XsConvertUnicodeTextParameter(
|
||
machineName,
|
||
(LPSTR)( usrLogonReq->wlreq1_workstation )
|
||
);
|
||
|
||
if ( SmbGetUshort( ¶meters->Level ) != 1 ) {
|
||
|
||
Header->Status = ERROR_INVALID_LEVEL;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Make sure the workstation name in the logon request is the
|
||
// name of the workstation from which the request came.
|
||
//
|
||
|
||
if ( wcscmp( machineName, Header->ClientMachineName ) ) {
|
||
|
||
Header->Status = (WORD)ERROR_ACCESS_DENIED;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Make the local call.
|
||
//
|
||
|
||
status = I_NetLogonUasLogon(
|
||
userName,
|
||
machineName,
|
||
&buffer
|
||
);
|
||
|
||
if ( !XsApiSuccess ( status )) {
|
||
|
||
IF_DEBUG(API_ERRORS) {
|
||
NetpKdPrint(( "XsNetWkstaUserLogon: I_NetLogonUasLogon failed: "
|
||
"%X\n", status));
|
||
}
|
||
Header->Status = (WORD) status;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Convert the structure returned by the 32-bit call to a 16-bit
|
||
// structure. The last possible location for variable data is
|
||
// calculated from buffer location and length.
|
||
//
|
||
|
||
stringLocation = (LPBYTE)( XsSmbGetPointer( ¶meters->OutBuf )
|
||
+ SmbGetUshort( ¶meters->OutBufLen ) );
|
||
|
||
status = RapConvertSingleEntry(
|
||
(LPBYTE)buffer,
|
||
Desc32_user_logon_info_1,
|
||
FALSE,
|
||
(LPBYTE)XsSmbGetPointer( ¶meters->OutBuf ),
|
||
(LPBYTE)XsSmbGetPointer( ¶meters->OutBuf ),
|
||
Desc16_user_logon_info_1,
|
||
TRUE,
|
||
&stringLocation,
|
||
&bytesRequired,
|
||
Response,
|
||
NativeToRap
|
||
);
|
||
|
||
if ( status != NERR_Success ) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetWkstaUserLogon: RapConvertSingleEntry "
|
||
"failed: %X\n", status ));
|
||
}
|
||
|
||
Header->Status = NERR_InternalError;
|
||
goto cleanup;
|
||
}
|
||
|
||
IF_DEBUG(LOGON) {
|
||
NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR\n",
|
||
buffer, SmbGetUlong( ¶meters->OutBuf ),
|
||
bytesRequired ));
|
||
}
|
||
|
||
//
|
||
// Determine return code based on the size of the buffer.
|
||
// The user_logoff_info_1 structure has no variable data to pack,
|
||
// but we do need to fill in the code field of the return structure.
|
||
//
|
||
|
||
if ( !XsCheckBufferSize(
|
||
SmbGetUshort( ¶meters->OutBufLen ),
|
||
Desc16_user_logon_info_1,
|
||
FALSE // not in native format
|
||
)) {
|
||
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetWkstaUserLogon: Buffer too small.\n" ));
|
||
}
|
||
Header->Status = NERR_BufTooSmall;
|
||
|
||
} else if ( bytesRequired > (DWORD)SmbGetUshort( ¶meters->OutBufLen )) {
|
||
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetWkstaUserLogoff: More data available.\n" ));
|
||
}
|
||
Header->Status = ERROR_MORE_DATA;
|
||
|
||
} else {
|
||
|
||
//
|
||
// Pack the response data.
|
||
//
|
||
|
||
Header->Converter = XsPackReturnData(
|
||
(LPVOID)XsSmbGetPointer( ¶meters->OutBuf ),
|
||
SmbGetUshort( ¶meters->OutBufLen ),
|
||
Desc16_user_logon_info_1,
|
||
1
|
||
);
|
||
}
|
||
|
||
if ( SmbGetUshort( ¶meters->OutBufLen ) > sizeof(WORD)) {
|
||
|
||
logonInfo = (PUSER_16_LOGON_INFO_1)XsSmbGetPointer(
|
||
¶meters->OutBuf );
|
||
SmbPutUshort( &logonInfo->usrlog1_code, VALIDATED_LOGON );
|
||
}
|
||
|
||
//
|
||
// Set up the response parameters.
|
||
//
|
||
|
||
SmbPutUshort( ¶meters->TotalAvail, (WORD)bytesRequired );
|
||
|
||
cleanup:
|
||
;
|
||
} except ( EXCEPTION_EXECUTE_HANDLER ) {
|
||
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
||
}
|
||
|
||
|
||
NetpMemoryFree( userName );
|
||
NetpMemoryFree( machineName );
|
||
if ( buffer != NULL ) {
|
||
NetApiBufferFree( buffer );
|
||
}
|
||
|
||
//
|
||
// Determine return buffer size.
|
||
//
|
||
|
||
XsSetDataCount(
|
||
¶meters->OutBufLen,
|
||
Desc16_user_logon_info_1,
|
||
Header->Converter,
|
||
1,
|
||
Header->Status
|
||
);
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // XsNetWkstaUserLogon
|