[MSV1_0]
[reactos.git] / reactos / 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 GetDomainSid(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 BuildInteractiveProfileBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
75 IN PSAMPR_USER_INFO_BUFFER UserInfo,
76 IN PUNICODE_STRING LogonServer,
77 OUT PMSV1_0_INTERACTIVE_PROFILE *ProfileBuffer,
78 OUT PULONG ProfileBufferLength)
79 {
80 PMSV1_0_INTERACTIVE_PROFILE LocalBuffer = NULL;
81 PVOID ClientBaseAddress = NULL;
82 LPWSTR Ptr;
83 ULONG BufferLength;
84 NTSTATUS Status = STATUS_SUCCESS;
85
86 *ProfileBuffer = NULL;
87 *ProfileBufferLength = 0;
88
89 BufferLength = sizeof(MSV1_0_INTERACTIVE_PROFILE) +
90 UserInfo->All.FullName.Length + sizeof(WCHAR) +
91 UserInfo->All.HomeDirectory.Length + sizeof(WCHAR) +
92 UserInfo->All.HomeDirectoryDrive.Length + sizeof(WCHAR) +
93 UserInfo->All.ScriptPath.Length + sizeof(WCHAR) +
94 UserInfo->All.ProfilePath.Length + sizeof(WCHAR) +
95 LogonServer->Length + sizeof(WCHAR);
96
97 LocalBuffer = DispatchTable.AllocateLsaHeap(BufferLength);
98 if (LocalBuffer == NULL)
99 {
100 TRACE("Failed to allocate the local buffer!\n");
101 Status = STATUS_INSUFFICIENT_RESOURCES;
102 goto done;
103 }
104
105 Status = DispatchTable.AllocateClientBuffer(ClientRequest,
106 BufferLength,
107 &ClientBaseAddress);
108 if (!NT_SUCCESS(Status))
109 {
110 TRACE("DispatchTable.AllocateClientBuffer failed (Status 0x%08lx)\n", Status);
111 goto done;
112 }
113
114 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
115
116 Ptr = (LPWSTR)((ULONG_PTR)LocalBuffer + sizeof(MSV1_0_INTERACTIVE_PROFILE));
117
118 LocalBuffer->MessageType = MsV1_0InteractiveProfile;
119 LocalBuffer->LogonCount = UserInfo->All.LogonCount;
120 LocalBuffer->BadPasswordCount = UserInfo->All.BadPasswordCount;
121
122 LocalBuffer->LogonTime.LowPart = UserInfo->All.LastLogon.LowPart;
123 LocalBuffer->LogonTime.HighPart = UserInfo->All.LastLogon.HighPart;
124
125 // LocalBuffer->LogoffTime.LowPart =
126 // LocalBuffer->LogoffTime.HighPart =
127
128 // LocalBuffer->KickOffTime.LowPart =
129 // LocalBuffer->KickOffTime.HighPart =
130
131 LocalBuffer->PasswordLastSet.LowPart = UserInfo->All.PasswordLastSet.LowPart;
132 LocalBuffer->PasswordLastSet.HighPart = UserInfo->All.PasswordLastSet.HighPart;
133
134 LocalBuffer->PasswordCanChange.LowPart = UserInfo->All.PasswordCanChange.LowPart;
135 LocalBuffer->PasswordCanChange.HighPart = UserInfo->All.PasswordCanChange.HighPart;
136
137 LocalBuffer->PasswordMustChange.LowPart = UserInfo->All.PasswordMustChange.LowPart;
138 LocalBuffer->PasswordMustChange.HighPart = UserInfo->All.PasswordMustChange.HighPart;
139
140 LocalBuffer->LogonScript.Length = UserInfo->All.ScriptPath.Length;
141 LocalBuffer->LogonScript.MaximumLength = UserInfo->All.ScriptPath.Length + sizeof(WCHAR);
142 LocalBuffer->LogonScript.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
143 memcpy(Ptr,
144 UserInfo->All.ScriptPath.Buffer,
145 UserInfo->All.ScriptPath.Length);
146
147 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->LogonScript.MaximumLength);
148
149 LocalBuffer->HomeDirectory.Length = UserInfo->All.HomeDirectory.Length;
150 LocalBuffer->HomeDirectory.MaximumLength = UserInfo->All.HomeDirectory.Length + sizeof(WCHAR);
151 LocalBuffer->HomeDirectory.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
152 memcpy(Ptr,
153 UserInfo->All.HomeDirectory.Buffer,
154 UserInfo->All.HomeDirectory.Length);
155
156 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectory.MaximumLength);
157
158 LocalBuffer->FullName.Length = UserInfo->All.FullName.Length;
159 LocalBuffer->FullName.MaximumLength = UserInfo->All.FullName.Length + sizeof(WCHAR);
160 LocalBuffer->FullName.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
161 memcpy(Ptr,
162 UserInfo->All.FullName.Buffer,
163 UserInfo->All.FullName.Length);
164 TRACE("FullName.Buffer: %p\n", LocalBuffer->FullName.Buffer);
165
166 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->FullName.MaximumLength);
167
168 LocalBuffer->ProfilePath.Length = UserInfo->All.ProfilePath.Length;
169 LocalBuffer->ProfilePath.MaximumLength = UserInfo->All.ProfilePath.Length + sizeof(WCHAR);
170 LocalBuffer->ProfilePath.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
171 memcpy(Ptr,
172 UserInfo->All.ProfilePath.Buffer,
173 UserInfo->All.ProfilePath.Length);
174
175 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->ProfilePath.MaximumLength);
176
177 LocalBuffer->HomeDirectoryDrive.Length = UserInfo->All.HomeDirectoryDrive.Length;
178 LocalBuffer->HomeDirectoryDrive.MaximumLength = UserInfo->All.HomeDirectoryDrive.Length + sizeof(WCHAR);
179 LocalBuffer->HomeDirectoryDrive.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
180 memcpy(Ptr,
181 UserInfo->All.HomeDirectoryDrive.Buffer,
182 UserInfo->All.HomeDirectoryDrive.Length);
183
184 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectoryDrive.MaximumLength);
185
186 LocalBuffer->LogonServer.Length = LogonServer->Length;
187 LocalBuffer->LogonServer.MaximumLength = LogonServer->Length + sizeof(WCHAR);
188 LocalBuffer->LogonServer.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);;
189 memcpy(Ptr,
190 LogonServer->Buffer,
191 LogonServer->Length);
192
193 LocalBuffer->UserFlags = 0;
194
195 Status = DispatchTable.CopyToClientBuffer(ClientRequest,
196 BufferLength,
197 ClientBaseAddress,
198 LocalBuffer);
199 if (!NT_SUCCESS(Status))
200 {
201 TRACE("DispatchTable.CopyToClientBuffer failed (Status 0x%08lx)\n", Status);
202 goto done;
203 }
204
205 *ProfileBuffer = (PMSV1_0_INTERACTIVE_PROFILE)ClientBaseAddress;
206 *ProfileBufferLength = BufferLength;
207
208 done:
209 if (LocalBuffer != NULL)
210 DispatchTable.FreeLsaHeap(LocalBuffer);
211
212 if (!NT_SUCCESS(Status))
213 {
214 if (ClientBaseAddress != NULL)
215 DispatchTable.FreeClientBuffer(ClientRequest,
216 ClientBaseAddress);
217 }
218
219 return Status;
220 }
221
222
223 static
224 PSID
225 AppendRidToSid(PSID SrcSid,
226 ULONG Rid)
227 {
228 PSID DstSid = NULL;
229 UCHAR RidCount;
230
231 RidCount = *RtlSubAuthorityCountSid(SrcSid);
232 if (RidCount >= 8)
233 return NULL;
234
235 DstSid = DispatchTable.AllocateLsaHeap(RtlLengthRequiredSid(RidCount + 1));
236 if (DstSid == NULL)
237 return NULL;
238
239 RtlCopyMemory(DstSid,
240 SrcSid,
241 RtlLengthRequiredSid(RidCount));
242
243 *RtlSubAuthorityCountSid(DstSid) = RidCount + 1;
244 *RtlSubAuthoritySid(DstSid, RidCount) = Rid;
245
246 return DstSid;
247 }
248
249 static
250 NTSTATUS
251 BuildTokenUser(OUT PTOKEN_USER User,
252 IN PSID AccountDomainSid,
253 IN ULONG RelativeId)
254 {
255 User->User.Sid = AppendRidToSid(AccountDomainSid,
256 RelativeId);
257 if (User->User.Sid == NULL)
258 {
259 ERR("Could not create the user SID\n");
260 return STATUS_INSUFFICIENT_RESOURCES;
261 }
262
263 User->User.Attributes = 0;
264
265 return STATUS_SUCCESS;
266 }
267
268
269 static
270 NTSTATUS
271 BuildTokenPrimaryGroup(OUT PTOKEN_PRIMARY_GROUP PrimaryGroup,
272 IN PSID AccountDomainSid,
273 IN ULONG RelativeId)
274 {
275 PrimaryGroup->PrimaryGroup = AppendRidToSid(AccountDomainSid,
276 RelativeId);
277 if (PrimaryGroup->PrimaryGroup == NULL)
278 {
279 ERR("Could not create the primary group SID\n");
280 return STATUS_INSUFFICIENT_RESOURCES;
281 }
282
283 return STATUS_SUCCESS;
284 }
285
286
287 static
288 NTSTATUS
289 BuildTokenGroups(OUT PTOKEN_GROUPS *Groups,
290 IN PSID AccountDomainSid)
291 {
292 SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
293 PTOKEN_GROUPS TokenGroups;
294 #define MAX_GROUPS 2
295 DWORD GroupCount = 0;
296 PSID Sid;
297 NTSTATUS Status = STATUS_SUCCESS;
298
299 TokenGroups = DispatchTable.AllocateLsaHeap(sizeof(TOKEN_GROUPS) +
300 MAX_GROUPS * sizeof(SID_AND_ATTRIBUTES));
301 if (TokenGroups == NULL)
302 {
303 return STATUS_INSUFFICIENT_RESOURCES;
304 }
305
306 Sid = AppendRidToSid(AccountDomainSid, DOMAIN_GROUP_RID_USERS);
307 if (Sid == NULL)
308 {
309
310 }
311
312 /* Member of the domain */
313 TokenGroups->Groups[GroupCount].Sid = Sid;
314 TokenGroups->Groups[GroupCount].Attributes =
315 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
316 GroupCount++;
317
318
319 /* Member of 'Authenticated users' */
320 RtlAllocateAndInitializeSid(&SystemAuthority,
321 1,
322 SECURITY_AUTHENTICATED_USER_RID,
323 SECURITY_NULL_RID,
324 SECURITY_NULL_RID,
325 SECURITY_NULL_RID,
326 SECURITY_NULL_RID,
327 SECURITY_NULL_RID,
328 SECURITY_NULL_RID,
329 SECURITY_NULL_RID,
330 &Sid);
331 TokenGroups->Groups[GroupCount].Sid = Sid;
332 TokenGroups->Groups[GroupCount].Attributes =
333 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
334 GroupCount++;
335
336 TokenGroups->GroupCount = GroupCount;
337 ASSERT(TokenGroups->GroupCount <= MAX_GROUPS);
338
339 *Groups = TokenGroups;
340
341 return Status;
342 }
343
344
345 static
346 NTSTATUS
347 BuildTokenInformationBuffer(PLSA_TOKEN_INFORMATION_V1 *TokenInformation,
348 PRPC_SID AccountDomainSid,
349 PSAMPR_USER_INFO_BUFFER UserInfo)
350 {
351 PLSA_TOKEN_INFORMATION_V1 Buffer = NULL;
352 ULONG i;
353 NTSTATUS Status = STATUS_SUCCESS;
354
355 Buffer = DispatchTable.AllocateLsaHeap(sizeof(LSA_TOKEN_INFORMATION_V1));
356 if (Buffer == NULL)
357 {
358 TRACE("Failed to allocate the local buffer!\n");
359 Status = STATUS_INSUFFICIENT_RESOURCES;
360 goto done;
361 }
362
363 /* FIXME: */
364 Buffer->ExpirationTime.QuadPart = -1;
365
366 Status = BuildTokenUser(&Buffer->User,
367 (PSID)AccountDomainSid,
368 UserInfo->All.UserId);
369 if (!NT_SUCCESS(Status))
370 goto done;
371
372 Status = BuildTokenPrimaryGroup(&Buffer->PrimaryGroup,
373 (PSID)AccountDomainSid,
374 UserInfo->All.PrimaryGroupId);
375 if (!NT_SUCCESS(Status))
376 goto done;
377
378 Status = BuildTokenGroups(&Buffer->Groups,
379 (PSID)AccountDomainSid);
380 if (!NT_SUCCESS(Status))
381 goto done;
382
383 *TokenInformation = Buffer;
384
385 done:
386 if (!NT_SUCCESS(Status))
387 {
388 if (Buffer != NULL)
389 {
390 if (Buffer->User.User.Sid != NULL)
391 DispatchTable.FreeLsaHeap(Buffer->User.User.Sid);
392
393 if (Buffer->Groups != NULL)
394 {
395 for (i = 0; i < Buffer->Groups->GroupCount; i++)
396 {
397 if (Buffer->Groups->Groups[i].Sid != NULL)
398 DispatchTable.FreeLsaHeap(Buffer->Groups->Groups[i].Sid);
399 }
400
401 DispatchTable.FreeLsaHeap(Buffer->Groups);
402 }
403
404 if (Buffer->PrimaryGroup.PrimaryGroup != NULL)
405 DispatchTable.FreeLsaHeap(Buffer->PrimaryGroup.PrimaryGroup);
406
407 if (Buffer->DefaultDacl.DefaultDacl != NULL)
408 DispatchTable.FreeLsaHeap(Buffer->DefaultDacl.DefaultDacl);
409
410 DispatchTable.FreeLsaHeap(Buffer);
411 }
412 }
413
414 return Status;
415 }
416
417
418 static
419 NTSTATUS
420 MsvpChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest,
421 IN PVOID ProtocolSubmitBuffer,
422 IN PVOID ClientBufferBase,
423 IN ULONG SubmitBufferLength,
424 OUT PVOID *ProtocolReturnBuffer,
425 OUT PULONG ReturnBufferLength,
426 OUT PNTSTATUS ProtocolStatus)
427 {
428 PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer;
429 ULONG_PTR PtrOffset;
430
431 SAMPR_HANDLE ServerHandle = NULL;
432 SAMPR_HANDLE DomainHandle = NULL;
433 SAMPR_HANDLE UserHandle = NULL;
434 PRPC_SID DomainSid = NULL;
435 RPC_UNICODE_STRING Names[1];
436 SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
437 SAMPR_ULONG_ARRAY Use = {0, NULL};
438 NTSTATUS Status;
439
440 ENCRYPTED_NT_OWF_PASSWORD OldNtPassword;
441 ENCRYPTED_NT_OWF_PASSWORD NewNtPassword;
442 ENCRYPTED_LM_OWF_PASSWORD OldLmPassword;
443 ENCRYPTED_LM_OWF_PASSWORD NewLmPassword;
444 OEM_STRING LmPwdString;
445 CHAR LmPwdBuffer[15];
446 BOOLEAN OldLmPasswordPresent = FALSE;
447 BOOLEAN NewLmPasswordPresent = FALSE;
448
449 ENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm;
450 ENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm;
451 ENCRYPTED_LM_OWF_PASSWORD OldNtEncryptedWithNewNt;
452 ENCRYPTED_LM_OWF_PASSWORD NewNtEncryptedWithOldNt;
453 PENCRYPTED_LM_OWF_PASSWORD pOldLmEncryptedWithNewLm = NULL;
454 PENCRYPTED_LM_OWF_PASSWORD pNewLmEncryptedWithOldLm = NULL;
455
456 TRACE("()\n");
457
458 RequestBuffer = (PMSV1_0_CHANGEPASSWORD_REQUEST)ProtocolSubmitBuffer;
459
460 /* Fix-up pointers in the request buffer info */
461 PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;
462
463 RequestBuffer->DomainName.Buffer = FIXUP_POINTER(RequestBuffer->DomainName.Buffer, PtrOffset);
464 RequestBuffer->AccountName.Buffer = FIXUP_POINTER(RequestBuffer->AccountName.Buffer, PtrOffset);
465 RequestBuffer->OldPassword.Buffer = FIXUP_POINTER(RequestBuffer->OldPassword.Buffer, PtrOffset);
466 RequestBuffer->NewPassword.Buffer = FIXUP_POINTER(RequestBuffer->NewPassword.Buffer, PtrOffset);
467
468 TRACE("Domain: %S\n", RequestBuffer->DomainName.Buffer);
469 TRACE("Account: %S\n", RequestBuffer->AccountName.Buffer);
470 TRACE("Old Password: %S\n", RequestBuffer->OldPassword.Buffer);
471 TRACE("New Password: %S\n", RequestBuffer->NewPassword.Buffer);
472
473 /* Connect to the SAM server */
474 Status = SamIConnect(NULL,
475 &ServerHandle,
476 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
477 TRUE);
478 if (!NT_SUCCESS(Status))
479 {
480 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
481 goto done;
482 }
483
484 /* Get the domain SID */
485 Status = SamrLookupDomainInSamServer(ServerHandle,
486 (PRPC_UNICODE_STRING)&RequestBuffer->DomainName,
487 &DomainSid);
488 if (!NT_SUCCESS(Status))
489 {
490 TRACE("SamrLookupDomainInSamServer failed (Status %08lx)\n", Status);
491 goto done;
492 }
493
494 /* Open the domain */
495 Status = SamrOpenDomain(ServerHandle,
496 DOMAIN_LOOKUP,
497 DomainSid,
498 &DomainHandle);
499 if (!NT_SUCCESS(Status))
500 {
501 TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
502 goto done;
503 }
504
505 Names[0].Length = RequestBuffer->AccountName.Length;
506 Names[0].MaximumLength = RequestBuffer->AccountName.MaximumLength;
507 Names[0].Buffer = RequestBuffer->AccountName.Buffer;
508
509 /* Try to get the RID for the user name */
510 Status = SamrLookupNamesInDomain(DomainHandle,
511 1,
512 Names,
513 &RelativeIds,
514 &Use);
515 if (!NT_SUCCESS(Status))
516 {
517 TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
518 Status = STATUS_NO_SUCH_USER;
519 goto done;
520 }
521
522 /* Fail, if it is not a user account */
523 if (Use.Element[0] != SidTypeUser)
524 {
525 TRACE("Account is not a user account!\n");
526 Status = STATUS_NO_SUCH_USER;
527 goto done;
528 }
529
530 /* Open the user object */
531 Status = SamrOpenUser(DomainHandle,
532 USER_CHANGE_PASSWORD,
533 RelativeIds.Element[0],
534 &UserHandle);
535 if (!NT_SUCCESS(Status))
536 {
537 TRACE("SamrOpenUser failed (Status %08lx)\n", Status);
538 goto done;
539 }
540
541
542 /* Calculate the NT hash for the old password */
543 Status = SystemFunction007(&RequestBuffer->OldPassword,
544 (LPBYTE)&OldNtPassword);
545 if (!NT_SUCCESS(Status))
546 {
547 TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
548 goto done;
549 }
550
551 /* Calculate the NT hash for the new password */
552 Status = SystemFunction007(&RequestBuffer->NewPassword,
553 (LPBYTE)&NewNtPassword);
554 if (!NT_SUCCESS(Status))
555 {
556 TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
557 goto done;
558 }
559
560 /* Calculate the LM password and hash for the old password */
561 LmPwdString.Length = 15;
562 LmPwdString.MaximumLength = 15;
563 LmPwdString.Buffer = LmPwdBuffer;
564 ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
565
566 Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
567 &RequestBuffer->OldPassword,
568 FALSE);
569 if (NT_SUCCESS(Status))
570 {
571 /* Calculate the LM hash value of the password */
572 Status = SystemFunction006(LmPwdString.Buffer,
573 (LPSTR)&OldLmPassword);
574 if (NT_SUCCESS(Status))
575 {
576 OldLmPasswordPresent = TRUE;
577 }
578 }
579
580 /* Calculate the LM password and hash for the new password */
581 LmPwdString.Length = 15;
582 LmPwdString.MaximumLength = 15;
583 LmPwdString.Buffer = LmPwdBuffer;
584 ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
585
586 Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
587 &RequestBuffer->NewPassword,
588 FALSE);
589 if (NT_SUCCESS(Status))
590 {
591 /* Calculate the LM hash value of the password */
592 Status = SystemFunction006(LmPwdString.Buffer,
593 (LPSTR)&NewLmPassword);
594 if (NT_SUCCESS(Status))
595 {
596 NewLmPasswordPresent = TRUE;
597 }
598 }
599
600 /* Encrypt the old and new LM passwords, if they exist */
601 if (OldLmPasswordPresent && NewLmPasswordPresent)
602 {
603 /* Encrypt the old LM password */
604 Status = SystemFunction012((const BYTE *)&OldLmPassword,
605 (const BYTE *)&NewLmPassword,
606 (LPBYTE)&OldLmEncryptedWithNewLm);
607 if (!NT_SUCCESS(Status))
608 {
609 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
610 goto done;
611 }
612
613 /* Encrypt the new LM password */
614 Status = SystemFunction012((const BYTE *)&NewLmPassword,
615 (const BYTE *)&OldLmPassword,
616 (LPBYTE)&NewLmEncryptedWithOldLm);
617 if (!NT_SUCCESS(Status))
618 {
619 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
620 goto done;
621 }
622
623 pOldLmEncryptedWithNewLm = &OldLmEncryptedWithNewLm;
624 pNewLmEncryptedWithOldLm = &NewLmEncryptedWithOldLm;
625 }
626
627 /* Encrypt the old NT password */
628 Status = SystemFunction012((const BYTE *)&OldNtPassword,
629 (const BYTE *)&NewNtPassword,
630 (LPBYTE)&OldNtEncryptedWithNewNt);
631 if (!NT_SUCCESS(Status))
632 {
633 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
634 goto done;
635 }
636
637 /* Encrypt the new NT password */
638 Status = SystemFunction012((const BYTE *)&NewNtPassword,
639 (const BYTE *)&OldNtPassword,
640 (LPBYTE)&NewNtEncryptedWithOldNt);
641 if (!NT_SUCCESS(Status))
642 {
643 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
644 goto done;
645 }
646
647 /* Change the password */
648 Status = SamrChangePasswordUser(UserHandle,
649 OldLmPasswordPresent && NewLmPasswordPresent,
650 pOldLmEncryptedWithNewLm,
651 pNewLmEncryptedWithOldLm,
652 TRUE,
653 &OldNtEncryptedWithNewNt,
654 &NewNtEncryptedWithOldNt,
655 FALSE,
656 NULL,
657 FALSE,
658 NULL);
659 if (!NT_SUCCESS(Status))
660 {
661 TRACE("SamrChangePasswordUser failed (Status %08lx)\n", Status);
662 goto done;
663 }
664
665 done:
666 if (UserHandle != NULL)
667 SamrCloseHandle(&UserHandle);
668
669 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
670 SamIFree_SAMPR_ULONG_ARRAY(&Use);
671
672 if (DomainHandle != NULL)
673 SamrCloseHandle(&DomainHandle);
674
675 if (DomainSid != NULL)
676 SamIFreeVoid(DomainSid);
677
678 if (ServerHandle != NULL)
679 SamrCloseHandle(&ServerHandle);
680
681 return Status;
682 }
683
684
685 static
686 NTSTATUS
687 MsvpCheckPassword(PUNICODE_STRING UserPassword,
688 PSAMPR_USER_INFO_BUFFER UserInfo)
689 {
690 ENCRYPTED_NT_OWF_PASSWORD UserNtPassword;
691 ENCRYPTED_LM_OWF_PASSWORD UserLmPassword;
692 BOOLEAN UserLmPasswordPresent = FALSE;
693 BOOLEAN UserNtPasswordPresent = FALSE;
694 OEM_STRING LmPwdString;
695 CHAR LmPwdBuffer[15];
696 NTSTATUS Status;
697
698 TRACE("(%p %p)\n", UserPassword, UserInfo);
699
700 /* Calculate the LM password and hash for the users password */
701 LmPwdString.Length = 15;
702 LmPwdString.MaximumLength = 15;
703 LmPwdString.Buffer = LmPwdBuffer;
704 ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
705
706 Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
707 UserPassword,
708 FALSE);
709 if (NT_SUCCESS(Status))
710 {
711 /* Calculate the LM hash value of the users password */
712 Status = SystemFunction006(LmPwdString.Buffer,
713 (LPSTR)&UserLmPassword);
714 if (NT_SUCCESS(Status))
715 {
716 UserLmPasswordPresent = TRUE;
717 }
718 }
719
720 /* Calculate the NT hash of the users password */
721 Status = SystemFunction007(UserPassword,
722 (LPBYTE)&UserNtPassword);
723 if (NT_SUCCESS(Status))
724 {
725 UserNtPasswordPresent = TRUE;
726 }
727
728 Status = STATUS_WRONG_PASSWORD;
729
730 /* Succeed, if no password has been set */
731 if (UserInfo->All.NtPasswordPresent == FALSE &&
732 UserInfo->All.LmPasswordPresent == FALSE)
733 {
734 TRACE("No password check!\n");
735 Status = STATUS_SUCCESS;
736 goto done;
737 }
738
739 /* Succeed, if NT password matches */
740 if (UserNtPasswordPresent && UserInfo->All.NtPasswordPresent)
741 {
742 TRACE("Check NT password hashes:\n");
743 if (RtlEqualMemory(&UserNtPassword,
744 UserInfo->All.NtOwfPassword.Buffer,
745 sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
746 {
747 TRACE(" success!\n");
748 Status = STATUS_SUCCESS;
749 goto done;
750 }
751
752 TRACE(" failed!\n");
753 }
754
755 /* Succeed, if LM password matches */
756 if (UserLmPasswordPresent && UserInfo->All.LmPasswordPresent)
757 {
758 TRACE("Check LM password hashes:\n");
759 if (RtlEqualMemory(&UserLmPassword,
760 UserInfo->All.LmOwfPassword.Buffer,
761 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
762 {
763 TRACE(" success!\n");
764 Status = STATUS_SUCCESS;
765 goto done;
766 }
767 TRACE(" failed!\n");
768 }
769
770 done:
771 return Status;
772 }
773
774
775 /*
776 * @unimplemented
777 */
778 NTSTATUS
779 NTAPI
780 LsaApCallPackage(IN PLSA_CLIENT_REQUEST ClientRequest,
781 IN PVOID ProtocolSubmitBuffer,
782 IN PVOID ClientBufferBase,
783 IN ULONG SubmitBufferLength,
784 OUT PVOID *ProtocolReturnBuffer,
785 OUT PULONG ReturnBufferLength,
786 OUT PNTSTATUS ProtocolStatus)
787 {
788 ULONG MessageType;
789 NTSTATUS Status;
790
791 TRACE("()\n");
792
793 if (SubmitBufferLength < sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE))
794 return STATUS_INVALID_PARAMETER;
795
796 MessageType = (ULONG)*((PMSV1_0_PROTOCOL_MESSAGE_TYPE)ProtocolSubmitBuffer);
797
798 *ProtocolReturnBuffer = NULL;
799 *ReturnBufferLength = 0;
800
801 switch (MessageType)
802 {
803 case MsV1_0Lm20ChallengeRequest:
804 case MsV1_0Lm20GetChallengeResponse:
805 case MsV1_0EnumerateUsers:
806 case MsV1_0GetUserInfo:
807 case MsV1_0ReLogonUsers:
808 Status = STATUS_NOT_IMPLEMENTED;
809 break;
810
811 case MsV1_0ChangePassword:
812 Status = MsvpChangePassword(ClientRequest,
813 ProtocolSubmitBuffer,
814 ClientBufferBase,
815 SubmitBufferLength,
816 ProtocolReturnBuffer,
817 ReturnBufferLength,
818 ProtocolStatus);
819 break;
820
821 case MsV1_0ChangeCachedPassword:
822 case MsV1_0GenericPassthrough:
823 case MsV1_0CacheLogon:
824 case MsV1_0SubAuth:
825 case MsV1_0DeriveCredential:
826 case MsV1_0CacheLookup:
827 Status = STATUS_NOT_IMPLEMENTED;
828 break;
829
830 default:
831 return STATUS_INVALID_PARAMETER;
832 }
833
834 return Status;
835 }
836
837
838 /*
839 * @unimplemented
840 */
841 NTSTATUS
842 NTAPI
843 LsaApCallPackagePassthrough(IN PLSA_CLIENT_REQUEST ClientRequest,
844 IN PVOID ProtocolSubmitBuffer,
845 IN PVOID ClientBufferBase,
846 IN ULONG SubmitBufferLength,
847 OUT PVOID *ProtocolReturnBuffer,
848 OUT PULONG ReturnBufferLength,
849 OUT PNTSTATUS ProtocolStatus)
850 {
851 TRACE("()\n");
852 return STATUS_NOT_IMPLEMENTED;
853 }
854
855
856 /*
857 * @unimplemented
858 */
859 NTSTATUS
860 NTAPI
861 LsaApCallPackageUntrusted(IN PLSA_CLIENT_REQUEST ClientRequest,
862 IN PVOID ProtocolSubmitBuffer,
863 IN PVOID ClientBufferBase,
864 IN ULONG SubmitBufferLength,
865 OUT PVOID *ProtocolReturnBuffer,
866 OUT PULONG ReturnBufferLength,
867 OUT PNTSTATUS ProtocolStatus)
868 {
869 TRACE("()\n");
870 return STATUS_NOT_IMPLEMENTED;
871 }
872
873
874 /*
875 * @unimplemented
876 */
877 NTSTATUS
878 NTAPI
879 LsaApInitializePackage(IN ULONG AuthenticationPackageId,
880 IN PLSA_DISPATCH_TABLE LsaDispatchTable,
881 IN PLSA_STRING Database OPTIONAL,
882 IN PLSA_STRING Confidentiality OPTIONAL,
883 OUT PLSA_STRING *AuthenticationPackageName)
884 {
885 PANSI_STRING NameString;
886 PCHAR NameBuffer;
887
888 TRACE("(%lu %p %p %p %p)\n",
889 AuthenticationPackageId, LsaDispatchTable, Database,
890 Confidentiality, AuthenticationPackageName);
891
892 /* Get the dispatch table entries */
893 DispatchTable.CreateLogonSession = LsaDispatchTable->CreateLogonSession;
894 DispatchTable.DeleteLogonSession = LsaDispatchTable->DeleteLogonSession;
895 DispatchTable.AddCredential = LsaDispatchTable->AddCredential;
896 DispatchTable.GetCredentials = LsaDispatchTable->GetCredentials;
897 DispatchTable.DeleteCredential = LsaDispatchTable->DeleteCredential;
898 DispatchTable.AllocateLsaHeap = LsaDispatchTable->AllocateLsaHeap;
899 DispatchTable.FreeLsaHeap = LsaDispatchTable->FreeLsaHeap;
900 DispatchTable.AllocateClientBuffer = LsaDispatchTable->AllocateClientBuffer;
901 DispatchTable.FreeClientBuffer = LsaDispatchTable->FreeClientBuffer;
902 DispatchTable.CopyToClientBuffer = LsaDispatchTable->CopyToClientBuffer;
903 DispatchTable.CopyFromClientBuffer = LsaDispatchTable->CopyFromClientBuffer;
904
905 /* Return the package name */
906 NameString = DispatchTable.AllocateLsaHeap(sizeof(LSA_STRING));
907 if (NameString == NULL)
908 return STATUS_INSUFFICIENT_RESOURCES;
909
910 NameBuffer = DispatchTable.AllocateLsaHeap(sizeof(MSV1_0_PACKAGE_NAME));
911 if (NameBuffer == NULL)
912 {
913 DispatchTable.FreeLsaHeap(NameString);
914 return STATUS_INSUFFICIENT_RESOURCES;
915 }
916
917 strcpy(NameBuffer, MSV1_0_PACKAGE_NAME);
918
919 RtlInitAnsiString(NameString, NameBuffer);
920
921 *AuthenticationPackageName = (PLSA_STRING)NameString;
922
923 return STATUS_SUCCESS;
924 }
925
926
927 /*
928 * @unimplemented
929 */
930 VOID
931 NTAPI
932 LsaApLogonTerminated(IN PLUID LogonId)
933 {
934 TRACE("()\n");
935 }
936
937
938 /*
939 * @unimplemented
940 */
941 NTSTATUS
942 NTAPI
943 LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
944 IN SECURITY_LOGON_TYPE LogonType,
945 IN PVOID AuthenticationInformation,
946 IN PVOID ClientAuthenticationBase,
947 IN ULONG AuthenticationInformationLength,
948 OUT PVOID *ProfileBuffer,
949 OUT PULONG ProfileBufferLength,
950 OUT PLUID LogonId,
951 OUT PNTSTATUS SubStatus,
952 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
953 OUT PVOID *TokenInformation,
954 OUT PLSA_UNICODE_STRING *AccountName,
955 OUT PLSA_UNICODE_STRING *AuthenticatingAuthority)
956 {
957 PMSV1_0_INTERACTIVE_LOGON LogonInfo;
958
959 SAMPR_HANDLE ServerHandle = NULL;
960 SAMPR_HANDLE DomainHandle = NULL;
961 SAMPR_HANDLE UserHandle = NULL;
962 PRPC_SID AccountDomainSid = NULL;
963 RPC_UNICODE_STRING Names[1];
964 SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
965 SAMPR_ULONG_ARRAY Use = {0, NULL};
966 PSAMPR_USER_INFO_BUFFER UserInfo = NULL;
967 UNICODE_STRING LogonServer;
968 BOOLEAN SessionCreated = FALSE;
969 LARGE_INTEGER LogonTime;
970 // LARGE_INTEGER AccountExpires;
971 LARGE_INTEGER PasswordMustChange;
972 LARGE_INTEGER PasswordLastSet;
973 NTSTATUS Status;
974
975 TRACE("()\n");
976
977 TRACE("LogonType: %lu\n", LogonType);
978 TRACE("AuthenticationInformation: %p\n", AuthenticationInformation);
979 TRACE("AuthenticationInformationLength: %lu\n", AuthenticationInformationLength);
980
981 *ProfileBuffer = NULL;
982 *ProfileBufferLength = 0;
983 *SubStatus = STATUS_SUCCESS;
984
985 if (LogonType == Interactive ||
986 LogonType == Batch ||
987 LogonType == Service)
988 {
989 ULONG_PTR PtrOffset;
990
991 LogonInfo = (PMSV1_0_INTERACTIVE_LOGON)AuthenticationInformation;
992
993 /* Fix-up pointers in the authentication info */
994 PtrOffset = (ULONG_PTR)AuthenticationInformation - (ULONG_PTR)ClientAuthenticationBase;
995
996 LogonInfo->LogonDomainName.Buffer = FIXUP_POINTER(LogonInfo->LogonDomainName.Buffer, PtrOffset);
997 LogonInfo->UserName.Buffer = FIXUP_POINTER(LogonInfo->UserName.Buffer, PtrOffset);
998 LogonInfo->Password.Buffer = FIXUP_POINTER(LogonInfo->Password.Buffer, PtrOffset);
999
1000 TRACE("Domain: %S\n", LogonInfo->LogonDomainName.Buffer);
1001 TRACE("User: %S\n", LogonInfo->UserName.Buffer);
1002 TRACE("Password: %S\n", LogonInfo->Password.Buffer);
1003
1004 RtlInitUnicodeString(&LogonServer, L"Testserver");
1005 }
1006 else
1007 {
1008 FIXME("LogonType %lu is not supported yet!\n", LogonType);
1009 return STATUS_NOT_IMPLEMENTED;
1010 }
1011
1012 /* Get the logon time */
1013 NtQuerySystemTime(&LogonTime);
1014
1015 /* Get the domain SID */
1016 Status = GetDomainSid(&AccountDomainSid);
1017 if (!NT_SUCCESS(Status))
1018 {
1019 TRACE("GetDomainSid() failed (Status 0x%08lx)\n", Status);
1020 return Status;
1021 }
1022
1023 /* Connect to the SAM server */
1024 Status = SamIConnect(NULL,
1025 &ServerHandle,
1026 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
1027 TRUE);
1028 if (!NT_SUCCESS(Status))
1029 {
1030 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
1031 goto done;
1032 }
1033
1034 /* Open the account domain */
1035 Status = SamrOpenDomain(ServerHandle,
1036 DOMAIN_LOOKUP,
1037 AccountDomainSid,
1038 &DomainHandle);
1039 if (!NT_SUCCESS(Status))
1040 {
1041 TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
1042 goto done;
1043 }
1044
1045 Names[0].Length = LogonInfo->UserName.Length;
1046 Names[0].MaximumLength = LogonInfo->UserName.MaximumLength;
1047 Names[0].Buffer = LogonInfo->UserName.Buffer;
1048
1049 /* Try to get the RID for the user name */
1050 Status = SamrLookupNamesInDomain(DomainHandle,
1051 1,
1052 Names,
1053 &RelativeIds,
1054 &Use);
1055 if (!NT_SUCCESS(Status))
1056 {
1057 TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
1058 Status = STATUS_NO_SUCH_USER;
1059 goto done;
1060 }
1061
1062 /* Fail, if it is not a user account */
1063 if (Use.Element[0] != SidTypeUser)
1064 {
1065 TRACE("Account is not a user account!\n");
1066 Status = STATUS_NO_SUCH_USER;
1067 goto done;
1068 }
1069
1070 /* Open the user object */
1071 Status = SamrOpenUser(DomainHandle,
1072 USER_READ_GENERAL | USER_READ_LOGON |
1073 USER_READ_ACCOUNT | USER_READ_PREFERENCES, /* FIXME */
1074 RelativeIds.Element[0],
1075 &UserHandle);
1076 if (!NT_SUCCESS(Status))
1077 {
1078 TRACE("SamrOpenUser failed (Status %08lx)\n", Status);
1079 goto done;
1080 }
1081
1082 Status = SamrQueryInformationUser(UserHandle,
1083 UserAllInformation,
1084 &UserInfo);
1085 if (!NT_SUCCESS(Status))
1086 {
1087 TRACE("SamrQueryInformationUser failed (Status %08lx)\n", Status);
1088 goto done;
1089 }
1090
1091 TRACE("UserName: %S\n", UserInfo->All.UserName.Buffer);
1092
1093 /* Check the password */
1094 if ((UserInfo->All.UserAccountControl & USER_PASSWORD_NOT_REQUIRED) == 0)
1095 {
1096 Status = MsvpCheckPassword(&(LogonInfo->Password),
1097 UserInfo);
1098 if (!NT_SUCCESS(Status))
1099 {
1100 TRACE("MsvpCheckPassword failed (Status %08lx)\n", Status);
1101 goto done;
1102 }
1103 }
1104
1105 /* Check account restrictions for non-administrator accounts */
1106 if (RelativeIds.Element[0] != DOMAIN_USER_RID_ADMIN)
1107 {
1108 /* Check if the account has been disabled */
1109 if (UserInfo->All.UserAccountControl & USER_ACCOUNT_DISABLED)
1110 {
1111 ERR("Account disabled!\n");
1112 *SubStatus = STATUS_ACCOUNT_DISABLED;
1113 Status = STATUS_ACCOUNT_RESTRICTION;
1114 goto done;
1115 }
1116
1117 /* Check if the account has been locked */
1118 if (UserInfo->All.UserAccountControl & USER_ACCOUNT_AUTO_LOCKED)
1119 {
1120 ERR("Account locked!\n");
1121 *SubStatus = STATUS_ACCOUNT_LOCKED_OUT;
1122 Status = STATUS_ACCOUNT_RESTRICTION;
1123 goto done;
1124 }
1125
1126 #if 0
1127 /* Check if the account expired */
1128 AccountExpires.LowPart = UserInfo->All.AccountExpires.LowPart;
1129 AccountExpires.HighPart = UserInfo->All.AccountExpires.HighPart;
1130
1131 if (AccountExpires.QuadPart != 0 &&
1132 LogonTime.QuadPart >= AccountExpires.QuadPart)
1133 {
1134 ERR("Account expired!\n");
1135 *SubStatus = STATUS_ACCOUNT_EXPIRED;
1136 Status = STATUS_ACCOUNT_RESTRICTION;
1137 goto done;
1138 }
1139 #endif
1140
1141 /* Check if the password expired */
1142 PasswordMustChange.LowPart = UserInfo->All.PasswordMustChange.LowPart;
1143 PasswordMustChange.HighPart = UserInfo->All.PasswordMustChange.HighPart;
1144 PasswordLastSet.LowPart = UserInfo->All.PasswordLastSet.LowPart;
1145 PasswordLastSet.HighPart = UserInfo->All.PasswordLastSet.HighPart;
1146
1147 if (LogonTime.QuadPart >= PasswordMustChange.QuadPart)
1148 {
1149 ERR("Password expired!\n");
1150 if (PasswordLastSet.QuadPart == 0)
1151 *SubStatus = STATUS_PASSWORD_MUST_CHANGE;
1152 else
1153 *SubStatus = STATUS_PASSWORD_EXPIRED;
1154
1155 Status = STATUS_ACCOUNT_RESTRICTION;
1156 goto done;
1157 }
1158
1159 /* FIXME: more checks */
1160 // STATUS_INVALID_LOGON_HOURS;
1161 // STATUS_INVALID_WORKSTATION;
1162 }
1163
1164 /* Return logon information */
1165
1166 /* Create and return a new logon id */
1167 Status = NtAllocateLocallyUniqueId(LogonId);
1168 if (!NT_SUCCESS(Status))
1169 {
1170 TRACE("NtAllocateLocallyUniqueId failed (Status %08lx)\n", Status);
1171 goto done;
1172 }
1173
1174 /* Create the logon session */
1175 Status = DispatchTable.CreateLogonSession(LogonId);
1176 if (!NT_SUCCESS(Status))
1177 {
1178 TRACE("CreateLogonSession failed (Status %08lx)\n", Status);
1179 goto done;
1180 }
1181
1182 SessionCreated = TRUE;
1183
1184 /* Build and fill the interactve profile buffer */
1185 Status = BuildInteractiveProfileBuffer(ClientRequest,
1186 UserInfo,
1187 &LogonServer,
1188 (PMSV1_0_INTERACTIVE_PROFILE*)ProfileBuffer,
1189 ProfileBufferLength);
1190 if (!NT_SUCCESS(Status))
1191 {
1192 TRACE("BuildInteractiveProfileBuffer failed (Status %08lx)\n", Status);
1193 goto done;
1194 }
1195
1196 /* Return the token information type */
1197 *TokenInformationType = LsaTokenInformationV1;
1198
1199 /* Build and fill the token information buffer */
1200 Status = BuildTokenInformationBuffer((PLSA_TOKEN_INFORMATION_V1*)TokenInformation,
1201 AccountDomainSid,
1202 UserInfo);
1203 if (!NT_SUCCESS(Status))
1204 {
1205 TRACE("BuildTokenInformationBuffer failed (Status %08lx)\n", Status);
1206 goto done;
1207 }
1208
1209 done:
1210 /* Return the account name */
1211 *AccountName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1212 if (*AccountName != NULL)
1213 {
1214 (*AccountName)->Buffer = DispatchTable.AllocateLsaHeap(LogonInfo->UserName.Length +
1215 sizeof(UNICODE_NULL));
1216 if ((*AccountName)->Buffer != NULL)
1217 {
1218 (*AccountName)->MaximumLength = LogonInfo->UserName.Length +
1219 sizeof(UNICODE_NULL);
1220 RtlCopyUnicodeString(*AccountName, &LogonInfo->UserName);
1221 }
1222 }
1223
1224 if (!NT_SUCCESS(Status))
1225 {
1226 if (SessionCreated == TRUE)
1227 DispatchTable.DeleteLogonSession(LogonId);
1228
1229 if (*ProfileBuffer != NULL)
1230 {
1231 DispatchTable.FreeClientBuffer(ClientRequest,
1232 *ProfileBuffer);
1233 *ProfileBuffer = NULL;
1234 }
1235 }
1236
1237 if (UserHandle != NULL)
1238 SamrCloseHandle(&UserHandle);
1239
1240 SamIFree_SAMPR_USER_INFO_BUFFER(UserInfo,
1241 UserAllInformation);
1242 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
1243 SamIFree_SAMPR_ULONG_ARRAY(&Use);
1244
1245 if (DomainHandle != NULL)
1246 SamrCloseHandle(&DomainHandle);
1247
1248 if (ServerHandle != NULL)
1249 SamrCloseHandle(&ServerHandle);
1250
1251 if (AccountDomainSid != NULL)
1252 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
1253
1254 if (Status == STATUS_NO_SUCH_USER ||
1255 Status == STATUS_WRONG_PASSWORD)
1256 {
1257 *SubStatus = Status;
1258 Status = STATUS_LOGON_FAILURE;
1259 }
1260
1261 TRACE("LsaApLogonUser done (Status 0x%08lx SubStatus 0x%08lx)\n", Status, *SubStatus);
1262
1263 return Status;
1264 }
1265
1266
1267 /*
1268 * @unimplemented
1269 */
1270 #if 0
1271 NTSTATUS
1272 NTAPI
1273 LsaApLogonUserEx(IN PLSA_CLIENT_REQUEST ClientRequest,
1274 IN SECURITY_LOGON_TYPE LogonType,
1275 IN PVOID AuthenticationInformation,
1276 IN PVOID ClientAuthenticationBase,
1277 IN ULONG AuthenticationInformationLength,
1278 OUT PVOID *ProfileBuffer,
1279 OUT PULONG ProfileBufferLength,
1280 OUT PLUID LogonId,
1281 OUT PNTSTATUS SubStatus,
1282 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
1283 OUT PVOID *TokenInformation,
1284 OUT PUNICODE_STRING *AccountName,
1285 OUT PUNICODE_STRING *AuthenticatingAuthority,
1286 OUT PUNICODE_STRING *MachineName)
1287 {
1288 TRACE("()\n");
1289
1290 TRACE("LogonType: %lu\n", LogonType);
1291 TRACE("AuthenticationInformation: %p\n", AuthenticationInformation);
1292 TRACE("AuthenticationInformationLength: %lu\n", AuthenticationInformationLength);
1293
1294 return STATUS_NOT_IMPLEMENTED;
1295 }
1296
1297
1298 /*
1299 * @unimplemented
1300 */
1301 NTSTATUS
1302 NTAPI
1303 LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
1304 IN SECURITY_LOGON_TYPE LogonType,
1305 IN PVOID ProtocolSubmitBuffer,
1306 IN PVOID ClientBufferBase,
1307 IN ULONG SubmitBufferSize,
1308 OUT PVOID *ProfileBuffer,
1309 OUT PULONG ProfileBufferSize,
1310 OUT PLUID LogonId,
1311 OUT PNTSTATUS SubStatus,
1312 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
1313 OUT PVOID *TokenInformation,
1314 OUT PUNICODE_STRING *AccountName,
1315 OUT PUNICODE_STRING *AuthenticatingAuthority,
1316 OUT PUNICODE_STRING *MachineName,
1317 OUT PSECPKG_PRIMARY_CRED PrimaryCredentials,
1318 OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY *SupplementalCredentials)
1319 {
1320 TRACE("()\n");
1321
1322 TRACE("LogonType: %lu\n", LogonType);
1323 TRACE("ProtocolSubmitBuffer: %p\n", ProtocolSubmitBuffer);
1324 TRACE("SubmitBufferSize: %lu\n", SubmitBufferSize);
1325
1326
1327 return STATUS_NOT_IMPLEMENTED;
1328 }
1329 #endif
1330
1331 /* EOF */