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 */ 1818