[REACTOS] Fix a number of MSVC warnings
[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 "precomp.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 USHORT ComputerNameLength;
106 NTSTATUS Status = STATUS_SUCCESS;
107
108 *ProfileBuffer = NULL;
109 *ProfileBufferLength = 0;
110
111 if (UIntPtrToUShort(wcslen(ComputerName), &ComputerNameLength) != S_OK)
112 {
113 return STATUS_INVALID_PARAMETER;
114 }
115
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));
123
124 LocalBuffer = DispatchTable.AllocateLsaHeap(BufferLength);
125 if (LocalBuffer == NULL)
126 {
127 TRACE("Failed to allocate the local buffer!\n");
128 Status = STATUS_INSUFFICIENT_RESOURCES;
129 goto done;
130 }
131
132 Status = DispatchTable.AllocateClientBuffer(ClientRequest,
133 BufferLength,
134 &ClientBaseAddress);
135 if (!NT_SUCCESS(Status))
136 {
137 TRACE("DispatchTable.AllocateClientBuffer failed (Status 0x%08lx)\n", Status);
138 goto done;
139 }
140
141 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
142
143 Ptr = (LPWSTR)((ULONG_PTR)LocalBuffer + sizeof(MSV1_0_INTERACTIVE_PROFILE));
144
145 LocalBuffer->MessageType = MsV1_0InteractiveProfile;
146 LocalBuffer->LogonCount = UserInfo->All.LogonCount;
147 LocalBuffer->BadPasswordCount = UserInfo->All.BadPasswordCount;
148
149 LocalBuffer->LogonTime.LowPart = UserInfo->All.LastLogon.LowPart;
150 LocalBuffer->LogonTime.HighPart = UserInfo->All.LastLogon.HighPart;
151
152 LocalBuffer->LogoffTime.LowPart = UserInfo->All.AccountExpires.LowPart;
153 LocalBuffer->LogoffTime.HighPart = UserInfo->All.AccountExpires.HighPart;
154
155 LocalBuffer->KickOffTime.LowPart = UserInfo->All.AccountExpires.LowPart;
156 LocalBuffer->KickOffTime.HighPart = UserInfo->All.AccountExpires.HighPart;
157
158 LocalBuffer->PasswordLastSet.LowPart = UserInfo->All.PasswordLastSet.LowPart;
159 LocalBuffer->PasswordLastSet.HighPart = UserInfo->All.PasswordLastSet.HighPart;
160
161 LocalBuffer->PasswordCanChange.LowPart = UserInfo->All.PasswordCanChange.LowPart;
162 LocalBuffer->PasswordCanChange.HighPart = UserInfo->All.PasswordCanChange.HighPart;
163
164 LocalBuffer->PasswordMustChange.LowPart = UserInfo->All.PasswordMustChange.LowPart;
165 LocalBuffer->PasswordMustChange.HighPart = UserInfo->All.PasswordMustChange.HighPart;
166
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);
170 memcpy(Ptr,
171 UserInfo->All.ScriptPath.Buffer,
172 UserInfo->All.ScriptPath.Length);
173
174 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->LogonScript.MaximumLength);
175
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);
179 memcpy(Ptr,
180 UserInfo->All.HomeDirectory.Buffer,
181 UserInfo->All.HomeDirectory.Length);
182
183 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectory.MaximumLength);
184
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);
188 memcpy(Ptr,
189 UserInfo->All.FullName.Buffer,
190 UserInfo->All.FullName.Length);
191 TRACE("FullName.Buffer: %p\n", LocalBuffer->FullName.Buffer);
192
193 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->FullName.MaximumLength);
194
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);
198 memcpy(Ptr,
199 UserInfo->All.ProfilePath.Buffer,
200 UserInfo->All.ProfilePath.Length);
201
202 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->ProfilePath.MaximumLength);
203
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);
207 memcpy(Ptr,
208 UserInfo->All.HomeDirectoryDrive.Buffer,
209 UserInfo->All.HomeDirectoryDrive.Length);
210
211 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectoryDrive.MaximumLength);
212
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);
216 wcscpy(Ptr, L"\\");
217 wcscat(Ptr, ComputerName);
218
219 LocalBuffer->UserFlags = 0;
220
221 Status = DispatchTable.CopyToClientBuffer(ClientRequest,
222 BufferLength,
223 ClientBaseAddress,
224 LocalBuffer);
225 if (!NT_SUCCESS(Status))
226 {
227 TRACE("DispatchTable.CopyToClientBuffer failed (Status 0x%08lx)\n", Status);
228 goto done;
229 }
230
231 *ProfileBuffer = (PMSV1_0_INTERACTIVE_PROFILE)ClientBaseAddress;
232 *ProfileBufferLength = BufferLength;
233
234 done:
235 if (LocalBuffer != NULL)
236 DispatchTable.FreeLsaHeap(LocalBuffer);
237
238 if (!NT_SUCCESS(Status))
239 {
240 if (ClientBaseAddress != NULL)
241 DispatchTable.FreeClientBuffer(ClientRequest,
242 ClientBaseAddress);
243 }
244
245 return Status;
246 }
247
248
249 static
250 PSID
251 AppendRidToSid(PSID SrcSid,
252 ULONG Rid)
253 {
254 PSID DstSid = NULL;
255 UCHAR RidCount;
256
257 RidCount = *RtlSubAuthorityCountSid(SrcSid);
258 if (RidCount >= 8)
259 return NULL;
260
261 DstSid = DispatchTable.AllocateLsaHeap(RtlLengthRequiredSid(RidCount + 1));
262 if (DstSid == NULL)
263 return NULL;
264
265 RtlCopyMemory(DstSid,
266 SrcSid,
267 RtlLengthRequiredSid(RidCount));
268
269 *RtlSubAuthorityCountSid(DstSid) = RidCount + 1;
270 *RtlSubAuthoritySid(DstSid, RidCount) = Rid;
271
272 return DstSid;
273 }
274
275
276 static
277 NTSTATUS
278 BuildTokenUser(OUT PTOKEN_USER User,
279 IN PSID AccountDomainSid,
280 IN ULONG RelativeId)
281 {
282 User->User.Sid = AppendRidToSid(AccountDomainSid,
283 RelativeId);
284 if (User->User.Sid == NULL)
285 {
286 ERR("Could not create the user SID\n");
287 return STATUS_INSUFFICIENT_RESOURCES;
288 }
289
290 User->User.Attributes = 0;
291
292 return STATUS_SUCCESS;
293 }
294
295
296 static
297 NTSTATUS
298 BuildTokenPrimaryGroup(OUT PTOKEN_PRIMARY_GROUP PrimaryGroup,
299 IN PSID AccountDomainSid,
300 IN ULONG RelativeId)
301 {
302 PrimaryGroup->PrimaryGroup = AppendRidToSid(AccountDomainSid,
303 RelativeId);
304 if (PrimaryGroup->PrimaryGroup == NULL)
305 {
306 ERR("Could not create the primary group SID\n");
307 return STATUS_INSUFFICIENT_RESOURCES;
308 }
309
310 return STATUS_SUCCESS;
311 }
312
313
314 static
315 NTSTATUS
316 BuildTokenGroups(OUT PTOKEN_GROUPS *Groups,
317 IN PSID AccountDomainSid,
318 IN ULONG RelativeId,
319 IN BOOL SpecialAccount)
320 {
321 SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
322 PTOKEN_GROUPS TokenGroups;
323 DWORD GroupCount = 0;
324 DWORD MaxGroups = 2;
325 PSID Sid;
326 NTSTATUS Status = STATUS_SUCCESS;
327
328 if (SpecialAccount)
329 MaxGroups++;
330
331 TokenGroups = DispatchTable.AllocateLsaHeap(sizeof(TOKEN_GROUPS) +
332 MaxGroups * sizeof(SID_AND_ATTRIBUTES));
333 if (TokenGroups == NULL)
334 {
335 return STATUS_INSUFFICIENT_RESOURCES;
336 }
337
338 if (SpecialAccount)
339 {
340 /* Self */
341 Sid = AppendRidToSid(AccountDomainSid, RelativeId);
342 if (Sid == NULL)
343 {
344
345 }
346
347 TokenGroups->Groups[GroupCount].Sid = Sid;
348 TokenGroups->Groups[GroupCount].Attributes =
349 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
350 GroupCount++;
351
352 /* Member of 'Users' alias */
353 RtlAllocateAndInitializeSid(&SystemAuthority,
354 2,
355 SECURITY_BUILTIN_DOMAIN_RID,
356 DOMAIN_ALIAS_RID_USERS,
357 SECURITY_NULL_RID,
358 SECURITY_NULL_RID,
359 SECURITY_NULL_RID,
360 SECURITY_NULL_RID,
361 SECURITY_NULL_RID,
362 SECURITY_NULL_RID,
363 &Sid);
364 TokenGroups->Groups[GroupCount].Sid = Sid;
365 TokenGroups->Groups[GroupCount].Attributes =
366 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
367 GroupCount++;
368 }
369 else
370 {
371 /* Member of the domains users group */
372 Sid = AppendRidToSid(AccountDomainSid, DOMAIN_GROUP_RID_USERS);
373 if (Sid == NULL)
374 {
375
376 }
377
378 TokenGroups->Groups[GroupCount].Sid = Sid;
379 TokenGroups->Groups[GroupCount].Attributes =
380 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
381 GroupCount++;
382 }
383
384 /* Member of 'Authenticated users' */
385 RtlAllocateAndInitializeSid(&SystemAuthority,
386 1,
387 SECURITY_AUTHENTICATED_USER_RID,
388 SECURITY_NULL_RID,
389 SECURITY_NULL_RID,
390 SECURITY_NULL_RID,
391 SECURITY_NULL_RID,
392 SECURITY_NULL_RID,
393 SECURITY_NULL_RID,
394 SECURITY_NULL_RID,
395 &Sid);
396 TokenGroups->Groups[GroupCount].Sid = Sid;
397 TokenGroups->Groups[GroupCount].Attributes =
398 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
399 GroupCount++;
400
401 TokenGroups->GroupCount = GroupCount;
402 ASSERT(TokenGroups->GroupCount <= MaxGroups);
403
404 *Groups = TokenGroups;
405
406 return Status;
407 }
408
409
410 static
411 NTSTATUS
412 BuildTokenInformationBuffer(PLSA_TOKEN_INFORMATION_V1 *TokenInformation,
413 PRPC_SID AccountDomainSid,
414 PSAMPR_USER_INFO_BUFFER UserInfo,
415 BOOL SpecialAccount)
416 {
417 PLSA_TOKEN_INFORMATION_V1 Buffer = NULL;
418 ULONG i;
419 NTSTATUS Status = STATUS_SUCCESS;
420
421 Buffer = DispatchTable.AllocateLsaHeap(sizeof(LSA_TOKEN_INFORMATION_V1));
422 if (Buffer == NULL)
423 {
424 WARN("Failed to allocate the local buffer!\n");
425 Status = STATUS_INSUFFICIENT_RESOURCES;
426 goto done;
427 }
428
429 Buffer->ExpirationTime.LowPart = UserInfo->All.AccountExpires.LowPart;
430 Buffer->ExpirationTime.HighPart = UserInfo->All.AccountExpires.HighPart;
431
432 Status = BuildTokenUser(&Buffer->User,
433 (PSID)AccountDomainSid,
434 UserInfo->All.UserId);
435 if (!NT_SUCCESS(Status))
436 {
437 WARN("BuildTokenUser() failed (Status 0x%08lx)\n", Status);
438 goto done;
439 }
440
441 Status = BuildTokenPrimaryGroup(&Buffer->PrimaryGroup,
442 (PSID)AccountDomainSid,
443 UserInfo->All.PrimaryGroupId);
444 if (!NT_SUCCESS(Status))
445 {
446 WARN("BuildTokenPrimaryGroup() failed (Status 0x%08lx)\n", Status);
447 goto done;
448 }
449
450 Status = BuildTokenGroups(&Buffer->Groups,
451 (PSID)AccountDomainSid,
452 UserInfo->All.UserId,
453 SpecialAccount);
454 if (!NT_SUCCESS(Status))
455 {
456 WARN("BuildTokenGroups() failed (Status 0x%08lx)\n", Status);
457 goto done;
458 }
459
460 *TokenInformation = Buffer;
461
462 done:
463 if (!NT_SUCCESS(Status))
464 {
465 if (Buffer != NULL)
466 {
467 if (Buffer->User.User.Sid != NULL)
468 DispatchTable.FreeLsaHeap(Buffer->User.User.Sid);
469
470 if (Buffer->Groups != NULL)
471 {
472 for (i = 0; i < Buffer->Groups->GroupCount; i++)
473 {
474 if (Buffer->Groups->Groups[i].Sid != NULL)
475 DispatchTable.FreeLsaHeap(Buffer->Groups->Groups[i].Sid);
476 }
477
478 DispatchTable.FreeLsaHeap(Buffer->Groups);
479 }
480
481 if (Buffer->PrimaryGroup.PrimaryGroup != NULL)
482 DispatchTable.FreeLsaHeap(Buffer->PrimaryGroup.PrimaryGroup);
483
484 if (Buffer->DefaultDacl.DefaultDacl != NULL)
485 DispatchTable.FreeLsaHeap(Buffer->DefaultDacl.DefaultDacl);
486
487 DispatchTable.FreeLsaHeap(Buffer);
488 }
489 }
490
491 return Status;
492 }
493
494
495 static
496 NTSTATUS
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)
504 {
505 NTSTATUS Status;
506 PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer;
507 ULONG_PTR PtrOffset;
508
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};
516
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;
525
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;
532
533 TRACE("MsvpChangePassword()\n");
534
535 /* Parameters validation */
536
537 if (SubmitBufferLength < sizeof(MSV1_0_CHANGEPASSWORD_REQUEST))
538 {
539 ERR("Invalid SubmitBufferLength %lu\n", SubmitBufferLength);
540 return STATUS_INVALID_PARAMETER;
541 }
542
543 RequestBuffer = (PMSV1_0_CHANGEPASSWORD_REQUEST)ProtocolSubmitBuffer;
544
545 /* Fix-up pointers in the request buffer info */
546 PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;
547
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;
554
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;
561
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;
568
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;
575
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);
580
581 /* Connect to the SAM server */
582 Status = SamIConnect(NULL,
583 &ServerHandle,
584 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
585 TRUE);
586 if (!NT_SUCCESS(Status))
587 {
588 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
589 goto done;
590 }
591
592 /* Get the domain SID */
593 Status = SamrLookupDomainInSamServer(ServerHandle,
594 (PRPC_UNICODE_STRING)&RequestBuffer->DomainName,
595 &DomainSid);
596 if (!NT_SUCCESS(Status))
597 {
598 TRACE("SamrLookupDomainInSamServer failed (Status %08lx)\n", Status);
599 goto done;
600 }
601
602 /* Open the domain */
603 Status = SamrOpenDomain(ServerHandle,
604 DOMAIN_LOOKUP,
605 DomainSid,
606 &DomainHandle);
607 if (!NT_SUCCESS(Status))
608 {
609 TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
610 goto done;
611 }
612
613 Names[0].Length = RequestBuffer->AccountName.Length;
614 Names[0].MaximumLength = RequestBuffer->AccountName.MaximumLength;
615 Names[0].Buffer = RequestBuffer->AccountName.Buffer;
616
617 /* Try to get the RID for the user name */
618 Status = SamrLookupNamesInDomain(DomainHandle,
619 1,
620 Names,
621 &RelativeIds,
622 &Use);
623 if (!NT_SUCCESS(Status))
624 {
625 TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
626 Status = STATUS_NO_SUCH_USER;
627 goto done;
628 }
629
630 /* Fail, if it is not a user account */
631 if (Use.Element[0] != SidTypeUser)
632 {
633 TRACE("Account is not a user account!\n");
634 Status = STATUS_NO_SUCH_USER;
635 goto done;
636 }
637
638 /* Open the user object */
639 Status = SamrOpenUser(DomainHandle,
640 USER_CHANGE_PASSWORD,
641 RelativeIds.Element[0],
642 &UserHandle);
643 if (!NT_SUCCESS(Status))
644 {
645 TRACE("SamrOpenUser failed (Status %08lx)\n", Status);
646 goto done;
647 }
648
649
650 /* Calculate the NT hash for the old password */
651 Status = SystemFunction007(&RequestBuffer->OldPassword,
652 (LPBYTE)&OldNtPassword);
653 if (!NT_SUCCESS(Status))
654 {
655 TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
656 goto done;
657 }
658
659 /* Calculate the NT hash for the new password */
660 Status = SystemFunction007(&RequestBuffer->NewPassword,
661 (LPBYTE)&NewNtPassword);
662 if (!NT_SUCCESS(Status))
663 {
664 TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
665 goto done;
666 }
667
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);
673
674 Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
675 &RequestBuffer->OldPassword,
676 FALSE);
677 if (NT_SUCCESS(Status))
678 {
679 /* Calculate the LM hash value of the password */
680 Status = SystemFunction006(LmPwdString.Buffer,
681 (LPSTR)&OldLmPassword);
682 if (NT_SUCCESS(Status))
683 {
684 OldLmPasswordPresent = TRUE;
685 }
686 }
687
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);
693
694 Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
695 &RequestBuffer->NewPassword,
696 FALSE);
697 if (NT_SUCCESS(Status))
698 {
699 /* Calculate the LM hash value of the password */
700 Status = SystemFunction006(LmPwdString.Buffer,
701 (LPSTR)&NewLmPassword);
702 if (NT_SUCCESS(Status))
703 {
704 NewLmPasswordPresent = TRUE;
705 }
706 }
707
708 /* Encrypt the old and new LM passwords, if they exist */
709 if (OldLmPasswordPresent && NewLmPasswordPresent)
710 {
711 /* Encrypt the old LM password */
712 Status = SystemFunction012((const BYTE *)&OldLmPassword,
713 (const BYTE *)&NewLmPassword,
714 (LPBYTE)&OldLmEncryptedWithNewLm);
715 if (!NT_SUCCESS(Status))
716 {
717 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
718 goto done;
719 }
720
721 /* Encrypt the new LM password */
722 Status = SystemFunction012((const BYTE *)&NewLmPassword,
723 (const BYTE *)&OldLmPassword,
724 (LPBYTE)&NewLmEncryptedWithOldLm);
725 if (!NT_SUCCESS(Status))
726 {
727 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
728 goto done;
729 }
730
731 pOldLmEncryptedWithNewLm = &OldLmEncryptedWithNewLm;
732 pNewLmEncryptedWithOldLm = &NewLmEncryptedWithOldLm;
733 }
734
735 /* Encrypt the old NT password */
736 Status = SystemFunction012((const BYTE *)&OldNtPassword,
737 (const BYTE *)&NewNtPassword,
738 (LPBYTE)&OldNtEncryptedWithNewNt);
739 if (!NT_SUCCESS(Status))
740 {
741 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
742 goto done;
743 }
744
745 /* Encrypt the new NT password */
746 Status = SystemFunction012((const BYTE *)&NewNtPassword,
747 (const BYTE *)&OldNtPassword,
748 (LPBYTE)&NewNtEncryptedWithOldNt);
749 if (!NT_SUCCESS(Status))
750 {
751 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
752 goto done;
753 }
754
755 /* Change the password */
756 Status = SamrChangePasswordUser(UserHandle,
757 OldLmPasswordPresent && NewLmPasswordPresent,
758 pOldLmEncryptedWithNewLm,
759 pNewLmEncryptedWithOldLm,
760 TRUE,
761 &OldNtEncryptedWithNewNt,
762 &NewNtEncryptedWithOldNt,
763 FALSE,
764 NULL,
765 FALSE,
766 NULL);
767 if (!NT_SUCCESS(Status))
768 {
769 TRACE("SamrChangePasswordUser failed (Status %08lx)\n", Status);
770 goto done;
771 }
772
773 done:
774 if (UserHandle != NULL)
775 SamrCloseHandle(&UserHandle);
776
777 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
778 SamIFree_SAMPR_ULONG_ARRAY(&Use);
779
780 if (DomainHandle != NULL)
781 SamrCloseHandle(&DomainHandle);
782
783 if (DomainSid != NULL)
784 SamIFreeVoid(DomainSid);
785
786 if (ServerHandle != NULL)
787 SamrCloseHandle(&ServerHandle);
788
789 return Status;
790 }
791
792
793 static
794 NTSTATUS
795 MsvpCheckPassword(PUNICODE_STRING UserPassword,
796 PSAMPR_USER_INFO_BUFFER UserInfo)
797 {
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];
804 NTSTATUS Status;
805
806 TRACE("(%p %p)\n", UserPassword, UserInfo);
807
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);
813
814 Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
815 UserPassword,
816 FALSE);
817 if (NT_SUCCESS(Status))
818 {
819 /* Calculate the LM hash value of the users password */
820 Status = SystemFunction006(LmPwdString.Buffer,
821 (LPSTR)&UserLmPassword);
822 if (NT_SUCCESS(Status))
823 {
824 UserLmPasswordPresent = TRUE;
825 }
826 }
827
828 /* Calculate the NT hash of the users password */
829 Status = SystemFunction007(UserPassword,
830 (LPBYTE)&UserNtPassword);
831 if (NT_SUCCESS(Status))
832 {
833 UserNtPasswordPresent = TRUE;
834 }
835
836 Status = STATUS_WRONG_PASSWORD;
837
838 /* Succeed, if no password has been set */
839 if (UserInfo->All.NtPasswordPresent == FALSE &&
840 UserInfo->All.LmPasswordPresent == FALSE)
841 {
842 TRACE("No password check!\n");
843 Status = STATUS_SUCCESS;
844 goto done;
845 }
846
847 /* Succeed, if NT password matches */
848 if (UserNtPasswordPresent && UserInfo->All.NtPasswordPresent)
849 {
850 TRACE("Check NT password hashes:\n");
851 if (RtlEqualMemory(&UserNtPassword,
852 UserInfo->All.NtOwfPassword.Buffer,
853 sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
854 {
855 TRACE(" success!\n");
856 Status = STATUS_SUCCESS;
857 goto done;
858 }
859
860 TRACE(" failed!\n");
861 }
862
863 /* Succeed, if LM password matches */
864 if (UserLmPasswordPresent && UserInfo->All.LmPasswordPresent)
865 {
866 TRACE("Check LM password hashes:\n");
867 if (RtlEqualMemory(&UserLmPassword,
868 UserInfo->All.LmOwfPassword.Buffer,
869 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
870 {
871 TRACE(" success!\n");
872 Status = STATUS_SUCCESS;
873 goto done;
874 }
875 TRACE(" failed!\n");
876 }
877
878 done:
879 return Status;
880 }
881
882
883 static
884 BOOL
885 MsvpCheckLogonHours(
886 _In_ PSAMPR_LOGON_HOURS LogonHours,
887 _In_ PLARGE_INTEGER LogonTime)
888 {
889 #if 0
890 LARGE_INTEGER LocalLogonTime;
891 TIME_FIELDS TimeFields;
892 USHORT MinutesPerUnit, Offset;
893 BOOL bFound;
894
895 FIXME("MsvpCheckLogonHours(%p %p)\n", LogonHours, LogonTime);
896
897 if (LogonHours->UnitsPerWeek == 0 || LogonHours->LogonHours == NULL)
898 {
899 FIXME("No logon hours!\n");
900 return TRUE;
901 }
902
903 RtlSystemTimeToLocalTime(LogonTime, &LocalLogonTime);
904 RtlTimeToTimeFields(&LocalLogonTime, &TimeFields);
905
906 FIXME("UnitsPerWeek: %u\n", LogonHours->UnitsPerWeek);
907 MinutesPerUnit = 10080 / LogonHours->UnitsPerWeek;
908
909 Offset = ((TimeFields.Weekday * 24 + TimeFields.Hour) * 60 + TimeFields.Minute) / MinutesPerUnit;
910 FIXME("Offset: %us\n", Offset);
911
912 bFound = (BOOL)(LogonHours->LogonHours[Offset / 8] & (1 << (Offset % 8)));
913 FIXME("Logon permitted: %s\n", bFound ? "Yes" : "No");
914
915 return bFound;
916 #endif
917 return TRUE;
918 }
919
920
921 static
922 BOOL
923 MsvpCheckWorkstations(
924 _In_ PRPC_UNICODE_STRING WorkStations,
925 _In_ PWSTR ComputerName)
926 {
927 PWSTR pStart, pEnd;
928 BOOL bFound = FALSE;
929
930 TRACE("MsvpCheckWorkstations(%p %S)\n", WorkStations, ComputerName);
931
932 if (WorkStations->Length == 0 || WorkStations->Buffer == NULL)
933 {
934 TRACE("No workstations!\n");
935 return TRUE;
936 }
937
938 TRACE("Workstations: %wZ\n", WorkStations);
939
940 pStart = WorkStations->Buffer;
941 for (;;)
942 {
943 pEnd = wcschr(pStart, L',');
944 if (pEnd != NULL)
945 *pEnd = UNICODE_NULL;
946
947 TRACE("Comparing '%S' and '%S'\n", ComputerName, pStart);
948 if (_wcsicmp(ComputerName, pStart) == 0)
949 {
950 bFound = TRUE;
951 if (pEnd != NULL)
952 *pEnd = L',';
953 break;
954 }
955
956 if (pEnd == NULL)
957 break;
958
959 *pEnd = L',';
960 pStart = pEnd + 1;
961 }
962
963 TRACE("Found allowed workstation: %s\n", (bFound) ? "Yes" : "No");
964
965 return bFound;
966 }
967
968
969 /*
970 * @unimplemented
971 */
972 NTSTATUS
973 NTAPI
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)
981 {
982 NTSTATUS Status;
983 MSV1_0_PROTOCOL_MESSAGE_TYPE MessageType;
984
985 TRACE("LsaApCallPackage()\n");
986
987 if (SubmitBufferLength < sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE))
988 return STATUS_INVALID_PARAMETER;
989
990 MessageType = *((PMSV1_0_PROTOCOL_MESSAGE_TYPE)ProtocolSubmitBuffer);
991
992 *ProtocolReturnBuffer = NULL;
993 *ReturnBufferLength = 0;
994
995 switch (MessageType)
996 {
997 case MsV1_0Lm20ChallengeRequest:
998 case MsV1_0Lm20GetChallengeResponse:
999 Status = STATUS_NOT_IMPLEMENTED;
1000 break;
1001
1002 case MsV1_0EnumerateUsers:
1003 case MsV1_0GetUserInfo:
1004 case MsV1_0ReLogonUsers:
1005 Status = STATUS_INVALID_PARAMETER;
1006 break;
1007
1008 case MsV1_0ChangePassword:
1009 Status = MsvpChangePassword(ClientRequest,
1010 ProtocolSubmitBuffer,
1011 ClientBufferBase,
1012 SubmitBufferLength,
1013 ProtocolReturnBuffer,
1014 ReturnBufferLength,
1015 ProtocolStatus);
1016 break;
1017
1018 case MsV1_0ChangeCachedPassword:
1019 case MsV1_0GenericPassthrough:
1020 case MsV1_0CacheLogon:
1021 case MsV1_0SubAuth:
1022 case MsV1_0DeriveCredential:
1023 case MsV1_0CacheLookup:
1024 Status = STATUS_NOT_IMPLEMENTED;
1025 break;
1026
1027 default:
1028 return STATUS_INVALID_PARAMETER;
1029 }
1030
1031 return Status;
1032 }
1033
1034
1035 /*
1036 * @unimplemented
1037 */
1038 NTSTATUS
1039 NTAPI
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)
1047 {
1048 TRACE("LsaApCallPackagePassthrough()\n");
1049 return STATUS_NOT_IMPLEMENTED;
1050 }
1051
1052
1053 /*
1054 * @implemented
1055 */
1056 NTSTATUS
1057 NTAPI
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)
1065 {
1066 ULONG MessageType;
1067 NTSTATUS Status;
1068
1069 TRACE("LsaApCallPackageUntrusted()\n");
1070
1071 if (SubmitBufferLength < sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE))
1072 return STATUS_INVALID_PARAMETER;
1073
1074 MessageType = (ULONG)*((PMSV1_0_PROTOCOL_MESSAGE_TYPE)ProtocolSubmitBuffer);
1075
1076 *ProtocolReturnBuffer = NULL;
1077 *ReturnBufferLength = 0;
1078
1079 if (MessageType == MsV1_0ChangePassword)
1080 Status = MsvpChangePassword(ClientRequest,
1081 ProtocolSubmitBuffer,
1082 ClientBufferBase,
1083 SubmitBufferLength,
1084 ProtocolReturnBuffer,
1085 ReturnBufferLength,
1086 ProtocolStatus);
1087 else
1088 Status = STATUS_ACCESS_DENIED;
1089
1090 return Status;
1091 }
1092
1093
1094 /*
1095 * @implemented
1096 */
1097 NTSTATUS
1098 NTAPI
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)
1104 {
1105 PANSI_STRING NameString;
1106 PCHAR NameBuffer;
1107
1108 TRACE("LsaApInitializePackage(%lu %p %p %p %p)\n",
1109 AuthenticationPackageId, LsaDispatchTable, Database,
1110 Confidentiality, AuthenticationPackageName);
1111
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;
1124
1125 /* Return the package name */
1126 NameString = DispatchTable.AllocateLsaHeap(sizeof(LSA_STRING));
1127 if (NameString == NULL)
1128 return STATUS_INSUFFICIENT_RESOURCES;
1129
1130 NameBuffer = DispatchTable.AllocateLsaHeap(sizeof(MSV1_0_PACKAGE_NAME));
1131 if (NameBuffer == NULL)
1132 {
1133 DispatchTable.FreeLsaHeap(NameString);
1134 return STATUS_INSUFFICIENT_RESOURCES;
1135 }
1136
1137 strcpy(NameBuffer, MSV1_0_PACKAGE_NAME);
1138
1139 RtlInitAnsiString(NameString, NameBuffer);
1140
1141 *AuthenticationPackageName = (PLSA_STRING)NameString;
1142
1143 return STATUS_SUCCESS;
1144 }
1145
1146
1147 /*
1148 * @unimplemented
1149 */
1150 VOID
1151 NTAPI
1152 LsaApLogonTerminated(IN PLUID LogonId)
1153 {
1154 TRACE("LsaApLogonTerminated()\n");
1155 }
1156
1157
1158 /*
1159 * @implemented
1160 */
1161 NTSTATUS
1162 NTAPI
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,
1170 OUT PLUID LogonId,
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 */
1179 {
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");
1183
1184 NTSTATUS Status;
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;
1204
1205 TRACE("LsaApLogonUserEx2()\n");
1206
1207 TRACE("LogonType: %lu\n", LogonType);
1208 TRACE("ProtocolSubmitBuffer: %p\n", ProtocolSubmitBuffer);
1209 TRACE("SubmitBufferSize: %lu\n", SubmitBufferSize);
1210
1211 *ProfileBuffer = NULL;
1212 *ProfileBufferSize = 0;
1213 *SubStatus = STATUS_SUCCESS;
1214 *AccountName = NULL;
1215 *AuthenticatingAuthority = NULL;
1216
1217 /* Parameters validation */
1218 if (LogonType == Interactive ||
1219 LogonType == Batch ||
1220 LogonType == Service)
1221 {
1222 ULONG_PTR PtrOffset;
1223
1224 if (SubmitBufferSize < sizeof(MSV1_0_INTERACTIVE_LOGON))
1225 {
1226 ERR("Invalid SubmitBufferSize %lu\n", SubmitBufferSize);
1227 return STATUS_INVALID_PARAMETER;
1228 }
1229
1230 LogonInfo = (PMSV1_0_INTERACTIVE_LOGON)ProtocolSubmitBuffer;
1231
1232 if (LogonInfo->MessageType != MsV1_0InteractiveLogon &&
1233 LogonInfo->MessageType != MsV1_0WorkstationUnlockLogon)
1234 {
1235 ERR("Invalid MessageType %lu\n", LogonInfo->MessageType);
1236 return STATUS_BAD_VALIDATION_CLASS;
1237 }
1238
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)
1241 {
1242 ERR("UserName too long (%lu, maximum 512)\n", LogonInfo->UserName.Length);
1243 return STATUS_NAME_TOO_LONG;
1244 }
1245 if (LogonInfo->Password.Length > 512) // CREDUI_MAX_PASSWORD_LENGTH * sizeof(WCHAR)
1246 {
1247 ERR("Password too long (%lu, maximum 512)\n", LogonInfo->Password.Length);
1248 return STATUS_NAME_TOO_LONG;
1249 }
1250 #endif
1251
1252 /* Fix-up pointers in the authentication info */
1253 PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;
1254
1255 /* LogonDomainName is optional and can be an empty string */
1256 if (LogonInfo->LogonDomainName.Length)
1257 {
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;
1261 }
1262 else
1263 {
1264 LogonInfo->LogonDomainName.Buffer = NULL;
1265 LogonInfo->LogonDomainName.MaximumLength = 0;
1266 }
1267 Status = RtlValidateUnicodeString(0, &LogonInfo->LogonDomainName);
1268 if (!NT_SUCCESS(Status))
1269 return STATUS_INVALID_PARAMETER;
1270
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;
1275
1276 Status = RtlValidateUnicodeString(0, &LogonInfo->UserName);
1277 if (!NT_SUCCESS(Status))
1278 return STATUS_INVALID_PARAMETER;
1279
1280 /* MS docs says max length is 0xFF bytes. But thats not the full story:
1281 *
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. ..."
1285 *
1286 * If the higher byte of length != 0 we have to use RtlRunDecodeUnicodeString.
1287 */
1288 LogonPassHash = (LogonInfo->Password.Length >> 8) & 0xFF;
1289 LogonInfo->Password.Length = LogonInfo->Password.Length & 0xFF;
1290
1291 /* Password is optional and can be an empty string */
1292 if (LogonInfo->Password.Length)
1293 {
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;
1297 }
1298 else
1299 {
1300 LogonInfo->Password.Buffer = NULL;
1301 LogonInfo->Password.MaximumLength = 0;
1302 }
1303
1304 /* Decode password */
1305 if (LogonPassHash > 0)
1306 {
1307 RtlRunDecodeUnicodeString(LogonPassHash, &LogonInfo->Password);
1308 }
1309
1310 /* ErasePassword will be "erased" before we return */
1311 ErasePassword = &LogonInfo->Password;
1312
1313 Status = RtlValidateUnicodeString(0, &LogonInfo->Password);
1314 if (!NT_SUCCESS(Status))
1315 return STATUS_INVALID_PARAMETER;
1316
1317 TRACE("Domain: %wZ\n", &LogonInfo->LogonDomainName);
1318 TRACE("User: %wZ\n", &LogonInfo->UserName);
1319 TRACE("Password: %wZ\n", &LogonInfo->Password);
1320
1321 // TODO: If LogonType == Service, do some extra work using LogonInfo->Password.
1322 }
1323 else
1324 {
1325 FIXME("LogonType %lu is not supported yet!\n", LogonType);
1326 return STATUS_NOT_IMPLEMENTED;
1327 }
1328 // TODO: Add other LogonType validity checks.
1329
1330 /* Get the logon time */
1331 NtQuerySystemTime(&LogonTime);
1332
1333 /* Get the computer name */
1334 ComputerNameSize = ARRAYSIZE(ComputerName);
1335 GetComputerNameW(ComputerName, &ComputerNameSize);
1336
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))
1340 {
1341 SpecialAccount = TRUE;
1342
1343 /* Get the authority domain SID */
1344 Status = GetNtAuthorityDomainSid(&AccountDomainSid);
1345 if (!NT_SUCCESS(Status))
1346 {
1347 ERR("GetNtAuthorityDomainSid() failed (Status 0x%08lx)\n", Status);
1348 return Status;
1349 }
1350
1351 if (RtlEqualUnicodeString(&LogonInfo->UserName, &LocalServiceU, TRUE))
1352 {
1353 TRACE("SpecialAccount: LocalService\n");
1354
1355 if (LogonType != Service)
1356 return STATUS_LOGON_FAILURE;
1357
1358 UserInfo = RtlAllocateHeap(RtlGetProcessHeap(),
1359 HEAP_ZERO_MEMORY,
1360 sizeof(SAMPR_USER_ALL_INFORMATION));
1361 if (UserInfo == NULL)
1362 {
1363 Status = STATUS_INSUFFICIENT_RESOURCES;
1364 goto done;
1365 }
1366
1367 UserInfo->All.UserId = SECURITY_LOCAL_SERVICE_RID;
1368 UserInfo->All.PrimaryGroupId = SECURITY_LOCAL_SERVICE_RID;
1369 }
1370 else if (RtlEqualUnicodeString(&LogonInfo->UserName, &NetworkServiceU, TRUE))
1371 {
1372 TRACE("SpecialAccount: NetworkService\n");
1373
1374 if (LogonType != Service)
1375 return STATUS_LOGON_FAILURE;
1376
1377 UserInfo = RtlAllocateHeap(RtlGetProcessHeap(),
1378 HEAP_ZERO_MEMORY,
1379 sizeof(SAMPR_USER_ALL_INFORMATION));
1380 if (UserInfo == NULL)
1381 {
1382 Status = STATUS_INSUFFICIENT_RESOURCES;
1383 goto done;
1384 }
1385
1386 UserInfo->All.UserId = SECURITY_NETWORK_SERVICE_RID;
1387 UserInfo->All.PrimaryGroupId = SECURITY_NETWORK_SERVICE_RID;
1388 }
1389 else
1390 {
1391 Status = STATUS_NO_SUCH_USER;
1392 goto done;
1393 }
1394 }
1395 else
1396 {
1397 TRACE("NormalAccount\n");
1398
1399 /* Get the account domain SID */
1400 Status = GetAccountDomainSid(&AccountDomainSid);
1401 if (!NT_SUCCESS(Status))
1402 {
1403 ERR("GetAccountDomainSid() failed (Status 0x%08lx)\n", Status);
1404 return Status;
1405 }
1406
1407 /* Connect to the SAM server */
1408 Status = SamIConnect(NULL,
1409 &ServerHandle,
1410 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
1411 TRUE);
1412 if (!NT_SUCCESS(Status))
1413 {
1414 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
1415 goto done;
1416 }
1417
1418 /* Open the account domain */
1419 Status = SamrOpenDomain(ServerHandle,
1420 DOMAIN_LOOKUP,
1421 AccountDomainSid,
1422 &DomainHandle);
1423 if (!NT_SUCCESS(Status))
1424 {
1425 ERR("SamrOpenDomain failed (Status %08lx)\n", Status);
1426 goto done;
1427 }
1428
1429 Names[0].Length = LogonInfo->UserName.Length;
1430 Names[0].MaximumLength = LogonInfo->UserName.MaximumLength;
1431 Names[0].Buffer = LogonInfo->UserName.Buffer;
1432
1433 /* Try to get the RID for the user name */
1434 Status = SamrLookupNamesInDomain(DomainHandle,
1435 1,
1436 Names,
1437 &RelativeIds,
1438 &Use);
1439 if (!NT_SUCCESS(Status))
1440 {
1441 ERR("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
1442 Status = STATUS_NO_SUCH_USER;
1443 goto done;
1444 }
1445
1446 /* Fail, if it is not a user account */
1447 if (Use.Element[0] != SidTypeUser)
1448 {
1449 ERR("Account is not a user account!\n");
1450 Status = STATUS_NO_SUCH_USER;
1451 goto done;
1452 }
1453
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],
1459 &UserHandle);
1460 if (!NT_SUCCESS(Status))
1461 {
1462 ERR("SamrOpenUser failed (Status %08lx)\n", Status);
1463 goto done;
1464 }
1465
1466 Status = SamrQueryInformationUser(UserHandle,
1467 UserAllInformation,
1468 &UserInfo);
1469 if (!NT_SUCCESS(Status))
1470 {
1471 ERR("SamrQueryInformationUser failed (Status %08lx)\n", Status);
1472 goto done;
1473 }
1474
1475 TRACE("UserName: %wZ\n", &UserInfo->All.UserName);
1476
1477 /* Check the password */
1478 if ((UserInfo->All.UserAccountControl & USER_PASSWORD_NOT_REQUIRED) == 0)
1479 {
1480 Status = MsvpCheckPassword(&LogonInfo->Password,
1481 UserInfo);
1482 if (!NT_SUCCESS(Status))
1483 {
1484 ERR("MsvpCheckPassword failed (Status %08lx)\n", Status);
1485 goto done;
1486 }
1487 }
1488
1489 /* Check account restrictions for non-administrator accounts */
1490 if (RelativeIds.Element[0] != DOMAIN_USER_RID_ADMIN)
1491 {
1492 /* Check if the account has been disabled */
1493 if (UserInfo->All.UserAccountControl & USER_ACCOUNT_DISABLED)
1494 {
1495 ERR("Account disabled!\n");
1496 *SubStatus = STATUS_ACCOUNT_DISABLED;
1497 Status = STATUS_ACCOUNT_RESTRICTION;
1498 goto done;
1499 }
1500
1501 /* Check if the account has been locked */
1502 if (UserInfo->All.UserAccountControl & USER_ACCOUNT_AUTO_LOCKED)
1503 {
1504 ERR("Account locked!\n");
1505 *SubStatus = STATUS_ACCOUNT_LOCKED_OUT;
1506 Status = STATUS_ACCOUNT_RESTRICTION;
1507 goto done;
1508 }
1509
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)
1514 {
1515 ERR("Account expired!\n");
1516 *SubStatus = STATUS_ACCOUNT_EXPIRED;
1517 Status = STATUS_ACCOUNT_RESTRICTION;
1518 goto done;
1519 }
1520
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;
1526
1527 if (LogonTime.QuadPart >= PasswordMustChange.QuadPart)
1528 {
1529 ERR("Password expired!\n");
1530 if (PasswordLastSet.QuadPart == 0)
1531 *SubStatus = STATUS_PASSWORD_MUST_CHANGE;
1532 else
1533 *SubStatus = STATUS_PASSWORD_EXPIRED;
1534
1535 Status = STATUS_ACCOUNT_RESTRICTION;
1536 goto done;
1537 }
1538
1539 /* Check logon hours */
1540 if (!MsvpCheckLogonHours(&UserInfo->All.LogonHours, &LogonTime))
1541 {
1542 ERR("Invalid logon hours!\n");
1543 *SubStatus = STATUS_INVALID_LOGON_HOURS;
1544 Status = STATUS_ACCOUNT_RESTRICTION;
1545 goto done;
1546 }
1547
1548 /* Check workstations */
1549 if (!MsvpCheckWorkstations(&UserInfo->All.WorkStations, ComputerName))
1550 {
1551 ERR("Invalid workstation!\n");
1552 *SubStatus = STATUS_INVALID_WORKSTATION;
1553 Status = STATUS_ACCOUNT_RESTRICTION;
1554 goto done;
1555 }
1556 }
1557 }
1558
1559 /* Return logon information */
1560
1561 /* Create and return a new logon id */
1562 Status = NtAllocateLocallyUniqueId(LogonId);
1563 if (!NT_SUCCESS(Status))
1564 {
1565 TRACE("NtAllocateLocallyUniqueId failed (Status %08lx)\n", Status);
1566 goto done;
1567 }
1568
1569 /* Create the logon session */
1570 Status = DispatchTable.CreateLogonSession(LogonId);
1571 if (!NT_SUCCESS(Status))
1572 {
1573 TRACE("CreateLogonSession failed (Status %08lx)\n", Status);
1574 goto done;
1575 }
1576
1577 SessionCreated = TRUE;
1578
1579 /* Build and fill the interactive profile buffer */
1580 Status = BuildInteractiveProfileBuffer(ClientRequest,
1581 UserInfo,
1582 ComputerName,
1583 (PMSV1_0_INTERACTIVE_PROFILE*)ProfileBuffer,
1584 ProfileBufferSize);
1585 if (!NT_SUCCESS(Status))
1586 {
1587 TRACE("BuildInteractiveProfileBuffer failed (Status %08lx)\n", Status);
1588 goto done;
1589 }
1590
1591 /* Return the token information type */
1592 *TokenInformationType = LsaTokenInformationV1;
1593
1594 /* Build and fill the token information buffer */
1595 Status = BuildTokenInformationBuffer((PLSA_TOKEN_INFORMATION_V1*)TokenInformation,
1596 AccountDomainSid,
1597 UserInfo,
1598 SpecialAccount);
1599 if (!NT_SUCCESS(Status))
1600 {
1601 TRACE("BuildTokenInformationBuffer failed (Status %08lx)\n", Status);
1602 goto done;
1603 }
1604
1605 done:
1606 /* Erase password */
1607 if (ErasePassword)
1608 {
1609 RtlEraseUnicodeString(ErasePassword);
1610 }
1611
1612 /* Update the logon time/count or the bad password time/count */
1613 if ((UserHandle != NULL) &&
1614 (Status == STATUS_SUCCESS || Status == STATUS_WRONG_PASSWORD))
1615 {
1616 SAMPR_USER_INFO_BUFFER InternalInfo;
1617
1618 RtlZeroMemory(&InternalInfo, sizeof(InternalInfo));
1619
1620 if (Status == STATUS_SUCCESS)
1621 InternalInfo.Internal2.Flags = USER_LOGON_SUCCESS;
1622 else
1623 InternalInfo.Internal2.Flags = USER_LOGON_BAD_PASSWORD;
1624
1625 SamrSetInformationUser(UserHandle,
1626 UserInternal2Information,
1627 &InternalInfo);
1628 }
1629
1630 /* Return the account name */
1631 *AccountName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1632 if (*AccountName != NULL)
1633 {
1634 (*AccountName)->Buffer = DispatchTable.AllocateLsaHeap(LogonInfo->UserName.Length +
1635 sizeof(UNICODE_NULL));
1636 if ((*AccountName)->Buffer != NULL)
1637 {
1638 (*AccountName)->MaximumLength = LogonInfo->UserName.Length +
1639 sizeof(UNICODE_NULL);
1640 RtlCopyUnicodeString(*AccountName, &LogonInfo->UserName);
1641 }
1642 }
1643
1644 /* Return the authenticating authority */
1645 *AuthenticatingAuthority = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1646 if (*AuthenticatingAuthority != NULL)
1647 {
1648 (*AuthenticatingAuthority)->Buffer = DispatchTable.AllocateLsaHeap(LogonInfo->LogonDomainName.Length +
1649 sizeof(UNICODE_NULL));
1650 if ((*AuthenticatingAuthority)->Buffer != NULL)
1651 {
1652 (*AuthenticatingAuthority)->MaximumLength = LogonInfo->LogonDomainName.Length +
1653 sizeof(UNICODE_NULL);
1654 RtlCopyUnicodeString(*AuthenticatingAuthority, &LogonInfo->LogonDomainName);
1655 }
1656 }
1657
1658 /* Return the machine name */
1659 *MachineName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1660 if (*MachineName != NULL)
1661 {
1662 (*MachineName)->Buffer = DispatchTable.AllocateLsaHeap((ComputerNameSize + 1) * sizeof(WCHAR));
1663 if ((*MachineName)->Buffer != NULL)
1664 {
1665 (*MachineName)->MaximumLength = (ComputerNameSize + 1) * sizeof(WCHAR);
1666 (*MachineName)->Length = ComputerNameSize * sizeof(WCHAR);
1667 RtlCopyMemory((*MachineName)->Buffer, ComputerName, (*MachineName)->MaximumLength);
1668 }
1669 }
1670
1671 if (!NT_SUCCESS(Status))
1672 {
1673 if (SessionCreated != FALSE)
1674 DispatchTable.DeleteLogonSession(LogonId);
1675
1676 if (*ProfileBuffer != NULL)
1677 {
1678 DispatchTable.FreeClientBuffer(ClientRequest,
1679 *ProfileBuffer);
1680 *ProfileBuffer = NULL;
1681 }
1682 }
1683
1684 if (UserHandle != NULL)
1685 SamrCloseHandle(&UserHandle);
1686
1687 SamIFree_SAMPR_USER_INFO_BUFFER(UserInfo,
1688 UserAllInformation);
1689 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
1690 SamIFree_SAMPR_ULONG_ARRAY(&Use);
1691
1692 if (DomainHandle != NULL)
1693 SamrCloseHandle(&DomainHandle);
1694
1695 if (ServerHandle != NULL)
1696 SamrCloseHandle(&ServerHandle);
1697
1698 if (AccountDomainSid != NULL)
1699 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
1700
1701 if (Status == STATUS_NO_SUCH_USER ||
1702 Status == STATUS_WRONG_PASSWORD)
1703 {
1704 *SubStatus = Status;
1705 Status = STATUS_LOGON_FAILURE;
1706 }
1707
1708 TRACE("LsaApLogonUserEx2 done (Status 0x%08lx, SubStatus 0x%08lx)\n", Status, *SubStatus);
1709
1710 return Status;
1711 }
1712
1713
1714 /*
1715 * @unimplemented
1716 */
1717 NTSTATUS
1718 NTAPI
1719 SpLsaModeInitialize(
1720 _In_ ULONG LsaVersion,
1721 _Out_ PULONG PackageVersion,
1722 _Out_ PSECPKG_FUNCTION_TABLE *ppTables,
1723 _Out_ PULONG pcTables)
1724 {
1725 TRACE("SpLsaModeInitialize(0x%lx %p %p %p)\n",
1726 LsaVersion, PackageVersion, ppTables, pcTables);
1727
1728 if (LsaVersion != SECPKG_INTERFACE_VERSION)
1729 return STATUS_INVALID_PARAMETER;
1730
1731 *PackageVersion = SECPKG_INTERFACE_VERSION;
1732
1733 RtlZeroMemory(NtlmLsaFn, sizeof(NtlmLsaFn));
1734
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;
1765
1766 *ppTables = NtlmLsaFn;
1767 *pcTables = 1;
1768
1769 return STATUS_SUCCESS;
1770 }
1771
1772
1773 /*
1774 * @unimplemented
1775 */
1776 NTSTATUS
1777 WINAPI
1778 SpUserModeInitialize(
1779 _In_ ULONG LsaVersion,
1780 _Out_ PULONG PackageVersion,
1781 _Out_ PSECPKG_USER_FUNCTION_TABLE *ppTables,
1782 _Out_ PULONG pcTables)
1783 {
1784 SECPKG_USER_FUNCTION_TABLE Tables[1];
1785
1786 TRACE("SpUserModeInitialize(0x%lx %p %p %p)\n",
1787 LsaVersion, PackageVersion, ppTables, pcTables);
1788
1789 if (LsaVersion != SECPKG_INTERFACE_VERSION)
1790 return STATUS_INVALID_PARAMETER;
1791
1792 *PackageVersion = SECPKG_INTERFACE_VERSION;
1793
1794 RtlZeroMemory(&Tables, sizeof(Tables));
1795
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;
1810
1811 *ppTables = Tables;
1812 *pcTables = 1;
1813
1814 return STATUS_SUCCESS;
1815 }
1816
1817 /* EOF */