[MSV1_0] LsaApCallPackage: The messages MsV1_0EnumerateUsers, MsV1_0GetUserInfo and...
[reactos.git] / dll / win32 / msv1_0 / msv1_0.c
1 /*
2 * PROJECT: Authentication Package DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/msv1_0/msv1_0.c
5 * PURPOSE: Main file
6 * COPYRIGHT: Copyright 2013 Eric Kohl
7 */
8
9 /* INCLUDES ****************************************************************/
10
11 #include "msv1_0.h"
12
13 WINE_DEFAULT_DEBUG_CHANNEL(msv1_0);
14
15
16 /* GLOBALS *****************************************************************/
17
18 LSA_DISPATCH_TABLE DispatchTable;
19
20
21 /* FUNCTIONS ***************************************************************/
22
23 static
24 NTSTATUS
25 GetAccountDomainSid(PRPC_SID *Sid)
26 {
27 LSAPR_HANDLE PolicyHandle = NULL;
28 PLSAPR_POLICY_INFORMATION PolicyInfo = NULL;
29 ULONG Length = 0;
30 NTSTATUS Status;
31
32 Status = LsaIOpenPolicyTrusted(&PolicyHandle);
33 if (!NT_SUCCESS(Status))
34 {
35 TRACE("LsaIOpenPolicyTrusted() failed (Status 0x%08lx)\n", Status);
36 return Status;
37 }
38
39 Status = LsarQueryInformationPolicy(PolicyHandle,
40 PolicyAccountDomainInformation,
41 &PolicyInfo);
42 if (!NT_SUCCESS(Status))
43 {
44 TRACE("LsarQueryInformationPolicy() failed (Status 0x%08lx)\n", Status);
45 goto done;
46 }
47
48 Length = RtlLengthSid(PolicyInfo->PolicyAccountDomainInfo.Sid);
49
50 *Sid = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
51 if (*Sid == NULL)
52 {
53 ERR("Failed to allocate SID\n");
54 Status = STATUS_INSUFFICIENT_RESOURCES;
55 goto done;
56 }
57
58 memcpy(*Sid, PolicyInfo->PolicyAccountDomainInfo.Sid, Length);
59
60 done:
61 if (PolicyInfo != NULL)
62 LsaIFree_LSAPR_POLICY_INFORMATION(PolicyAccountDomainInformation,
63 PolicyInfo);
64
65 if (PolicyHandle != NULL)
66 LsarClose(&PolicyHandle);
67
68 return Status;
69 }
70
71
72 static
73 NTSTATUS
74 GetNtAuthorityDomainSid(PRPC_SID *Sid)
75 {
76 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
77 ULONG Length = 0;
78
79 Length = RtlLengthRequiredSid(0);
80 *Sid = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
81 if (*Sid == NULL)
82 {
83 ERR("Failed to allocate SID\n");
84 return STATUS_INSUFFICIENT_RESOURCES;
85 }
86
87 RtlInitializeSid(*Sid,&NtAuthority, 0);
88
89 return STATUS_SUCCESS;
90 }
91
92
93 static
94 NTSTATUS
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)
100 {
101 PMSV1_0_INTERACTIVE_PROFILE LocalBuffer = NULL;
102 PVOID ClientBaseAddress = NULL;
103 LPWSTR Ptr;
104 ULONG BufferLength;
105 NTSTATUS Status = STATUS_SUCCESS;
106
107 *ProfileBuffer = NULL;
108 *ProfileBufferLength = 0;
109
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));
117
118 LocalBuffer = DispatchTable.AllocateLsaHeap(BufferLength);
119 if (LocalBuffer == NULL)
120 {
121 TRACE("Failed to allocate the local buffer!\n");
122 Status = STATUS_INSUFFICIENT_RESOURCES;
123 goto done;
124 }
125
126 Status = DispatchTable.AllocateClientBuffer(ClientRequest,
127 BufferLength,
128 &ClientBaseAddress);
129 if (!NT_SUCCESS(Status))
130 {
131 TRACE("DispatchTable.AllocateClientBuffer failed (Status 0x%08lx)\n", Status);
132 goto done;
133 }
134
135 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
136
137 Ptr = (LPWSTR)((ULONG_PTR)LocalBuffer + sizeof(MSV1_0_INTERACTIVE_PROFILE));
138
139 LocalBuffer->MessageType = MsV1_0InteractiveProfile;
140 LocalBuffer->LogonCount = UserInfo->All.LogonCount;
141 LocalBuffer->BadPasswordCount = UserInfo->All.BadPasswordCount;
142
143 LocalBuffer->LogonTime.LowPart = UserInfo->All.LastLogon.LowPart;
144 LocalBuffer->LogonTime.HighPart = UserInfo->All.LastLogon.HighPart;
145
146 LocalBuffer->LogoffTime.LowPart = UserInfo->All.AccountExpires.LowPart;
147 LocalBuffer->LogoffTime.HighPart = UserInfo->All.AccountExpires.HighPart;
148
149 LocalBuffer->KickOffTime.LowPart = UserInfo->All.AccountExpires.LowPart;
150 LocalBuffer->KickOffTime.HighPart = UserInfo->All.AccountExpires.HighPart;
151
152 LocalBuffer->PasswordLastSet.LowPart = UserInfo->All.PasswordLastSet.LowPart;
153 LocalBuffer->PasswordLastSet.HighPart = UserInfo->All.PasswordLastSet.HighPart;
154
155 LocalBuffer->PasswordCanChange.LowPart = UserInfo->All.PasswordCanChange.LowPart;
156 LocalBuffer->PasswordCanChange.HighPart = UserInfo->All.PasswordCanChange.HighPart;
157
158 LocalBuffer->PasswordMustChange.LowPart = UserInfo->All.PasswordMustChange.LowPart;
159 LocalBuffer->PasswordMustChange.HighPart = UserInfo->All.PasswordMustChange.HighPart;
160
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);
164 memcpy(Ptr,
165 UserInfo->All.ScriptPath.Buffer,
166 UserInfo->All.ScriptPath.Length);
167
168 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->LogonScript.MaximumLength);
169
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);
173 memcpy(Ptr,
174 UserInfo->All.HomeDirectory.Buffer,
175 UserInfo->All.HomeDirectory.Length);
176
177 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectory.MaximumLength);
178
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);
182 memcpy(Ptr,
183 UserInfo->All.FullName.Buffer,
184 UserInfo->All.FullName.Length);
185 TRACE("FullName.Buffer: %p\n", LocalBuffer->FullName.Buffer);
186
187 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->FullName.MaximumLength);
188
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);
192 memcpy(Ptr,
193 UserInfo->All.ProfilePath.Buffer,
194 UserInfo->All.ProfilePath.Length);
195
196 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->ProfilePath.MaximumLength);
197
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);
201 memcpy(Ptr,
202 UserInfo->All.HomeDirectoryDrive.Buffer,
203 UserInfo->All.HomeDirectoryDrive.Length);
204
205 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectoryDrive.MaximumLength);
206
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);
210 wcscpy(Ptr, L"\\");
211 wcscat(Ptr, ComputerName);
212
213 LocalBuffer->UserFlags = 0;
214
215 Status = DispatchTable.CopyToClientBuffer(ClientRequest,
216 BufferLength,
217 ClientBaseAddress,
218 LocalBuffer);
219 if (!NT_SUCCESS(Status))
220 {
221 TRACE("DispatchTable.CopyToClientBuffer failed (Status 0x%08lx)\n", Status);
222 goto done;
223 }
224
225 *ProfileBuffer = (PMSV1_0_INTERACTIVE_PROFILE)ClientBaseAddress;
226 *ProfileBufferLength = BufferLength;
227
228 done:
229 if (LocalBuffer != NULL)
230 DispatchTable.FreeLsaHeap(LocalBuffer);
231
232 if (!NT_SUCCESS(Status))
233 {
234 if (ClientBaseAddress != NULL)
235 DispatchTable.FreeClientBuffer(ClientRequest,
236 ClientBaseAddress);
237 }
238
239 return Status;
240 }
241
242
243 static
244 PSID
245 AppendRidToSid(PSID SrcSid,
246 ULONG Rid)
247 {
248 PSID DstSid = NULL;
249 UCHAR RidCount;
250
251 RidCount = *RtlSubAuthorityCountSid(SrcSid);
252 if (RidCount >= 8)
253 return NULL;
254
255 DstSid = DispatchTable.AllocateLsaHeap(RtlLengthRequiredSid(RidCount + 1));
256 if (DstSid == NULL)
257 return NULL;
258
259 RtlCopyMemory(DstSid,
260 SrcSid,
261 RtlLengthRequiredSid(RidCount));
262
263 *RtlSubAuthorityCountSid(DstSid) = RidCount + 1;
264 *RtlSubAuthoritySid(DstSid, RidCount) = Rid;
265
266 return DstSid;
267 }
268
269
270 static
271 NTSTATUS
272 BuildTokenUser(OUT PTOKEN_USER User,
273 IN PSID AccountDomainSid,
274 IN ULONG RelativeId)
275 {
276 User->User.Sid = AppendRidToSid(AccountDomainSid,
277 RelativeId);
278 if (User->User.Sid == NULL)
279 {
280 ERR("Could not create the user SID\n");
281 return STATUS_INSUFFICIENT_RESOURCES;
282 }
283
284 User->User.Attributes = 0;
285
286 return STATUS_SUCCESS;
287 }
288
289
290 static
291 NTSTATUS
292 BuildTokenPrimaryGroup(OUT PTOKEN_PRIMARY_GROUP PrimaryGroup,
293 IN PSID AccountDomainSid,
294 IN ULONG RelativeId)
295 {
296 PrimaryGroup->PrimaryGroup = AppendRidToSid(AccountDomainSid,
297 RelativeId);
298 if (PrimaryGroup->PrimaryGroup == NULL)
299 {
300 ERR("Could not create the primary group SID\n");
301 return STATUS_INSUFFICIENT_RESOURCES;
302 }
303
304 return STATUS_SUCCESS;
305 }
306
307
308 static
309 NTSTATUS
310 BuildTokenGroups(OUT PTOKEN_GROUPS *Groups,
311 IN PSID AccountDomainSid,
312 IN ULONG RelativeId,
313 IN BOOL SpecialAccount)
314 {
315 SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
316 PTOKEN_GROUPS TokenGroups;
317 DWORD GroupCount = 0;
318 DWORD MaxGroups = 2;
319 PSID Sid;
320 NTSTATUS Status = STATUS_SUCCESS;
321
322 if (SpecialAccount)
323 MaxGroups++;
324
325 TokenGroups = DispatchTable.AllocateLsaHeap(sizeof(TOKEN_GROUPS) +
326 MaxGroups * sizeof(SID_AND_ATTRIBUTES));
327 if (TokenGroups == NULL)
328 {
329 return STATUS_INSUFFICIENT_RESOURCES;
330 }
331
332 if (SpecialAccount)
333 {
334 /* Self */
335 Sid = AppendRidToSid(AccountDomainSid, RelativeId);
336 if (Sid == NULL)
337 {
338
339 }
340
341 TokenGroups->Groups[GroupCount].Sid = Sid;
342 TokenGroups->Groups[GroupCount].Attributes =
343 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
344 GroupCount++;
345
346 /* Member of 'Users' alias */
347 RtlAllocateAndInitializeSid(&SystemAuthority,
348 2,
349 SECURITY_BUILTIN_DOMAIN_RID,
350 DOMAIN_ALIAS_RID_USERS,
351 SECURITY_NULL_RID,
352 SECURITY_NULL_RID,
353 SECURITY_NULL_RID,
354 SECURITY_NULL_RID,
355 SECURITY_NULL_RID,
356 SECURITY_NULL_RID,
357 &Sid);
358 TokenGroups->Groups[GroupCount].Sid = Sid;
359 TokenGroups->Groups[GroupCount].Attributes =
360 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
361 GroupCount++;
362 }
363 else
364 {
365 /* Member of the domains users group */
366 Sid = AppendRidToSid(AccountDomainSid, DOMAIN_GROUP_RID_USERS);
367 if (Sid == NULL)
368 {
369
370 }
371
372 TokenGroups->Groups[GroupCount].Sid = Sid;
373 TokenGroups->Groups[GroupCount].Attributes =
374 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
375 GroupCount++;
376 }
377
378 /* Member of 'Authenticated users' */
379 RtlAllocateAndInitializeSid(&SystemAuthority,
380 1,
381 SECURITY_AUTHENTICATED_USER_RID,
382 SECURITY_NULL_RID,
383 SECURITY_NULL_RID,
384 SECURITY_NULL_RID,
385 SECURITY_NULL_RID,
386 SECURITY_NULL_RID,
387 SECURITY_NULL_RID,
388 SECURITY_NULL_RID,
389 &Sid);
390 TokenGroups->Groups[GroupCount].Sid = Sid;
391 TokenGroups->Groups[GroupCount].Attributes =
392 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
393 GroupCount++;
394
395 TokenGroups->GroupCount = GroupCount;
396 ASSERT(TokenGroups->GroupCount <= MaxGroups);
397
398 *Groups = TokenGroups;
399
400 return Status;
401 }
402
403
404 static
405 NTSTATUS
406 BuildTokenInformationBuffer(PLSA_TOKEN_INFORMATION_V1 *TokenInformation,
407 PRPC_SID AccountDomainSid,
408 PSAMPR_USER_INFO_BUFFER UserInfo,
409 BOOL SpecialAccount)
410 {
411 PLSA_TOKEN_INFORMATION_V1 Buffer = NULL;
412 ULONG i;
413 NTSTATUS Status = STATUS_SUCCESS;
414
415 Buffer = DispatchTable.AllocateLsaHeap(sizeof(LSA_TOKEN_INFORMATION_V1));
416 if (Buffer == NULL)
417 {
418 WARN("Failed to allocate the local buffer!\n");
419 Status = STATUS_INSUFFICIENT_RESOURCES;
420 goto done;
421 }
422
423 Buffer->ExpirationTime.LowPart = UserInfo->All.AccountExpires.LowPart;
424 Buffer->ExpirationTime.HighPart = UserInfo->All.AccountExpires.HighPart;
425
426 Status = BuildTokenUser(&Buffer->User,
427 (PSID)AccountDomainSid,
428 UserInfo->All.UserId);
429 if (!NT_SUCCESS(Status))
430 {
431 WARN("BuildTokenUser() failed (Status 0x%08lx)\n", Status);
432 goto done;
433 }
434
435 Status = BuildTokenPrimaryGroup(&Buffer->PrimaryGroup,
436 (PSID)AccountDomainSid,
437 UserInfo->All.PrimaryGroupId);
438 if (!NT_SUCCESS(Status))
439 {
440 WARN("BuildTokenPrimaryGroup() failed (Status 0x%08lx)\n", Status);
441 goto done;
442 }
443
444 Status = BuildTokenGroups(&Buffer->Groups,
445 (PSID)AccountDomainSid,
446 UserInfo->All.UserId,
447 SpecialAccount);
448 if (!NT_SUCCESS(Status))
449 {
450 WARN("BuildTokenGroups() failed (Status 0x%08lx)\n", Status);
451 goto done;
452 }
453
454 *TokenInformation = Buffer;
455
456 done:
457 if (!NT_SUCCESS(Status))
458 {
459 if (Buffer != NULL)
460 {
461 if (Buffer->User.User.Sid != NULL)
462 DispatchTable.FreeLsaHeap(Buffer->User.User.Sid);
463
464 if (Buffer->Groups != NULL)
465 {
466 for (i = 0; i < Buffer->Groups->GroupCount; i++)
467 {
468 if (Buffer->Groups->Groups[i].Sid != NULL)
469 DispatchTable.FreeLsaHeap(Buffer->Groups->Groups[i].Sid);
470 }
471
472 DispatchTable.FreeLsaHeap(Buffer->Groups);
473 }
474
475 if (Buffer->PrimaryGroup.PrimaryGroup != NULL)
476 DispatchTable.FreeLsaHeap(Buffer->PrimaryGroup.PrimaryGroup);
477
478 if (Buffer->DefaultDacl.DefaultDacl != NULL)
479 DispatchTable.FreeLsaHeap(Buffer->DefaultDacl.DefaultDacl);
480
481 DispatchTable.FreeLsaHeap(Buffer);
482 }
483 }
484
485 return Status;
486 }
487
488
489 static
490 NTSTATUS
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)
498 {
499 PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer;
500 ULONG_PTR PtrOffset;
501
502 SAMPR_HANDLE ServerHandle = NULL;
503 SAMPR_HANDLE DomainHandle = NULL;
504 SAMPR_HANDLE UserHandle = NULL;
505 PRPC_SID DomainSid = NULL;
506 RPC_UNICODE_STRING Names[1];
507 SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
508 SAMPR_ULONG_ARRAY Use = {0, NULL};
509 NTSTATUS Status;
510
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;
519
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;
526
527 TRACE("()\n");
528
529 RequestBuffer = (PMSV1_0_CHANGEPASSWORD_REQUEST)ProtocolSubmitBuffer;
530
531 /* Fix-up pointers in the request buffer info */
532 PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;
533
534 RequestBuffer->DomainName.Buffer = FIXUP_POINTER(RequestBuffer->DomainName.Buffer, PtrOffset);
535 RequestBuffer->AccountName.Buffer = FIXUP_POINTER(RequestBuffer->AccountName.Buffer, PtrOffset);
536 RequestBuffer->OldPassword.Buffer = FIXUP_POINTER(RequestBuffer->OldPassword.Buffer, PtrOffset);
537 RequestBuffer->NewPassword.Buffer = FIXUP_POINTER(RequestBuffer->NewPassword.Buffer, PtrOffset);
538
539 TRACE("Domain: %S\n", RequestBuffer->DomainName.Buffer);
540 TRACE("Account: %S\n", RequestBuffer->AccountName.Buffer);
541 TRACE("Old Password: %S\n", RequestBuffer->OldPassword.Buffer);
542 TRACE("New Password: %S\n", RequestBuffer->NewPassword.Buffer);
543
544 /* Connect to the SAM server */
545 Status = SamIConnect(NULL,
546 &ServerHandle,
547 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
548 TRUE);
549 if (!NT_SUCCESS(Status))
550 {
551 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
552 goto done;
553 }
554
555 /* Get the domain SID */
556 Status = SamrLookupDomainInSamServer(ServerHandle,
557 (PRPC_UNICODE_STRING)&RequestBuffer->DomainName,
558 &DomainSid);
559 if (!NT_SUCCESS(Status))
560 {
561 TRACE("SamrLookupDomainInSamServer failed (Status %08lx)\n", Status);
562 goto done;
563 }
564
565 /* Open the domain */
566 Status = SamrOpenDomain(ServerHandle,
567 DOMAIN_LOOKUP,
568 DomainSid,
569 &DomainHandle);
570 if (!NT_SUCCESS(Status))
571 {
572 TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
573 goto done;
574 }
575
576 Names[0].Length = RequestBuffer->AccountName.Length;
577 Names[0].MaximumLength = RequestBuffer->AccountName.MaximumLength;
578 Names[0].Buffer = RequestBuffer->AccountName.Buffer;
579
580 /* Try to get the RID for the user name */
581 Status = SamrLookupNamesInDomain(DomainHandle,
582 1,
583 Names,
584 &RelativeIds,
585 &Use);
586 if (!NT_SUCCESS(Status))
587 {
588 TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
589 Status = STATUS_NO_SUCH_USER;
590 goto done;
591 }
592
593 /* Fail, if it is not a user account */
594 if (Use.Element[0] != SidTypeUser)
595 {
596 TRACE("Account is not a user account!\n");
597 Status = STATUS_NO_SUCH_USER;
598 goto done;
599 }
600
601 /* Open the user object */
602 Status = SamrOpenUser(DomainHandle,
603 USER_CHANGE_PASSWORD,
604 RelativeIds.Element[0],
605 &UserHandle);
606 if (!NT_SUCCESS(Status))
607 {
608 TRACE("SamrOpenUser failed (Status %08lx)\n", Status);
609 goto done;
610 }
611
612
613 /* Calculate the NT hash for the old password */
614 Status = SystemFunction007(&RequestBuffer->OldPassword,
615 (LPBYTE)&OldNtPassword);
616 if (!NT_SUCCESS(Status))
617 {
618 TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
619 goto done;
620 }
621
622 /* Calculate the NT hash for the new password */
623 Status = SystemFunction007(&RequestBuffer->NewPassword,
624 (LPBYTE)&NewNtPassword);
625 if (!NT_SUCCESS(Status))
626 {
627 TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
628 goto done;
629 }
630
631 /* Calculate the LM password and hash for the old password */
632 LmPwdString.Length = 15;
633 LmPwdString.MaximumLength = 15;
634 LmPwdString.Buffer = LmPwdBuffer;
635 ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
636
637 Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
638 &RequestBuffer->OldPassword,
639 FALSE);
640 if (NT_SUCCESS(Status))
641 {
642 /* Calculate the LM hash value of the password */
643 Status = SystemFunction006(LmPwdString.Buffer,
644 (LPSTR)&OldLmPassword);
645 if (NT_SUCCESS(Status))
646 {
647 OldLmPasswordPresent = TRUE;
648 }
649 }
650
651 /* Calculate the LM password and hash for the new password */
652 LmPwdString.Length = 15;
653 LmPwdString.MaximumLength = 15;
654 LmPwdString.Buffer = LmPwdBuffer;
655 ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
656
657 Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
658 &RequestBuffer->NewPassword,
659 FALSE);
660 if (NT_SUCCESS(Status))
661 {
662 /* Calculate the LM hash value of the password */
663 Status = SystemFunction006(LmPwdString.Buffer,
664 (LPSTR)&NewLmPassword);
665 if (NT_SUCCESS(Status))
666 {
667 NewLmPasswordPresent = TRUE;
668 }
669 }
670
671 /* Encrypt the old and new LM passwords, if they exist */
672 if (OldLmPasswordPresent && NewLmPasswordPresent)
673 {
674 /* Encrypt the old LM password */
675 Status = SystemFunction012((const BYTE *)&OldLmPassword,
676 (const BYTE *)&NewLmPassword,
677 (LPBYTE)&OldLmEncryptedWithNewLm);
678 if (!NT_SUCCESS(Status))
679 {
680 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
681 goto done;
682 }
683
684 /* Encrypt the new LM password */
685 Status = SystemFunction012((const BYTE *)&NewLmPassword,
686 (const BYTE *)&OldLmPassword,
687 (LPBYTE)&NewLmEncryptedWithOldLm);
688 if (!NT_SUCCESS(Status))
689 {
690 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
691 goto done;
692 }
693
694 pOldLmEncryptedWithNewLm = &OldLmEncryptedWithNewLm;
695 pNewLmEncryptedWithOldLm = &NewLmEncryptedWithOldLm;
696 }
697
698 /* Encrypt the old NT password */
699 Status = SystemFunction012((const BYTE *)&OldNtPassword,
700 (const BYTE *)&NewNtPassword,
701 (LPBYTE)&OldNtEncryptedWithNewNt);
702 if (!NT_SUCCESS(Status))
703 {
704 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
705 goto done;
706 }
707
708 /* Encrypt the new NT password */
709 Status = SystemFunction012((const BYTE *)&NewNtPassword,
710 (const BYTE *)&OldNtPassword,
711 (LPBYTE)&NewNtEncryptedWithOldNt);
712 if (!NT_SUCCESS(Status))
713 {
714 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
715 goto done;
716 }
717
718 /* Change the password */
719 Status = SamrChangePasswordUser(UserHandle,
720 OldLmPasswordPresent && NewLmPasswordPresent,
721 pOldLmEncryptedWithNewLm,
722 pNewLmEncryptedWithOldLm,
723 TRUE,
724 &OldNtEncryptedWithNewNt,
725 &NewNtEncryptedWithOldNt,
726 FALSE,
727 NULL,
728 FALSE,
729 NULL);
730 if (!NT_SUCCESS(Status))
731 {
732 TRACE("SamrChangePasswordUser failed (Status %08lx)\n", Status);
733 goto done;
734 }
735
736 done:
737 if (UserHandle != NULL)
738 SamrCloseHandle(&UserHandle);
739
740 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
741 SamIFree_SAMPR_ULONG_ARRAY(&Use);
742
743 if (DomainHandle != NULL)
744 SamrCloseHandle(&DomainHandle);
745
746 if (DomainSid != NULL)
747 SamIFreeVoid(DomainSid);
748
749 if (ServerHandle != NULL)
750 SamrCloseHandle(&ServerHandle);
751
752 return Status;
753 }
754
755
756 static
757 NTSTATUS
758 MsvpCheckPassword(PUNICODE_STRING UserPassword,
759 PSAMPR_USER_INFO_BUFFER UserInfo)
760 {
761 ENCRYPTED_NT_OWF_PASSWORD UserNtPassword;
762 ENCRYPTED_LM_OWF_PASSWORD UserLmPassword;
763 BOOLEAN UserLmPasswordPresent = FALSE;
764 BOOLEAN UserNtPasswordPresent = FALSE;
765 OEM_STRING LmPwdString;
766 CHAR LmPwdBuffer[15];
767 NTSTATUS Status;
768
769 TRACE("(%p %p)\n", UserPassword, UserInfo);
770
771 /* Calculate the LM password and hash for the users password */
772 LmPwdString.Length = 15;
773 LmPwdString.MaximumLength = 15;
774 LmPwdString.Buffer = LmPwdBuffer;
775 ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
776
777 Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
778 UserPassword,
779 FALSE);
780 if (NT_SUCCESS(Status))
781 {
782 /* Calculate the LM hash value of the users password */
783 Status = SystemFunction006(LmPwdString.Buffer,
784 (LPSTR)&UserLmPassword);
785 if (NT_SUCCESS(Status))
786 {
787 UserLmPasswordPresent = TRUE;
788 }
789 }
790
791 /* Calculate the NT hash of the users password */
792 Status = SystemFunction007(UserPassword,
793 (LPBYTE)&UserNtPassword);
794 if (NT_SUCCESS(Status))
795 {
796 UserNtPasswordPresent = TRUE;
797 }
798
799 Status = STATUS_WRONG_PASSWORD;
800
801 /* Succeed, if no password has been set */
802 if (UserInfo->All.NtPasswordPresent == FALSE &&
803 UserInfo->All.LmPasswordPresent == FALSE)
804 {
805 TRACE("No password check!\n");
806 Status = STATUS_SUCCESS;
807 goto done;
808 }
809
810 /* Succeed, if NT password matches */
811 if (UserNtPasswordPresent && UserInfo->All.NtPasswordPresent)
812 {
813 TRACE("Check NT password hashes:\n");
814 if (RtlEqualMemory(&UserNtPassword,
815 UserInfo->All.NtOwfPassword.Buffer,
816 sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
817 {
818 TRACE(" success!\n");
819 Status = STATUS_SUCCESS;
820 goto done;
821 }
822
823 TRACE(" failed!\n");
824 }
825
826 /* Succeed, if LM password matches */
827 if (UserLmPasswordPresent && UserInfo->All.LmPasswordPresent)
828 {
829 TRACE("Check LM password hashes:\n");
830 if (RtlEqualMemory(&UserLmPassword,
831 UserInfo->All.LmOwfPassword.Buffer,
832 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
833 {
834 TRACE(" success!\n");
835 Status = STATUS_SUCCESS;
836 goto done;
837 }
838 TRACE(" failed!\n");
839 }
840
841 done:
842 return Status;
843 }
844
845
846 static
847 BOOL
848 MsvpCheckLogonHours(
849 _In_ PSAMPR_LOGON_HOURS LogonHours,
850 _In_ PLARGE_INTEGER LogonTime)
851 {
852 LARGE_INTEGER LocalLogonTime;
853 TIME_FIELDS TimeFields;
854 USHORT MinutesPerUnit, Offset;
855
856 TRACE("MsvpCheckLogonHours(%p %p)\n", LogonHours, LogonTime);
857
858 if (LogonHours->UnitsPerWeek == 0 || LogonHours->LogonHours == NULL)
859 return TRUE;
860
861 RtlSystemTimeToLocalTime(LogonTime, &LocalLogonTime);
862 RtlTimeToTimeFields(&LocalLogonTime, &TimeFields);
863
864 TRACE("UnitsPerWeek: %u\n", LogonHours->UnitsPerWeek);
865 MinutesPerUnit = 10080 / LogonHours->UnitsPerWeek;
866
867 Offset = ((TimeFields.Weekday * 24 + TimeFields.Hour) * 60 + TimeFields.Minute) / MinutesPerUnit;
868
869 return (BOOL)(LogonHours->LogonHours[Offset / 8] & (1 << (Offset % 8)));
870 }
871
872
873 static
874 BOOL
875 MsvpCheckWorkstations(
876 _In_ PRPC_UNICODE_STRING WorkStations,
877 _In_ PWSTR ComputerName)
878 {
879 PWSTR pStart, pEnd;
880 BOOL bFound = FALSE;
881
882 TRACE("MsvpCheckWorkstations(%wZ %S)\n", WorkStations, ComputerName);
883
884 if (WorkStations->Length == 0 || WorkStations->Buffer == NULL)
885 return TRUE;
886
887 pStart = WorkStations->Buffer;
888 for (;;)
889 {
890 pEnd = wcschr(pStart, L',');
891 if (pEnd != NULL)
892 *pEnd = UNICODE_NULL;
893
894 if (_wcsicmp(ComputerName, pStart) == 0)
895 {
896 bFound = TRUE;
897 if (pEnd != NULL)
898 *pEnd = L',';
899 break;
900 }
901
902 if (pEnd == NULL)
903 break;
904
905 *pEnd = L',';
906 pStart = pEnd + 1;
907 }
908
909 return bFound;
910 }
911
912
913 /*
914 * @unimplemented
915 */
916 NTSTATUS
917 NTAPI
918 LsaApCallPackage(IN PLSA_CLIENT_REQUEST ClientRequest,
919 IN PVOID ProtocolSubmitBuffer,
920 IN PVOID ClientBufferBase,
921 IN ULONG SubmitBufferLength,
922 OUT PVOID *ProtocolReturnBuffer,
923 OUT PULONG ReturnBufferLength,
924 OUT PNTSTATUS ProtocolStatus)
925 {
926 ULONG MessageType;
927 NTSTATUS Status;
928
929 TRACE("LsaApCallPackage()\n");
930
931 if (SubmitBufferLength < sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE))
932 return STATUS_INVALID_PARAMETER;
933
934 MessageType = (ULONG)*((PMSV1_0_PROTOCOL_MESSAGE_TYPE)ProtocolSubmitBuffer);
935
936 *ProtocolReturnBuffer = NULL;
937 *ReturnBufferLength = 0;
938
939 switch (MessageType)
940 {
941 case MsV1_0Lm20ChallengeRequest:
942 case MsV1_0Lm20GetChallengeResponse:
943 Status = STATUS_NOT_IMPLEMENTED;
944 break;
945
946 case MsV1_0EnumerateUsers:
947 case MsV1_0GetUserInfo:
948 case MsV1_0ReLogonUsers:
949 Status = STATUS_INVALID_PARAMETER;
950 break;
951
952 case MsV1_0ChangePassword:
953 Status = MsvpChangePassword(ClientRequest,
954 ProtocolSubmitBuffer,
955 ClientBufferBase,
956 SubmitBufferLength,
957 ProtocolReturnBuffer,
958 ReturnBufferLength,
959 ProtocolStatus);
960 break;
961
962 case MsV1_0ChangeCachedPassword:
963 case MsV1_0GenericPassthrough:
964 case MsV1_0CacheLogon:
965 case MsV1_0SubAuth:
966 case MsV1_0DeriveCredential:
967 case MsV1_0CacheLookup:
968 Status = STATUS_NOT_IMPLEMENTED;
969 break;
970
971 default:
972 return STATUS_INVALID_PARAMETER;
973 }
974
975 return Status;
976 }
977
978
979 /*
980 * @unimplemented
981 */
982 NTSTATUS
983 NTAPI
984 LsaApCallPackagePassthrough(IN PLSA_CLIENT_REQUEST ClientRequest,
985 IN PVOID ProtocolSubmitBuffer,
986 IN PVOID ClientBufferBase,
987 IN ULONG SubmitBufferLength,
988 OUT PVOID *ProtocolReturnBuffer,
989 OUT PULONG ReturnBufferLength,
990 OUT PNTSTATUS ProtocolStatus)
991 {
992 TRACE("LsaApCallPackagePassthrough()\n");
993 return STATUS_NOT_IMPLEMENTED;
994 }
995
996
997 /*
998 * @unimplemented
999 */
1000 NTSTATUS
1001 NTAPI
1002 LsaApCallPackageUntrusted(IN PLSA_CLIENT_REQUEST ClientRequest,
1003 IN PVOID ProtocolSubmitBuffer,
1004 IN PVOID ClientBufferBase,
1005 IN ULONG SubmitBufferLength,
1006 OUT PVOID *ProtocolReturnBuffer,
1007 OUT PULONG ReturnBufferLength,
1008 OUT PNTSTATUS ProtocolStatus)
1009 {
1010 TRACE("LsaApCallPackageUntrusted()\n");
1011 return STATUS_NOT_IMPLEMENTED;
1012 }
1013
1014
1015 /*
1016 * @implemented
1017 */
1018 NTSTATUS
1019 NTAPI
1020 LsaApInitializePackage(IN ULONG AuthenticationPackageId,
1021 IN PLSA_DISPATCH_TABLE LsaDispatchTable,
1022 IN PLSA_STRING Database OPTIONAL,
1023 IN PLSA_STRING Confidentiality OPTIONAL,
1024 OUT PLSA_STRING *AuthenticationPackageName)
1025 {
1026 PANSI_STRING NameString;
1027 PCHAR NameBuffer;
1028
1029 TRACE("LsaApInitializePackage(%lu %p %p %p %p)\n",
1030 AuthenticationPackageId, LsaDispatchTable, Database,
1031 Confidentiality, AuthenticationPackageName);
1032
1033 /* Get the dispatch table entries */
1034 DispatchTable.CreateLogonSession = LsaDispatchTable->CreateLogonSession;
1035 DispatchTable.DeleteLogonSession = LsaDispatchTable->DeleteLogonSession;
1036 DispatchTable.AddCredential = LsaDispatchTable->AddCredential;
1037 DispatchTable.GetCredentials = LsaDispatchTable->GetCredentials;
1038 DispatchTable.DeleteCredential = LsaDispatchTable->DeleteCredential;
1039 DispatchTable.AllocateLsaHeap = LsaDispatchTable->AllocateLsaHeap;
1040 DispatchTable.FreeLsaHeap = LsaDispatchTable->FreeLsaHeap;
1041 DispatchTable.AllocateClientBuffer = LsaDispatchTable->AllocateClientBuffer;
1042 DispatchTable.FreeClientBuffer = LsaDispatchTable->FreeClientBuffer;
1043 DispatchTable.CopyToClientBuffer = LsaDispatchTable->CopyToClientBuffer;
1044 DispatchTable.CopyFromClientBuffer = LsaDispatchTable->CopyFromClientBuffer;
1045
1046 /* Return the package name */
1047 NameString = DispatchTable.AllocateLsaHeap(sizeof(LSA_STRING));
1048 if (NameString == NULL)
1049 return STATUS_INSUFFICIENT_RESOURCES;
1050
1051 NameBuffer = DispatchTable.AllocateLsaHeap(sizeof(MSV1_0_PACKAGE_NAME));
1052 if (NameBuffer == NULL)
1053 {
1054 DispatchTable.FreeLsaHeap(NameString);
1055 return STATUS_INSUFFICIENT_RESOURCES;
1056 }
1057
1058 strcpy(NameBuffer, MSV1_0_PACKAGE_NAME);
1059
1060 RtlInitAnsiString(NameString, NameBuffer);
1061
1062 *AuthenticationPackageName = (PLSA_STRING)NameString;
1063
1064 return STATUS_SUCCESS;
1065 }
1066
1067
1068 /*
1069 * @unimplemented
1070 */
1071 VOID
1072 NTAPI
1073 LsaApLogonTerminated(IN PLUID LogonId)
1074 {
1075 TRACE("LsaApLogonTerminated()\n");
1076 }
1077
1078
1079 /*
1080 * @implemented
1081 */
1082 NTSTATUS
1083 NTAPI
1084 LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
1085 IN SECURITY_LOGON_TYPE LogonType,
1086 IN PVOID ProtocolSubmitBuffer,
1087 IN PVOID ClientBufferBase,
1088 IN ULONG SubmitBufferSize,
1089 OUT PVOID *ProfileBuffer,
1090 OUT PULONG ProfileBufferSize,
1091 OUT PLUID LogonId,
1092 OUT PNTSTATUS SubStatus,
1093 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
1094 OUT PVOID *TokenInformation,
1095 OUT PUNICODE_STRING *AccountName,
1096 OUT PUNICODE_STRING *AuthenticatingAuthority,
1097 OUT PUNICODE_STRING *MachineName,
1098 OUT PSECPKG_PRIMARY_CRED PrimaryCredentials, /* Not supported yet */
1099 OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY *SupplementalCredentials) /* Not supported yet */
1100 {
1101 PMSV1_0_INTERACTIVE_LOGON LogonInfo;
1102 WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
1103 SAMPR_HANDLE ServerHandle = NULL;
1104 SAMPR_HANDLE DomainHandle = NULL;
1105 SAMPR_HANDLE UserHandle = NULL;
1106 PRPC_SID AccountDomainSid = NULL;
1107 RPC_UNICODE_STRING Names[1];
1108 SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
1109 SAMPR_ULONG_ARRAY Use = {0, NULL};
1110 PSAMPR_USER_INFO_BUFFER UserInfo = NULL;
1111 BOOLEAN SessionCreated = FALSE;
1112 LARGE_INTEGER LogonTime;
1113 LARGE_INTEGER AccountExpires;
1114 LARGE_INTEGER PasswordMustChange;
1115 LARGE_INTEGER PasswordLastSet;
1116 DWORD ComputerNameSize;
1117 BOOL SpecialAccount = FALSE;
1118 NTSTATUS Status;
1119
1120 TRACE("LsaApLogonUser()\n");
1121
1122 TRACE("LogonType: %lu\n", LogonType);
1123 TRACE("ProtocolSubmitBuffer: %p\n", ProtocolSubmitBuffer);
1124 TRACE("SubmitBufferSize: %lu\n", SubmitBufferSize);
1125
1126 *ProfileBuffer = NULL;
1127 *ProfileBufferSize = 0;
1128 *SubStatus = STATUS_SUCCESS;
1129 *AccountName = NULL;
1130 *AuthenticatingAuthority = NULL;
1131
1132 if (LogonType == Interactive ||
1133 LogonType == Batch ||
1134 LogonType == Service)
1135 {
1136 ULONG_PTR PtrOffset;
1137
1138 LogonInfo = (PMSV1_0_INTERACTIVE_LOGON)ProtocolSubmitBuffer;
1139
1140 /* Fix-up pointers in the authentication info */
1141 PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;
1142
1143 LogonInfo->LogonDomainName.Buffer = FIXUP_POINTER(LogonInfo->LogonDomainName.Buffer, PtrOffset);
1144 LogonInfo->UserName.Buffer = FIXUP_POINTER(LogonInfo->UserName.Buffer, PtrOffset);
1145 LogonInfo->Password.Buffer = FIXUP_POINTER(LogonInfo->Password.Buffer, PtrOffset);
1146
1147 TRACE("Domain: %S\n", LogonInfo->LogonDomainName.Buffer);
1148 TRACE("User: %S\n", LogonInfo->UserName.Buffer);
1149 TRACE("Password: %S\n", LogonInfo->Password.Buffer);
1150 }
1151 else
1152 {
1153 FIXME("LogonType %lu is not supported yet!\n", LogonType);
1154 return STATUS_NOT_IMPLEMENTED;
1155 }
1156
1157 /* Get the logon time */
1158 NtQuerySystemTime(&LogonTime);
1159
1160 /* Get the computer name */
1161 ComputerNameSize = MAX_COMPUTERNAME_LENGTH + 1;
1162 GetComputerNameW(ComputerName, &ComputerNameSize);
1163
1164 /* Check for special accounts */
1165 if (_wcsicmp(LogonInfo->LogonDomainName.Buffer, L"NT AUTHORITY") == 0)
1166 {
1167 SpecialAccount = TRUE;
1168
1169 /* Get the authority domain SID */
1170 Status = GetNtAuthorityDomainSid(&AccountDomainSid);
1171 if (!NT_SUCCESS(Status))
1172 {
1173 ERR("GetNtAuthorityDomainSid() failed (Status 0x%08lx)\n", Status);
1174 return Status;
1175 }
1176
1177 if (_wcsicmp(LogonInfo->UserName.Buffer, L"LocalService") == 0)
1178 {
1179 TRACE("SpecialAccount: LocalService\n");
1180
1181 if (LogonType != Service)
1182 return STATUS_LOGON_FAILURE;
1183
1184 UserInfo = RtlAllocateHeap(RtlGetProcessHeap(),
1185 HEAP_ZERO_MEMORY,
1186 sizeof(SAMPR_USER_ALL_INFORMATION));
1187 if (UserInfo == NULL)
1188 {
1189 Status = STATUS_INSUFFICIENT_RESOURCES;
1190 goto done;
1191 }
1192
1193 UserInfo->All.UserId = SECURITY_LOCAL_SERVICE_RID;
1194 UserInfo->All.PrimaryGroupId = SECURITY_LOCAL_SERVICE_RID;
1195 }
1196 else if (_wcsicmp(LogonInfo->UserName.Buffer, L"NetworkService") == 0)
1197 {
1198 TRACE("SpecialAccount: NetworkService\n");
1199
1200 if (LogonType != Service)
1201 return STATUS_LOGON_FAILURE;
1202
1203 UserInfo = RtlAllocateHeap(RtlGetProcessHeap(),
1204 HEAP_ZERO_MEMORY,
1205 sizeof(SAMPR_USER_ALL_INFORMATION));
1206 if (UserInfo == NULL)
1207 {
1208 Status = STATUS_INSUFFICIENT_RESOURCES;
1209 goto done;
1210 }
1211
1212 UserInfo->All.UserId = SECURITY_NETWORK_SERVICE_RID;
1213 UserInfo->All.PrimaryGroupId = SECURITY_NETWORK_SERVICE_RID;
1214 }
1215 else
1216 {
1217 Status = STATUS_NO_SUCH_USER;
1218 goto done;
1219 }
1220 }
1221 else
1222 {
1223 TRACE("NormalAccount\n");
1224
1225 /* Get the account domain SID */
1226 Status = GetAccountDomainSid(&AccountDomainSid);
1227 if (!NT_SUCCESS(Status))
1228 {
1229 ERR("GetAccountDomainSid() failed (Status 0x%08lx)\n", Status);
1230 return Status;
1231 }
1232
1233 /* Connect to the SAM server */
1234 Status = SamIConnect(NULL,
1235 &ServerHandle,
1236 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
1237 TRUE);
1238 if (!NT_SUCCESS(Status))
1239 {
1240 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
1241 goto done;
1242 }
1243
1244 /* Open the account domain */
1245 Status = SamrOpenDomain(ServerHandle,
1246 DOMAIN_LOOKUP,
1247 AccountDomainSid,
1248 &DomainHandle);
1249 if (!NT_SUCCESS(Status))
1250 {
1251 ERR("SamrOpenDomain failed (Status %08lx)\n", Status);
1252 goto done;
1253 }
1254
1255 Names[0].Length = LogonInfo->UserName.Length;
1256 Names[0].MaximumLength = LogonInfo->UserName.MaximumLength;
1257 Names[0].Buffer = LogonInfo->UserName.Buffer;
1258
1259 /* Try to get the RID for the user name */
1260 Status = SamrLookupNamesInDomain(DomainHandle,
1261 1,
1262 Names,
1263 &RelativeIds,
1264 &Use);
1265 if (!NT_SUCCESS(Status))
1266 {
1267 ERR("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
1268 Status = STATUS_NO_SUCH_USER;
1269 goto done;
1270 }
1271
1272 /* Fail, if it is not a user account */
1273 if (Use.Element[0] != SidTypeUser)
1274 {
1275 ERR("Account is not a user account!\n");
1276 Status = STATUS_NO_SUCH_USER;
1277 goto done;
1278 }
1279
1280 /* Open the user object */
1281 Status = SamrOpenUser(DomainHandle,
1282 USER_READ_GENERAL | USER_READ_LOGON |
1283 USER_READ_ACCOUNT | USER_READ_PREFERENCES, /* FIXME */
1284 RelativeIds.Element[0],
1285 &UserHandle);
1286 if (!NT_SUCCESS(Status))
1287 {
1288 ERR("SamrOpenUser failed (Status %08lx)\n", Status);
1289 goto done;
1290 }
1291
1292 Status = SamrQueryInformationUser(UserHandle,
1293 UserAllInformation,
1294 &UserInfo);
1295 if (!NT_SUCCESS(Status))
1296 {
1297 ERR("SamrQueryInformationUser failed (Status %08lx)\n", Status);
1298 goto done;
1299 }
1300
1301 TRACE("UserName: %S\n", UserInfo->All.UserName.Buffer);
1302
1303 /* Check the password */
1304 if ((UserInfo->All.UserAccountControl & USER_PASSWORD_NOT_REQUIRED) == 0)
1305 {
1306 Status = MsvpCheckPassword(&(LogonInfo->Password),
1307 UserInfo);
1308 if (!NT_SUCCESS(Status))
1309 {
1310 ERR("MsvpCheckPassword failed (Status %08lx)\n", Status);
1311 goto done;
1312 }
1313 }
1314
1315 /* Check account restrictions for non-administrator accounts */
1316 if (RelativeIds.Element[0] != DOMAIN_USER_RID_ADMIN)
1317 {
1318 /* Check if the account has been disabled */
1319 if (UserInfo->All.UserAccountControl & USER_ACCOUNT_DISABLED)
1320 {
1321 ERR("Account disabled!\n");
1322 *SubStatus = STATUS_ACCOUNT_DISABLED;
1323 Status = STATUS_ACCOUNT_RESTRICTION;
1324 goto done;
1325 }
1326
1327 /* Check if the account has been locked */
1328 if (UserInfo->All.UserAccountControl & USER_ACCOUNT_AUTO_LOCKED)
1329 {
1330 ERR("Account locked!\n");
1331 *SubStatus = STATUS_ACCOUNT_LOCKED_OUT;
1332 Status = STATUS_ACCOUNT_RESTRICTION;
1333 goto done;
1334 }
1335
1336 /* Check if the account expired */
1337 AccountExpires.LowPart = UserInfo->All.AccountExpires.LowPart;
1338 AccountExpires.HighPart = UserInfo->All.AccountExpires.HighPart;
1339 if (LogonTime.QuadPart >= AccountExpires.QuadPart)
1340 {
1341 ERR("Account expired!\n");
1342 *SubStatus = STATUS_ACCOUNT_EXPIRED;
1343 Status = STATUS_ACCOUNT_RESTRICTION;
1344 goto done;
1345 }
1346
1347 /* Check if the password expired */
1348 PasswordMustChange.LowPart = UserInfo->All.PasswordMustChange.LowPart;
1349 PasswordMustChange.HighPart = UserInfo->All.PasswordMustChange.HighPart;
1350 PasswordLastSet.LowPart = UserInfo->All.PasswordLastSet.LowPart;
1351 PasswordLastSet.HighPart = UserInfo->All.PasswordLastSet.HighPart;
1352
1353 if (LogonTime.QuadPart >= PasswordMustChange.QuadPart)
1354 {
1355 ERR("Password expired!\n");
1356 if (PasswordLastSet.QuadPart == 0)
1357 *SubStatus = STATUS_PASSWORD_MUST_CHANGE;
1358 else
1359 *SubStatus = STATUS_PASSWORD_EXPIRED;
1360
1361 Status = STATUS_ACCOUNT_RESTRICTION;
1362 goto done;
1363 }
1364
1365 /* Check logon hours */
1366 if (!MsvpCheckLogonHours(&UserInfo->All.LogonHours, &LogonTime))
1367 {
1368 ERR("Invalid logon hours!\n");
1369 *SubStatus = STATUS_INVALID_LOGON_HOURS;
1370 Status = STATUS_ACCOUNT_RESTRICTION;
1371 goto done;
1372 }
1373
1374 /* Check workstations */
1375 if (!MsvpCheckWorkstations(&UserInfo->All.WorkStations, ComputerName))
1376 {
1377 ERR("Invalid workstation!\n");
1378 *SubStatus = STATUS_INVALID_WORKSTATION;
1379 Status = STATUS_ACCOUNT_RESTRICTION;
1380 goto done;
1381 }
1382 }
1383 }
1384
1385 /* Return logon information */
1386
1387 /* Create and return a new logon id */
1388 Status = NtAllocateLocallyUniqueId(LogonId);
1389 if (!NT_SUCCESS(Status))
1390 {
1391 TRACE("NtAllocateLocallyUniqueId failed (Status %08lx)\n", Status);
1392 goto done;
1393 }
1394
1395 /* Create the logon session */
1396 Status = DispatchTable.CreateLogonSession(LogonId);
1397 if (!NT_SUCCESS(Status))
1398 {
1399 TRACE("CreateLogonSession failed (Status %08lx)\n", Status);
1400 goto done;
1401 }
1402
1403 SessionCreated = TRUE;
1404
1405 /* Build and fill the interactive profile buffer */
1406 Status = BuildInteractiveProfileBuffer(ClientRequest,
1407 UserInfo,
1408 ComputerName,
1409 (PMSV1_0_INTERACTIVE_PROFILE*)ProfileBuffer,
1410 ProfileBufferSize);
1411 if (!NT_SUCCESS(Status))
1412 {
1413 TRACE("BuildInteractiveProfileBuffer failed (Status %08lx)\n", Status);
1414 goto done;
1415 }
1416
1417 /* Return the token information type */
1418 *TokenInformationType = LsaTokenInformationV1;
1419
1420 /* Build and fill the token information buffer */
1421 Status = BuildTokenInformationBuffer((PLSA_TOKEN_INFORMATION_V1*)TokenInformation,
1422 AccountDomainSid,
1423 UserInfo,
1424 SpecialAccount);
1425 if (!NT_SUCCESS(Status))
1426 {
1427 TRACE("BuildTokenInformationBuffer failed (Status %08lx)\n", Status);
1428 goto done;
1429 }
1430
1431 done:
1432 /* Update the logon time/count or the bad password time/count */
1433 if ((UserHandle != NULL) &&
1434 (Status == STATUS_SUCCESS || Status == STATUS_WRONG_PASSWORD))
1435 {
1436 SAMPR_USER_INFO_BUFFER InternalInfo;
1437
1438 RtlZeroMemory(&InternalInfo, sizeof(InternalInfo));
1439
1440 if (Status == STATUS_SUCCESS)
1441 InternalInfo.Internal2.Flags = USER_LOGON_SUCCESS;
1442 else
1443 InternalInfo.Internal2.Flags = USER_LOGON_BAD_PASSWORD;
1444
1445 SamrSetInformationUser(UserHandle,
1446 UserInternal2Information,
1447 &InternalInfo);
1448 }
1449
1450 /* Return the account name */
1451 *AccountName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1452 if (*AccountName != NULL)
1453 {
1454 (*AccountName)->Buffer = DispatchTable.AllocateLsaHeap(LogonInfo->UserName.Length +
1455 sizeof(UNICODE_NULL));
1456 if ((*AccountName)->Buffer != NULL)
1457 {
1458 (*AccountName)->MaximumLength = LogonInfo->UserName.Length +
1459 sizeof(UNICODE_NULL);
1460 RtlCopyUnicodeString(*AccountName, &LogonInfo->UserName);
1461 }
1462 }
1463
1464 /* Return the authenticating authority */
1465 *AuthenticatingAuthority = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1466 if (*AuthenticatingAuthority != NULL)
1467 {
1468 (*AuthenticatingAuthority)->Buffer = DispatchTable.AllocateLsaHeap(LogonInfo->LogonDomainName.Length +
1469 sizeof(UNICODE_NULL));
1470 if ((*AuthenticatingAuthority)->Buffer != NULL)
1471 {
1472 (*AuthenticatingAuthority)->MaximumLength = LogonInfo->LogonDomainName.Length +
1473 sizeof(UNICODE_NULL);
1474 RtlCopyUnicodeString(*AuthenticatingAuthority, &LogonInfo->LogonDomainName);
1475 }
1476 }
1477
1478 /* Return the machine name */
1479 *MachineName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1480 if (*MachineName != NULL)
1481 {
1482 (*MachineName)->Buffer = DispatchTable.AllocateLsaHeap((ComputerNameSize + 1) * sizeof(WCHAR));
1483 if ((*MachineName)->Buffer != NULL)
1484 {
1485 (*MachineName)->MaximumLength = (ComputerNameSize + 1) * sizeof(WCHAR);
1486 (*MachineName)->Length = ComputerNameSize * sizeof(WCHAR);
1487 RtlCopyMemory((*MachineName)->Buffer, ComputerName, (*MachineName)->MaximumLength);
1488 }
1489 }
1490
1491 if (!NT_SUCCESS(Status))
1492 {
1493 if (SessionCreated != FALSE)
1494 DispatchTable.DeleteLogonSession(LogonId);
1495
1496 if (*ProfileBuffer != NULL)
1497 {
1498 DispatchTable.FreeClientBuffer(ClientRequest,
1499 *ProfileBuffer);
1500 *ProfileBuffer = NULL;
1501 }
1502 }
1503
1504 if (UserHandle != NULL)
1505 SamrCloseHandle(&UserHandle);
1506
1507 SamIFree_SAMPR_USER_INFO_BUFFER(UserInfo,
1508 UserAllInformation);
1509 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
1510 SamIFree_SAMPR_ULONG_ARRAY(&Use);
1511
1512 if (DomainHandle != NULL)
1513 SamrCloseHandle(&DomainHandle);
1514
1515 if (ServerHandle != NULL)
1516 SamrCloseHandle(&ServerHandle);
1517
1518 if (AccountDomainSid != NULL)
1519 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
1520
1521 if (Status == STATUS_NO_SUCH_USER ||
1522 Status == STATUS_WRONG_PASSWORD)
1523 {
1524 *SubStatus = Status;
1525 Status = STATUS_LOGON_FAILURE;
1526 }
1527
1528 TRACE("LsaApLogonUser done (Status 0x%08lx SubStatus 0x%08lx)\n", Status, *SubStatus);
1529
1530 return Status;
1531 }
1532
1533 /* EOF */