/*++

Copyright (c) 1989-1997  Microsoft Corporation

Module Name:

    userkey.c

Abstract:

    Implentation of the functions that get and generate user session keys

        RtlCalculateUserSessionKeyLm
        RtlCalculateUserSessionKeyNt

Author:

    David Chalmers (Davidc) 10-21-91

Revision History:

    Adam Barr (AdamBa) 12-15-97
        Modified from private\security\lsa\crypt\dll

--*/

#include <rdrssp.h>


//
// Define this if you want to know all about user session keys
//

// #define DEBUG_USER_SESSION_KEYS

//
// Define the user session key that represents an error.
// This value will be generated by other parts of the system on failure.
// We will check for it in our query code and return an error if it's found.
//

USER_SESSION_KEY ErrorSessionKey = { 0, 0, 0, 0, 0, 0, 0, 0,
                                     0, 0, 0, 0, 0, 0, 0, 0
                                   };



NTSTATUS
RtlCalculateUserSessionKeyLm(
    IN PLM_RESPONSE LmResponse,
    IN PLM_OWF_PASSWORD LmOwfPassword,
    OUT PUSER_SESSION_KEY UserSessionKey)

/*++

Routine Description:

    Takes the passed Response and OwfPassword and generates a UserSessionKey.

    The current implementation takes the one-way-function of the OwfPassword
    and returns this as the key.

Arguments:

    LmResponse - The response sent during session setup.

    LmOwfPassword - The hashed version of the user's password.

Return Values:

    STATUS_SUCCESS - The function was completed successfully.
                     The UserSessionKey is in UserSessionKey.

    STATUS_UNSUCCESSFUL - Something failed. The UserSessionKey is undefined.
--*/

{
    NTSTATUS Status;
    NT_PASSWORD NtPassword;

    //
    // Make the Owf password look like an NT password
    //

    NtPassword.Buffer = (PWSTR)LmOwfPassword; // We can do this cast because we
                                              // know the OWF routine treats this
                                              // pointer as a byte pointer.
    NtPassword.Length = sizeof(*LmOwfPassword);
    NtPassword.MaximumLength = sizeof(*LmOwfPassword);


    //
    // Calculate the OWF of the OwfPassword
    //

    ASSERT(sizeof(NT_OWF_PASSWORD) == sizeof(*UserSessionKey));

    Status = RtlCalculateNtOwfPassword( &NtPassword,
                                        (PNT_OWF_PASSWORD)UserSessionKey
                                        );
    if (!NT_SUCCESS(Status)) {
        KdPrint(("RtlCalculateUserSessionKeyLm : OWF calculation failed, status = 0x%lx\n", Status));
        return(Status);
    }

    //
    // Check if we've generated the error session key
    //

    if (RtlCompareMemory(UserSessionKey, &ErrorSessionKey,
                       sizeof(*UserSessionKey)) == sizeof(*UserSessionKey)) {

#ifdef DEBUG_USER_SESSION_KEYS
        KdPrint(("RtlCalculateSessionKeyLm - generated error session key, modifying it\n"));
#endif
        //
        // Move away from the error session key
        //

        UserSessionKey->data[0].data[0] ++;

        ASSERT(RtlCompareMemory(UserSessionKey, &ErrorSessionKey,
                       sizeof(*UserSessionKey)) != sizeof(*UserSessionKey));
    }

#ifdef DEBUG_USER_SESSION_KEYS
    KdPrint(("RtlCalculateUserSessionKeyLm : Key = 0x%lx : %lx : %lx : %lx\n",
            ((PULONG)UserSessionKey)[0], ((PULONG)UserSessionKey)[1],
            ((PULONG)UserSessionKey)[2], ((PULONG)UserSessionKey)[3]));
#endif

    return(STATUS_SUCCESS);

    UNREFERENCED_PARAMETER(LmResponse);
}



NTSTATUS
RtlCalculateUserSessionKeyNt(
    IN PNT_RESPONSE NtResponse,
    IN PNT_OWF_PASSWORD NtOwfPassword,
    OUT PUSER_SESSION_KEY UserSessionKey)

/*++

Routine Description:

    Takes the passed Response and OwfPassword and generates a UserSessionKey.

Arguments:

    NtResponse - The response sent during session setup.

    NtOwfPassword - The hashed version of the user's password.

Return Values:

    STATUS_SUCCESS - The function was completed successfully.
                     The UserSessionKey is in UserSessionKey.

    STATUS_UNSUCCESSFUL - Something failed. The UserSessionKey is undefined.
--*/

{
    // Just call the LM version

    ASSERT(sizeof(NT_RESPONSE) == sizeof(LM_RESPONSE));
    ASSERT(sizeof(NT_OWF_PASSWORD) == sizeof(LM_OWF_PASSWORD));

    return(RtlCalculateUserSessionKeyLm((PLM_RESPONSE)NtResponse,
                                        (PLM_OWF_PASSWORD)NtOwfPassword,
                                        UserSessionKey));
}



