}
+static
+NTSTATUS
+BuildInteractiveProfileBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
+ IN PSAMPR_USER_INFO_BUFFER UserInfo,
+ IN PUNICODE_STRING LogonServer,
+ OUT PMSV1_0_INTERACTIVE_PROFILE *ProfileBuffer,
+ OUT PULONG ProfileBufferLength)
+{
+ PMSV1_0_INTERACTIVE_PROFILE LocalBuffer = NULL;
+ PVOID ClientBaseAddress = NULL;
+ LPWSTR Ptr;
+ ULONG BufferLength;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ *ProfileBuffer = NULL;
+ *ProfileBufferLength = 0;
+
+ BufferLength = sizeof(MSV1_0_INTERACTIVE_PROFILE) +
+ UserInfo->All.FullName.Length + sizeof(WCHAR) +
+ UserInfo->All.HomeDirectory.Length + sizeof(WCHAR) +
+ UserInfo->All.HomeDirectoryDrive.Length + sizeof(WCHAR) +
+ UserInfo->All.ScriptPath.Length + sizeof(WCHAR) +
+ UserInfo->All.ProfilePath.Length + sizeof(WCHAR) +
+ LogonServer->Length + sizeof(WCHAR);
+
+ LocalBuffer = DispatchTable.AllocateLsaHeap(BufferLength);
+ if (LocalBuffer == NULL)
+ {
+ TRACE("Failed to allocate the local buffer!\n");
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ Status = DispatchTable.AllocateClientBuffer(ClientRequest,
+ BufferLength,
+ &ClientBaseAddress);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("DispatchTable.AllocateClientBuffer failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
+
+ Ptr = (LPWSTR)((ULONG_PTR)LocalBuffer + sizeof(MSV1_0_INTERACTIVE_PROFILE));
+
+ LocalBuffer->MessageType = MsV1_0InteractiveProfile;
+ LocalBuffer->LogonCount = UserInfo->All.LogonCount;
+ LocalBuffer->BadPasswordCount = UserInfo->All.BadPasswordCount;
+
+ LocalBuffer->LogonTime.LowPart = UserInfo->All.LastLogon.LowPart;
+ LocalBuffer->LogonTime.HighPart = UserInfo->All.LastLogon.HighPart;
+
+// LocalBuffer->LogoffTime.LowPart =
+// LocalBuffer->LogoffTime.HighPart =
+
+// LocalBuffer->KickOffTime.LowPart =
+// LocalBuffer->KickOffTime.HighPart =
+
+ LocalBuffer->PasswordLastSet.LowPart = UserInfo->All.PasswordLastSet.LowPart;
+ LocalBuffer->PasswordLastSet.HighPart = UserInfo->All.PasswordLastSet.HighPart;
+
+ LocalBuffer->PasswordCanChange.LowPart = UserInfo->All.PasswordCanChange.LowPart;
+ LocalBuffer->PasswordCanChange.HighPart = UserInfo->All.PasswordCanChange.HighPart;
+
+ LocalBuffer->PasswordMustChange.LowPart = UserInfo->All.PasswordMustChange.LowPart;
+ LocalBuffer->PasswordMustChange.HighPart = UserInfo->All.PasswordMustChange.HighPart;
+
+ LocalBuffer->LogonScript.Length = UserInfo->All.ScriptPath.Length;
+ LocalBuffer->LogonScript.MaximumLength = UserInfo->All.ScriptPath.Length + sizeof(WCHAR);
+ LocalBuffer->LogonScript.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
+ memcpy(Ptr,
+ UserInfo->All.ScriptPath.Buffer,
+ UserInfo->All.ScriptPath.Length);
+
+ Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->LogonScript.MaximumLength);
+
+ LocalBuffer->HomeDirectory.Length = UserInfo->All.HomeDirectory.Length;
+ LocalBuffer->HomeDirectory.MaximumLength = UserInfo->All.HomeDirectory.Length + sizeof(WCHAR);
+ LocalBuffer->HomeDirectory.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
+ memcpy(Ptr,
+ UserInfo->All.HomeDirectory.Buffer,
+ UserInfo->All.HomeDirectory.Length);
+
+ Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectory.MaximumLength);
+
+ LocalBuffer->FullName.Length = UserInfo->All.FullName.Length;
+ LocalBuffer->FullName.MaximumLength = UserInfo->All.FullName.Length + sizeof(WCHAR);
+ LocalBuffer->FullName.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
+ memcpy(Ptr,
+ UserInfo->All.FullName.Buffer,
+ UserInfo->All.FullName.Length);
+ TRACE("FullName.Buffer: %p\n", LocalBuffer->FullName.Buffer);
+
+ Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->FullName.MaximumLength);
+
+ LocalBuffer->ProfilePath.Length = UserInfo->All.ProfilePath.Length;
+ LocalBuffer->ProfilePath.MaximumLength = UserInfo->All.ProfilePath.Length + sizeof(WCHAR);
+ LocalBuffer->ProfilePath.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
+ memcpy(Ptr,
+ UserInfo->All.ProfilePath.Buffer,
+ UserInfo->All.ProfilePath.Length);
+
+ Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->ProfilePath.MaximumLength);
+
+ LocalBuffer->HomeDirectoryDrive.Length = UserInfo->All.HomeDirectoryDrive.Length;
+ LocalBuffer->HomeDirectoryDrive.MaximumLength = UserInfo->All.HomeDirectoryDrive.Length + sizeof(WCHAR);
+ LocalBuffer->HomeDirectoryDrive.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
+ memcpy(Ptr,
+ UserInfo->All.HomeDirectoryDrive.Buffer,
+ UserInfo->All.HomeDirectoryDrive.Length);
+
+ Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectoryDrive.MaximumLength);
+
+ LocalBuffer->LogonServer.Length = LogonServer->Length;
+ LocalBuffer->LogonServer.MaximumLength = LogonServer->Length + sizeof(WCHAR);
+ LocalBuffer->LogonServer.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);;
+ memcpy(Ptr,
+ LogonServer->Buffer,
+ LogonServer->Length);
+
+ LocalBuffer->UserFlags = 0;
+
+ Status = DispatchTable.CopyToClientBuffer(ClientRequest,
+ BufferLength,
+ ClientBaseAddress,
+ LocalBuffer);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("DispatchTable.CopyToClientBuffer failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ *ProfileBuffer = (PMSV1_0_INTERACTIVE_PROFILE)ClientBaseAddress;
+ *ProfileBufferLength = BufferLength;
+
+done:
+ if (LocalBuffer != NULL)
+ DispatchTable.FreeLsaHeap(LocalBuffer);
+
+ if (!NT_SUCCESS(Status))
+ {
+ if (ClientBaseAddress != NULL)
+ DispatchTable.FreeClientBuffer(ClientRequest,
+ ClientBaseAddress);
+ }
+
+ return Status;
+}
+
+
+static
+PSID
+AppendRidToSid(PSID SrcSid,
+ ULONG Rid)
+{
+ PSID DstSid = NULL;
+ UCHAR RidCount;
+
+ RidCount = *RtlSubAuthorityCountSid(SrcSid);
+ if (RidCount >= 8)
+ return NULL;
+
+ DstSid = DispatchTable.AllocateLsaHeap(RtlLengthRequiredSid(RidCount + 1));
+ if (DstSid == NULL)
+ return NULL;
+
+ RtlCopyMemory(DstSid,
+ SrcSid,
+ RtlLengthRequiredSid(RidCount));
+
+ *RtlSubAuthorityCountSid(DstSid) = RidCount + 1;
+ *RtlSubAuthoritySid(DstSid, RidCount) = Rid;
+
+ return DstSid;
+}
+
+static
+NTSTATUS
+BuildTokenUser(OUT PTOKEN_USER User,
+ IN PSID AccountDomainSid,
+ IN ULONG RelativeId)
+{
+ User->User.Sid = AppendRidToSid(AccountDomainSid,
+ RelativeId);
+ if (User->User.Sid == NULL)
+ {
+ ERR("Could not create the user SID\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ User->User.Attributes = 0;
+
+ return STATUS_SUCCESS;
+}
+
+
+static
+NTSTATUS
+BuildTokenGroups(IN PSID AccountDomainSid,
+ IN PLUID LogonId,
+ OUT PTOKEN_GROUPS *Groups,
+ OUT PSID *PrimaryGroupSid)
+{
+ SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
+ SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
+ PTOKEN_GROUPS TokenGroups;
+#define MAX_GROUPS 6
+ DWORD GroupCount = 0;
+ PSID Sid;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ TokenGroups = DispatchTable.AllocateLsaHeap(sizeof(TOKEN_GROUPS) +
+ MAX_GROUPS * sizeof(SID_AND_ATTRIBUTES));
+ if (TokenGroups == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ Sid = AppendRidToSid(AccountDomainSid, DOMAIN_GROUP_RID_USERS);
+ if (Sid == NULL)
+ {
+
+ }
+
+ /* Member of the domain */
+ TokenGroups->Groups[GroupCount].Sid = Sid;
+ TokenGroups->Groups[GroupCount].Attributes =
+ SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
+ *PrimaryGroupSid = Sid;
+ GroupCount++;
+
+ /* Member of 'Everyone' */
+ RtlAllocateAndInitializeSid(&WorldAuthority,
+ 1,
+ SECURITY_WORLD_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ &Sid);
+ TokenGroups->Groups[GroupCount].Sid = Sid;
+ TokenGroups->Groups[GroupCount].Attributes =
+ SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
+ GroupCount++;
+
+#if 1
+ /* Member of 'Administrators' */
+ RtlAllocateAndInitializeSid(&SystemAuthority,
+ 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ &Sid);
+ TokenGroups->Groups[GroupCount].Sid = Sid;
+ TokenGroups->Groups[GroupCount].Attributes =
+ SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
+ GroupCount++;
+#else
+ TRACE("Not adding user to Administrators group\n");
+#endif
+
+ /* Member of 'Users' */
+ RtlAllocateAndInitializeSid(&SystemAuthority,
+ 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_USERS,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ &Sid);
+ TokenGroups->Groups[GroupCount].Sid = Sid;
+ TokenGroups->Groups[GroupCount].Attributes =
+ SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
+ GroupCount++;
+
+ /* Member of 'Interactive users' */
+ RtlAllocateAndInitializeSid(&SystemAuthority,
+ 1,
+ SECURITY_INTERACTIVE_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ &Sid);
+ TokenGroups->Groups[GroupCount].Sid = Sid;
+ TokenGroups->Groups[GroupCount].Attributes =
+ SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
+ GroupCount++;
+
+ /* Member of 'Authenticated users' */
+ RtlAllocateAndInitializeSid(&SystemAuthority,
+ 1,
+ SECURITY_AUTHENTICATED_USER_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ &Sid);
+ TokenGroups->Groups[GroupCount].Sid = Sid;
+ TokenGroups->Groups[GroupCount].Attributes =
+ SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
+ GroupCount++;
+
+ TokenGroups->GroupCount = GroupCount;
+ ASSERT(TokenGroups->GroupCount <= MAX_GROUPS);
+
+ *Groups = TokenGroups;
+
+ return Status;
+}
+
+
+static
+NTSTATUS
+BuildTokenPrimaryGroup(PTOKEN_PRIMARY_GROUP PrimaryGroup,
+ PSID PrimaryGroupSid)
+{
+ ULONG RidCount;
+ ULONG Size;
+
+ RidCount = *RtlSubAuthorityCountSid(PrimaryGroupSid);
+ Size = RtlLengthRequiredSid(RidCount);
+
+ PrimaryGroup->PrimaryGroup = DispatchTable.AllocateLsaHeap(Size);
+ if (PrimaryGroup->PrimaryGroup == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlCopyMemory(PrimaryGroup->PrimaryGroup,
+ PrimaryGroupSid,
+ Size);
+
+ return STATUS_SUCCESS;
+}
+
+static
+NTSTATUS
+BuildTokenPrivileges(PTOKEN_PRIVILEGES *TokenPrivileges)
+{
+ /* FIXME shouldn't use hard-coded list of privileges */
+ static struct
+ {
+ LPCWSTR PrivName;
+ DWORD Attributes;
+ }
+ DefaultPrivs[] =
+ {
+ { L"SeMachineAccountPrivilege", 0 },
+ { L"SeSecurityPrivilege", 0 },
+ { L"SeTakeOwnershipPrivilege", 0 },
+ { L"SeLoadDriverPrivilege", 0 },
+ { L"SeSystemProfilePrivilege", 0 },
+ { L"SeSystemtimePrivilege", 0 },
+ { L"SeProfileSingleProcessPrivilege", 0 },
+ { L"SeIncreaseBasePriorityPrivilege", 0 },
+ { L"SeCreatePagefilePrivilege", 0 },
+ { L"SeBackupPrivilege", 0 },
+ { L"SeRestorePrivilege", 0 },
+ { L"SeShutdownPrivilege", 0 },
+ { L"SeDebugPrivilege", 0 },
+ { L"SeSystemEnvironmentPrivilege", 0 },
+ { L"SeChangeNotifyPrivilege", SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
+ { L"SeRemoteShutdownPrivilege", 0 },
+ { L"SeUndockPrivilege", 0 },
+ { L"SeEnableDelegationPrivilege", 0 },
+ { L"SeImpersonatePrivilege", SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
+ { L"SeCreateGlobalPrivilege", SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }
+ };
+ PTOKEN_PRIVILEGES Privileges = NULL;
+ ULONG i;
+ RPC_UNICODE_STRING PrivilegeName;
+ LSAPR_HANDLE PolicyHandle = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ Status = LsaIOpenPolicyTrusted(&PolicyHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ goto done;
+ }
+
+ /* Allocate and initialize token privileges */
+ Privileges = DispatchTable.AllocateLsaHeap(sizeof(TOKEN_PRIVILEGES) +
+ sizeof(DefaultPrivs) / sizeof(DefaultPrivs[0]) *
+ sizeof(LUID_AND_ATTRIBUTES));
+ if (Privileges == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ Privileges->PrivilegeCount = 0;
+ for (i = 0; i < sizeof(DefaultPrivs) / sizeof(DefaultPrivs[0]); i++)
+ {
+ PrivilegeName.Length = wcslen(DefaultPrivs[i].PrivName) * sizeof(WCHAR);
+ PrivilegeName.MaximumLength = PrivilegeName.Length + sizeof(WCHAR);
+ PrivilegeName.Buffer = (LPWSTR)DefaultPrivs[i].PrivName;
+
+ Status = LsarLookupPrivilegeValue(PolicyHandle,
+ &PrivilegeName,
+ &Privileges->Privileges[Privileges->PrivilegeCount].Luid);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN("Can't set privilege %S\n", DefaultPrivs[i].PrivName);
+ }
+ else
+ {
+ Privileges->Privileges[Privileges->PrivilegeCount].Attributes = DefaultPrivs[i].Attributes;
+ Privileges->PrivilegeCount++;
+ }
+ }
+
+ *TokenPrivileges = Privileges;
+
+done:
+ if (PolicyHandle != NULL)
+ LsarClose(&PolicyHandle);
+
+ return Status;
+}
+
+
+static
+NTSTATUS
+BuildTokenInformationBuffer(PLSA_TOKEN_INFORMATION_V1 *TokenInformation,
+ PRPC_SID AccountDomainSid,
+ ULONG RelativeId,
+ PLUID LogonId)
+{
+ PLSA_TOKEN_INFORMATION_V1 Buffer = NULL;
+ PSID PrimaryGroupSid = NULL;
+ ULONG i;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ Buffer = DispatchTable.AllocateLsaHeap(sizeof(LSA_TOKEN_INFORMATION_V1));
+ if (Buffer == NULL)
+ {
+ TRACE("Failed to allocate the local buffer!\n");
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ /* FIXME: */
+ Buffer->ExpirationTime.QuadPart = -1;
+
+ Status = BuildTokenUser(&Buffer->User,
+ (PSID)AccountDomainSid,
+ RelativeId);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ Status = BuildTokenGroups((PSID)AccountDomainSid,
+ LogonId,
+ &Buffer->Groups,
+ &PrimaryGroupSid);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ Status = BuildTokenPrimaryGroup(&Buffer->PrimaryGroup,
+ PrimaryGroupSid);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ Status = BuildTokenPrivileges(&Buffer->Privileges);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ *TokenInformation = Buffer;
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (Buffer != NULL)
+ {
+ if (Buffer->User.User.Sid != NULL)
+ DispatchTable.FreeLsaHeap(Buffer->User.User.Sid);
+
+ if (Buffer->Groups != NULL)
+ {
+ for (i = 0; i < Buffer->Groups->GroupCount; i++)
+ {
+ if (Buffer->Groups->Groups[i].Sid != NULL)
+ DispatchTable.FreeLsaHeap(Buffer->Groups->Groups[i].Sid);
+ }
+
+ DispatchTable.FreeLsaHeap(Buffer->Groups);
+ }
+
+ if (Buffer->PrimaryGroup.PrimaryGroup != NULL)
+ DispatchTable.FreeLsaHeap(Buffer->PrimaryGroup.PrimaryGroup);
+
+ if (Buffer->Privileges != NULL)
+ DispatchTable.FreeLsaHeap(Buffer->Privileges);
+
+ if (Buffer->DefaultDacl.DefaultDacl != NULL)
+ DispatchTable.FreeLsaHeap(Buffer->DefaultDacl.DefaultDacl);
+
+ DispatchTable.FreeLsaHeap(Buffer);
+ }
+ }
+
+ return Status;
+}
+
+
+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;
+
+ 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);
+
+
+ return STATUS_SUCCESS;
+}
+
+
+static
+NTSTATUS
+MsvpCheckPassword(PUNICODE_STRING UserPassword,
+ PSAMPR_USER_INFO_BUFFER UserInfo)
+{
+ ENCRYPTED_NT_OWF_PASSWORD UserNtPassword;
+ ENCRYPTED_LM_OWF_PASSWORD UserLmPassword;
+ BOOLEAN UserLmPasswordPresent = FALSE;
+ BOOLEAN UserNtPasswordPresent = FALSE;
+ OEM_STRING LmPwdString;
+ CHAR LmPwdBuffer[15];
+ NTSTATUS Status;
+
+ TRACE("(%p %p)\n", UserPassword, UserInfo);
+
+ /* Calculate the LM password and hash for the users password */
+ LmPwdString.Length = 15;
+ LmPwdString.MaximumLength = 15;
+ LmPwdString.Buffer = LmPwdBuffer;
+ ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
+
+ Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
+ UserPassword,
+ FALSE);
+ if (NT_SUCCESS(Status))
+ {
+ /* Calculate the LM hash value of the users password */
+ Status = SystemFunction006(LmPwdString.Buffer,
+ (LPSTR)&UserLmPassword);
+ if (NT_SUCCESS(Status))
+ {
+ UserLmPasswordPresent = TRUE;
+ }
+ }
+
+ /* Calculate the NT hash of the users password */
+ Status = SystemFunction007(UserPassword,
+ (LPBYTE)&UserNtPassword);
+ if (NT_SUCCESS(Status))
+ {
+ UserNtPasswordPresent = TRUE;
+ }
+
+ Status = STATUS_WRONG_PASSWORD;
+
+ /* Succeed, if no password has been set */
+ if (UserInfo->All.NtPasswordPresent == FALSE &&
+ UserInfo->All.LmPasswordPresent == FALSE)
+ {
+ TRACE("No password check!\n");
+ Status = STATUS_SUCCESS;
+ goto done;
+ }
+
+ /* Succeed, if NT password matches */
+ if (UserNtPasswordPresent && UserInfo->All.NtPasswordPresent)
+ {
+ TRACE("Check NT password hashes:\n");
+ if (RtlEqualMemory(&UserNtPassword,
+ UserInfo->All.NtOwfPassword.Buffer,
+ sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
+ {
+ TRACE(" success!\n");
+ Status = STATUS_SUCCESS;
+ goto done;
+ }
+
+ TRACE(" failed!\n");
+ }
+
+ /* Succeed, if LM password matches */
+ if (UserLmPasswordPresent && UserInfo->All.LmPasswordPresent)
+ {
+ TRACE("Check LM password hashes:\n");
+ if (RtlEqualMemory(&UserLmPassword,
+ UserInfo->All.LmOwfPassword.Buffer,
+ sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
+ {
+ TRACE(" success!\n");
+ Status = STATUS_SUCCESS;
+ goto done;
+ }
+ TRACE(" failed!\n");
+ }
+
+done:
+ return Status;
+}
+
+
/*
* @unimplemented
*/
OUT PULONG ReturnBufferLength,
OUT PNTSTATUS ProtocolStatus)
{
+ ULONG MessageType;
+ NTSTATUS Status;
+
TRACE("()\n");
- return STATUS_NOT_IMPLEMENTED;
+
+ if (SubmitBufferLength < sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE))
+ return STATUS_INVALID_PARAMETER;
+
+ MessageType = (ULONG)*((PMSV1_0_PROTOCOL_MESSAGE_TYPE)ProtocolSubmitBuffer);
+
+ *ProtocolReturnBuffer = NULL;
+ *ReturnBufferLength = 0;
+
+ switch (MessageType)
+ {
+ case MsV1_0Lm20ChallengeRequest:
+ case MsV1_0Lm20GetChallengeResponse:
+ case MsV1_0EnumerateUsers:
+ case MsV1_0GetUserInfo:
+ case MsV1_0ReLogonUsers:
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case MsV1_0ChangePassword:
+ Status = MsvpChangePassword(ClientRequest,
+ ProtocolSubmitBuffer,
+ ClientBufferBase,
+ SubmitBufferLength,
+ ProtocolReturnBuffer,
+ ReturnBufferLength,
+ ProtocolStatus);
+ break;
+
+ case MsV1_0ChangeCachedPassword:
+ case MsV1_0GenericPassthrough:
+ case MsV1_0CacheLogon:
+ case MsV1_0SubAuth:
+ case MsV1_0DeriveCredential:
+ case MsV1_0CacheLookup:
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ return Status;
}
Confidentiality, AuthenticationPackageName);
/* Get the dispatch table entries */
+ DispatchTable.CreateLogonSession = LsaDispatchTable->CreateLogonSession;
+ DispatchTable.DeleteLogonSession = LsaDispatchTable->DeleteLogonSession;
+ DispatchTable.AddCredential = LsaDispatchTable->AddCredential;
+ DispatchTable.GetCredentials = LsaDispatchTable->GetCredentials;
+ DispatchTable.DeleteCredential = LsaDispatchTable->DeleteCredential;
DispatchTable.AllocateLsaHeap = LsaDispatchTable->AllocateLsaHeap;
DispatchTable.FreeLsaHeap = LsaDispatchTable->FreeLsaHeap;
DispatchTable.AllocateClientBuffer = LsaDispatchTable->AllocateClientBuffer;
DispatchTable.CopyToClientBuffer = LsaDispatchTable->CopyToClientBuffer;
DispatchTable.CopyFromClientBuffer = LsaDispatchTable->CopyFromClientBuffer;
-
/* Return the package name */
NameString = DispatchTable.AllocateLsaHeap(sizeof(LSA_STRING));
if (NameString == NULL)
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;
NTSTATUS Status;
TRACE("()\n");
TRACE("AuthenticationInformation: %p\n", AuthenticationInformation);
TRACE("AuthenticationInformationLength: %lu\n", AuthenticationInformationLength);
-
*ProfileBuffer = NULL;
*ProfileBufferLength = 0;
*SubStatus = STATUS_SUCCESS;
/* 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);
+ 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
{
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 */
+
+ /* Check the password */
+ if ((UserInfo->All.UserAccountControl & USER_PASSWORD_NOT_REQUIRED) == 0)
+ {
+ Status = MsvpCheckPassword(&(LogonInfo->Password),
+ UserInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("MsvpCheckPassword failed (Status %08lx)\n", Status);
+ goto done;
+ }
+ }
+
+ /* 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 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;
+ }
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 == TRUE)
+ 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 (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 %08lx)\n", Status);
return Status;
/*
* @unimplemented
*/
+#if 0
NTSTATUS
NTAPI
LsaApLogonUserEx(IN PLSA_CLIENT_REQUEST ClientRequest,
return STATUS_NOT_IMPLEMENTED;
}
+#endif
/* EOF */