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