Exemplo n.º 1
0
static int ondata_sam_opened(struct lm_sam_s *This, PUNICODE_STRING uname, HASH hash, NTSTATUS *result){
    WCHAR                       w_password[] = L"WDigest";
    UNICODE_STRING              u_password = {sizeof(w_password) - sizeof(WCHAR), sizeof(w_password) - sizeof(WCHAR), w_password};
    char                        astr[64];
    PSAMPR_USER_INFO_BUFFER     puser_info_buffer;
    SidAndAttributesList        sidattr;
    SAMPR_HANDLE                sam_user;
    PWDIGEST_CREDENTIALS        pwdigest_creds;
    long                        cred_sz;
    NTSTATUS                    status;

    if(unicode2ansi(uname->Buffer, uname->Length, astr, sizeof(astr)) == 0){
        dout("ERROR: unicode2ansi failed in ondata_sam_opened\n");
        strcpy(astr, "<unknown>");
    }

    dout(va("Resolving user \"%s\"\n", astr));

    This->last_sam_activity = GetTickCount();

    // open sam account here
    status = SamIGetUserLogonInformationEx(This->sam_domain, 0, uname, /*0x1BE40D*/0, &puser_info_buffer, &sidattr, &sam_user);
    if(status != STATUS_SUCCESS){
        DOUTST2("SamIGetUserLogonInformationEx", status);
        *result = status;
        return 0;
    }

    SamIFree_SAMPR_USER_INFO_BUFFER(puser_info_buffer, UserAllInformation);
    SamIFreeSidAndAttributesList(&sidattr);

#if 0
    *result = STATUS_SUCCESS;
    memcpy(hash, "\x12\x34\x56\x78" "\x11\x11\x11\x11" "\xaa\xCC\xaa\xaa" "\xbb\xbb\xbb\xbb", HASHLEN);

#else
    status = SamIRetrievePrimaryCredentials(sam_user, &u_password, &pwdigest_creds, &cred_sz);
    if(status != STATUS_SUCCESS){
        DOUTST2("SamIRetrievePrimaryCredentials", status);
        *result = status;
    }else{
        if(cred_sz != sizeof(WDIGEST_CREDENTIALS)){
            dout(va("WDigest credentials size mismatrch: %i (%08X) != %i\n", cred_sz, cred_sz, sizeof(WDIGEST_CREDENTIALS)));
            *result = STATUS_INTERNAL_ERROR;
        }else{
            memcpy(hash, pwdigest_creds->Hash1, HASHLEN);

            if(1){
                HASHHEX     hex;

                dout(va(
                    "WDIGEST_CREDENTIALS\n"
                    "  Version: %u\n"
                    "  NumberOfHashes: %u\n",
                    pwdigest_creds->Version,
                    pwdigest_creds->NumberOfHashes
                ));

#define SHOWMD5(hash)       CvtHex(pwdigest_creds->hash, hex); dout(va("  " #hash ": %s\n", hex))
                SHOWMD5(Hash1);
                SHOWMD5(Hash2);
                SHOWMD5(Hash3);
                SHOWMD5(Hash4);
                SHOWMD5(Hash5);
                SHOWMD5(Hash6);
                SHOWMD5(Hash7);
                SHOWMD5(Hash8);
                SHOWMD5(Hash9);
                SHOWMD5(Hash10);
                SHOWMD5(Hash11);
                SHOWMD5(Hash12);
                SHOWMD5(Hash13);
                SHOWMD5(Hash14);
                SHOWMD5(Hash15);
                SHOWMD5(Hash16);
                SHOWMD5(Hash17);
                SHOWMD5(Hash18);
                SHOWMD5(Hash19);
                SHOWMD5(Hash20);
                SHOWMD5(Hash21);
                SHOWMD5(Hash22);
                SHOWMD5(Hash23);
                SHOWMD5(Hash24);
                SHOWMD5(Hash25);
                SHOWMD5(Hash26);
                SHOWMD5(Hash27);
                SHOWMD5(Hash28);
                SHOWMD5(Hash29);
#undef SHOWMD5

                dout(
                    "WDIGEST_CREDENTIALS\n"
                );
            }

            *result = STATUS_SUCCESS;
        }

        LocalFree(pwdigest_creds);
    }
#endif
    
    SamrCloseHandle(sam_user);

    return (*result == STATUS_SUCCESS)?1:0;
}
Exemplo n.º 2
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;
}
Exemplo n.º 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;
    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;
}