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