Example #1
0
static
NTSTATUS
MsvpChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest,
                   IN PVOID ProtocolSubmitBuffer,
                   IN PVOID ClientBufferBase,
                   IN ULONG SubmitBufferLength,
                   OUT PVOID *ProtocolReturnBuffer,
                   OUT PULONG ReturnBufferLength,
                   OUT PNTSTATUS ProtocolStatus)
{
    PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer;
    ULONG_PTR PtrOffset;

    SAMPR_HANDLE ServerHandle = NULL;
    SAMPR_HANDLE DomainHandle = NULL;
    SAMPR_HANDLE UserHandle = NULL;
    PRPC_SID DomainSid = NULL;
    RPC_UNICODE_STRING Names[1];
    SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
    SAMPR_ULONG_ARRAY Use = {0, NULL};
    NTSTATUS Status;

    ENCRYPTED_NT_OWF_PASSWORD OldNtPassword;
    ENCRYPTED_NT_OWF_PASSWORD NewNtPassword;
    ENCRYPTED_LM_OWF_PASSWORD OldLmPassword;
    ENCRYPTED_LM_OWF_PASSWORD NewLmPassword;
    OEM_STRING LmPwdString;
    CHAR LmPwdBuffer[15];
    BOOLEAN OldLmPasswordPresent = FALSE;
    BOOLEAN NewLmPasswordPresent = FALSE;

    ENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm;
    ENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm;
    ENCRYPTED_LM_OWF_PASSWORD OldNtEncryptedWithNewNt;
    ENCRYPTED_LM_OWF_PASSWORD NewNtEncryptedWithOldNt;
    PENCRYPTED_LM_OWF_PASSWORD pOldLmEncryptedWithNewLm = NULL;
    PENCRYPTED_LM_OWF_PASSWORD pNewLmEncryptedWithOldLm = NULL;

    TRACE("()\n");

    RequestBuffer = (PMSV1_0_CHANGEPASSWORD_REQUEST)ProtocolSubmitBuffer;

    /* Fix-up pointers in the request buffer info */
    PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;

    RequestBuffer->DomainName.Buffer = FIXUP_POINTER(RequestBuffer->DomainName.Buffer, PtrOffset);
    RequestBuffer->AccountName.Buffer = FIXUP_POINTER(RequestBuffer->AccountName.Buffer, PtrOffset);
    RequestBuffer->OldPassword.Buffer = FIXUP_POINTER(RequestBuffer->OldPassword.Buffer, PtrOffset);
    RequestBuffer->NewPassword.Buffer = FIXUP_POINTER(RequestBuffer->NewPassword.Buffer, PtrOffset);

    TRACE("Domain: %S\n", RequestBuffer->DomainName.Buffer);
    TRACE("Account: %S\n", RequestBuffer->AccountName.Buffer);
    TRACE("Old Password: %S\n", RequestBuffer->OldPassword.Buffer);
    TRACE("New Password: %S\n", RequestBuffer->NewPassword.Buffer);

    /* Connect to the SAM server */
    Status = SamIConnect(NULL,
                         &ServerHandle,
                         SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
                         TRUE);
    if (!NT_SUCCESS(Status))
    {
        TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
        goto done;
    }

    /* Get the domain SID */
    Status = SamrLookupDomainInSamServer(ServerHandle,
                                         (PRPC_UNICODE_STRING)&RequestBuffer->DomainName,
                                         &DomainSid);
    if (!NT_SUCCESS(Status))
    {
        TRACE("SamrLookupDomainInSamServer failed (Status %08lx)\n", Status);
        goto done;
    }

    /* Open the domain */
    Status = SamrOpenDomain(ServerHandle,
                            DOMAIN_LOOKUP,
                            DomainSid,
                            &DomainHandle);
    if (!NT_SUCCESS(Status))
    {
        TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
        goto done;
    }

    Names[0].Length = RequestBuffer->AccountName.Length;
    Names[0].MaximumLength = RequestBuffer->AccountName.MaximumLength;
    Names[0].Buffer = RequestBuffer->AccountName.Buffer;

    /* Try to get the RID for the user name */
    Status = SamrLookupNamesInDomain(DomainHandle,
                                     1,
                                     Names,
                                     &RelativeIds,
                                     &Use);
    if (!NT_SUCCESS(Status))
    {
        TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
        Status = STATUS_NO_SUCH_USER;
        goto done;
    }

    /* Fail, if it is not a user account */
    if (Use.Element[0] != SidTypeUser)
    {
        TRACE("Account is not a user account!\n");
        Status = STATUS_NO_SUCH_USER;
        goto done;
    }

    /* Open the user object */
    Status = SamrOpenUser(DomainHandle,
                          USER_CHANGE_PASSWORD,
                          RelativeIds.Element[0],
                          &UserHandle);
    if (!NT_SUCCESS(Status))
    {
        TRACE("SamrOpenUser failed (Status %08lx)\n", Status);
        goto done;
    }


    /* Calculate the NT hash for the old password */
    Status = SystemFunction007(&RequestBuffer->OldPassword,
                               (LPBYTE)&OldNtPassword);
    if (!NT_SUCCESS(Status))
    {
        TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
        goto done;
    }

    /* Calculate the NT hash for the new password */
    Status = SystemFunction007(&RequestBuffer->NewPassword,
                               (LPBYTE)&NewNtPassword);
    if (!NT_SUCCESS(Status))
    {
        TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
        goto done;
    }

    /* Calculate the LM password and hash for the old password */
    LmPwdString.Length = 15;
    LmPwdString.MaximumLength = 15;
    LmPwdString.Buffer = LmPwdBuffer;
    ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);

    Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
                                               &RequestBuffer->OldPassword,
                                               FALSE);
    if (NT_SUCCESS(Status))
    {
        /* Calculate the LM hash value of the password */
        Status = SystemFunction006(LmPwdString.Buffer,
                                   (LPSTR)&OldLmPassword);
        if (NT_SUCCESS(Status))
        {
            OldLmPasswordPresent = TRUE;
        }
    }

    /* Calculate the LM password and hash for the new password */
    LmPwdString.Length = 15;
    LmPwdString.MaximumLength = 15;
    LmPwdString.Buffer = LmPwdBuffer;
    ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);

    Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
                                               &RequestBuffer->NewPassword,
                                               FALSE);
    if (NT_SUCCESS(Status))
    {
        /* Calculate the LM hash value of the password */
        Status = SystemFunction006(LmPwdString.Buffer,
                                   (LPSTR)&NewLmPassword);
        if (NT_SUCCESS(Status))
        {
            NewLmPasswordPresent = TRUE;
        }
    }

    /* Encrypt the old and new LM passwords, if they exist */
    if (OldLmPasswordPresent && NewLmPasswordPresent)
    {
        /* Encrypt the old LM password */
        Status = SystemFunction012((const BYTE *)&OldLmPassword,
                                   (const BYTE *)&NewLmPassword,
                                   (LPBYTE)&OldLmEncryptedWithNewLm);
        if (!NT_SUCCESS(Status))
        {
            TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
            goto done;
        }

        /* Encrypt the new LM password */
        Status = SystemFunction012((const BYTE *)&NewLmPassword,
                                   (const BYTE *)&OldLmPassword,
                                   (LPBYTE)&NewLmEncryptedWithOldLm);
        if (!NT_SUCCESS(Status))
        {
            TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
            goto done;
        }

        pOldLmEncryptedWithNewLm = &OldLmEncryptedWithNewLm;
        pNewLmEncryptedWithOldLm = &NewLmEncryptedWithOldLm;
    }

    /* Encrypt the old NT password */
    Status = SystemFunction012((const BYTE *)&OldNtPassword,
                               (const BYTE *)&NewNtPassword,
                               (LPBYTE)&OldNtEncryptedWithNewNt);
    if (!NT_SUCCESS(Status))
    {
        TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
        goto done;
    }

    /* Encrypt the new NT password */
    Status = SystemFunction012((const BYTE *)&NewNtPassword,
                               (const BYTE *)&OldNtPassword,
                               (LPBYTE)&NewNtEncryptedWithOldNt);
    if (!NT_SUCCESS(Status))
    {
        TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
        goto done;
    }

    /* Change the password */
    Status = SamrChangePasswordUser(UserHandle,
                                    OldLmPasswordPresent && NewLmPasswordPresent,
                                    pOldLmEncryptedWithNewLm,
                                    pNewLmEncryptedWithOldLm,
                                    TRUE,
                                    &OldNtEncryptedWithNewNt,
                                    &NewNtEncryptedWithOldNt,
                                    FALSE,
                                    NULL,
                                    FALSE,
                                    NULL);
    if (!NT_SUCCESS(Status))
    {
        TRACE("SamrChangePasswordUser failed (Status %08lx)\n", Status);
        goto done;
    }

done:
    if (UserHandle != NULL)
        SamrCloseHandle(&UserHandle);

    SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
    SamIFree_SAMPR_ULONG_ARRAY(&Use);

    if (DomainHandle != NULL)
        SamrCloseHandle(&DomainHandle);

    if (DomainSid != NULL)
        SamIFreeVoid(DomainSid);

    if (ServerHandle != NULL)
        SamrCloseHandle(&ServerHandle);

    return Status;
}
Example #2
0
BOOL
NlIsServersGroupEmpty(
    ULONG ServersGroupRid
    )
/*++

Routine Description:

    This procedure determines whether the Servers group is empty or not.

Arguments:

    Rid : Rid of the SERVERS group. If it is zero then determine the RID
            by lookup.

Return Value:

    FALSE : If the servers group exist and it is non-empty.
    TRUE : otherwise

--*/
{
    NTSTATUS Status;

    SAMPR_ULONG_ARRAY RelativeIdArray = {0, NULL};
    SAMPR_ULONG_ARRAY UseArray = {0, NULL};
    RPC_UNICODE_STRING GroupNameString;
    SAMPR_HANDLE GroupHandle = NULL;
    BOOL ReturnValue = TRUE;

    PSAMPR_GET_MEMBERS_BUFFER MembersBuffer = NULL;

    if ( ServersGroupRid == 0 ) {

        //
        // Convert the group name to a RelativeId.
        //

        RtlInitUnicodeString( (PUNICODE_STRING)&GroupNameString,
                                SSI_SERVER_GROUP_W );

        Status = SamrLookupNamesInDomain(
                    NlGlobalChWorkerSamDBHandle,
                    1,
                    &GroupNameString,
                    &RelativeIdArray,
                    &UseArray );

        if ( !NT_SUCCESS(Status) ) {

            RelativeIdArray.Element = NULL;
            UseArray.Element = NULL;
            goto Cleanup;
        }

        //
        // we should get back exactly one entry of info back.
        //

        NlAssert( UseArray.Count == 1 );
        NlAssert( UseArray.Element != NULL );
        NlAssert( RelativeIdArray.Count == 1 );
        NlAssert( RelativeIdArray.Element != NULL );

        if ( UseArray.Element[0] != SidTypeGroup ) {
            goto Cleanup;
        }

        ServersGroupRid = RelativeIdArray.Element[0];
    }

    //
    // Open the SERVERS group
    //

    Status = SamrOpenGroup( NlGlobalChWorkerSamDBHandle,
                            0, // No desired access
                            ServersGroupRid,
                            &GroupHandle );

    if ( !NT_SUCCESS(Status) ) {
        GroupHandle = NULL;
        goto Cleanup;
    }

    //
    // enumerate members in the group.
    //

    Status = SamrGetMembersInGroup( GroupHandle, &MembersBuffer );

    if (!NT_SUCCESS(Status)) {
        MembersBuffer = NULL;
        goto Cleanup;
    }

    if ( MembersBuffer->MemberCount != 0 ) {

        //
        // atleast a member in there.
        //

        ReturnValue = FALSE;

        //
        // Save the list of LmBdcs

        NlLmBdcListSet( MembersBuffer->MemberCount,
                        MembersBuffer->Members );
    }

Cleanup:

    SamIFree_SAMPR_ULONG_ARRAY( &RelativeIdArray );
    SamIFree_SAMPR_ULONG_ARRAY( &UseArray );

    if ( MembersBuffer != NULL ) {
        SamIFree_SAMPR_GET_MEMBERS_BUFFER( MembersBuffer );
    }

    if( GroupHandle != NULL ) {
        (VOID) SamrCloseHandle( &GroupHandle );
    }

    return ReturnValue;
}
Example #3
0
/*
 * @unimplemented
 */
NTSTATUS
NTAPI
LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
               IN SECURITY_LOGON_TYPE LogonType,
               IN PVOID AuthenticationInformation,
               IN PVOID ClientAuthenticationBase,
               IN ULONG AuthenticationInformationLength,
               OUT PVOID *ProfileBuffer,
               OUT PULONG ProfileBufferLength,
               OUT PLUID LogonId,
               OUT PNTSTATUS SubStatus,
               OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
               OUT PVOID *TokenInformation,
               OUT PLSA_UNICODE_STRING *AccountName,
               OUT PLSA_UNICODE_STRING *AuthenticatingAuthority)
{
    PMSV1_0_INTERACTIVE_LOGON LogonInfo;

    SAMPR_HANDLE ServerHandle = NULL;
    SAMPR_HANDLE DomainHandle = NULL;
    SAMPR_HANDLE UserHandle = NULL;
    PRPC_SID AccountDomainSid = NULL;
    RPC_UNICODE_STRING Names[1];
    SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
    SAMPR_ULONG_ARRAY Use = {0, NULL};
    PSAMPR_USER_INFO_BUFFER UserInfo = NULL;
    UNICODE_STRING LogonServer;
    BOOLEAN SessionCreated = FALSE;
    LARGE_INTEGER LogonTime;
//    LARGE_INTEGER AccountExpires;
    LARGE_INTEGER PasswordMustChange;
    LARGE_INTEGER PasswordLastSet;
    BOOL SpecialAccount = FALSE;
    NTSTATUS Status;

    TRACE("LsaApLogonUser()\n");

    TRACE("LogonType: %lu\n", LogonType);
    TRACE("AuthenticationInformation: %p\n", AuthenticationInformation);
    TRACE("AuthenticationInformationLength: %lu\n", AuthenticationInformationLength);

    *ProfileBuffer = NULL;
    *ProfileBufferLength = 0;
    *SubStatus = STATUS_SUCCESS;

    if (LogonType == Interactive ||
        LogonType == Batch ||
        LogonType == Service)
    {
        ULONG_PTR PtrOffset;

        LogonInfo = (PMSV1_0_INTERACTIVE_LOGON)AuthenticationInformation;

        /* Fix-up pointers in the authentication info */
        PtrOffset = (ULONG_PTR)AuthenticationInformation - (ULONG_PTR)ClientAuthenticationBase;

        LogonInfo->LogonDomainName.Buffer = FIXUP_POINTER(LogonInfo->LogonDomainName.Buffer, PtrOffset);
        LogonInfo->UserName.Buffer = FIXUP_POINTER(LogonInfo->UserName.Buffer, PtrOffset);
        LogonInfo->Password.Buffer = FIXUP_POINTER(LogonInfo->Password.Buffer, PtrOffset);

        TRACE("Domain: %S\n", LogonInfo->LogonDomainName.Buffer);
        TRACE("User: %S\n", LogonInfo->UserName.Buffer);
        TRACE("Password: %S\n", LogonInfo->Password.Buffer);

        RtlInitUnicodeString(&LogonServer, L"Testserver");
    }
    else
    {
        FIXME("LogonType %lu is not supported yet!\n", LogonType);
        return STATUS_NOT_IMPLEMENTED;
    }

    /* Get the logon time */
    NtQuerySystemTime(&LogonTime);

    /* Check for special accounts */
    if (_wcsicmp(LogonInfo->LogonDomainName.Buffer, L"NT AUTHORITY") == 0)
    {
        SpecialAccount = TRUE;

        /* Get the authority domain SID */
        Status = GetNtAuthorityDomainSid(&AccountDomainSid);
        if (!NT_SUCCESS(Status))
        {
            ERR("GetNtAuthorityDomainSid() failed (Status 0x%08lx)\n", Status);
            return Status;
        }

        if (_wcsicmp(LogonInfo->UserName.Buffer, L"LocalService") == 0)
        {
            TRACE("SpecialAccount: LocalService\n");

            if (LogonType != Service)
                return STATUS_LOGON_FAILURE;

            UserInfo = RtlAllocateHeap(RtlGetProcessHeap(),
                                       HEAP_ZERO_MEMORY,
                                       sizeof(SAMPR_USER_ALL_INFORMATION));
            if (UserInfo == NULL)
            {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                goto done;
            }

            UserInfo->All.UserId = SECURITY_LOCAL_SERVICE_RID;
            UserInfo->All.PrimaryGroupId = SECURITY_LOCAL_SERVICE_RID;
        }
        else if (_wcsicmp(LogonInfo->UserName.Buffer, L"NetworkService") == 0)
        {
            TRACE("SpecialAccount: NetworkService\n");

            if (LogonType != Service)
                return STATUS_LOGON_FAILURE;

            UserInfo = RtlAllocateHeap(RtlGetProcessHeap(),
                                       HEAP_ZERO_MEMORY,
                                       sizeof(SAMPR_USER_ALL_INFORMATION));
            if (UserInfo == NULL)
            {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                goto done;
            }

            UserInfo->All.UserId = SECURITY_NETWORK_SERVICE_RID;
            UserInfo->All.PrimaryGroupId = SECURITY_NETWORK_SERVICE_RID;
        }
        else
        {
            Status = STATUS_NO_SUCH_USER;
            goto done;
        }
    }
    else
    {
        TRACE("NormalAccount\n");

        /* Get the account domain SID */
        Status = GetAccountDomainSid(&AccountDomainSid);
        if (!NT_SUCCESS(Status))
        {
            ERR("GetAccountDomainSid() failed (Status 0x%08lx)\n", Status);
            return Status;
        }

        /* Connect to the SAM server */
        Status = SamIConnect(NULL,
                             &ServerHandle,
                             SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
                             TRUE);
        if (!NT_SUCCESS(Status))
        {
            TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
            goto done;
        }

        /* Open the account domain */
        Status = SamrOpenDomain(ServerHandle,
                                DOMAIN_LOOKUP,
                                AccountDomainSid,
                                &DomainHandle);
        if (!NT_SUCCESS(Status))
        {
            ERR("SamrOpenDomain failed (Status %08lx)\n", Status);
            goto done;
        }

        Names[0].Length = LogonInfo->UserName.Length;
        Names[0].MaximumLength = LogonInfo->UserName.MaximumLength;
        Names[0].Buffer = LogonInfo->UserName.Buffer;

        /* Try to get the RID for the user name */
        Status = SamrLookupNamesInDomain(DomainHandle,
                                         1,
                                         Names,
                                         &RelativeIds,
                                         &Use);
        if (!NT_SUCCESS(Status))
        {
            ERR("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
            Status = STATUS_NO_SUCH_USER;
            goto done;
        }

        /* Fail, if it is not a user account */
        if (Use.Element[0] != SidTypeUser)
        {
            ERR("Account is not a user account!\n");
            Status = STATUS_NO_SUCH_USER;
            goto done;
        }

        /* Open the user object */
        Status = SamrOpenUser(DomainHandle,
                              USER_READ_GENERAL | USER_READ_LOGON |
                              USER_READ_ACCOUNT | USER_READ_PREFERENCES, /* FIXME */
                              RelativeIds.Element[0],
                              &UserHandle);
        if (!NT_SUCCESS(Status))
        {
            ERR("SamrOpenUser failed (Status %08lx)\n", Status);
            goto done;
        }

        Status = SamrQueryInformationUser(UserHandle,
                                          UserAllInformation,
                                          &UserInfo);
        if (!NT_SUCCESS(Status))
        {
            ERR("SamrQueryInformationUser failed (Status %08lx)\n", Status);
            goto done;
        }

        TRACE("UserName: %S\n", UserInfo->All.UserName.Buffer);

        /* Check the password */
        if ((UserInfo->All.UserAccountControl & USER_PASSWORD_NOT_REQUIRED) == 0)
        {
            Status = MsvpCheckPassword(&(LogonInfo->Password),
                                       UserInfo);
            if (!NT_SUCCESS(Status))
            {
                ERR("MsvpCheckPassword failed (Status %08lx)\n", Status);
                goto done;
            }
        }

        /* Check account restrictions for non-administrator accounts */
        if (RelativeIds.Element[0] != DOMAIN_USER_RID_ADMIN)
        {
            /* Check if the account has been disabled */
            if (UserInfo->All.UserAccountControl & USER_ACCOUNT_DISABLED)
            {
                ERR("Account disabled!\n");
                *SubStatus = STATUS_ACCOUNT_DISABLED;
                Status = STATUS_ACCOUNT_RESTRICTION;
                goto done;
            }

            /* Check if the account has been locked */
            if (UserInfo->All.UserAccountControl & USER_ACCOUNT_AUTO_LOCKED)
            {
                ERR("Account locked!\n");
                *SubStatus = STATUS_ACCOUNT_LOCKED_OUT;
                Status = STATUS_ACCOUNT_RESTRICTION;
                goto done;
            }

#if 0
            /* Check if the account expired */
            AccountExpires.LowPart = UserInfo->All.AccountExpires.LowPart;
            AccountExpires.HighPart = UserInfo->All.AccountExpires.HighPart;

            if (AccountExpires.QuadPart != 0 &&
                LogonTime.QuadPart >= AccountExpires.QuadPart)
            {
                ERR("Account expired!\n");
                *SubStatus = STATUS_ACCOUNT_EXPIRED;
                Status = STATUS_ACCOUNT_RESTRICTION;
                goto done;
            }
#endif

            /* Check if the password expired */
            PasswordMustChange.LowPart = UserInfo->All.PasswordMustChange.LowPart;
            PasswordMustChange.HighPart = UserInfo->All.PasswordMustChange.HighPart;
            PasswordLastSet.LowPart = UserInfo->All.PasswordLastSet.LowPart;
            PasswordLastSet.HighPart = UserInfo->All.PasswordLastSet.HighPart;

            if (LogonTime.QuadPart >= PasswordMustChange.QuadPart)
            {
                ERR("Password expired!\n");
                if (PasswordLastSet.QuadPart == 0)
                    *SubStatus = STATUS_PASSWORD_MUST_CHANGE;
                else
                    *SubStatus = STATUS_PASSWORD_EXPIRED;

                Status = STATUS_ACCOUNT_RESTRICTION;
                goto done;
            }

            /* FIXME: more checks */
            // STATUS_INVALID_LOGON_HOURS;
            // STATUS_INVALID_WORKSTATION;
        }
    }

    /* Return logon information */

    /* Create and return a new logon id */
    Status = NtAllocateLocallyUniqueId(LogonId);
    if (!NT_SUCCESS(Status))
    {
        TRACE("NtAllocateLocallyUniqueId failed (Status %08lx)\n", Status);
        goto done;
    }

    /* Create the logon session */
    Status = DispatchTable.CreateLogonSession(LogonId);
    if (!NT_SUCCESS(Status))
    {
        TRACE("CreateLogonSession failed (Status %08lx)\n", Status);
        goto done;
    }

    SessionCreated = TRUE;

    /* Build and fill the interactive profile buffer */
    Status = BuildInteractiveProfileBuffer(ClientRequest,
                                           UserInfo,
                                           &LogonServer,
                                           (PMSV1_0_INTERACTIVE_PROFILE*)ProfileBuffer,
                                           ProfileBufferLength);
    if (!NT_SUCCESS(Status))
    {
        TRACE("BuildInteractiveProfileBuffer failed (Status %08lx)\n", Status);
        goto done;
    }

    /* Return the token information type */
    *TokenInformationType = LsaTokenInformationV1;

    /* Build and fill the token information buffer */
    Status = BuildTokenInformationBuffer((PLSA_TOKEN_INFORMATION_V1*)TokenInformation,
                                         AccountDomainSid,
                                         UserInfo,
                                         SpecialAccount);
    if (!NT_SUCCESS(Status))
    {
        TRACE("BuildTokenInformationBuffer failed (Status %08lx)\n", Status);
        goto done;
    }

done:
    /* Return the account name */
    *AccountName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
    if (*AccountName != NULL)
    {
        (*AccountName)->Buffer = DispatchTable.AllocateLsaHeap(LogonInfo->UserName.Length +
                                                               sizeof(UNICODE_NULL));
        if ((*AccountName)->Buffer != NULL)
        {
            (*AccountName)->MaximumLength = LogonInfo->UserName.Length +
                                            sizeof(UNICODE_NULL);
            RtlCopyUnicodeString(*AccountName, &LogonInfo->UserName);
        }
    }

    if (!NT_SUCCESS(Status))
    {
        if (SessionCreated != FALSE)
            DispatchTable.DeleteLogonSession(LogonId);

        if (*ProfileBuffer != NULL)
        {
            DispatchTable.FreeClientBuffer(ClientRequest,
                                           *ProfileBuffer);
            *ProfileBuffer = NULL;
        }
    }

    if (UserHandle != NULL)
        SamrCloseHandle(&UserHandle);

    SamIFree_SAMPR_USER_INFO_BUFFER(UserInfo,
                                    UserAllInformation);
    SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
    SamIFree_SAMPR_ULONG_ARRAY(&Use);

    if (DomainHandle != NULL)
        SamrCloseHandle(&DomainHandle);

    if (ServerHandle != NULL)
        SamrCloseHandle(&ServerHandle);

    if (AccountDomainSid != NULL)
        RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);

    if (Status == STATUS_NO_SUCH_USER ||
        Status == STATUS_WRONG_PASSWORD)
    {
        *SubStatus = Status;
        Status = STATUS_LOGON_FAILURE;
    }

    TRACE("LsaApLogonUser done (Status 0x%08lx  SubStatus 0x%08lx)\n", Status, *SubStatus);

    return Status;
}
Example #4
0
/*
 * @unimplemented
 */
NTSTATUS
NTAPI
LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
               IN SECURITY_LOGON_TYPE LogonType,
               IN PVOID AuthenticationInformation,
               IN PVOID ClientAuthenticationBase,
               IN ULONG AuthenticationInformationLength,
               OUT PVOID *ProfileBuffer,
               OUT PULONG ProfileBufferLength,
               OUT PLUID LogonId,
               OUT PNTSTATUS SubStatus,
               OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
               OUT PVOID *TokenInformation,
               OUT PLSA_UNICODE_STRING *AccountName,
               OUT PLSA_UNICODE_STRING *AuthenticatingAuthority)
{
    PMSV1_0_INTERACTIVE_LOGON LogonInfo;

    SAMPR_HANDLE ServerHandle = NULL;
    SAMPR_HANDLE DomainHandle = NULL;
    SAMPR_HANDLE UserHandle = NULL;
    PRPC_SID AccountDomainSid = NULL;
    RPC_UNICODE_STRING Names[1];
    SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
    SAMPR_ULONG_ARRAY Use = {0, NULL};
    PSAMPR_USER_INFO_BUFFER UserInfo = NULL;
    UNICODE_STRING LogonServer;
    NTSTATUS Status;

    TRACE("()\n");

    TRACE("LogonType: %lu\n", LogonType);
    TRACE("AuthenticationInformation: %p\n", AuthenticationInformation);
    TRACE("AuthenticationInformationLength: %lu\n", AuthenticationInformationLength);


    *ProfileBuffer = NULL;
    *ProfileBufferLength = 0;
    *SubStatus = STATUS_SUCCESS;

    if (LogonType == Interactive ||
        LogonType == Batch ||
        LogonType == Service)
    {
        ULONG_PTR PtrOffset;

        LogonInfo = (PMSV1_0_INTERACTIVE_LOGON)AuthenticationInformation;

        /* Fix-up pointers in the authentication info */
        PtrOffset = (ULONG_PTR)AuthenticationInformation - (ULONG_PTR)ClientAuthenticationBase;

        LogonInfo->LogonDomainName.Buffer = (PWSTR)((ULONG_PTR)LogonInfo->LogonDomainName.Buffer + PtrOffset);
        LogonInfo->UserName.Buffer = (PWSTR)((ULONG_PTR)LogonInfo->UserName.Buffer + PtrOffset);
        LogonInfo->Password.Buffer = (PWSTR)((ULONG_PTR)LogonInfo->Password.Buffer + PtrOffset);

        TRACE("Domain: %S\n", LogonInfo->LogonDomainName.Buffer);
        TRACE("User: %S\n", LogonInfo->UserName.Buffer);
        TRACE("Password: %S\n", LogonInfo->Password.Buffer);

        RtlInitUnicodeString(&LogonServer, L"Testserver");
    }
    else
    {
        FIXME("LogonType %lu is not supported yet!\n", LogonType);
        return STATUS_NOT_IMPLEMENTED;
    }

    Status = GetDomainSid(&AccountDomainSid);
    if (!NT_SUCCESS(Status))
    {
        TRACE("GetDomainSid() failed (Status 0x%08lx)\n", Status);
        return Status;
    }

    /* Connect to the SAM server */
    Status = SamIConnect(NULL,
                         &ServerHandle,
                         SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
                         TRUE);
    if (!NT_SUCCESS(Status))
    {
        TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
        goto done;
    }

    /* Open the account domain */
    Status = SamrOpenDomain(ServerHandle,
                            DOMAIN_LOOKUP,
                            AccountDomainSid,
                            &DomainHandle);
    if (!NT_SUCCESS(Status))
    {
        TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
        goto done;
    }

    Names[0].Length = LogonInfo->UserName.Length;
    Names[0].MaximumLength = LogonInfo->UserName.MaximumLength;
    Names[0].Buffer = LogonInfo->UserName.Buffer;

    /* Try to get the RID for the user name */
    Status = SamrLookupNamesInDomain(DomainHandle,
                                     1,
                                     Names,
                                     &RelativeIds,
                                     &Use);
    if (!NT_SUCCESS(Status))
    {
        TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
        Status = STATUS_NO_SUCH_USER;
        goto done;
    }

    /* Fail, if it is not a user account */
    if (Use.Element[0] != SidTypeUser)
    {
        TRACE("Account is not a user account!\n");
        Status = STATUS_NO_SUCH_USER;
        goto done;
    }

    /* Open the user object */
    Status = SamrOpenUser(DomainHandle,
                          USER_READ_GENERAL | USER_READ_LOGON |
                          USER_READ_ACCOUNT | USER_READ_PREFERENCES, /* FIXME */
                          RelativeIds.Element[0],
                          &UserHandle);
    if (!NT_SUCCESS(Status))
    {
        TRACE("SamrOpenUser failed (Status %08lx)\n", Status);
        goto done;
    }

    Status = SamrQueryInformationUser(UserHandle,
                                      UserAllInformation,
                                      &UserInfo);
    if (!NT_SUCCESS(Status))
    {
        TRACE("SamrQueryInformationUser failed (Status %08lx)\n", Status);
        goto done;
    }


    TRACE("UserName: %S\n", UserInfo->All.UserName.Buffer);

    /* FIXME: Check restrictions */

    /* FIXME: Check the password */
    if ((UserInfo->All.UserAccountControl & USER_PASSWORD_NOT_REQUIRED) == 0)
    {
        FIXME("Must check the password!\n");

    }

    /* Return logon information */

    /* Create and return a new logon id */
    Status = NtAllocateLocallyUniqueId(LogonId);
    if (!NT_SUCCESS(Status))
    {
        TRACE("NtAllocateLocallyUniqueId failed (Status %08lx)\n", Status);
        goto done;
    }

    /* Build and fill the interactve profile buffer */
    Status = BuildInteractiveProfileBuffer(ClientRequest,
                                           UserInfo,
                                           &LogonServer,
                                           (PMSV1_0_INTERACTIVE_PROFILE*)ProfileBuffer,
                                           ProfileBufferLength);
    if (!NT_SUCCESS(Status))
    {
        TRACE("BuildInteractiveProfileBuffer failed (Status %08lx)\n", Status);
        goto done;
    }

    /* Return the token information type */
    *TokenInformationType = LsaTokenInformationV1;

    /* Build and fill the token information buffer */
    Status = BuildTokenInformationBuffer((PLSA_TOKEN_INFORMATION_V1*)TokenInformation,
                                         AccountDomainSid,
                                         RelativeIds.Element[0],
                                         LogonId);
    if (!NT_SUCCESS(Status))
    {
        TRACE("BuildTokenInformationBuffer failed (Status %08lx)\n", Status);
        goto done;
    }

    *SubStatus = STATUS_SUCCESS;

done:
    /* Return the account name */
    *AccountName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
    if (*AccountName != NULL)
    {
        (*AccountName)->Buffer = DispatchTable.AllocateLsaHeap(LogonInfo->UserName.Length +
                                                               sizeof(UNICODE_NULL));
        if ((*AccountName)->Buffer != NULL)
        {
            (*AccountName)->MaximumLength = LogonInfo->UserName.Length +
                                            sizeof(UNICODE_NULL);
            RtlCopyUnicodeString(*AccountName, &LogonInfo->UserName);
        }
    }

    if (!NT_SUCCESS(Status))
    {
        if (*ProfileBuffer != NULL)
        {
            DispatchTable.FreeClientBuffer(ClientRequest,
                                           *ProfileBuffer);
            *ProfileBuffer = NULL;
        }
    }

    if (UserHandle != NULL)
        SamrCloseHandle(&UserHandle);

    SamIFree_SAMPR_USER_INFO_BUFFER(UserInfo,
                                    UserAllInformation);
    SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
    SamIFree_SAMPR_ULONG_ARRAY(&Use);

    if (DomainHandle != NULL)
        SamrCloseHandle(&DomainHandle);

    if (ServerHandle != NULL)
        SamrCloseHandle(&ServerHandle);

    if (AccountDomainSid != NULL)
        RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);

    TRACE("LsaApLogonUser done (Status %08lx)\n", Status);

    return Status;
}