/*++

Copyright (c) 1991-1992  Microsoft Corporation

Module Name:

    wslsa.c

Abstract:

    This module contains the interfaces to the Local Security Authority
    MS V 1.0 authentication package.

Author:

    Rita Wong (ritaw) 15-May-1991

Revision History:

--*/


#include "wsutil.h"
#include "wslsa.h"
#include "winreg.h"

//-------------------------------------------------------------------//
//                                                                   //
// Global variables                                                  //
//                                                                   //
//-------------------------------------------------------------------//

STATIC HANDLE LsaHandle = NULL;
STATIC ULONG AuthPackageId = 0;

#define FULL_LSA_CONTROL_REGISTRY_PATH L"SYSTEM\\CurrentControlSet\\Control\\Lsa"
#define LSA_RESTRICT_ANONYMOUS_VALUE_NAME L"RestrictAnonymous"

DWORD WsLsaRestrictAnonymous = 0;


NET_API_STATUS
WsInitializeLsa(
    VOID
    )
/*++

Routine Description:

    This function registers the Workstation service as a logon process and
    gets a handle to the MS V1.0 authentication package.

Arguments:

    None.

Return Value:

    NET_API_STATUS - NERR_Success or reason for failing.

--*/
{

    NTSTATUS ntstatus;

    STRING InputString;
    LSA_OPERATIONAL_MODE SecurityMode = 0;

    //
    // Register the Workstation service as a logon process
    //
    RtlInitString(&InputString, "LAN Manager Workstation Service");

    ntstatus = LsaRegisterLogonProcess(
                   &InputString,
                   &LsaHandle,
                   &SecurityMode
                   );

    IF_DEBUG(INFO) {
        NetpKdPrint(("[Wksta] LsaRegisterLogonProcess returns x%08lx, "
                     "SecurityMode=x%08lx\n", ntstatus, SecurityMode));
    }

    if (! NT_SUCCESS(ntstatus)) {
        return WsMapStatus(ntstatus);
    }


    //
    // Look up the MS V1.0 authentication package
    //
    RtlInitString(&InputString,
                  "MICROSOFT_AUTHENTICATION_PACKAGE_V1_0");

    ntstatus = LsaLookupAuthenticationPackage(
                   LsaHandle,
                   &InputString,
                   &AuthPackageId
                   );


    if (! NT_SUCCESS(ntstatus)) {

        IF_DEBUG(INFO) {
            NetpKdPrint(("[Wksta] LsaLookupAuthenticationPackage returns x%08lx, "
                         "AuthPackageId=%lu\n", ntstatus, AuthPackageId));
        }

    }

    WsLsaRestrictAnonymous = 0;

    if (NT_SUCCESS(ntstatus)) {
        HKEY  handle;
        DWORD error;

        error = RegOpenKeyEx(
                    HKEY_LOCAL_MACHINE,
                    FULL_LSA_CONTROL_REGISTRY_PATH,
                    0,
                    KEY_READ,
                    &handle
                    );

        if( error == ERROR_SUCCESS ) {
            DWORD type;
            DWORD size = sizeof( WsLsaRestrictAnonymous );

            error = RegQueryValueEx(
                        handle,
                        LSA_RESTRICT_ANONYMOUS_VALUE_NAME,
                        NULL,
                        &type,
                        (LPBYTE)&WsLsaRestrictAnonymous,
                        &size);

            if ((error != ERROR_SUCCESS) ||
                (type != REG_DWORD) ||
                (size != sizeof(DWORD))) {
                WsLsaRestrictAnonymous = 0;
            }

            RegCloseKey(handle);
        }
    }

    return WsMapStatus(ntstatus);
}


VOID
WsShutdownLsa(
    VOID
    )
/*++

Routine Description:

    This function deregisters the Workstation service as a logon process.

Arguments:

    None.

Return Value:

    None.

--*/
{
    (void) LsaDeregisterLogonProcess(
               LsaHandle
               );
}


NET_API_STATUS
WsLsaEnumUsers(
    OUT LPBYTE *EnumUsersResponse
    )
/*++

Routine Description:

    This function asks the MS V1.0 Authentication Package to list all users
    who are physically logged on to the local computer.

Arguments:

    EnumUsersResponse - Returns a pointer to a list of user logon ids.  This
        memory is allocated by the authentication package and must be freed
        with LsaFreeReturnBuffer when done with it.

Return Value:

    NET_API_STATUS - NERR_Success or reason for failure.

--*/
{
    NTSTATUS ntstatus;
    NTSTATUS AuthPackageStatus;

    MSV1_0_ENUMUSERS_REQUEST EnumUsersRequest;
    ULONG EnumUsersResponseLength;


    //
    // Ask authentication package to enumerate users who are physically
    // logged to the local machine.
    //
    EnumUsersRequest.MessageType = MsV1_0EnumerateUsers;

    ntstatus = LsaCallAuthenticationPackage(
                   LsaHandle,
                   AuthPackageId,
                   &EnumUsersRequest,
                   sizeof(MSV1_0_ENUMUSERS_REQUEST),
                   (PVOID *)EnumUsersResponse,
                   &EnumUsersResponseLength,
                   &AuthPackageStatus
                   );

    if (ntstatus == STATUS_SUCCESS) {
        ntstatus = AuthPackageStatus;
    }

    if (ntstatus != STATUS_SUCCESS) {
        return WsMapStatus(ntstatus);
    }

    return(NERR_Success);
}


NET_API_STATUS
WsLsaGetUserInfo(
    IN  PLUID LogonId,
    OUT LPBYTE *UserInfoResponse,
    OUT LPDWORD UserInfoResponseLength
    )
/*++

Routine Description:

    This function asks the MS V1.0 Authentication Package for information on
    a specific user.

Arguments:

    LogonId - Supplies the logon id of the user we want information about.

    UserInfoResponse - Returns a pointer to a structure of information about
        the user.  This memory is allocated by the authentication package
        and must be freed with LsaFreeReturnBuffer when done with it.

    UserInfoResponseLength - Returns the length of the returned information
        in number of bytes.

Return Value:

    NET_API_STATUS - NERR_Success or reason for failure.

--*/
{
    NTSTATUS ntstatus;
    NTSTATUS AuthPackageStatus;

    MSV1_0_GETUSERINFO_REQUEST UserInfoRequest;


    //
    // Ask authentication package for user information.
    //
    UserInfoRequest.MessageType = MsV1_0GetUserInfo;
    RtlCopyLuid(&UserInfoRequest.LogonId, LogonId);

    ntstatus = LsaCallAuthenticationPackage(
                   LsaHandle,
                   AuthPackageId,
                   &UserInfoRequest,
                   sizeof(MSV1_0_GETUSERINFO_REQUEST),
                   (PVOID *)UserInfoResponse,
                   UserInfoResponseLength,
                   &AuthPackageStatus
                   );

    if (ntstatus == STATUS_SUCCESS) {
        ntstatus = AuthPackageStatus;
    }

    if (ntstatus != STATUS_SUCCESS) {
        return WsMapStatus(ntstatus);
    }

    return(NERR_Success);
}


NET_API_STATUS
WsLsaRelogonUsers(
    IN LPTSTR LogonServer
    )
/*++

Routine Description:

    This function asks the MS V1.0 Authentication Package to relogon users
    that are logged on by the specified logon server.  This is because the
    server had been reset and need to restore the database of users logged
    on by it before it went down.

Arguments:

    LogonServer - Name of logon server which requests that all its previously
        logged on users be relogged on.

Return Value:

    NET_API_STATUS - NERR_Success or reason for failure.

--*/
{
    NTSTATUS ntstatus;
    NTSTATUS AuthPackageStatus;

    OEM_STRING AnsiLogonServerName;

    PMSV1_0_RELOGON_REQUEST RelogonUsersRequest;
    ULONG RelogonUsersRequestLength = sizeof(MSV1_0_RELOGON_REQUEST) +
                                 (STRLEN(LogonServer) + 1) * sizeof(WCHAR);

    //
    // NTRAID-70701-2/6/2000 davey Since we cannot yet use optional parameters in call to
    // LsaCallAuthentication package, provide these variables for now.
    //
    PVOID RelogonUsersResponse;
    ULONG ResponseLength;


    //
    // Allocate the relogon request package dynamically because the logon
    // server name length is dynamic
    //
    if ((RelogonUsersRequest = (PMSV1_0_RELOGON_REQUEST)
                               LocalAlloc(
                                   LMEM_ZEROINIT,
                                   (UINT) RelogonUsersRequestLength
                                   )) == NULL) {
        return GetLastError();
    }

    RelogonUsersRequest->LogonServer.Buffer = (LPWSTR)
                                              ((DWORD_PTR) RelogonUsersRequest) +
                                                sizeof(MSV1_0_RELOGON_REQUEST);

    RtlInitUnicodeString(&RelogonUsersRequest->LogonServer, LogonServer);

    //
    // Ask authentication package to relogon users for the specified
    // logon server.
    //
    RelogonUsersRequest->MessageType = MsV1_0ReLogonUsers;

    ntstatus = LsaCallAuthenticationPackage(
                   LsaHandle,
                   AuthPackageId,
                   &RelogonUsersRequest,
                   RelogonUsersRequestLength,
                   &RelogonUsersResponse,  // should be NULL if OPTIONAL
                   &ResponseLength,        // should be NULL if OPTIONAL
                   &AuthPackageStatus
                   );

    //
    // Free memory allocated for request package
    //
    (void) LocalFree(RelogonUsersRequest);

    if (ntstatus == STATUS_SUCCESS) {
        ntstatus = AuthPackageStatus;
    }

    if (ntstatus != STATUS_SUCCESS) {
        return WsMapStatus(ntstatus);
    }

    return(NERR_Success);
}