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