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 USHORT ComputerNameLength
;
106 NTSTATUS Status
= STATUS_SUCCESS
;
108 *ProfileBuffer
= NULL
;
109 *ProfileBufferLength
= 0;
111 if (UIntPtrToUShort(wcslen(ComputerName
), &ComputerNameLength
) != S_OK
)
113 return STATUS_INVALID_PARAMETER
;
116 BufferLength
= sizeof(MSV1_0_INTERACTIVE_PROFILE
) +
117 UserInfo
->All
.FullName
.Length
+ sizeof(WCHAR
) +
118 UserInfo
->All
.HomeDirectory
.Length
+ sizeof(WCHAR
) +
119 UserInfo
->All
.HomeDirectoryDrive
.Length
+ sizeof(WCHAR
) +
120 UserInfo
->All
.ScriptPath
.Length
+ sizeof(WCHAR
) +
121 UserInfo
->All
.ProfilePath
.Length
+ sizeof(WCHAR
) +
122 ((ComputerNameLength
+ 3) * sizeof(WCHAR
));
124 LocalBuffer
= DispatchTable
.AllocateLsaHeap(BufferLength
);
125 if (LocalBuffer
== NULL
)
127 TRACE("Failed to allocate the local buffer!\n");
128 Status
= STATUS_INSUFFICIENT_RESOURCES
;
132 Status
= DispatchTable
.AllocateClientBuffer(ClientRequest
,
135 if (!NT_SUCCESS(Status
))
137 TRACE("DispatchTable.AllocateClientBuffer failed (Status 0x%08lx)\n", Status
);
141 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress
);
143 Ptr
= (LPWSTR
)((ULONG_PTR
)LocalBuffer
+ sizeof(MSV1_0_INTERACTIVE_PROFILE
));
145 LocalBuffer
->MessageType
= MsV1_0InteractiveProfile
;
146 LocalBuffer
->LogonCount
= UserInfo
->All
.LogonCount
;
147 LocalBuffer
->BadPasswordCount
= UserInfo
->All
.BadPasswordCount
;
149 LocalBuffer
->LogonTime
.LowPart
= UserInfo
->All
.LastLogon
.LowPart
;
150 LocalBuffer
->LogonTime
.HighPart
= UserInfo
->All
.LastLogon
.HighPart
;
152 LocalBuffer
->LogoffTime
.LowPart
= UserInfo
->All
.AccountExpires
.LowPart
;
153 LocalBuffer
->LogoffTime
.HighPart
= UserInfo
->All
.AccountExpires
.HighPart
;
155 LocalBuffer
->KickOffTime
.LowPart
= UserInfo
->All
.AccountExpires
.LowPart
;
156 LocalBuffer
->KickOffTime
.HighPart
= UserInfo
->All
.AccountExpires
.HighPart
;
158 LocalBuffer
->PasswordLastSet
.LowPart
= UserInfo
->All
.PasswordLastSet
.LowPart
;
159 LocalBuffer
->PasswordLastSet
.HighPart
= UserInfo
->All
.PasswordLastSet
.HighPart
;
161 LocalBuffer
->PasswordCanChange
.LowPart
= UserInfo
->All
.PasswordCanChange
.LowPart
;
162 LocalBuffer
->PasswordCanChange
.HighPart
= UserInfo
->All
.PasswordCanChange
.HighPart
;
164 LocalBuffer
->PasswordMustChange
.LowPart
= UserInfo
->All
.PasswordMustChange
.LowPart
;
165 LocalBuffer
->PasswordMustChange
.HighPart
= UserInfo
->All
.PasswordMustChange
.HighPart
;
167 LocalBuffer
->LogonScript
.Length
= UserInfo
->All
.ScriptPath
.Length
;
168 LocalBuffer
->LogonScript
.MaximumLength
= UserInfo
->All
.ScriptPath
.Length
+ sizeof(WCHAR
);
169 LocalBuffer
->LogonScript
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
171 UserInfo
->All
.ScriptPath
.Buffer
,
172 UserInfo
->All
.ScriptPath
.Length
);
174 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ LocalBuffer
->LogonScript
.MaximumLength
);
176 LocalBuffer
->HomeDirectory
.Length
= UserInfo
->All
.HomeDirectory
.Length
;
177 LocalBuffer
->HomeDirectory
.MaximumLength
= UserInfo
->All
.HomeDirectory
.Length
+ sizeof(WCHAR
);
178 LocalBuffer
->HomeDirectory
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
180 UserInfo
->All
.HomeDirectory
.Buffer
,
181 UserInfo
->All
.HomeDirectory
.Length
);
183 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ LocalBuffer
->HomeDirectory
.MaximumLength
);
185 LocalBuffer
->FullName
.Length
= UserInfo
->All
.FullName
.Length
;
186 LocalBuffer
->FullName
.MaximumLength
= UserInfo
->All
.FullName
.Length
+ sizeof(WCHAR
);
187 LocalBuffer
->FullName
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
189 UserInfo
->All
.FullName
.Buffer
,
190 UserInfo
->All
.FullName
.Length
);
191 TRACE("FullName.Buffer: %p\n", LocalBuffer
->FullName
.Buffer
);
193 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ LocalBuffer
->FullName
.MaximumLength
);
195 LocalBuffer
->ProfilePath
.Length
= UserInfo
->All
.ProfilePath
.Length
;
196 LocalBuffer
->ProfilePath
.MaximumLength
= UserInfo
->All
.ProfilePath
.Length
+ sizeof(WCHAR
);
197 LocalBuffer
->ProfilePath
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
199 UserInfo
->All
.ProfilePath
.Buffer
,
200 UserInfo
->All
.ProfilePath
.Length
);
202 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ LocalBuffer
->ProfilePath
.MaximumLength
);
204 LocalBuffer
->HomeDirectoryDrive
.Length
= UserInfo
->All
.HomeDirectoryDrive
.Length
;
205 LocalBuffer
->HomeDirectoryDrive
.MaximumLength
= UserInfo
->All
.HomeDirectoryDrive
.Length
+ sizeof(WCHAR
);
206 LocalBuffer
->HomeDirectoryDrive
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
208 UserInfo
->All
.HomeDirectoryDrive
.Buffer
,
209 UserInfo
->All
.HomeDirectoryDrive
.Length
);
211 Ptr
= (LPWSTR
)((ULONG_PTR
)Ptr
+ LocalBuffer
->HomeDirectoryDrive
.MaximumLength
);
213 LocalBuffer
->LogonServer
.Length
= (ComputerNameLength
+ 2) * sizeof(WCHAR
);
214 LocalBuffer
->LogonServer
.MaximumLength
= LocalBuffer
->LogonServer
.Length
+ sizeof(WCHAR
);
215 LocalBuffer
->LogonServer
.Buffer
= (LPWSTR
)((ULONG_PTR
)ClientBaseAddress
+ (ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalBuffer
);
217 wcscat(Ptr
, ComputerName
);
219 LocalBuffer
->UserFlags
= 0;
221 Status
= DispatchTable
.CopyToClientBuffer(ClientRequest
,
225 if (!NT_SUCCESS(Status
))
227 TRACE("DispatchTable.CopyToClientBuffer failed (Status 0x%08lx)\n", Status
);
231 *ProfileBuffer
= (PMSV1_0_INTERACTIVE_PROFILE
)ClientBaseAddress
;
232 *ProfileBufferLength
= BufferLength
;
235 if (LocalBuffer
!= NULL
)
236 DispatchTable
.FreeLsaHeap(LocalBuffer
);
238 if (!NT_SUCCESS(Status
))
240 if (ClientBaseAddress
!= NULL
)
241 DispatchTable
.FreeClientBuffer(ClientRequest
,
251 AppendRidToSid(PSID SrcSid
,
257 RidCount
= *RtlSubAuthorityCountSid(SrcSid
);
261 DstSid
= DispatchTable
.AllocateLsaHeap(RtlLengthRequiredSid(RidCount
+ 1));
265 RtlCopyMemory(DstSid
,
267 RtlLengthRequiredSid(RidCount
));
269 *RtlSubAuthorityCountSid(DstSid
) = RidCount
+ 1;
270 *RtlSubAuthoritySid(DstSid
, RidCount
) = Rid
;
278 BuildTokenUser(OUT PTOKEN_USER User
,
279 IN PSID AccountDomainSid
,
282 User
->User
.Sid
= AppendRidToSid(AccountDomainSid
,
284 if (User
->User
.Sid
== NULL
)
286 ERR("Could not create the user SID\n");
287 return STATUS_INSUFFICIENT_RESOURCES
;
290 User
->User
.Attributes
= 0;
292 return STATUS_SUCCESS
;
298 BuildTokenPrimaryGroup(OUT PTOKEN_PRIMARY_GROUP PrimaryGroup
,
299 IN PSID AccountDomainSid
,
302 PrimaryGroup
->PrimaryGroup
= AppendRidToSid(AccountDomainSid
,
304 if (PrimaryGroup
->PrimaryGroup
== NULL
)
306 ERR("Could not create the primary group SID\n");
307 return STATUS_INSUFFICIENT_RESOURCES
;
310 return STATUS_SUCCESS
;
316 BuildTokenGroups(OUT PTOKEN_GROUPS
*Groups
,
317 IN PSID AccountDomainSid
,
319 IN BOOL SpecialAccount
)
321 SID_IDENTIFIER_AUTHORITY SystemAuthority
= {SECURITY_NT_AUTHORITY
};
322 PTOKEN_GROUPS TokenGroups
;
323 DWORD GroupCount
= 0;
326 NTSTATUS Status
= STATUS_SUCCESS
;
331 TokenGroups
= DispatchTable
.AllocateLsaHeap(sizeof(TOKEN_GROUPS
) +
332 MaxGroups
* sizeof(SID_AND_ATTRIBUTES
));
333 if (TokenGroups
== NULL
)
335 return STATUS_INSUFFICIENT_RESOURCES
;
341 Sid
= AppendRidToSid(AccountDomainSid
, RelativeId
);
347 TokenGroups
->Groups
[GroupCount
].Sid
= Sid
;
348 TokenGroups
->Groups
[GroupCount
].Attributes
=
349 SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
| SE_GROUP_MANDATORY
;
352 /* Member of 'Users' alias */
353 RtlAllocateAndInitializeSid(&SystemAuthority
,
355 SECURITY_BUILTIN_DOMAIN_RID
,
356 DOMAIN_ALIAS_RID_USERS
,
364 TokenGroups
->Groups
[GroupCount
].Sid
= Sid
;
365 TokenGroups
->Groups
[GroupCount
].Attributes
=
366 SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
| SE_GROUP_MANDATORY
;
371 /* Member of the domains users group */
372 Sid
= AppendRidToSid(AccountDomainSid
, DOMAIN_GROUP_RID_USERS
);
378 TokenGroups
->Groups
[GroupCount
].Sid
= Sid
;
379 TokenGroups
->Groups
[GroupCount
].Attributes
=
380 SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
| SE_GROUP_MANDATORY
;
384 /* Member of 'Authenticated users' */
385 RtlAllocateAndInitializeSid(&SystemAuthority
,
387 SECURITY_AUTHENTICATED_USER_RID
,
396 TokenGroups
->Groups
[GroupCount
].Sid
= Sid
;
397 TokenGroups
->Groups
[GroupCount
].Attributes
=
398 SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
| SE_GROUP_MANDATORY
;
401 TokenGroups
->GroupCount
= GroupCount
;
402 ASSERT(TokenGroups
->GroupCount
<= MaxGroups
);
404 *Groups
= TokenGroups
;
412 BuildTokenInformationBuffer(PLSA_TOKEN_INFORMATION_V1
*TokenInformation
,
413 PRPC_SID AccountDomainSid
,
414 PSAMPR_USER_INFO_BUFFER UserInfo
,
417 PLSA_TOKEN_INFORMATION_V1 Buffer
= NULL
;
419 NTSTATUS Status
= STATUS_SUCCESS
;
421 Buffer
= DispatchTable
.AllocateLsaHeap(sizeof(LSA_TOKEN_INFORMATION_V1
));
424 WARN("Failed to allocate the local buffer!\n");
425 Status
= STATUS_INSUFFICIENT_RESOURCES
;
429 Buffer
->ExpirationTime
.LowPart
= UserInfo
->All
.AccountExpires
.LowPart
;
430 Buffer
->ExpirationTime
.HighPart
= UserInfo
->All
.AccountExpires
.HighPart
;
432 Status
= BuildTokenUser(&Buffer
->User
,
433 (PSID
)AccountDomainSid
,
434 UserInfo
->All
.UserId
);
435 if (!NT_SUCCESS(Status
))
437 WARN("BuildTokenUser() failed (Status 0x%08lx)\n", Status
);
441 Status
= BuildTokenPrimaryGroup(&Buffer
->PrimaryGroup
,
442 (PSID
)AccountDomainSid
,
443 UserInfo
->All
.PrimaryGroupId
);
444 if (!NT_SUCCESS(Status
))
446 WARN("BuildTokenPrimaryGroup() failed (Status 0x%08lx)\n", Status
);
450 Status
= BuildTokenGroups(&Buffer
->Groups
,
451 (PSID
)AccountDomainSid
,
452 UserInfo
->All
.UserId
,
454 if (!NT_SUCCESS(Status
))
456 WARN("BuildTokenGroups() failed (Status 0x%08lx)\n", Status
);
460 *TokenInformation
= Buffer
;
463 if (!NT_SUCCESS(Status
))
467 if (Buffer
->User
.User
.Sid
!= NULL
)
468 DispatchTable
.FreeLsaHeap(Buffer
->User
.User
.Sid
);
470 if (Buffer
->Groups
!= NULL
)
472 for (i
= 0; i
< Buffer
->Groups
->GroupCount
; i
++)
474 if (Buffer
->Groups
->Groups
[i
].Sid
!= NULL
)
475 DispatchTable
.FreeLsaHeap(Buffer
->Groups
->Groups
[i
].Sid
);
478 DispatchTable
.FreeLsaHeap(Buffer
->Groups
);
481 if (Buffer
->PrimaryGroup
.PrimaryGroup
!= NULL
)
482 DispatchTable
.FreeLsaHeap(Buffer
->PrimaryGroup
.PrimaryGroup
);
484 if (Buffer
->DefaultDacl
.DefaultDacl
!= NULL
)
485 DispatchTable
.FreeLsaHeap(Buffer
->DefaultDacl
.DefaultDacl
);
487 DispatchTable
.FreeLsaHeap(Buffer
);
497 MsvpChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest
,
498 IN PVOID ProtocolSubmitBuffer
,
499 IN PVOID ClientBufferBase
,
500 IN ULONG SubmitBufferLength
,
501 OUT PVOID
*ProtocolReturnBuffer
,
502 OUT PULONG ReturnBufferLength
,
503 OUT PNTSTATUS ProtocolStatus
)
506 PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer
;
509 SAMPR_HANDLE ServerHandle
= NULL
;
510 SAMPR_HANDLE DomainHandle
= NULL
;
511 SAMPR_HANDLE UserHandle
= NULL
;
512 PRPC_SID DomainSid
= NULL
;
513 RPC_UNICODE_STRING Names
[1];
514 SAMPR_ULONG_ARRAY RelativeIds
= {0, NULL
};
515 SAMPR_ULONG_ARRAY Use
= {0, NULL
};
517 ENCRYPTED_NT_OWF_PASSWORD OldNtPassword
;
518 ENCRYPTED_NT_OWF_PASSWORD NewNtPassword
;
519 ENCRYPTED_LM_OWF_PASSWORD OldLmPassword
;
520 ENCRYPTED_LM_OWF_PASSWORD NewLmPassword
;
521 OEM_STRING LmPwdString
;
522 CHAR LmPwdBuffer
[15];
523 BOOLEAN OldLmPasswordPresent
= FALSE
;
524 BOOLEAN NewLmPasswordPresent
= FALSE
;
526 ENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm
;
527 ENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm
;
528 ENCRYPTED_LM_OWF_PASSWORD OldNtEncryptedWithNewNt
;
529 ENCRYPTED_LM_OWF_PASSWORD NewNtEncryptedWithOldNt
;
530 PENCRYPTED_LM_OWF_PASSWORD pOldLmEncryptedWithNewLm
= NULL
;
531 PENCRYPTED_LM_OWF_PASSWORD pNewLmEncryptedWithOldLm
= NULL
;
533 TRACE("MsvpChangePassword()\n");
535 /* Parameters validation */
537 if (SubmitBufferLength
< sizeof(MSV1_0_CHANGEPASSWORD_REQUEST
))
539 ERR("Invalid SubmitBufferLength %lu\n", SubmitBufferLength
);
540 return STATUS_INVALID_PARAMETER
;
543 RequestBuffer
= (PMSV1_0_CHANGEPASSWORD_REQUEST
)ProtocolSubmitBuffer
;
545 /* Fix-up pointers in the request buffer info */
546 PtrOffset
= (ULONG_PTR
)ProtocolSubmitBuffer
- (ULONG_PTR
)ClientBufferBase
;
548 Status
= RtlValidateUnicodeString(0, &RequestBuffer
->DomainName
);
549 if (!NT_SUCCESS(Status
))
550 return STATUS_INVALID_PARAMETER
;
551 // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
552 RequestBuffer
->DomainName
.Buffer
= FIXUP_POINTER(RequestBuffer
->DomainName
.Buffer
, PtrOffset
);
553 RequestBuffer
->DomainName
.MaximumLength
= RequestBuffer
->DomainName
.Length
;
555 Status
= RtlValidateUnicodeString(0, &RequestBuffer
->AccountName
);
556 if (!NT_SUCCESS(Status
))
557 return STATUS_INVALID_PARAMETER
;
558 // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
559 RequestBuffer
->AccountName
.Buffer
= FIXUP_POINTER(RequestBuffer
->AccountName
.Buffer
, PtrOffset
);
560 RequestBuffer
->AccountName
.MaximumLength
= RequestBuffer
->AccountName
.Length
;
562 Status
= RtlValidateUnicodeString(0, &RequestBuffer
->OldPassword
);
563 if (!NT_SUCCESS(Status
))
564 return STATUS_INVALID_PARAMETER
;
565 // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
566 RequestBuffer
->OldPassword
.Buffer
= FIXUP_POINTER(RequestBuffer
->OldPassword
.Buffer
, PtrOffset
);
567 RequestBuffer
->OldPassword
.MaximumLength
= RequestBuffer
->OldPassword
.Length
;
569 Status
= RtlValidateUnicodeString(0, &RequestBuffer
->NewPassword
);
570 if (!NT_SUCCESS(Status
))
571 return STATUS_INVALID_PARAMETER
;
572 // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
573 RequestBuffer
->NewPassword
.Buffer
= FIXUP_POINTER(RequestBuffer
->NewPassword
.Buffer
, PtrOffset
);
574 RequestBuffer
->NewPassword
.MaximumLength
= RequestBuffer
->NewPassword
.Length
;
576 TRACE("Domain: %S\n", RequestBuffer
->DomainName
.Buffer
);
577 TRACE("Account: %S\n", RequestBuffer
->AccountName
.Buffer
);
578 TRACE("Old Password: %S\n", RequestBuffer
->OldPassword
.Buffer
);
579 TRACE("New Password: %S\n", RequestBuffer
->NewPassword
.Buffer
);
581 /* Connect to the SAM server */
582 Status
= SamIConnect(NULL
,
584 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
586 if (!NT_SUCCESS(Status
))
588 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status
);
592 /* Get the domain SID */
593 Status
= SamrLookupDomainInSamServer(ServerHandle
,
594 (PRPC_UNICODE_STRING
)&RequestBuffer
->DomainName
,
596 if (!NT_SUCCESS(Status
))
598 TRACE("SamrLookupDomainInSamServer failed (Status %08lx)\n", Status
);
602 /* Open the domain */
603 Status
= SamrOpenDomain(ServerHandle
,
607 if (!NT_SUCCESS(Status
))
609 TRACE("SamrOpenDomain failed (Status %08lx)\n", Status
);
613 Names
[0].Length
= RequestBuffer
->AccountName
.Length
;
614 Names
[0].MaximumLength
= RequestBuffer
->AccountName
.MaximumLength
;
615 Names
[0].Buffer
= RequestBuffer
->AccountName
.Buffer
;
617 /* Try to get the RID for the user name */
618 Status
= SamrLookupNamesInDomain(DomainHandle
,
623 if (!NT_SUCCESS(Status
))
625 TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status
);
626 Status
= STATUS_NO_SUCH_USER
;
630 /* Fail, if it is not a user account */
631 if (Use
.Element
[0] != SidTypeUser
)
633 TRACE("Account is not a user account!\n");
634 Status
= STATUS_NO_SUCH_USER
;
638 /* Open the user object */
639 Status
= SamrOpenUser(DomainHandle
,
640 USER_CHANGE_PASSWORD
,
641 RelativeIds
.Element
[0],
643 if (!NT_SUCCESS(Status
))
645 TRACE("SamrOpenUser failed (Status %08lx)\n", Status
);
650 /* Calculate the NT hash for the old password */
651 Status
= SystemFunction007(&RequestBuffer
->OldPassword
,
652 (LPBYTE
)&OldNtPassword
);
653 if (!NT_SUCCESS(Status
))
655 TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status
);
659 /* Calculate the NT hash for the new password */
660 Status
= SystemFunction007(&RequestBuffer
->NewPassword
,
661 (LPBYTE
)&NewNtPassword
);
662 if (!NT_SUCCESS(Status
))
664 TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status
);
668 /* Calculate the LM password and hash for the old password */
669 LmPwdString
.Length
= 15;
670 LmPwdString
.MaximumLength
= 15;
671 LmPwdString
.Buffer
= LmPwdBuffer
;
672 ZeroMemory(LmPwdString
.Buffer
, LmPwdString
.MaximumLength
);
674 Status
= RtlUpcaseUnicodeStringToOemString(&LmPwdString
,
675 &RequestBuffer
->OldPassword
,
677 if (NT_SUCCESS(Status
))
679 /* Calculate the LM hash value of the password */
680 Status
= SystemFunction006(LmPwdString
.Buffer
,
681 (LPSTR
)&OldLmPassword
);
682 if (NT_SUCCESS(Status
))
684 OldLmPasswordPresent
= TRUE
;
688 /* Calculate the LM password and hash for the new password */
689 LmPwdString
.Length
= 15;
690 LmPwdString
.MaximumLength
= 15;
691 LmPwdString
.Buffer
= LmPwdBuffer
;
692 ZeroMemory(LmPwdString
.Buffer
, LmPwdString
.MaximumLength
);
694 Status
= RtlUpcaseUnicodeStringToOemString(&LmPwdString
,
695 &RequestBuffer
->NewPassword
,
697 if (NT_SUCCESS(Status
))
699 /* Calculate the LM hash value of the password */
700 Status
= SystemFunction006(LmPwdString
.Buffer
,
701 (LPSTR
)&NewLmPassword
);
702 if (NT_SUCCESS(Status
))
704 NewLmPasswordPresent
= TRUE
;
708 /* Encrypt the old and new LM passwords, if they exist */
709 if (OldLmPasswordPresent
&& NewLmPasswordPresent
)
711 /* Encrypt the old LM password */
712 Status
= SystemFunction012((const BYTE
*)&OldLmPassword
,
713 (const BYTE
*)&NewLmPassword
,
714 (LPBYTE
)&OldLmEncryptedWithNewLm
);
715 if (!NT_SUCCESS(Status
))
717 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status
);
721 /* Encrypt the new LM password */
722 Status
= SystemFunction012((const BYTE
*)&NewLmPassword
,
723 (const BYTE
*)&OldLmPassword
,
724 (LPBYTE
)&NewLmEncryptedWithOldLm
);
725 if (!NT_SUCCESS(Status
))
727 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status
);
731 pOldLmEncryptedWithNewLm
= &OldLmEncryptedWithNewLm
;
732 pNewLmEncryptedWithOldLm
= &NewLmEncryptedWithOldLm
;
735 /* Encrypt the old NT password */
736 Status
= SystemFunction012((const BYTE
*)&OldNtPassword
,
737 (const BYTE
*)&NewNtPassword
,
738 (LPBYTE
)&OldNtEncryptedWithNewNt
);
739 if (!NT_SUCCESS(Status
))
741 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status
);
745 /* Encrypt the new NT password */
746 Status
= SystemFunction012((const BYTE
*)&NewNtPassword
,
747 (const BYTE
*)&OldNtPassword
,
748 (LPBYTE
)&NewNtEncryptedWithOldNt
);
749 if (!NT_SUCCESS(Status
))
751 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status
);
755 /* Change the password */
756 Status
= SamrChangePasswordUser(UserHandle
,
757 OldLmPasswordPresent
&& NewLmPasswordPresent
,
758 pOldLmEncryptedWithNewLm
,
759 pNewLmEncryptedWithOldLm
,
761 &OldNtEncryptedWithNewNt
,
762 &NewNtEncryptedWithOldNt
,
767 if (!NT_SUCCESS(Status
))
769 TRACE("SamrChangePasswordUser failed (Status %08lx)\n", Status
);
774 if (UserHandle
!= NULL
)
775 SamrCloseHandle(&UserHandle
);
777 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds
);
778 SamIFree_SAMPR_ULONG_ARRAY(&Use
);
780 if (DomainHandle
!= NULL
)
781 SamrCloseHandle(&DomainHandle
);
783 if (DomainSid
!= NULL
)
784 SamIFreeVoid(DomainSid
);
786 if (ServerHandle
!= NULL
)
787 SamrCloseHandle(&ServerHandle
);
795 MsvpCheckPassword(PUNICODE_STRING UserPassword
,
796 PSAMPR_USER_INFO_BUFFER UserInfo
)
798 ENCRYPTED_NT_OWF_PASSWORD UserNtPassword
;
799 ENCRYPTED_LM_OWF_PASSWORD UserLmPassword
;
800 BOOLEAN UserLmPasswordPresent
= FALSE
;
801 BOOLEAN UserNtPasswordPresent
= FALSE
;
802 OEM_STRING LmPwdString
;
803 CHAR LmPwdBuffer
[15];
806 TRACE("(%p %p)\n", UserPassword
, UserInfo
);
808 /* Calculate the LM password and hash for the users password */
809 LmPwdString
.Length
= 15;
810 LmPwdString
.MaximumLength
= 15;
811 LmPwdString
.Buffer
= LmPwdBuffer
;
812 ZeroMemory(LmPwdString
.Buffer
, LmPwdString
.MaximumLength
);
814 Status
= RtlUpcaseUnicodeStringToOemString(&LmPwdString
,
817 if (NT_SUCCESS(Status
))
819 /* Calculate the LM hash value of the users password */
820 Status
= SystemFunction006(LmPwdString
.Buffer
,
821 (LPSTR
)&UserLmPassword
);
822 if (NT_SUCCESS(Status
))
824 UserLmPasswordPresent
= TRUE
;
828 /* Calculate the NT hash of the users password */
829 Status
= SystemFunction007(UserPassword
,
830 (LPBYTE
)&UserNtPassword
);
831 if (NT_SUCCESS(Status
))
833 UserNtPasswordPresent
= TRUE
;
836 Status
= STATUS_WRONG_PASSWORD
;
838 /* Succeed, if no password has been set */
839 if (UserInfo
->All
.NtPasswordPresent
== FALSE
&&
840 UserInfo
->All
.LmPasswordPresent
== FALSE
)
842 TRACE("No password check!\n");
843 Status
= STATUS_SUCCESS
;
847 /* Succeed, if NT password matches */
848 if (UserNtPasswordPresent
&& UserInfo
->All
.NtPasswordPresent
)
850 TRACE("Check NT password hashes:\n");
851 if (RtlEqualMemory(&UserNtPassword
,
852 UserInfo
->All
.NtOwfPassword
.Buffer
,
853 sizeof(ENCRYPTED_NT_OWF_PASSWORD
)))
855 TRACE(" success!\n");
856 Status
= STATUS_SUCCESS
;
863 /* Succeed, if LM password matches */
864 if (UserLmPasswordPresent
&& UserInfo
->All
.LmPasswordPresent
)
866 TRACE("Check LM password hashes:\n");
867 if (RtlEqualMemory(&UserLmPassword
,
868 UserInfo
->All
.LmOwfPassword
.Buffer
,
869 sizeof(ENCRYPTED_LM_OWF_PASSWORD
)))
871 TRACE(" success!\n");
872 Status
= STATUS_SUCCESS
;
886 _In_ PSAMPR_LOGON_HOURS LogonHours
,
887 _In_ PLARGE_INTEGER LogonTime
)
890 LARGE_INTEGER LocalLogonTime
;
891 TIME_FIELDS TimeFields
;
892 USHORT MinutesPerUnit
, Offset
;
895 FIXME("MsvpCheckLogonHours(%p %p)\n", LogonHours
, LogonTime
);
897 if (LogonHours
->UnitsPerWeek
== 0 || LogonHours
->LogonHours
== NULL
)
899 FIXME("No logon hours!\n");
903 RtlSystemTimeToLocalTime(LogonTime
, &LocalLogonTime
);
904 RtlTimeToTimeFields(&LocalLogonTime
, &TimeFields
);
906 FIXME("UnitsPerWeek: %u\n", LogonHours
->UnitsPerWeek
);
907 MinutesPerUnit
= 10080 / LogonHours
->UnitsPerWeek
;
909 Offset
= ((TimeFields
.Weekday
* 24 + TimeFields
.Hour
) * 60 + TimeFields
.Minute
) / MinutesPerUnit
;
910 FIXME("Offset: %us\n", Offset
);
912 bFound
= (BOOL
)(LogonHours
->LogonHours
[Offset
/ 8] & (1 << (Offset
% 8)));
913 FIXME("Logon permitted: %s\n", bFound
? "Yes" : "No");
923 MsvpCheckWorkstations(
924 _In_ PRPC_UNICODE_STRING WorkStations
,
925 _In_ PWSTR ComputerName
)
930 TRACE("MsvpCheckWorkstations(%p %S)\n", WorkStations
, ComputerName
);
932 if (WorkStations
->Length
== 0 || WorkStations
->Buffer
== NULL
)
934 TRACE("No workstations!\n");
938 TRACE("Workstations: %wZ\n", WorkStations
);
940 pStart
= WorkStations
->Buffer
;
943 pEnd
= wcschr(pStart
, L
',');
945 *pEnd
= UNICODE_NULL
;
947 TRACE("Comparing '%S' and '%S'\n", ComputerName
, pStart
);
948 if (_wcsicmp(ComputerName
, pStart
) == 0)
963 TRACE("Found allowed workstation: %s\n", (bFound
) ? "Yes" : "No");
974 LsaApCallPackage(IN PLSA_CLIENT_REQUEST ClientRequest
,
975 IN PVOID ProtocolSubmitBuffer
,
976 IN PVOID ClientBufferBase
,
977 IN ULONG SubmitBufferLength
,
978 OUT PVOID
*ProtocolReturnBuffer
,
979 OUT PULONG ReturnBufferLength
,
980 OUT PNTSTATUS ProtocolStatus
)
983 MSV1_0_PROTOCOL_MESSAGE_TYPE MessageType
;
985 TRACE("LsaApCallPackage()\n");
987 if (SubmitBufferLength
< sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE
))
988 return STATUS_INVALID_PARAMETER
;
990 MessageType
= *((PMSV1_0_PROTOCOL_MESSAGE_TYPE
)ProtocolSubmitBuffer
);
992 *ProtocolReturnBuffer
= NULL
;
993 *ReturnBufferLength
= 0;
997 case MsV1_0Lm20ChallengeRequest
:
998 case MsV1_0Lm20GetChallengeResponse
:
999 Status
= STATUS_NOT_IMPLEMENTED
;
1002 case MsV1_0EnumerateUsers
:
1003 case MsV1_0GetUserInfo
:
1004 case MsV1_0ReLogonUsers
:
1005 Status
= STATUS_INVALID_PARAMETER
;
1008 case MsV1_0ChangePassword
:
1009 Status
= MsvpChangePassword(ClientRequest
,
1010 ProtocolSubmitBuffer
,
1013 ProtocolReturnBuffer
,
1018 case MsV1_0ChangeCachedPassword
:
1019 case MsV1_0GenericPassthrough
:
1020 case MsV1_0CacheLogon
:
1022 case MsV1_0DeriveCredential
:
1023 case MsV1_0CacheLookup
:
1024 Status
= STATUS_NOT_IMPLEMENTED
;
1028 return STATUS_INVALID_PARAMETER
;
1040 LsaApCallPackagePassthrough(IN PLSA_CLIENT_REQUEST ClientRequest
,
1041 IN PVOID ProtocolSubmitBuffer
,
1042 IN PVOID ClientBufferBase
,
1043 IN ULONG SubmitBufferLength
,
1044 OUT PVOID
*ProtocolReturnBuffer
,
1045 OUT PULONG ReturnBufferLength
,
1046 OUT PNTSTATUS ProtocolStatus
)
1048 TRACE("LsaApCallPackagePassthrough()\n");
1049 return STATUS_NOT_IMPLEMENTED
;
1058 LsaApCallPackageUntrusted(IN PLSA_CLIENT_REQUEST ClientRequest
,
1059 IN PVOID ProtocolSubmitBuffer
,
1060 IN PVOID ClientBufferBase
,
1061 IN ULONG SubmitBufferLength
,
1062 OUT PVOID
*ProtocolReturnBuffer
,
1063 OUT PULONG ReturnBufferLength
,
1064 OUT PNTSTATUS ProtocolStatus
)
1069 TRACE("LsaApCallPackageUntrusted()\n");
1071 if (SubmitBufferLength
< sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE
))
1072 return STATUS_INVALID_PARAMETER
;
1074 MessageType
= (ULONG
)*((PMSV1_0_PROTOCOL_MESSAGE_TYPE
)ProtocolSubmitBuffer
);
1076 *ProtocolReturnBuffer
= NULL
;
1077 *ReturnBufferLength
= 0;
1079 if (MessageType
== MsV1_0ChangePassword
)
1080 Status
= MsvpChangePassword(ClientRequest
,
1081 ProtocolSubmitBuffer
,
1084 ProtocolReturnBuffer
,
1088 Status
= STATUS_ACCESS_DENIED
;
1099 LsaApInitializePackage(IN ULONG AuthenticationPackageId
,
1100 IN PLSA_DISPATCH_TABLE LsaDispatchTable
,
1101 IN PLSA_STRING Database OPTIONAL
,
1102 IN PLSA_STRING Confidentiality OPTIONAL
,
1103 OUT PLSA_STRING
*AuthenticationPackageName
)
1105 PANSI_STRING NameString
;
1108 TRACE("LsaApInitializePackage(%lu %p %p %p %p)\n",
1109 AuthenticationPackageId
, LsaDispatchTable
, Database
,
1110 Confidentiality
, AuthenticationPackageName
);
1112 /* Get the dispatch table entries */
1113 DispatchTable
.CreateLogonSession
= LsaDispatchTable
->CreateLogonSession
;
1114 DispatchTable
.DeleteLogonSession
= LsaDispatchTable
->DeleteLogonSession
;
1115 DispatchTable
.AddCredential
= LsaDispatchTable
->AddCredential
;
1116 DispatchTable
.GetCredentials
= LsaDispatchTable
->GetCredentials
;
1117 DispatchTable
.DeleteCredential
= LsaDispatchTable
->DeleteCredential
;
1118 DispatchTable
.AllocateLsaHeap
= LsaDispatchTable
->AllocateLsaHeap
;
1119 DispatchTable
.FreeLsaHeap
= LsaDispatchTable
->FreeLsaHeap
;
1120 DispatchTable
.AllocateClientBuffer
= LsaDispatchTable
->AllocateClientBuffer
;
1121 DispatchTable
.FreeClientBuffer
= LsaDispatchTable
->FreeClientBuffer
;
1122 DispatchTable
.CopyToClientBuffer
= LsaDispatchTable
->CopyToClientBuffer
;
1123 DispatchTable
.CopyFromClientBuffer
= LsaDispatchTable
->CopyFromClientBuffer
;
1125 /* Return the package name */
1126 NameString
= DispatchTable
.AllocateLsaHeap(sizeof(LSA_STRING
));
1127 if (NameString
== NULL
)
1128 return STATUS_INSUFFICIENT_RESOURCES
;
1130 NameBuffer
= DispatchTable
.AllocateLsaHeap(sizeof(MSV1_0_PACKAGE_NAME
));
1131 if (NameBuffer
== NULL
)
1133 DispatchTable
.FreeLsaHeap(NameString
);
1134 return STATUS_INSUFFICIENT_RESOURCES
;
1137 strcpy(NameBuffer
, MSV1_0_PACKAGE_NAME
);
1139 RtlInitAnsiString(NameString
, NameBuffer
);
1141 *AuthenticationPackageName
= (PLSA_STRING
)NameString
;
1143 return STATUS_SUCCESS
;
1152 LsaApLogonTerminated(IN PLUID LogonId
)
1154 TRACE("LsaApLogonTerminated()\n");
1163 LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest
,
1164 IN SECURITY_LOGON_TYPE LogonType
,
1165 IN PVOID ProtocolSubmitBuffer
,
1166 IN PVOID ClientBufferBase
,
1167 IN ULONG SubmitBufferSize
,
1168 OUT PVOID
*ProfileBuffer
,
1169 OUT PULONG ProfileBufferSize
,
1171 OUT PNTSTATUS SubStatus
,
1172 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType
,
1173 OUT PVOID
*TokenInformation
,
1174 OUT PUNICODE_STRING
*AccountName
,
1175 OUT PUNICODE_STRING
*AuthenticatingAuthority
,
1176 OUT PUNICODE_STRING
*MachineName
,
1177 OUT PSECPKG_PRIMARY_CRED PrimaryCredentials
, /* Not supported yet */
1178 OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY
*SupplementalCredentials
) /* Not supported yet */
1180 static const UNICODE_STRING NtAuthorityU
= RTL_CONSTANT_STRING(L
"NT AUTHORITY");
1181 static const UNICODE_STRING LocalServiceU
= RTL_CONSTANT_STRING(L
"LocalService");
1182 static const UNICODE_STRING NetworkServiceU
= RTL_CONSTANT_STRING(L
"NetworkService");
1185 PMSV1_0_INTERACTIVE_LOGON LogonInfo
;
1186 WCHAR ComputerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1187 SAMPR_HANDLE ServerHandle
= NULL
;
1188 SAMPR_HANDLE DomainHandle
= NULL
;
1189 SAMPR_HANDLE UserHandle
= NULL
;
1190 PRPC_SID AccountDomainSid
= NULL
;
1191 RPC_UNICODE_STRING Names
[1];
1192 SAMPR_ULONG_ARRAY RelativeIds
= {0, NULL
};
1193 SAMPR_ULONG_ARRAY Use
= {0, NULL
};
1194 PSAMPR_USER_INFO_BUFFER UserInfo
= NULL
;
1195 BOOLEAN SessionCreated
= FALSE
;
1196 LARGE_INTEGER LogonTime
;
1197 LARGE_INTEGER AccountExpires
;
1198 LARGE_INTEGER PasswordMustChange
;
1199 LARGE_INTEGER PasswordLastSet
;
1200 DWORD ComputerNameSize
;
1201 BOOL SpecialAccount
= FALSE
;
1202 UCHAR LogonPassHash
;
1203 PUNICODE_STRING ErasePassword
= NULL
;
1205 TRACE("LsaApLogonUserEx2()\n");
1207 TRACE("LogonType: %lu\n", LogonType
);
1208 TRACE("ProtocolSubmitBuffer: %p\n", ProtocolSubmitBuffer
);
1209 TRACE("SubmitBufferSize: %lu\n", SubmitBufferSize
);
1211 *ProfileBuffer
= NULL
;
1212 *ProfileBufferSize
= 0;
1213 *SubStatus
= STATUS_SUCCESS
;
1214 *AccountName
= NULL
;
1215 *AuthenticatingAuthority
= NULL
;
1217 /* Parameters validation */
1218 if (LogonType
== Interactive
||
1219 LogonType
== Batch
||
1220 LogonType
== Service
)
1222 ULONG_PTR PtrOffset
;
1224 if (SubmitBufferSize
< sizeof(MSV1_0_INTERACTIVE_LOGON
))
1226 ERR("Invalid SubmitBufferSize %lu\n", SubmitBufferSize
);
1227 return STATUS_INVALID_PARAMETER
;
1230 LogonInfo
= (PMSV1_0_INTERACTIVE_LOGON
)ProtocolSubmitBuffer
;
1232 if (LogonInfo
->MessageType
!= MsV1_0InteractiveLogon
&&
1233 LogonInfo
->MessageType
!= MsV1_0WorkstationUnlockLogon
)
1235 ERR("Invalid MessageType %lu\n", LogonInfo
->MessageType
);
1236 return STATUS_BAD_VALIDATION_CLASS
;
1239 #if 0 // FIXME: These checks happen to be done on Windows. We however keep them general on ReactOS for now...
1240 if (LogonInfo
->UserName
.Length
> 512) // CRED_MAX_STRING_LENGTH * sizeof(WCHAR) or (CREDUI_MAX_USERNAME_LENGTH (== CRED_MAX_USERNAME_LENGTH) - 1) * sizeof(WCHAR)
1242 ERR("UserName too long (%lu, maximum 512)\n", LogonInfo
->UserName
.Length
);
1243 return STATUS_NAME_TOO_LONG
;
1245 if (LogonInfo
->Password
.Length
> 512) // CREDUI_MAX_PASSWORD_LENGTH * sizeof(WCHAR)
1247 ERR("Password too long (%lu, maximum 512)\n", LogonInfo
->Password
.Length
);
1248 return STATUS_NAME_TOO_LONG
;
1252 /* Fix-up pointers in the authentication info */
1253 PtrOffset
= (ULONG_PTR
)ProtocolSubmitBuffer
- (ULONG_PTR
)ClientBufferBase
;
1255 /* LogonDomainName is optional and can be an empty string */
1256 if (LogonInfo
->LogonDomainName
.Length
)
1258 // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
1259 LogonInfo
->LogonDomainName
.Buffer
= FIXUP_POINTER(LogonInfo
->LogonDomainName
.Buffer
, PtrOffset
);
1260 LogonInfo
->LogonDomainName
.MaximumLength
= LogonInfo
->LogonDomainName
.Length
;
1264 LogonInfo
->LogonDomainName
.Buffer
= NULL
;
1265 LogonInfo
->LogonDomainName
.MaximumLength
= 0;
1267 Status
= RtlValidateUnicodeString(0, &LogonInfo
->LogonDomainName
);
1268 if (!NT_SUCCESS(Status
))
1269 return STATUS_INVALID_PARAMETER
;
1271 /* UserName is mandatory and cannot be an empty string */
1272 // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
1273 LogonInfo
->UserName
.Buffer
= FIXUP_POINTER(LogonInfo
->UserName
.Buffer
, PtrOffset
);
1274 LogonInfo
->UserName
.MaximumLength
= LogonInfo
->UserName
.Length
;
1276 Status
= RtlValidateUnicodeString(0, &LogonInfo
->UserName
);
1277 if (!NT_SUCCESS(Status
))
1278 return STATUS_INVALID_PARAMETER
;
1280 /* MS docs says max length is 0xFF bytes. But thats not the full story:
1282 * A Quote from https://groups.google.com/forum/#!topic/microsoft.public.win32.programmer.kernel/eFGcCo_ZObk:
1283 * "... At least on my WinXP SP2. Domain and UserName are passed
1284 * in clear text, but the Password is NOT. ..."
1286 * If the higher byte of length != 0 we have to use RtlRunDecodeUnicodeString.
1288 LogonPassHash
= (LogonInfo
->Password
.Length
>> 8) & 0xFF;
1289 LogonInfo
->Password
.Length
= LogonInfo
->Password
.Length
& 0xFF;
1291 /* Password is optional and can be an empty string */
1292 if (LogonInfo
->Password
.Length
)
1294 // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
1295 LogonInfo
->Password
.Buffer
= FIXUP_POINTER(LogonInfo
->Password
.Buffer
, PtrOffset
);
1296 LogonInfo
->Password
.MaximumLength
= LogonInfo
->Password
.Length
;
1300 LogonInfo
->Password
.Buffer
= NULL
;
1301 LogonInfo
->Password
.MaximumLength
= 0;
1304 /* Decode password */
1305 if (LogonPassHash
> 0)
1307 RtlRunDecodeUnicodeString(LogonPassHash
, &LogonInfo
->Password
);
1310 /* ErasePassword will be "erased" before we return */
1311 ErasePassword
= &LogonInfo
->Password
;
1313 Status
= RtlValidateUnicodeString(0, &LogonInfo
->Password
);
1314 if (!NT_SUCCESS(Status
))
1315 return STATUS_INVALID_PARAMETER
;
1317 TRACE("Domain: %wZ\n", &LogonInfo
->LogonDomainName
);
1318 TRACE("User: %wZ\n", &LogonInfo
->UserName
);
1319 TRACE("Password: %wZ\n", &LogonInfo
->Password
);
1321 // TODO: If LogonType == Service, do some extra work using LogonInfo->Password.
1325 FIXME("LogonType %lu is not supported yet!\n", LogonType
);
1326 return STATUS_NOT_IMPLEMENTED
;
1328 // TODO: Add other LogonType validity checks.
1330 /* Get the logon time */
1331 NtQuerySystemTime(&LogonTime
);
1333 /* Get the computer name */
1334 ComputerNameSize
= ARRAYSIZE(ComputerName
);
1335 GetComputerNameW(ComputerName
, &ComputerNameSize
);
1337 /* Check for special accounts */
1338 // FIXME: Windows does not do this that way!! (msv1_0 does not contain these hardcoded values)
1339 if (RtlEqualUnicodeString(&LogonInfo
->LogonDomainName
, &NtAuthorityU
, TRUE
))
1341 SpecialAccount
= TRUE
;
1343 /* Get the authority domain SID */
1344 Status
= GetNtAuthorityDomainSid(&AccountDomainSid
);
1345 if (!NT_SUCCESS(Status
))
1347 ERR("GetNtAuthorityDomainSid() failed (Status 0x%08lx)\n", Status
);
1351 if (RtlEqualUnicodeString(&LogonInfo
->UserName
, &LocalServiceU
, TRUE
))
1353 TRACE("SpecialAccount: LocalService\n");
1355 if (LogonType
!= Service
)
1356 return STATUS_LOGON_FAILURE
;
1358 UserInfo
= RtlAllocateHeap(RtlGetProcessHeap(),
1360 sizeof(SAMPR_USER_ALL_INFORMATION
));
1361 if (UserInfo
== NULL
)
1363 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1367 UserInfo
->All
.UserId
= SECURITY_LOCAL_SERVICE_RID
;
1368 UserInfo
->All
.PrimaryGroupId
= SECURITY_LOCAL_SERVICE_RID
;
1370 else if (RtlEqualUnicodeString(&LogonInfo
->UserName
, &NetworkServiceU
, TRUE
))
1372 TRACE("SpecialAccount: NetworkService\n");
1374 if (LogonType
!= Service
)
1375 return STATUS_LOGON_FAILURE
;
1377 UserInfo
= RtlAllocateHeap(RtlGetProcessHeap(),
1379 sizeof(SAMPR_USER_ALL_INFORMATION
));
1380 if (UserInfo
== NULL
)
1382 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1386 UserInfo
->All
.UserId
= SECURITY_NETWORK_SERVICE_RID
;
1387 UserInfo
->All
.PrimaryGroupId
= SECURITY_NETWORK_SERVICE_RID
;
1391 Status
= STATUS_NO_SUCH_USER
;
1397 TRACE("NormalAccount\n");
1399 /* Get the account domain SID */
1400 Status
= GetAccountDomainSid(&AccountDomainSid
);
1401 if (!NT_SUCCESS(Status
))
1403 ERR("GetAccountDomainSid() failed (Status 0x%08lx)\n", Status
);
1407 /* Connect to the SAM server */
1408 Status
= SamIConnect(NULL
,
1410 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
1412 if (!NT_SUCCESS(Status
))
1414 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status
);
1418 /* Open the account domain */
1419 Status
= SamrOpenDomain(ServerHandle
,
1423 if (!NT_SUCCESS(Status
))
1425 ERR("SamrOpenDomain failed (Status %08lx)\n", Status
);
1429 Names
[0].Length
= LogonInfo
->UserName
.Length
;
1430 Names
[0].MaximumLength
= LogonInfo
->UserName
.MaximumLength
;
1431 Names
[0].Buffer
= LogonInfo
->UserName
.Buffer
;
1433 /* Try to get the RID for the user name */
1434 Status
= SamrLookupNamesInDomain(DomainHandle
,
1439 if (!NT_SUCCESS(Status
))
1441 ERR("SamrLookupNamesInDomain failed (Status %08lx)\n", Status
);
1442 Status
= STATUS_NO_SUCH_USER
;
1446 /* Fail, if it is not a user account */
1447 if (Use
.Element
[0] != SidTypeUser
)
1449 ERR("Account is not a user account!\n");
1450 Status
= STATUS_NO_SUCH_USER
;
1454 /* Open the user object */
1455 Status
= SamrOpenUser(DomainHandle
,
1456 USER_READ_GENERAL
| USER_READ_LOGON
|
1457 USER_READ_ACCOUNT
| USER_READ_PREFERENCES
, /* FIXME */
1458 RelativeIds
.Element
[0],
1460 if (!NT_SUCCESS(Status
))
1462 ERR("SamrOpenUser failed (Status %08lx)\n", Status
);
1466 Status
= SamrQueryInformationUser(UserHandle
,
1469 if (!NT_SUCCESS(Status
))
1471 ERR("SamrQueryInformationUser failed (Status %08lx)\n", Status
);
1475 TRACE("UserName: %wZ\n", &UserInfo
->All
.UserName
);
1477 /* Check the password */
1478 if ((UserInfo
->All
.UserAccountControl
& USER_PASSWORD_NOT_REQUIRED
) == 0)
1480 Status
= MsvpCheckPassword(&LogonInfo
->Password
,
1482 if (!NT_SUCCESS(Status
))
1484 ERR("MsvpCheckPassword failed (Status %08lx)\n", Status
);
1489 /* Check account restrictions for non-administrator accounts */
1490 if (RelativeIds
.Element
[0] != DOMAIN_USER_RID_ADMIN
)
1492 /* Check if the account has been disabled */
1493 if (UserInfo
->All
.UserAccountControl
& USER_ACCOUNT_DISABLED
)
1495 ERR("Account disabled!\n");
1496 *SubStatus
= STATUS_ACCOUNT_DISABLED
;
1497 Status
= STATUS_ACCOUNT_RESTRICTION
;
1501 /* Check if the account has been locked */
1502 if (UserInfo
->All
.UserAccountControl
& USER_ACCOUNT_AUTO_LOCKED
)
1504 ERR("Account locked!\n");
1505 *SubStatus
= STATUS_ACCOUNT_LOCKED_OUT
;
1506 Status
= STATUS_ACCOUNT_RESTRICTION
;
1510 /* Check if the account expired */
1511 AccountExpires
.LowPart
= UserInfo
->All
.AccountExpires
.LowPart
;
1512 AccountExpires
.HighPart
= UserInfo
->All
.AccountExpires
.HighPart
;
1513 if (LogonTime
.QuadPart
>= AccountExpires
.QuadPart
)
1515 ERR("Account expired!\n");
1516 *SubStatus
= STATUS_ACCOUNT_EXPIRED
;
1517 Status
= STATUS_ACCOUNT_RESTRICTION
;
1521 /* Check if the password expired */
1522 PasswordMustChange
.LowPart
= UserInfo
->All
.PasswordMustChange
.LowPart
;
1523 PasswordMustChange
.HighPart
= UserInfo
->All
.PasswordMustChange
.HighPart
;
1524 PasswordLastSet
.LowPart
= UserInfo
->All
.PasswordLastSet
.LowPart
;
1525 PasswordLastSet
.HighPart
= UserInfo
->All
.PasswordLastSet
.HighPart
;
1527 if (LogonTime
.QuadPart
>= PasswordMustChange
.QuadPart
)
1529 ERR("Password expired!\n");
1530 if (PasswordLastSet
.QuadPart
== 0)
1531 *SubStatus
= STATUS_PASSWORD_MUST_CHANGE
;
1533 *SubStatus
= STATUS_PASSWORD_EXPIRED
;
1535 Status
= STATUS_ACCOUNT_RESTRICTION
;
1539 /* Check logon hours */
1540 if (!MsvpCheckLogonHours(&UserInfo
->All
.LogonHours
, &LogonTime
))
1542 ERR("Invalid logon hours!\n");
1543 *SubStatus
= STATUS_INVALID_LOGON_HOURS
;
1544 Status
= STATUS_ACCOUNT_RESTRICTION
;
1548 /* Check workstations */
1549 if (!MsvpCheckWorkstations(&UserInfo
->All
.WorkStations
, ComputerName
))
1551 ERR("Invalid workstation!\n");
1552 *SubStatus
= STATUS_INVALID_WORKSTATION
;
1553 Status
= STATUS_ACCOUNT_RESTRICTION
;
1559 /* Return logon information */
1561 /* Create and return a new logon id */
1562 Status
= NtAllocateLocallyUniqueId(LogonId
);
1563 if (!NT_SUCCESS(Status
))
1565 TRACE("NtAllocateLocallyUniqueId failed (Status %08lx)\n", Status
);
1569 /* Create the logon session */
1570 Status
= DispatchTable
.CreateLogonSession(LogonId
);
1571 if (!NT_SUCCESS(Status
))
1573 TRACE("CreateLogonSession failed (Status %08lx)\n", Status
);
1577 SessionCreated
= TRUE
;
1579 /* Build and fill the interactive profile buffer */
1580 Status
= BuildInteractiveProfileBuffer(ClientRequest
,
1583 (PMSV1_0_INTERACTIVE_PROFILE
*)ProfileBuffer
,
1585 if (!NT_SUCCESS(Status
))
1587 TRACE("BuildInteractiveProfileBuffer failed (Status %08lx)\n", Status
);
1591 /* Return the token information type */
1592 *TokenInformationType
= LsaTokenInformationV1
;
1594 /* Build and fill the token information buffer */
1595 Status
= BuildTokenInformationBuffer((PLSA_TOKEN_INFORMATION_V1
*)TokenInformation
,
1599 if (!NT_SUCCESS(Status
))
1601 TRACE("BuildTokenInformationBuffer failed (Status %08lx)\n", Status
);
1606 /* Erase password */
1609 RtlEraseUnicodeString(ErasePassword
);
1612 /* Update the logon time/count or the bad password time/count */
1613 if ((UserHandle
!= NULL
) &&
1614 (Status
== STATUS_SUCCESS
|| Status
== STATUS_WRONG_PASSWORD
))
1616 SAMPR_USER_INFO_BUFFER InternalInfo
;
1618 RtlZeroMemory(&InternalInfo
, sizeof(InternalInfo
));
1620 if (Status
== STATUS_SUCCESS
)
1621 InternalInfo
.Internal2
.Flags
= USER_LOGON_SUCCESS
;
1623 InternalInfo
.Internal2
.Flags
= USER_LOGON_BAD_PASSWORD
;
1625 SamrSetInformationUser(UserHandle
,
1626 UserInternal2Information
,
1630 /* Return the account name */
1631 *AccountName
= DispatchTable
.AllocateLsaHeap(sizeof(UNICODE_STRING
));
1632 if (*AccountName
!= NULL
)
1634 (*AccountName
)->Buffer
= DispatchTable
.AllocateLsaHeap(LogonInfo
->UserName
.Length
+
1635 sizeof(UNICODE_NULL
));
1636 if ((*AccountName
)->Buffer
!= NULL
)
1638 (*AccountName
)->MaximumLength
= LogonInfo
->UserName
.Length
+
1639 sizeof(UNICODE_NULL
);
1640 RtlCopyUnicodeString(*AccountName
, &LogonInfo
->UserName
);
1644 /* Return the authenticating authority */
1645 *AuthenticatingAuthority
= DispatchTable
.AllocateLsaHeap(sizeof(UNICODE_STRING
));
1646 if (*AuthenticatingAuthority
!= NULL
)
1648 (*AuthenticatingAuthority
)->Buffer
= DispatchTable
.AllocateLsaHeap(LogonInfo
->LogonDomainName
.Length
+
1649 sizeof(UNICODE_NULL
));
1650 if ((*AuthenticatingAuthority
)->Buffer
!= NULL
)
1652 (*AuthenticatingAuthority
)->MaximumLength
= LogonInfo
->LogonDomainName
.Length
+
1653 sizeof(UNICODE_NULL
);
1654 RtlCopyUnicodeString(*AuthenticatingAuthority
, &LogonInfo
->LogonDomainName
);
1658 /* Return the machine name */
1659 *MachineName
= DispatchTable
.AllocateLsaHeap(sizeof(UNICODE_STRING
));
1660 if (*MachineName
!= NULL
)
1662 (*MachineName
)->Buffer
= DispatchTable
.AllocateLsaHeap((ComputerNameSize
+ 1) * sizeof(WCHAR
));
1663 if ((*MachineName
)->Buffer
!= NULL
)
1665 (*MachineName
)->MaximumLength
= (ComputerNameSize
+ 1) * sizeof(WCHAR
);
1666 (*MachineName
)->Length
= ComputerNameSize
* sizeof(WCHAR
);
1667 RtlCopyMemory((*MachineName
)->Buffer
, ComputerName
, (*MachineName
)->MaximumLength
);
1671 if (!NT_SUCCESS(Status
))
1673 if (SessionCreated
!= FALSE
)
1674 DispatchTable
.DeleteLogonSession(LogonId
);
1676 if (*ProfileBuffer
!= NULL
)
1678 DispatchTable
.FreeClientBuffer(ClientRequest
,
1680 *ProfileBuffer
= NULL
;
1684 if (UserHandle
!= NULL
)
1685 SamrCloseHandle(&UserHandle
);
1687 SamIFree_SAMPR_USER_INFO_BUFFER(UserInfo
,
1688 UserAllInformation
);
1689 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds
);
1690 SamIFree_SAMPR_ULONG_ARRAY(&Use
);
1692 if (DomainHandle
!= NULL
)
1693 SamrCloseHandle(&DomainHandle
);
1695 if (ServerHandle
!= NULL
)
1696 SamrCloseHandle(&ServerHandle
);
1698 if (AccountDomainSid
!= NULL
)
1699 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid
);
1701 if (Status
== STATUS_NO_SUCH_USER
||
1702 Status
== STATUS_WRONG_PASSWORD
)
1704 *SubStatus
= Status
;
1705 Status
= STATUS_LOGON_FAILURE
;
1708 TRACE("LsaApLogonUserEx2 done (Status 0x%08lx, SubStatus 0x%08lx)\n", Status
, *SubStatus
);
1719 SpLsaModeInitialize(
1720 _In_ ULONG LsaVersion
,
1721 _Out_ PULONG PackageVersion
,
1722 _Out_ PSECPKG_FUNCTION_TABLE
*ppTables
,
1723 _Out_ PULONG pcTables
)
1725 TRACE("SpLsaModeInitialize(0x%lx %p %p %p)\n",
1726 LsaVersion
, PackageVersion
, ppTables
, pcTables
);
1728 if (LsaVersion
!= SECPKG_INTERFACE_VERSION
)
1729 return STATUS_INVALID_PARAMETER
;
1731 *PackageVersion
= SECPKG_INTERFACE_VERSION
;
1733 RtlZeroMemory(NtlmLsaFn
, sizeof(NtlmLsaFn
));
1735 /* msv1_0 (XP, win2k) returns NULL for
1736 * InitializePackage, LsaLogonUser,LsaLogonUserEx,
1737 * SpQueryContextAttributes and SpAddCredentials */
1738 NtlmLsaFn
[0].InitializePackage
= NULL
;
1739 NtlmLsaFn
[0].LsaLogonUser
= NULL
;
1740 NtlmLsaFn
[0].CallPackage
= LsaApCallPackage
;
1741 NtlmLsaFn
[0].LogonTerminated
= LsaApLogonTerminated
;
1742 NtlmLsaFn
[0].CallPackageUntrusted
= LsaApCallPackageUntrusted
;
1743 NtlmLsaFn
[0].CallPackagePassthrough
= LsaApCallPackagePassthrough
;
1744 NtlmLsaFn
[0].LogonUserEx
= NULL
;
1745 NtlmLsaFn
[0].LogonUserEx2
= LsaApLogonUserEx2
;
1746 NtlmLsaFn
[0].Initialize
= SpInitialize
;
1747 NtlmLsaFn
[0].Shutdown
= LsaSpShutDown
;
1748 NtlmLsaFn
[0].GetInfo
= LsaSpGetInfoW
;
1749 NtlmLsaFn
[0].AcceptCredentials
= SpAcceptCredentials
;
1750 NtlmLsaFn
[0].SpAcquireCredentialsHandle
= LsaSpAcquireCredentialsHandle
;
1751 NtlmLsaFn
[0].SpQueryCredentialsAttributes
= LsaSpQueryCredentialsAttributes
;
1752 NtlmLsaFn
[0].FreeCredentialsHandle
= LsaSpFreeCredentialsHandle
;
1753 NtlmLsaFn
[0].SaveCredentials
= LsaSpSaveCredentials
;
1754 NtlmLsaFn
[0].GetCredentials
= LsaSpGetCredentials
;
1755 NtlmLsaFn
[0].DeleteCredentials
= LsaSpDeleteCredentials
;
1756 NtlmLsaFn
[0].InitLsaModeContext
= LsaSpInitLsaModeContext
;
1757 NtlmLsaFn
[0].AcceptLsaModeContext
= LsaSpAcceptLsaModeContext
;
1758 NtlmLsaFn
[0].DeleteContext
= LsaSpDeleteContext
;
1759 NtlmLsaFn
[0].ApplyControlToken
= LsaSpApplyControlToken
;
1760 NtlmLsaFn
[0].GetUserInfo
= LsaSpGetUserInfo
;
1761 NtlmLsaFn
[0].GetExtendedInformation
= LsaSpGetExtendedInformation
;
1762 NtlmLsaFn
[0].SpQueryContextAttributes
= NULL
;
1763 NtlmLsaFn
[0].SpAddCredentials
= NULL
;
1764 NtlmLsaFn
[0].SetExtendedInformation
= LsaSpSetExtendedInformation
;
1766 *ppTables
= NtlmLsaFn
;
1769 return STATUS_SUCCESS
;
1778 SpUserModeInitialize(
1779 _In_ ULONG LsaVersion
,
1780 _Out_ PULONG PackageVersion
,
1781 _Out_ PSECPKG_USER_FUNCTION_TABLE
*ppTables
,
1782 _Out_ PULONG pcTables
)
1784 SECPKG_USER_FUNCTION_TABLE Tables
[1];
1786 TRACE("SpUserModeInitialize(0x%lx %p %p %p)\n",
1787 LsaVersion
, PackageVersion
, ppTables
, pcTables
);
1789 if (LsaVersion
!= SECPKG_INTERFACE_VERSION
)
1790 return STATUS_INVALID_PARAMETER
;
1792 *PackageVersion
= SECPKG_INTERFACE_VERSION
;
1794 RtlZeroMemory(&Tables
, sizeof(Tables
));
1796 // Tables[0].InstanceInit = SpInstanceInit;
1797 // Tables[0].InitUserModeContext = NULL;
1798 // Tables[0].MakeSignature = NULL;
1799 // Tables[0].VerifySignature = NULL;
1800 // Tables[0].SealMessage = NULL;
1801 // Tables[0].UnsealMessage = NULL;
1802 // Tables[0].GetContextToken = NULL;
1803 // Tables[0].SpQueryContextAttributes = NULL;
1804 // Tables[0].CompleteAuthToken = NULL;
1805 // Tables[0].DeleteUserModeContext = NULL;
1806 // Tables[0].FormatCredentials = NULL;
1807 // Tables[0].MarshallSupplementalCreds = NULL;
1808 // Tables[0].ExportContext = NULL;
1809 // Tables[0].ImportContext = NULL;
1814 return STATUS_SUCCESS
;