2 * PROJECT: Authentication Package DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/msv1_0/msv1_0.c
6 * COPYRIGHT: Copyright 2013 Eric Kohl
9 /* INCLUDES ****************************************************************/
13 WINE_DEFAULT_DEBUG_CHANNEL(msv1_0
);
16 /* GLOBALS *****************************************************************/
18 LSA_DISPATCH_TABLE DispatchTable
;
21 /* FUNCTIONS ***************************************************************/
25 GetAccountDomainSid(PRPC_SID
*Sid
)
27 LSAPR_HANDLE PolicyHandle
= NULL
;
28 PLSAPR_POLICY_INFORMATION PolicyInfo
= NULL
;
32 Status
= LsaIOpenPolicyTrusted(&PolicyHandle
);
33 if (!NT_SUCCESS(Status
))
35 TRACE("LsaIOpenPolicyTrusted() failed (Status 0x%08lx)\n", Status
);
39 Status
= LsarQueryInformationPolicy(PolicyHandle
,
40 PolicyAccountDomainInformation
,
42 if (!NT_SUCCESS(Status
))
44 TRACE("LsarQueryInformationPolicy() failed (Status 0x%08lx)\n", Status
);
48 Length
= RtlLengthSid(PolicyInfo
->PolicyAccountDomainInfo
.Sid
);
50 *Sid
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Length
);
53 ERR("Failed to allocate SID\n");
54 Status
= STATUS_INSUFFICIENT_RESOURCES
;
58 memcpy(*Sid
, PolicyInfo
->PolicyAccountDomainInfo
.Sid
, Length
);
61 if (PolicyInfo
!= NULL
)
62 LsaIFree_LSAPR_POLICY_INFORMATION(PolicyAccountDomainInformation
,
65 if (PolicyHandle
!= NULL
)
66 LsarClose(&PolicyHandle
);
74 GetNtAuthorityDomainSid(PRPC_SID
*Sid
)
76 SID_IDENTIFIER_AUTHORITY NtAuthority
= {SECURITY_NT_AUTHORITY
};
79 Length
= RtlLengthRequiredSid(0);
80 *Sid
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Length
);
83 ERR("Failed to allocate SID\n");
84 return STATUS_INSUFFICIENT_RESOURCES
;
87 RtlInitializeSid(*Sid
,&NtAuthority
, 0);
89 return STATUS_SUCCESS
;
95 BuildInteractiveProfileBuffer(IN PLSA_CLIENT_REQUEST ClientRequest
,
96 IN PSAMPR_USER_INFO_BUFFER UserInfo
,
97 IN PWSTR ComputerName
,
98 OUT PMSV1_0_INTERACTIVE_PROFILE
*ProfileBuffer
,
99 OUT PULONG ProfileBufferLength
)
101 PMSV1_0_INTERACTIVE_PROFILE LocalBuffer
= NULL
;
102 PVOID ClientBaseAddress
= NULL
;
105 NTSTATUS Status
= STATUS_SUCCESS
;
107 *ProfileBuffer
= NULL
;
108 *ProfileBufferLength
= 0;
110 BufferLength
= sizeof(MSV1_0_INTERACTIVE_PROFILE
) +
111 UserInfo
->All
.FullName
.Length
+ sizeof(WCHAR
) +
112 UserInfo
->All
.HomeDirectory
.Length
+ sizeof(WCHAR
) +
113 UserInfo
->All
.HomeDirectoryDrive
.Length
+ sizeof(WCHAR
) +
114 UserInfo
->All
.ScriptPath
.Length
+ sizeof(WCHAR
) +
115 UserInfo
->All
.ProfilePath
.Length
+ sizeof(WCHAR
) +
116 ((wcslen(ComputerName
) + 3) * sizeof(WCHAR
));
118 LocalBuffer
= DispatchTable
.AllocateLsaHeap(BufferLength
);
119 if (LocalBuffer
== NULL
)
121 TRACE("Failed to allocate the local buffer!\n");
122 Status
= STATUS_INSUFFICIENT_RESOURCES
;
126 Status
= DispatchTable
.AllocateClientBuffer(ClientRequest
,
129 if (!NT_SUCCESS(Status
))
131 TRACE("DispatchTable.AllocateClientBuffer failed (Status 0x%08lx)\n", Status
);
135 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress
);
137 Ptr
= (LPWSTR
)((ULONG_PTR
)LocalBuffer
+ sizeof(MSV1_0_INTERACTIVE_PROFILE
));
139 LocalBuffer
->MessageType
= MsV1_0InteractiveProfile
;
140 LocalBuffer
->LogonCount
= UserInfo
->All
.LogonCount
;
141 LocalBuffer
->BadPasswordCount
= UserInfo
->All
.BadPasswordCount
;
143 LocalBuffer
->LogonTime
.LowPart
= UserInfo
->All
.LastLogon
.LowPart
;
144 LocalBuffer
->LogonTime
.HighPart
= UserInfo
->All
.LastLogon
.HighPart
;
146 LocalBuffer
->LogoffTime
.LowPart
= UserInfo
->All
.AccountExpires
.LowPart
;
147 LocalBuffer
->LogoffTime
.HighPart
= UserInfo
->All
.AccountExpires
.HighPart
;
149 LocalBuffer
->KickOffTime
.LowPart
= UserInfo
->All
.AccountExpires
.LowPart
;
150 LocalBuffer
->KickOffTime
.HighPart
= UserInfo
->All
.AccountExpires
.HighPart
;
152 LocalBuffer
->PasswordLastSet
.LowPart
= UserInfo
->All
.PasswordLastSet
.LowPart
;
153 LocalBuffer
->PasswordLastSet
.HighPart
= UserInfo
->All
.PasswordLastSet
.HighPart
;
155 LocalBuffer
->PasswordCanChange
.LowPart
= UserInfo
->All
.PasswordCanChange
.LowPart
;
156 LocalBuffer
->PasswordCanChange
.HighPart
= UserInfo
->All
.PasswordCanChange
.HighPart
;
158 LocalBuffer
->PasswordMustChange
.LowPart
= UserInfo
->All
.PasswordMustChange
.LowPart
;
159 LocalBuffer
->PasswordMustChange
.HighPart
= UserInfo
->All
.PasswordMustChange
.HighPart
;
161 LocalBuffer
->LogonScript
.Length
= UserInfo
->All
.ScriptPath
.Length
;
162 LocalBuffer
->LogonScript
.MaximumLength
= UserInfo
->All
.ScriptPath
.Length
+ sizeof(WCHAR
);
163 LocalBuffer
->LogonScript
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
165 UserInfo
->All
.ScriptPath
.Buffer
,
166 UserInfo
->All
.ScriptPath
.Length
);
168 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ LocalBuffer
->LogonScript
.MaximumLength
);
170 LocalBuffer
->HomeDirectory
.Length
= UserInfo
->All
.HomeDirectory
.Length
;
171 LocalBuffer
->HomeDirectory
.MaximumLength
= UserInfo
->All
.HomeDirectory
.Length
+ sizeof(WCHAR
);
172 LocalBuffer
->HomeDirectory
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
174 UserInfo
->All
.HomeDirectory
.Buffer
,
175 UserInfo
->All
.HomeDirectory
.Length
);
177 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ LocalBuffer
->HomeDirectory
.MaximumLength
);
179 LocalBuffer
->FullName
.Length
= UserInfo
->All
.FullName
.Length
;
180 LocalBuffer
->FullName
.MaximumLength
= UserInfo
->All
.FullName
.Length
+ sizeof(WCHAR
);
181 LocalBuffer
->FullName
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
183 UserInfo
->All
.FullName
.Buffer
,
184 UserInfo
->All
.FullName
.Length
);
185 TRACE("FullName.Buffer: %p\n", LocalBuffer
->FullName
.Buffer
);
187 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ LocalBuffer
->FullName
.MaximumLength
);
189 LocalBuffer
->ProfilePath
.Length
= UserInfo
->All
.ProfilePath
.Length
;
190 LocalBuffer
->ProfilePath
.MaximumLength
= UserInfo
->All
.ProfilePath
.Length
+ sizeof(WCHAR
);
191 LocalBuffer
->ProfilePath
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
193 UserInfo
->All
.ProfilePath
.Buffer
,
194 UserInfo
->All
.ProfilePath
.Length
);
196 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ LocalBuffer
->ProfilePath
.MaximumLength
);
198 LocalBuffer
->HomeDirectoryDrive
.Length
= UserInfo
->All
.HomeDirectoryDrive
.Length
;
199 LocalBuffer
->HomeDirectoryDrive
.MaximumLength
= UserInfo
->All
.HomeDirectoryDrive
.Length
+ sizeof(WCHAR
);
200 LocalBuffer
->HomeDirectoryDrive
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
202 UserInfo
->All
.HomeDirectoryDrive
.Buffer
,
203 UserInfo
->All
.HomeDirectoryDrive
.Length
);
205 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ LocalBuffer
->HomeDirectoryDrive
.MaximumLength
);
207 LocalBuffer
->LogonServer
.Length
= (wcslen(ComputerName
) + 2) * sizeof(WCHAR
);
208 LocalBuffer
->LogonServer
.MaximumLength
= LocalBuffer
->LogonServer
.Length
+ sizeof(WCHAR
);
209 LocalBuffer
->LogonServer
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
211 wcscat(Ptr
, ComputerName
);
213 LocalBuffer
->UserFlags
= 0;
215 Status
= DispatchTable
.CopyToClientBuffer(ClientRequest
,
219 if (!NT_SUCCESS(Status
))
221 TRACE("DispatchTable.CopyToClientBuffer failed (Status 0x%08lx)\n", Status
);
225 *ProfileBuffer
= (PMSV1_0_INTERACTIVE_PROFILE
)ClientBaseAddress
;
226 *ProfileBufferLength
= BufferLength
;
229 if (LocalBuffer
!= NULL
)
230 DispatchTable
.FreeLsaHeap(LocalBuffer
);
232 if (!NT_SUCCESS(Status
))
234 if (ClientBaseAddress
!= NULL
)
235 DispatchTable
.FreeClientBuffer(ClientRequest
,
245 AppendRidToSid(PSID SrcSid
,
251 RidCount
= *RtlSubAuthorityCountSid(SrcSid
);
255 DstSid
= DispatchTable
.AllocateLsaHeap(RtlLengthRequiredSid(RidCount
+ 1));
259 RtlCopyMemory(DstSid
,
261 RtlLengthRequiredSid(RidCount
));
263 *RtlSubAuthorityCountSid(DstSid
) = RidCount
+ 1;
264 *RtlSubAuthoritySid(DstSid
, RidCount
) = Rid
;
272 BuildTokenUser(OUT PTOKEN_USER User
,
273 IN PSID AccountDomainSid
,
276 User
->User
.Sid
= AppendRidToSid(AccountDomainSid
,
278 if (User
->User
.Sid
== NULL
)
280 ERR("Could not create the user SID\n");
281 return STATUS_INSUFFICIENT_RESOURCES
;
284 User
->User
.Attributes
= 0;
286 return STATUS_SUCCESS
;
292 BuildTokenPrimaryGroup(OUT PTOKEN_PRIMARY_GROUP PrimaryGroup
,
293 IN PSID AccountDomainSid
,
296 PrimaryGroup
->PrimaryGroup
= AppendRidToSid(AccountDomainSid
,
298 if (PrimaryGroup
->PrimaryGroup
== NULL
)
300 ERR("Could not create the primary group SID\n");
301 return STATUS_INSUFFICIENT_RESOURCES
;
304 return STATUS_SUCCESS
;
310 BuildTokenGroups(OUT PTOKEN_GROUPS
*Groups
,
311 IN PSID AccountDomainSid
,
313 IN BOOL SpecialAccount
)
315 SID_IDENTIFIER_AUTHORITY SystemAuthority
= {SECURITY_NT_AUTHORITY
};
316 PTOKEN_GROUPS TokenGroups
;
317 DWORD GroupCount
= 0;
320 NTSTATUS Status
= STATUS_SUCCESS
;
325 TokenGroups
= DispatchTable
.AllocateLsaHeap(sizeof(TOKEN_GROUPS
) +
326 MaxGroups
* sizeof(SID_AND_ATTRIBUTES
));
327 if (TokenGroups
== NULL
)
329 return STATUS_INSUFFICIENT_RESOURCES
;
335 Sid
= AppendRidToSid(AccountDomainSid
, RelativeId
);
341 TokenGroups
->Groups
[GroupCount
].Sid
= Sid
;
342 TokenGroups
->Groups
[GroupCount
].Attributes
=
343 SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
| SE_GROUP_MANDATORY
;
346 /* Member of 'Users' alias */
347 RtlAllocateAndInitializeSid(&SystemAuthority
,
349 SECURITY_BUILTIN_DOMAIN_RID
,
350 DOMAIN_ALIAS_RID_USERS
,
358 TokenGroups
->Groups
[GroupCount
].Sid
= Sid
;
359 TokenGroups
->Groups
[GroupCount
].Attributes
=
360 SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
| SE_GROUP_MANDATORY
;
365 /* Member of the domains users group */
366 Sid
= AppendRidToSid(AccountDomainSid
, DOMAIN_GROUP_RID_USERS
);
372 TokenGroups
->Groups
[GroupCount
].Sid
= Sid
;
373 TokenGroups
->Groups
[GroupCount
].Attributes
=
374 SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
| SE_GROUP_MANDATORY
;
378 /* Member of 'Authenticated users' */
379 RtlAllocateAndInitializeSid(&SystemAuthority
,
381 SECURITY_AUTHENTICATED_USER_RID
,
390 TokenGroups
->Groups
[GroupCount
].Sid
= Sid
;
391 TokenGroups
->Groups
[GroupCount
].Attributes
=
392 SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
| SE_GROUP_MANDATORY
;
395 TokenGroups
->GroupCount
= GroupCount
;
396 ASSERT(TokenGroups
->GroupCount
<= MaxGroups
);
398 *Groups
= TokenGroups
;
406 BuildTokenInformationBuffer(PLSA_TOKEN_INFORMATION_V1
*TokenInformation
,
407 PRPC_SID AccountDomainSid
,
408 PSAMPR_USER_INFO_BUFFER UserInfo
,
411 PLSA_TOKEN_INFORMATION_V1 Buffer
= NULL
;
413 NTSTATUS Status
= STATUS_SUCCESS
;
415 Buffer
= DispatchTable
.AllocateLsaHeap(sizeof(LSA_TOKEN_INFORMATION_V1
));
418 WARN("Failed to allocate the local buffer!\n");
419 Status
= STATUS_INSUFFICIENT_RESOURCES
;
423 Buffer
->ExpirationTime
.LowPart
= UserInfo
->All
.AccountExpires
.LowPart
;
424 Buffer
->ExpirationTime
.HighPart
= UserInfo
->All
.AccountExpires
.HighPart
;
426 Status
= BuildTokenUser(&Buffer
->User
,
427 (PSID
)AccountDomainSid
,
428 UserInfo
->All
.UserId
);
429 if (!NT_SUCCESS(Status
))
431 WARN("BuildTokenUser() failed (Status 0x%08lx)\n", Status
);
435 Status
= BuildTokenPrimaryGroup(&Buffer
->PrimaryGroup
,
436 (PSID
)AccountDomainSid
,
437 UserInfo
->All
.PrimaryGroupId
);
438 if (!NT_SUCCESS(Status
))
440 WARN("BuildTokenPrimaryGroup() failed (Status 0x%08lx)\n", Status
);
444 Status
= BuildTokenGroups(&Buffer
->Groups
,
445 (PSID
)AccountDomainSid
,
446 UserInfo
->All
.UserId
,
448 if (!NT_SUCCESS(Status
))
450 WARN("BuildTokenGroups() failed (Status 0x%08lx)\n", Status
);
454 *TokenInformation
= Buffer
;
457 if (!NT_SUCCESS(Status
))
461 if (Buffer
->User
.User
.Sid
!= NULL
)
462 DispatchTable
.FreeLsaHeap(Buffer
->User
.User
.Sid
);
464 if (Buffer
->Groups
!= NULL
)
466 for (i
= 0; i
< Buffer
->Groups
->GroupCount
; i
++)
468 if (Buffer
->Groups
->Groups
[i
].Sid
!= NULL
)
469 DispatchTable
.FreeLsaHeap(Buffer
->Groups
->Groups
[i
].Sid
);
472 DispatchTable
.FreeLsaHeap(Buffer
->Groups
);
475 if (Buffer
->PrimaryGroup
.PrimaryGroup
!= NULL
)
476 DispatchTable
.FreeLsaHeap(Buffer
->PrimaryGroup
.PrimaryGroup
);
478 if (Buffer
->DefaultDacl
.DefaultDacl
!= NULL
)
479 DispatchTable
.FreeLsaHeap(Buffer
->DefaultDacl
.DefaultDacl
);
481 DispatchTable
.FreeLsaHeap(Buffer
);
491 MsvpChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest
,
492 IN PVOID ProtocolSubmitBuffer
,
493 IN PVOID ClientBufferBase
,
494 IN ULONG SubmitBufferLength
,
495 OUT PVOID
*ProtocolReturnBuffer
,
496 OUT PULONG ReturnBufferLength
,
497 OUT PNTSTATUS ProtocolStatus
)
500 PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer
;
503 SAMPR_HANDLE ServerHandle
= NULL
;
504 SAMPR_HANDLE DomainHandle
= NULL
;
505 SAMPR_HANDLE UserHandle
= NULL
;
506 PRPC_SID DomainSid
= NULL
;
507 RPC_UNICODE_STRING Names
[1];
508 SAMPR_ULONG_ARRAY RelativeIds
= {0, NULL
};
509 SAMPR_ULONG_ARRAY Use
= {0, NULL
};
511 ENCRYPTED_NT_OWF_PASSWORD OldNtPassword
;
512 ENCRYPTED_NT_OWF_PASSWORD NewNtPassword
;
513 ENCRYPTED_LM_OWF_PASSWORD OldLmPassword
;
514 ENCRYPTED_LM_OWF_PASSWORD NewLmPassword
;
515 OEM_STRING LmPwdString
;
516 CHAR LmPwdBuffer
[15];
517 BOOLEAN OldLmPasswordPresent
= FALSE
;
518 BOOLEAN NewLmPasswordPresent
= FALSE
;
520 ENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm
;
521 ENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm
;
522 ENCRYPTED_LM_OWF_PASSWORD OldNtEncryptedWithNewNt
;
523 ENCRYPTED_LM_OWF_PASSWORD NewNtEncryptedWithOldNt
;
524 PENCRYPTED_LM_OWF_PASSWORD pOldLmEncryptedWithNewLm
= NULL
;
525 PENCRYPTED_LM_OWF_PASSWORD pNewLmEncryptedWithOldLm
= NULL
;
527 TRACE("MsvpChangePassword()\n");
529 /* Parameters validation */
531 if (SubmitBufferLength
< sizeof(MSV1_0_CHANGEPASSWORD_REQUEST
))
533 ERR("Invalid SubmitBufferLength %lu\n", SubmitBufferLength
);
534 return STATUS_INVALID_PARAMETER
;
537 RequestBuffer
= (PMSV1_0_CHANGEPASSWORD_REQUEST
)ProtocolSubmitBuffer
;
539 /* Fix-up pointers in the request buffer info */
540 PtrOffset
= (ULONG_PTR
)ProtocolSubmitBuffer
- (ULONG_PTR
)ClientBufferBase
;
542 Status
= RtlValidateUnicodeString(0, &RequestBuffer
->DomainName
);
543 if (!NT_SUCCESS(Status
))
544 return STATUS_INVALID_PARAMETER
;
545 // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
546 RequestBuffer
->DomainName
.Buffer
= FIXUP_POINTER(RequestBuffer
->DomainName
.Buffer
, PtrOffset
);
547 RequestBuffer
->DomainName
.MaximumLength
= RequestBuffer
->DomainName
.Length
;
549 Status
= RtlValidateUnicodeString(0, &RequestBuffer
->AccountName
);
550 if (!NT_SUCCESS(Status
))
551 return STATUS_INVALID_PARAMETER
;
552 // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
553 RequestBuffer
->AccountName
.Buffer
= FIXUP_POINTER(RequestBuffer
->AccountName
.Buffer
, PtrOffset
);
554 RequestBuffer
->AccountName
.MaximumLength
= RequestBuffer
->AccountName
.Length
;
556 Status
= RtlValidateUnicodeString(0, &RequestBuffer
->OldPassword
);
557 if (!NT_SUCCESS(Status
))
558 return STATUS_INVALID_PARAMETER
;
559 // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
560 RequestBuffer
->OldPassword
.Buffer
= FIXUP_POINTER(RequestBuffer
->OldPassword
.Buffer
, PtrOffset
);
561 RequestBuffer
->OldPassword
.MaximumLength
= RequestBuffer
->OldPassword
.Length
;
563 Status
= RtlValidateUnicodeString(0, &RequestBuffer
->NewPassword
);
564 if (!NT_SUCCESS(Status
))
565 return STATUS_INVALID_PARAMETER
;
566 // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
567 RequestBuffer
->NewPassword
.Buffer
= FIXUP_POINTER(RequestBuffer
->NewPassword
.Buffer
, PtrOffset
);
568 RequestBuffer
->NewPassword
.MaximumLength
= RequestBuffer
->NewPassword
.Length
;
570 TRACE("Domain: %S\n", RequestBuffer
->DomainName
.Buffer
);
571 TRACE("Account: %S\n", RequestBuffer
->AccountName
.Buffer
);
572 TRACE("Old Password: %S\n", RequestBuffer
->OldPassword
.Buffer
);
573 TRACE("New Password: %S\n", RequestBuffer
->NewPassword
.Buffer
);
575 /* Connect to the SAM server */
576 Status
= SamIConnect(NULL
,
578 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
580 if (!NT_SUCCESS(Status
))
582 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status
);
586 /* Get the domain SID */
587 Status
= SamrLookupDomainInSamServer(ServerHandle
,
588 (PRPC_UNICODE_STRING
)&RequestBuffer
->DomainName
,
590 if (!NT_SUCCESS(Status
))
592 TRACE("SamrLookupDomainInSamServer failed (Status %08lx)\n", Status
);
596 /* Open the domain */
597 Status
= SamrOpenDomain(ServerHandle
,
601 if (!NT_SUCCESS(Status
))
603 TRACE("SamrOpenDomain failed (Status %08lx)\n", Status
);
607 Names
[0].Length
= RequestBuffer
->AccountName
.Length
;
608 Names
[0].MaximumLength
= RequestBuffer
->AccountName
.MaximumLength
;
609 Names
[0].Buffer
= RequestBuffer
->AccountName
.Buffer
;
611 /* Try to get the RID for the user name */
612 Status
= SamrLookupNamesInDomain(DomainHandle
,
617 if (!NT_SUCCESS(Status
))
619 TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status
);
620 Status
= STATUS_NO_SUCH_USER
;
624 /* Fail, if it is not a user account */
625 if (Use
.Element
[0] != SidTypeUser
)
627 TRACE("Account is not a user account!\n");
628 Status
= STATUS_NO_SUCH_USER
;
632 /* Open the user object */
633 Status
= SamrOpenUser(DomainHandle
,
634 USER_CHANGE_PASSWORD
,
635 RelativeIds
.Element
[0],
637 if (!NT_SUCCESS(Status
))
639 TRACE("SamrOpenUser failed (Status %08lx)\n", Status
);
644 /* Calculate the NT hash for the old password */
645 Status
= SystemFunction007(&RequestBuffer
->OldPassword
,
646 (LPBYTE
)&OldNtPassword
);
647 if (!NT_SUCCESS(Status
))
649 TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status
);
653 /* Calculate the NT hash for the new password */
654 Status
= SystemFunction007(&RequestBuffer
->NewPassword
,
655 (LPBYTE
)&NewNtPassword
);
656 if (!NT_SUCCESS(Status
))
658 TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status
);
662 /* Calculate the LM password and hash for the old password */
663 LmPwdString
.Length
= 15;
664 LmPwdString
.MaximumLength
= 15;
665 LmPwdString
.Buffer
= LmPwdBuffer
;
666 ZeroMemory(LmPwdString
.Buffer
, LmPwdString
.MaximumLength
);
668 Status
= RtlUpcaseUnicodeStringToOemString(&LmPwdString
,
669 &RequestBuffer
->OldPassword
,
671 if (NT_SUCCESS(Status
))
673 /* Calculate the LM hash value of the password */
674 Status
= SystemFunction006(LmPwdString
.Buffer
,
675 (LPSTR
)&OldLmPassword
);
676 if (NT_SUCCESS(Status
))
678 OldLmPasswordPresent
= TRUE
;
682 /* Calculate the LM password and hash for the new password */
683 LmPwdString
.Length
= 15;
684 LmPwdString
.MaximumLength
= 15;
685 LmPwdString
.Buffer
= LmPwdBuffer
;
686 ZeroMemory(LmPwdString
.Buffer
, LmPwdString
.MaximumLength
);
688 Status
= RtlUpcaseUnicodeStringToOemString(&LmPwdString
,
689 &RequestBuffer
->NewPassword
,
691 if (NT_SUCCESS(Status
))
693 /* Calculate the LM hash value of the password */
694 Status
= SystemFunction006(LmPwdString
.Buffer
,
695 (LPSTR
)&NewLmPassword
);
696 if (NT_SUCCESS(Status
))
698 NewLmPasswordPresent
= TRUE
;
702 /* Encrypt the old and new LM passwords, if they exist */
703 if (OldLmPasswordPresent
&& NewLmPasswordPresent
)
705 /* Encrypt the old LM password */
706 Status
= SystemFunction012((const BYTE
*)&OldLmPassword
,
707 (const BYTE
*)&NewLmPassword
,
708 (LPBYTE
)&OldLmEncryptedWithNewLm
);
709 if (!NT_SUCCESS(Status
))
711 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status
);
715 /* Encrypt the new LM password */
716 Status
= SystemFunction012((const BYTE
*)&NewLmPassword
,
717 (const BYTE
*)&OldLmPassword
,
718 (LPBYTE
)&NewLmEncryptedWithOldLm
);
719 if (!NT_SUCCESS(Status
))
721 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status
);
725 pOldLmEncryptedWithNewLm
= &OldLmEncryptedWithNewLm
;
726 pNewLmEncryptedWithOldLm
= &NewLmEncryptedWithOldLm
;
729 /* Encrypt the old NT password */
730 Status
= SystemFunction012((const BYTE
*)&OldNtPassword
,
731 (const BYTE
*)&NewNtPassword
,
732 (LPBYTE
)&OldNtEncryptedWithNewNt
);
733 if (!NT_SUCCESS(Status
))
735 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status
);
739 /* Encrypt the new NT password */
740 Status
= SystemFunction012((const BYTE
*)&NewNtPassword
,
741 (const BYTE
*)&OldNtPassword
,
742 (LPBYTE
)&NewNtEncryptedWithOldNt
);
743 if (!NT_SUCCESS(Status
))
745 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status
);
749 /* Change the password */
750 Status
= SamrChangePasswordUser(UserHandle
,
751 OldLmPasswordPresent
&& NewLmPasswordPresent
,
752 pOldLmEncryptedWithNewLm
,
753 pNewLmEncryptedWithOldLm
,
755 &OldNtEncryptedWithNewNt
,
756 &NewNtEncryptedWithOldNt
,
761 if (!NT_SUCCESS(Status
))
763 TRACE("SamrChangePasswordUser failed (Status %08lx)\n", Status
);
768 if (UserHandle
!= NULL
)
769 SamrCloseHandle(&UserHandle
);
771 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds
);
772 SamIFree_SAMPR_ULONG_ARRAY(&Use
);
774 if (DomainHandle
!= NULL
)
775 SamrCloseHandle(&DomainHandle
);
777 if (DomainSid
!= NULL
)
778 SamIFreeVoid(DomainSid
);
780 if (ServerHandle
!= NULL
)
781 SamrCloseHandle(&ServerHandle
);
789 MsvpCheckPassword(PUNICODE_STRING UserPassword
,
790 PSAMPR_USER_INFO_BUFFER UserInfo
)
792 ENCRYPTED_NT_OWF_PASSWORD UserNtPassword
;
793 ENCRYPTED_LM_OWF_PASSWORD UserLmPassword
;
794 BOOLEAN UserLmPasswordPresent
= FALSE
;
795 BOOLEAN UserNtPasswordPresent
= FALSE
;
796 OEM_STRING LmPwdString
;
797 CHAR LmPwdBuffer
[15];
800 TRACE("(%p %p)\n", UserPassword
, UserInfo
);
802 /* Calculate the LM password and hash for the users password */
803 LmPwdString
.Length
= 15;
804 LmPwdString
.MaximumLength
= 15;
805 LmPwdString
.Buffer
= LmPwdBuffer
;
806 ZeroMemory(LmPwdString
.Buffer
, LmPwdString
.MaximumLength
);
808 Status
= RtlUpcaseUnicodeStringToOemString(&LmPwdString
,
811 if (NT_SUCCESS(Status
))
813 /* Calculate the LM hash value of the users password */
814 Status
= SystemFunction006(LmPwdString
.Buffer
,
815 (LPSTR
)&UserLmPassword
);
816 if (NT_SUCCESS(Status
))
818 UserLmPasswordPresent
= TRUE
;
822 /* Calculate the NT hash of the users password */
823 Status
= SystemFunction007(UserPassword
,
824 (LPBYTE
)&UserNtPassword
);
825 if (NT_SUCCESS(Status
))
827 UserNtPasswordPresent
= TRUE
;
830 Status
= STATUS_WRONG_PASSWORD
;
832 /* Succeed, if no password has been set */
833 if (UserInfo
->All
.NtPasswordPresent
== FALSE
&&
834 UserInfo
->All
.LmPasswordPresent
== FALSE
)
836 TRACE("No password check!\n");
837 Status
= STATUS_SUCCESS
;
841 /* Succeed, if NT password matches */
842 if (UserNtPasswordPresent
&& UserInfo
->All
.NtPasswordPresent
)
844 TRACE("Check NT password hashes:\n");
845 if (RtlEqualMemory(&UserNtPassword
,
846 UserInfo
->All
.NtOwfPassword
.Buffer
,
847 sizeof(ENCRYPTED_NT_OWF_PASSWORD
)))
849 TRACE(" success!\n");
850 Status
= STATUS_SUCCESS
;
857 /* Succeed, if LM password matches */
858 if (UserLmPasswordPresent
&& UserInfo
->All
.LmPasswordPresent
)
860 TRACE("Check LM password hashes:\n");
861 if (RtlEqualMemory(&UserLmPassword
,
862 UserInfo
->All
.LmOwfPassword
.Buffer
,
863 sizeof(ENCRYPTED_LM_OWF_PASSWORD
)))
865 TRACE(" success!\n");
866 Status
= STATUS_SUCCESS
;
880 _In_ PSAMPR_LOGON_HOURS LogonHours
,
881 _In_ PLARGE_INTEGER LogonTime
)
884 LARGE_INTEGER LocalLogonTime
;
885 TIME_FIELDS TimeFields
;
886 USHORT MinutesPerUnit
, Offset
;
889 FIXME("MsvpCheckLogonHours(%p %p)\n", LogonHours
, LogonTime
);
891 if (LogonHours
->UnitsPerWeek
== 0 || LogonHours
->LogonHours
== NULL
)
893 FIXME("No logon hours!\n");
897 RtlSystemTimeToLocalTime(LogonTime
, &LocalLogonTime
);
898 RtlTimeToTimeFields(&LocalLogonTime
, &TimeFields
);
900 FIXME("UnitsPerWeek: %u\n", LogonHours
->UnitsPerWeek
);
901 MinutesPerUnit
= 10080 / LogonHours
->UnitsPerWeek
;
903 Offset
= ((TimeFields
.Weekday
* 24 + TimeFields
.Hour
) * 60 + TimeFields
.Minute
) / MinutesPerUnit
;
904 FIXME("Offset: %us\n", Offset
);
906 bFound
= (BOOL
)(LogonHours
->LogonHours
[Offset
/ 8] & (1 << (Offset
% 8)));
907 FIXME("Logon permitted: %s\n", bFound
? "Yes" : "No");
917 MsvpCheckWorkstations(
918 _In_ PRPC_UNICODE_STRING WorkStations
,
919 _In_ PWSTR ComputerName
)
924 TRACE("MsvpCheckWorkstations(%p %S)\n", WorkStations
, ComputerName
);
926 if (WorkStations
->Length
== 0 || WorkStations
->Buffer
== NULL
)
928 TRACE("No workstations!\n");
932 TRACE("Workstations: %wZ\n", WorkStations
);
934 pStart
= WorkStations
->Buffer
;
937 pEnd
= wcschr(pStart
, L
',');
939 *pEnd
= UNICODE_NULL
;
941 TRACE("Comparing '%S' and '%S'\n", ComputerName
, pStart
);
942 if (_wcsicmp(ComputerName
, pStart
) == 0)
957 TRACE("Found allowed workstation: %s\n", (bFound
) ? "Yes" : "No");
968 LsaApCallPackage(IN PLSA_CLIENT_REQUEST ClientRequest
,
969 IN PVOID ProtocolSubmitBuffer
,
970 IN PVOID ClientBufferBase
,
971 IN ULONG SubmitBufferLength
,
972 OUT PVOID
*ProtocolReturnBuffer
,
973 OUT PULONG ReturnBufferLength
,
974 OUT PNTSTATUS ProtocolStatus
)
977 MSV1_0_PROTOCOL_MESSAGE_TYPE MessageType
;
979 TRACE("LsaApCallPackage()\n");
981 if (SubmitBufferLength
< sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE
))
982 return STATUS_INVALID_PARAMETER
;
984 MessageType
= *((PMSV1_0_PROTOCOL_MESSAGE_TYPE
)ProtocolSubmitBuffer
);
986 *ProtocolReturnBuffer
= NULL
;
987 *ReturnBufferLength
= 0;
991 case MsV1_0Lm20ChallengeRequest
:
992 case MsV1_0Lm20GetChallengeResponse
:
993 Status
= STATUS_NOT_IMPLEMENTED
;
996 case MsV1_0EnumerateUsers
:
997 case MsV1_0GetUserInfo
:
998 case MsV1_0ReLogonUsers
:
999 Status
= STATUS_INVALID_PARAMETER
;
1002 case MsV1_0ChangePassword
:
1003 Status
= MsvpChangePassword(ClientRequest
,
1004 ProtocolSubmitBuffer
,
1007 ProtocolReturnBuffer
,
1012 case MsV1_0ChangeCachedPassword
:
1013 case MsV1_0GenericPassthrough
:
1014 case MsV1_0CacheLogon
:
1016 case MsV1_0DeriveCredential
:
1017 case MsV1_0CacheLookup
:
1018 Status
= STATUS_NOT_IMPLEMENTED
;
1022 return STATUS_INVALID_PARAMETER
;
1034 LsaApCallPackagePassthrough(IN PLSA_CLIENT_REQUEST ClientRequest
,
1035 IN PVOID ProtocolSubmitBuffer
,
1036 IN PVOID ClientBufferBase
,
1037 IN ULONG SubmitBufferLength
,
1038 OUT PVOID
*ProtocolReturnBuffer
,
1039 OUT PULONG ReturnBufferLength
,
1040 OUT PNTSTATUS ProtocolStatus
)
1042 TRACE("LsaApCallPackagePassthrough()\n");
1043 return STATUS_NOT_IMPLEMENTED
;
1052 LsaApCallPackageUntrusted(IN PLSA_CLIENT_REQUEST ClientRequest
,
1053 IN PVOID ProtocolSubmitBuffer
,
1054 IN PVOID ClientBufferBase
,
1055 IN ULONG SubmitBufferLength
,
1056 OUT PVOID
*ProtocolReturnBuffer
,
1057 OUT PULONG ReturnBufferLength
,
1058 OUT PNTSTATUS ProtocolStatus
)
1063 TRACE("LsaApCallPackageUntrusted()\n");
1065 if (SubmitBufferLength
< sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE
))
1066 return STATUS_INVALID_PARAMETER
;
1068 MessageType
= (ULONG
)*((PMSV1_0_PROTOCOL_MESSAGE_TYPE
)ProtocolSubmitBuffer
);
1070 *ProtocolReturnBuffer
= NULL
;
1071 *ReturnBufferLength
= 0;
1073 if (MessageType
== MsV1_0ChangePassword
)
1074 Status
= MsvpChangePassword(ClientRequest
,
1075 ProtocolSubmitBuffer
,
1078 ProtocolReturnBuffer
,
1082 Status
= STATUS_ACCESS_DENIED
;
1093 LsaApInitializePackage(IN ULONG AuthenticationPackageId
,
1094 IN PLSA_DISPATCH_TABLE LsaDispatchTable
,
1095 IN PLSA_STRING Database OPTIONAL
,
1096 IN PLSA_STRING Confidentiality OPTIONAL
,
1097 OUT PLSA_STRING
*AuthenticationPackageName
)
1099 PANSI_STRING NameString
;
1102 TRACE("LsaApInitializePackage(%lu %p %p %p %p)\n",
1103 AuthenticationPackageId
, LsaDispatchTable
, Database
,
1104 Confidentiality
, AuthenticationPackageName
);
1106 /* Get the dispatch table entries */
1107 DispatchTable
.CreateLogonSession
= LsaDispatchTable
->CreateLogonSession
;
1108 DispatchTable
.DeleteLogonSession
= LsaDispatchTable
->DeleteLogonSession
;
1109 DispatchTable
.AddCredential
= LsaDispatchTable
->AddCredential
;
1110 DispatchTable
.GetCredentials
= LsaDispatchTable
->GetCredentials
;
1111 DispatchTable
.DeleteCredential
= LsaDispatchTable
->DeleteCredential
;
1112 DispatchTable
.AllocateLsaHeap
= LsaDispatchTable
->AllocateLsaHeap
;
1113 DispatchTable
.FreeLsaHeap
= LsaDispatchTable
->FreeLsaHeap
;
1114 DispatchTable
.AllocateClientBuffer
= LsaDispatchTable
->AllocateClientBuffer
;
1115 DispatchTable
.FreeClientBuffer
= LsaDispatchTable
->FreeClientBuffer
;
1116 DispatchTable
.CopyToClientBuffer
= LsaDispatchTable
->CopyToClientBuffer
;
1117 DispatchTable
.CopyFromClientBuffer
= LsaDispatchTable
->CopyFromClientBuffer
;
1119 /* Return the package name */
1120 NameString
= DispatchTable
.AllocateLsaHeap(sizeof(LSA_STRING
));
1121 if (NameString
== NULL
)
1122 return STATUS_INSUFFICIENT_RESOURCES
;
1124 NameBuffer
= DispatchTable
.AllocateLsaHeap(sizeof(MSV1_0_PACKAGE_NAME
));
1125 if (NameBuffer
== NULL
)
1127 DispatchTable
.FreeLsaHeap(NameString
);
1128 return STATUS_INSUFFICIENT_RESOURCES
;
1131 strcpy(NameBuffer
, MSV1_0_PACKAGE_NAME
);
1133 RtlInitAnsiString(NameString
, NameBuffer
);
1135 *AuthenticationPackageName
= (PLSA_STRING
)NameString
;
1137 return STATUS_SUCCESS
;
1146 LsaApLogonTerminated(IN PLUID LogonId
)
1148 TRACE("LsaApLogonTerminated()\n");
1157 LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest
,
1158 IN SECURITY_LOGON_TYPE LogonType
,
1159 IN PVOID ProtocolSubmitBuffer
,
1160 IN PVOID ClientBufferBase
,
1161 IN ULONG SubmitBufferSize
,
1162 OUT PVOID
*ProfileBuffer
,
1163 OUT PULONG ProfileBufferSize
,
1165 OUT PNTSTATUS SubStatus
,
1166 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType
,
1167 OUT PVOID
*TokenInformation
,
1168 OUT PUNICODE_STRING
*AccountName
,
1169 OUT PUNICODE_STRING
*AuthenticatingAuthority
,
1170 OUT PUNICODE_STRING
*MachineName
,
1171 OUT PSECPKG_PRIMARY_CRED PrimaryCredentials
, /* Not supported yet */
1172 OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY
*SupplementalCredentials
) /* Not supported yet */
1174 static const UNICODE_STRING NtAuthorityU
= RTL_CONSTANT_STRING(L
"NT AUTHORITY");
1175 static const UNICODE_STRING LocalServiceU
= RTL_CONSTANT_STRING(L
"LocalService");
1176 static const UNICODE_STRING NetworkServiceU
= RTL_CONSTANT_STRING(L
"NetworkService");
1179 PMSV1_0_INTERACTIVE_LOGON LogonInfo
;
1180 WCHAR ComputerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1181 SAMPR_HANDLE ServerHandle
= NULL
;
1182 SAMPR_HANDLE DomainHandle
= NULL
;
1183 SAMPR_HANDLE UserHandle
= NULL
;
1184 PRPC_SID AccountDomainSid
= NULL
;
1185 RPC_UNICODE_STRING Names
[1];
1186 SAMPR_ULONG_ARRAY RelativeIds
= {0, NULL
};
1187 SAMPR_ULONG_ARRAY Use
= {0, NULL
};
1188 PSAMPR_USER_INFO_BUFFER UserInfo
= NULL
;
1189 BOOLEAN SessionCreated
= FALSE
;
1190 LARGE_INTEGER LogonTime
;
1191 LARGE_INTEGER AccountExpires
;
1192 LARGE_INTEGER PasswordMustChange
;
1193 LARGE_INTEGER PasswordLastSet
;
1194 DWORD ComputerNameSize
;
1195 BOOL SpecialAccount
= FALSE
;
1197 TRACE("LsaApLogonUserEx2()\n");
1199 TRACE("LogonType: %lu\n", LogonType
);
1200 TRACE("ProtocolSubmitBuffer: %p\n", ProtocolSubmitBuffer
);
1201 TRACE("SubmitBufferSize: %lu\n", SubmitBufferSize
);
1203 *ProfileBuffer
= NULL
;
1204 *ProfileBufferSize
= 0;
1205 *SubStatus
= STATUS_SUCCESS
;
1206 *AccountName
= NULL
;
1207 *AuthenticatingAuthority
= NULL
;
1209 /* Parameters validation */
1210 if (LogonType
== Interactive
||
1211 LogonType
== Batch
||
1212 LogonType
== Service
)
1214 ULONG_PTR PtrOffset
;
1216 if (SubmitBufferSize
< sizeof(MSV1_0_INTERACTIVE_LOGON
))
1218 ERR("Invalid SubmitBufferSize %lu\n", SubmitBufferSize
);
1219 return STATUS_INVALID_PARAMETER
;
1222 LogonInfo
= (PMSV1_0_INTERACTIVE_LOGON
)ProtocolSubmitBuffer
;
1224 if (LogonInfo
->MessageType
!= MsV1_0InteractiveLogon
&&
1225 LogonInfo
->MessageType
!= MsV1_0WorkstationUnlockLogon
)
1227 ERR("Invalid MessageType %lu\n", LogonInfo
->MessageType
);
1228 return STATUS_BAD_VALIDATION_CLASS
;
1231 #if 0 // FIXME: These checks happen to be done on Windows. We however keep them general on ReactOS for now...
1232 if (LogonInfo
->UserName
.Length
> 512) // CRED_MAX_STRING_LENGTH * sizeof(WCHAR) or (CREDUI_MAX_USERNAME_LENGTH (== CRED_MAX_USERNAME_LENGTH) - 1) * sizeof(WCHAR)
1234 ERR("UserName too long (%lu, maximum 512)\n", LogonInfo
->UserName
.Length
);
1235 return STATUS_NAME_TOO_LONG
;
1237 if (LogonInfo
->Password
.Length
> 512) // CREDUI_MAX_PASSWORD_LENGTH * sizeof(WCHAR)
1239 ERR("Password too long (%lu, maximum 512)\n", LogonInfo
->Password
.Length
);
1240 return STATUS_NAME_TOO_LONG
;
1244 /* Fix-up pointers in the authentication info */
1245 PtrOffset
= (ULONG_PTR
)ProtocolSubmitBuffer
- (ULONG_PTR
)ClientBufferBase
;
1247 Status
= RtlValidateUnicodeString(0, &LogonInfo
->LogonDomainName
);
1248 if (!NT_SUCCESS(Status
))
1249 return STATUS_INVALID_PARAMETER
;
1250 /* LogonDomainName is optional and can be an empty string */
1251 if (LogonInfo
->LogonDomainName
.Length
)
1253 // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
1254 LogonInfo
->LogonDomainName
.Buffer
= FIXUP_POINTER(LogonInfo
->LogonDomainName
.Buffer
, PtrOffset
);
1255 LogonInfo
->LogonDomainName
.MaximumLength
= LogonInfo
->LogonDomainName
.Length
;
1259 LogonInfo
->LogonDomainName
.Buffer
= NULL
;
1260 LogonInfo
->LogonDomainName
.MaximumLength
= 0;
1263 Status
= RtlValidateUnicodeString(0, &LogonInfo
->UserName
);
1264 if (!NT_SUCCESS(Status
))
1265 return STATUS_INVALID_PARAMETER
;
1266 /* UserName is mandatory and cannot be an empty string */
1267 // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
1268 LogonInfo
->UserName
.Buffer
= FIXUP_POINTER(LogonInfo
->UserName
.Buffer
, PtrOffset
);
1269 LogonInfo
->UserName
.MaximumLength
= LogonInfo
->UserName
.Length
;
1271 Status
= RtlValidateUnicodeString(0, &LogonInfo
->Password
);
1272 if (!NT_SUCCESS(Status
))
1273 return STATUS_INVALID_PARAMETER
;
1274 /* Password is optional and can be an empty string */
1275 if (LogonInfo
->Password
.Length
)
1277 // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
1278 LogonInfo
->Password
.Buffer
= FIXUP_POINTER(LogonInfo
->Password
.Buffer
, PtrOffset
);
1279 LogonInfo
->Password
.MaximumLength
= LogonInfo
->Password
.Length
;
1283 LogonInfo
->Password
.Buffer
= NULL
;
1284 LogonInfo
->Password
.MaximumLength
= 0;
1287 TRACE("Domain: %S\n", LogonInfo
->LogonDomainName
.Buffer
);
1288 TRACE("User: %S\n", LogonInfo
->UserName
.Buffer
);
1289 TRACE("Password: %S\n", LogonInfo
->Password
.Buffer
);
1291 // TODO: If LogonType == Service, do some extra work using LogonInfo->Password.
1295 FIXME("LogonType %lu is not supported yet!\n", LogonType
);
1296 return STATUS_NOT_IMPLEMENTED
;
1298 // TODO: Add other LogonType validity checks.
1300 /* Get the logon time */
1301 NtQuerySystemTime(&LogonTime
);
1303 /* Get the computer name */
1304 ComputerNameSize
= ARRAYSIZE(ComputerName
);
1305 GetComputerNameW(ComputerName
, &ComputerNameSize
);
1307 /* Check for special accounts */
1308 // FIXME: Windows does not do this that way!! (msv1_0 does not contain these hardcoded values)
1309 if (RtlEqualUnicodeString(&LogonInfo
->LogonDomainName
, &NtAuthorityU
, TRUE
))
1311 SpecialAccount
= TRUE
;
1313 /* Get the authority domain SID */
1314 Status
= GetNtAuthorityDomainSid(&AccountDomainSid
);
1315 if (!NT_SUCCESS(Status
))
1317 ERR("GetNtAuthorityDomainSid() failed (Status 0x%08lx)\n", Status
);
1321 if (RtlEqualUnicodeString(&LogonInfo
->UserName
, &LocalServiceU
, TRUE
))
1323 TRACE("SpecialAccount: LocalService\n");
1325 if (LogonType
!= Service
)
1326 return STATUS_LOGON_FAILURE
;
1328 UserInfo
= RtlAllocateHeap(RtlGetProcessHeap(),
1330 sizeof(SAMPR_USER_ALL_INFORMATION
));
1331 if (UserInfo
== NULL
)
1333 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1337 UserInfo
->All
.UserId
= SECURITY_LOCAL_SERVICE_RID
;
1338 UserInfo
->All
.PrimaryGroupId
= SECURITY_LOCAL_SERVICE_RID
;
1340 else if (RtlEqualUnicodeString(&LogonInfo
->UserName
, &NetworkServiceU
, TRUE
))
1342 TRACE("SpecialAccount: NetworkService\n");
1344 if (LogonType
!= Service
)
1345 return STATUS_LOGON_FAILURE
;
1347 UserInfo
= RtlAllocateHeap(RtlGetProcessHeap(),
1349 sizeof(SAMPR_USER_ALL_INFORMATION
));
1350 if (UserInfo
== NULL
)
1352 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1356 UserInfo
->All
.UserId
= SECURITY_NETWORK_SERVICE_RID
;
1357 UserInfo
->All
.PrimaryGroupId
= SECURITY_NETWORK_SERVICE_RID
;
1361 Status
= STATUS_NO_SUCH_USER
;
1367 TRACE("NormalAccount\n");
1369 /* Get the account domain SID */
1370 Status
= GetAccountDomainSid(&AccountDomainSid
);
1371 if (!NT_SUCCESS(Status
))
1373 ERR("GetAccountDomainSid() failed (Status 0x%08lx)\n", Status
);
1377 /* Connect to the SAM server */
1378 Status
= SamIConnect(NULL
,
1380 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
1382 if (!NT_SUCCESS(Status
))
1384 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status
);
1388 /* Open the account domain */
1389 Status
= SamrOpenDomain(ServerHandle
,
1393 if (!NT_SUCCESS(Status
))
1395 ERR("SamrOpenDomain failed (Status %08lx)\n", Status
);
1399 Names
[0].Length
= LogonInfo
->UserName
.Length
;
1400 Names
[0].MaximumLength
= LogonInfo
->UserName
.MaximumLength
;
1401 Names
[0].Buffer
= LogonInfo
->UserName
.Buffer
;
1403 /* Try to get the RID for the user name */
1404 Status
= SamrLookupNamesInDomain(DomainHandle
,
1409 if (!NT_SUCCESS(Status
))
1411 ERR("SamrLookupNamesInDomain failed (Status %08lx)\n", Status
);
1412 Status
= STATUS_NO_SUCH_USER
;
1416 /* Fail, if it is not a user account */
1417 if (Use
.Element
[0] != SidTypeUser
)
1419 ERR("Account is not a user account!\n");
1420 Status
= STATUS_NO_SUCH_USER
;
1424 /* Open the user object */
1425 Status
= SamrOpenUser(DomainHandle
,
1426 USER_READ_GENERAL
| USER_READ_LOGON
|
1427 USER_READ_ACCOUNT
| USER_READ_PREFERENCES
, /* FIXME */
1428 RelativeIds
.Element
[0],
1430 if (!NT_SUCCESS(Status
))
1432 ERR("SamrOpenUser failed (Status %08lx)\n", Status
);
1436 Status
= SamrQueryInformationUser(UserHandle
,
1439 if (!NT_SUCCESS(Status
))
1441 ERR("SamrQueryInformationUser failed (Status %08lx)\n", Status
);
1445 TRACE("UserName: %S\n", UserInfo
->All
.UserName
.Buffer
);
1447 /* Check the password */
1448 if ((UserInfo
->All
.UserAccountControl
& USER_PASSWORD_NOT_REQUIRED
) == 0)
1450 Status
= MsvpCheckPassword(&LogonInfo
->Password
,
1452 if (!NT_SUCCESS(Status
))
1454 ERR("MsvpCheckPassword failed (Status %08lx)\n", Status
);
1459 /* Check account restrictions for non-administrator accounts */
1460 if (RelativeIds
.Element
[0] != DOMAIN_USER_RID_ADMIN
)
1462 /* Check if the account has been disabled */
1463 if (UserInfo
->All
.UserAccountControl
& USER_ACCOUNT_DISABLED
)
1465 ERR("Account disabled!\n");
1466 *SubStatus
= STATUS_ACCOUNT_DISABLED
;
1467 Status
= STATUS_ACCOUNT_RESTRICTION
;
1471 /* Check if the account has been locked */
1472 if (UserInfo
->All
.UserAccountControl
& USER_ACCOUNT_AUTO_LOCKED
)
1474 ERR("Account locked!\n");
1475 *SubStatus
= STATUS_ACCOUNT_LOCKED_OUT
;
1476 Status
= STATUS_ACCOUNT_RESTRICTION
;
1480 /* Check if the account expired */
1481 AccountExpires
.LowPart
= UserInfo
->All
.AccountExpires
.LowPart
;
1482 AccountExpires
.HighPart
= UserInfo
->All
.AccountExpires
.HighPart
;
1483 if (LogonTime
.QuadPart
>= AccountExpires
.QuadPart
)
1485 ERR("Account expired!\n");
1486 *SubStatus
= STATUS_ACCOUNT_EXPIRED
;
1487 Status
= STATUS_ACCOUNT_RESTRICTION
;
1491 /* Check if the password expired */
1492 PasswordMustChange
.LowPart
= UserInfo
->All
.PasswordMustChange
.LowPart
;
1493 PasswordMustChange
.HighPart
= UserInfo
->All
.PasswordMustChange
.HighPart
;
1494 PasswordLastSet
.LowPart
= UserInfo
->All
.PasswordLastSet
.LowPart
;
1495 PasswordLastSet
.HighPart
= UserInfo
->All
.PasswordLastSet
.HighPart
;
1497 if (LogonTime
.QuadPart
>= PasswordMustChange
.QuadPart
)
1499 ERR("Password expired!\n");
1500 if (PasswordLastSet
.QuadPart
== 0)
1501 *SubStatus
= STATUS_PASSWORD_MUST_CHANGE
;
1503 *SubStatus
= STATUS_PASSWORD_EXPIRED
;
1505 Status
= STATUS_ACCOUNT_RESTRICTION
;
1509 /* Check logon hours */
1510 if (!MsvpCheckLogonHours(&UserInfo
->All
.LogonHours
, &LogonTime
))
1512 ERR("Invalid logon hours!\n");
1513 *SubStatus
= STATUS_INVALID_LOGON_HOURS
;
1514 Status
= STATUS_ACCOUNT_RESTRICTION
;
1518 /* Check workstations */
1519 if (!MsvpCheckWorkstations(&UserInfo
->All
.WorkStations
, ComputerName
))
1521 ERR("Invalid workstation!\n");
1522 *SubStatus
= STATUS_INVALID_WORKSTATION
;
1523 Status
= STATUS_ACCOUNT_RESTRICTION
;
1529 /* Return logon information */
1531 /* Create and return a new logon id */
1532 Status
= NtAllocateLocallyUniqueId(LogonId
);
1533 if (!NT_SUCCESS(Status
))
1535 TRACE("NtAllocateLocallyUniqueId failed (Status %08lx)\n", Status
);
1539 /* Create the logon session */
1540 Status
= DispatchTable
.CreateLogonSession(LogonId
);
1541 if (!NT_SUCCESS(Status
))
1543 TRACE("CreateLogonSession failed (Status %08lx)\n", Status
);
1547 SessionCreated
= TRUE
;
1549 /* Build and fill the interactive profile buffer */
1550 Status
= BuildInteractiveProfileBuffer(ClientRequest
,
1553 (PMSV1_0_INTERACTIVE_PROFILE
*)ProfileBuffer
,
1555 if (!NT_SUCCESS(Status
))
1557 TRACE("BuildInteractiveProfileBuffer failed (Status %08lx)\n", Status
);
1561 /* Return the token information type */
1562 *TokenInformationType
= LsaTokenInformationV1
;
1564 /* Build and fill the token information buffer */
1565 Status
= BuildTokenInformationBuffer((PLSA_TOKEN_INFORMATION_V1
*)TokenInformation
,
1569 if (!NT_SUCCESS(Status
))
1571 TRACE("BuildTokenInformationBuffer failed (Status %08lx)\n", Status
);
1576 /* Update the logon time/count or the bad password time/count */
1577 if ((UserHandle
!= NULL
) &&
1578 (Status
== STATUS_SUCCESS
|| Status
== STATUS_WRONG_PASSWORD
))
1580 SAMPR_USER_INFO_BUFFER InternalInfo
;
1582 RtlZeroMemory(&InternalInfo
, sizeof(InternalInfo
));
1584 if (Status
== STATUS_SUCCESS
)
1585 InternalInfo
.Internal2
.Flags
= USER_LOGON_SUCCESS
;
1587 InternalInfo
.Internal2
.Flags
= USER_LOGON_BAD_PASSWORD
;
1589 SamrSetInformationUser(UserHandle
,
1590 UserInternal2Information
,
1594 /* Return the account name */
1595 *AccountName
= DispatchTable
.AllocateLsaHeap(sizeof(UNICODE_STRING
));
1596 if (*AccountName
!= NULL
)
1598 (*AccountName
)->Buffer
= DispatchTable
.AllocateLsaHeap(LogonInfo
->UserName
.Length
+
1599 sizeof(UNICODE_NULL
));
1600 if ((*AccountName
)->Buffer
!= NULL
)
1602 (*AccountName
)->MaximumLength
= LogonInfo
->UserName
.Length
+
1603 sizeof(UNICODE_NULL
);
1604 RtlCopyUnicodeString(*AccountName
, &LogonInfo
->UserName
);
1608 /* Return the authenticating authority */
1609 *AuthenticatingAuthority
= DispatchTable
.AllocateLsaHeap(sizeof(UNICODE_STRING
));
1610 if (*AuthenticatingAuthority
!= NULL
)
1612 (*AuthenticatingAuthority
)->Buffer
= DispatchTable
.AllocateLsaHeap(LogonInfo
->LogonDomainName
.Length
+
1613 sizeof(UNICODE_NULL
));
1614 if ((*AuthenticatingAuthority
)->Buffer
!= NULL
)
1616 (*AuthenticatingAuthority
)->MaximumLength
= LogonInfo
->LogonDomainName
.Length
+
1617 sizeof(UNICODE_NULL
);
1618 RtlCopyUnicodeString(*AuthenticatingAuthority
, &LogonInfo
->LogonDomainName
);
1622 /* Return the machine name */
1623 *MachineName
= DispatchTable
.AllocateLsaHeap(sizeof(UNICODE_STRING
));
1624 if (*MachineName
!= NULL
)
1626 (*MachineName
)->Buffer
= DispatchTable
.AllocateLsaHeap((ComputerNameSize
+ 1) * sizeof(WCHAR
));
1627 if ((*MachineName
)->Buffer
!= NULL
)
1629 (*MachineName
)->MaximumLength
= (ComputerNameSize
+ 1) * sizeof(WCHAR
);
1630 (*MachineName
)->Length
= ComputerNameSize
* sizeof(WCHAR
);
1631 RtlCopyMemory((*MachineName
)->Buffer
, ComputerName
, (*MachineName
)->MaximumLength
);
1635 if (!NT_SUCCESS(Status
))
1637 if (SessionCreated
!= FALSE
)
1638 DispatchTable
.DeleteLogonSession(LogonId
);
1640 if (*ProfileBuffer
!= NULL
)
1642 DispatchTable
.FreeClientBuffer(ClientRequest
,
1644 *ProfileBuffer
= NULL
;
1648 if (UserHandle
!= NULL
)
1649 SamrCloseHandle(&UserHandle
);
1651 SamIFree_SAMPR_USER_INFO_BUFFER(UserInfo
,
1652 UserAllInformation
);
1653 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds
);
1654 SamIFree_SAMPR_ULONG_ARRAY(&Use
);
1656 if (DomainHandle
!= NULL
)
1657 SamrCloseHandle(&DomainHandle
);
1659 if (ServerHandle
!= NULL
)
1660 SamrCloseHandle(&ServerHandle
);
1662 if (AccountDomainSid
!= NULL
)
1663 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid
);
1665 if (Status
== STATUS_NO_SUCH_USER
||
1666 Status
== STATUS_WRONG_PASSWORD
)
1668 *SubStatus
= Status
;
1669 Status
= STATUS_LOGON_FAILURE
;
1672 TRACE("LsaApLogonUserEx2 done (Status 0x%08lx, SubStatus 0x%08lx)\n", Status
, *SubStatus
);
1683 SpLsaModeInitialize(
1684 _In_ ULONG LsaVersion
,
1685 _Out_ PULONG PackageVersion
,
1686 _Out_ PSECPKG_FUNCTION_TABLE
*ppTables
,
1687 _Out_ PULONG pcTables
)
1689 SECPKG_FUNCTION_TABLE Tables
[1];
1691 TRACE("SpLsaModeInitialize(0x%lx %p %p %p)\n",
1692 LsaVersion
, PackageVersion
, ppTables
, pcTables
);
1694 if (LsaVersion
!= SECPKG_INTERFACE_VERSION
)
1695 return STATUS_INVALID_PARAMETER
;
1697 *PackageVersion
= SECPKG_INTERFACE_VERSION
;
1699 RtlZeroMemory(&Tables
, sizeof(Tables
));
1701 Tables
[0].InitializePackage
= LsaApInitializePackage
;
1702 // Tables[0].LogonUser = NULL;
1703 Tables
[0].CallPackage
= (PLSA_AP_CALL_PACKAGE
)LsaApCallPackage
;
1704 Tables
[0].LogonTerminated
= LsaApLogonTerminated
;
1705 Tables
[0].CallPackageUntrusted
= LsaApCallPackageUntrusted
;
1706 Tables
[0].CallPackagePassthrough
= (PLSA_AP_CALL_PACKAGE_PASSTHROUGH
)LsaApCallPackagePassthrough
;
1707 // Tables[0].LogonUserEx = NULL;
1708 Tables
[0].LogonUserEx2
= LsaApLogonUserEx2
;
1709 // Tables[0].Initialize = SpInitialize;
1710 // Tables[0].Shutdown = NULL;
1711 // Tables[0].GetInfo = NULL;
1712 // Tables[0].AcceptCredentials = NULL;
1713 // Tables[0].SpAcquireCredentialsHandle = NULL;
1714 // Tables[0].SpQueryCredentialsAttributes = NULL;
1715 // Tables[0].FreeCredentialsHandle = NULL;
1716 // Tables[0].SaveCredentials = NULL;
1717 // Tables[0].GetCredentials = NULL;
1718 // Tables[0].DeleteCredentials = NULL;
1719 // Tables[0].InitLsaModeContext = NULL;
1720 // Tables[0].AcceptLsaModeContext = NULL;
1721 // Tables[0].DeleteContext = NULL;
1722 // Tables[0].ApplyControlToken = NULL;
1723 // Tables[0].GetUserInfo = NULL;
1724 // Tables[0].GetExtendedInformation = NULL;
1725 // Tables[0].SpQueryContextAttributes = NULL;
1726 // Tables[0].SpAddCredentials = NULL;
1727 // Tables[0].SetExtendedInformation = NULL;
1732 return STATUS_SUCCESS
;
1741 SpUserModeInitialize(
1742 _In_ ULONG LsaVersion
,
1743 _Out_ PULONG PackageVersion
,
1744 _Out_ PSECPKG_USER_FUNCTION_TABLE
*ppTables
,
1745 _Out_ PULONG pcTables
)
1747 SECPKG_USER_FUNCTION_TABLE Tables
[1];
1749 TRACE("SpUserModeInitialize(0x%lx %p %p %p)\n",
1750 LsaVersion
, PackageVersion
, ppTables
, pcTables
);
1752 if (LsaVersion
!= SECPKG_INTERFACE_VERSION
)
1753 return STATUS_INVALID_PARAMETER
;
1755 *PackageVersion
= SECPKG_INTERFACE_VERSION
;
1757 RtlZeroMemory(&Tables
, sizeof(Tables
));
1759 // Tables[0].InstanceInit = SpInstanceInit;
1760 // Tables[0].InitUserModeContext = NULL;
1761 // Tables[0].MakeSignature = NULL;
1762 // Tables[0].VerifySignature = NULL;
1763 // Tables[0].SealMessage = NULL;
1764 // Tables[0].UnsealMessage = NULL;
1765 // Tables[0].GetContextToken = NULL;
1766 // Tables[0].SpQueryContextAttributes = NULL;
1767 // Tables[0].CompleteAuthToken = NULL;
1768 // Tables[0].DeleteUserModeContext = NULL;
1769 // Tables[0].FormatCredentials = NULL;
1770 // Tables[0].MarshallSupplementalCreds = NULL;
1771 // Tables[0].ExportContext = NULL;
1772 // Tables[0].ImportContext = NULL;
1777 return STATUS_SUCCESS
;