Changeset 988 for vendor/current/source4/auth/sam.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source4/auth/sam.c
r740 r988 42 42 "msDS-SupportedEncryptionTypes", \ 43 43 "supplementalCredentials", \ 44 "msDS-AllowedToDelegateTo", \ 44 45 \ 45 46 /* passwords */ \ … … 47 48 "unicodePwd", \ 48 49 \ 49 "userAccountControl", \ 50 "userAccountControl", \ 51 "msDS-User-Account-Control-Computed", \ 50 52 "objectSid", \ 51 53 \ … … 65 67 66 68 "logonHours", 69 70 /* 71 * To allow us to zero the badPwdCount and lockoutTime on 72 * successful logon, without database churn 73 */ 74 "lockoutTime", 67 75 68 76 /* check 'allowed workstations' */ … … 76 84 "homeDrive", 77 85 "lastLogon", 86 "lastLogonTimestamp", 78 87 "lastLogoff", 79 88 "accountExpires", … … 82 91 "primaryGroupID", 83 92 "memberOf", 93 "badPasswordTime", 94 "lmPwdHistory", 95 "ntPwdHistory", 84 96 NULL, 85 97 }; … … 165 177 NTTIME acct_expiry; 166 178 NTTIME must_change_time; 167 168 NTTIME now; 179 struct timeval tv_now = timeval_current(); 180 NTTIME now = timeval_to_nttime(&tv_now); 181 169 182 DEBUG(4,("authsam_account_ok: Checking SMB password for user %s\n", name_for_logs)); 170 183 171 acct_flags = samdb_result_acct_flags( sam_ctx, mem_ctx, msg, domain_dn);184 acct_flags = samdb_result_acct_flags(msg, "msDS-User-Account-Control-Computed"); 172 185 173 186 acct_expiry = samdb_result_account_expires(msg); … … 193 206 194 207 /* Test account expire time */ 195 unix_to_nt_time(&now, time(NULL));196 208 if (now > acct_expiry) { 197 209 DEBUG(2,("authsam_account_ok: Account for user '%s' has expired.\n", name_for_logs)); … … 221 233 bool invalid_ws = true; 222 234 int i; 223 c onst char **workstations = (const char **)str_list_make(mem_ctx, workstation_list, ",");224 235 char **workstations = str_list_make(mem_ctx, workstation_list, ","); 236 225 237 for (i = 0; workstations && workstations[i]; i++) { 226 238 DEBUG(10,("sam_account_ok: checking for workstation match '%s' and '%s'\n", … … 298 310 299 311 tmp_ctx = talloc_new(user_info_dc); 300 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(user_info_dc, user_info_dc); 312 if (user_info_dc == NULL) { 313 TALLOC_FREE(user_info_dc); 314 return NT_STATUS_NO_MEMORY; 315 } 301 316 302 317 sids = talloc_array(user_info_dc, struct dom_sid, 2); 303 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sids, user_info_dc); 318 if (sids == NULL) { 319 TALLOC_FREE(user_info_dc); 320 return NT_STATUS_NO_MEMORY; 321 } 304 322 305 323 num_sids = 2; 306 324 307 325 account_sid = samdb_result_dom_sid(user_info_dc, msg, "objectSid"); 308 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(account_sid, user_info_dc); 326 if (account_sid == NULL) { 327 TALLOC_FREE(user_info_dc); 328 return NT_STATUS_NO_MEMORY; 329 } 309 330 310 331 status = dom_sid_split_rid(tmp_ctx, account_sid, &domain_sid, NULL); … … 322 343 * on SamLogon validation info */ 323 344 filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(!(groupType:1.2.840.113556.1.4.803:=%u))(groupType:1.2.840.113556.1.4.803:=%u))", GROUP_TYPE_BUILTIN_LOCAL_GROUP, GROUP_TYPE_SECURITY_ENABLED); 324 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(filter, user_info_dc); 345 if (filter == NULL) { 346 TALLOC_FREE(user_info_dc); 347 return NT_STATUS_NO_MEMORY; 348 } 325 349 326 350 primary_group_string = dom_sid_string(tmp_ctx, &sids[PRIMARY_GROUP_SID_INDEX]); 327 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(primary_group_string, user_info_dc); 351 if (primary_group_string == NULL) { 352 TALLOC_FREE(user_info_dc); 353 return NT_STATUS_NO_MEMORY; 354 } 328 355 329 356 primary_group_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", primary_group_string); 330 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(primary_group_dn, user_info_dc); 357 if (primary_group_dn == NULL) { 358 TALLOC_FREE(user_info_dc); 359 return NT_STATUS_NO_MEMORY; 360 } 331 361 332 362 primary_group_blob = data_blob_string_const(primary_group_dn); … … 372 402 373 403 info->domain_name = talloc_strdup(info, domain_name); 374 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(info->domain_name, 375 user_info_dc); 404 if (info->domain_name == NULL) { 405 TALLOC_FREE(user_info_dc); 406 return NT_STATUS_NO_MEMORY; 407 } 376 408 377 409 str = ldb_msg_find_attr_as_string(msg, "displayName", ""); 378 410 info->full_name = talloc_strdup(info, str); 379 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(info->full_name, user_info_dc); 411 if (info->full_name == NULL) { 412 TALLOC_FREE(user_info_dc); 413 return NT_STATUS_NO_MEMORY; 414 } 380 415 381 416 str = ldb_msg_find_attr_as_string(msg, "scriptPath", ""); 382 417 info->logon_script = talloc_strdup(info, str); 383 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(info->logon_script, 384 user_info_dc); 418 if (info->logon_script == NULL) { 419 TALLOC_FREE(user_info_dc); 420 return NT_STATUS_NO_MEMORY; 421 } 385 422 386 423 str = ldb_msg_find_attr_as_string(msg, "profilePath", ""); 387 424 info->profile_path = talloc_strdup(info, str); 388 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(info->profile_path, 389 user_info_dc); 425 if (info->profile_path == NULL) { 426 TALLOC_FREE(user_info_dc); 427 return NT_STATUS_NO_MEMORY; 428 } 390 429 391 430 str = ldb_msg_find_attr_as_string(msg, "homeDirectory", ""); 392 431 info->home_directory = talloc_strdup(info, str); 393 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(info->home_directory, 394 user_info_dc); 432 if (info->home_directory == NULL) { 433 TALLOC_FREE(user_info_dc); 434 return NT_STATUS_NO_MEMORY; 435 } 395 436 396 437 str = ldb_msg_find_attr_as_string(msg, "homeDrive", ""); 397 438 info->home_drive = talloc_strdup(info, str); 398 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(info->home_drive, user_info_dc); 439 if (info->home_drive == NULL) { 440 TALLOC_FREE(user_info_dc); 441 return NT_STATUS_NO_MEMORY; 442 } 399 443 400 444 info->logon_server = talloc_strdup(info, netbios_name); 401 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(info->logon_server, 402 user_info_dc); 445 if (info->logon_server == NULL) { 446 TALLOC_FREE(user_info_dc); 447 return NT_STATUS_NO_MEMORY; 448 } 403 449 404 450 info->last_logon = samdb_result_nttime(msg, "lastLogon", 0); … … 417 463 0); 418 464 419 info->acct_flags = samdb_result_acct_flags(sam_ctx, mem_ctx, 420 msg, domain_dn); 465 info->acct_flags = samdb_result_acct_flags(msg, "msDS-User-Account-Control-Computed"); 421 466 422 467 user_info_dc->user_session_key = data_blob_talloc(user_info_dc, … … 424 469 user_sess_key.length); 425 470 if (user_sess_key.data) { 426 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(user_info_dc->user_session_key.data, 427 user_info_dc); 471 if (user_info_dc->user_session_key.data == NULL) { 472 TALLOC_FREE(user_info_dc); 473 return NT_STATUS_NO_MEMORY; 474 } 428 475 } 429 476 user_info_dc->lm_session_key = data_blob_talloc(user_info_dc, … … 431 478 lm_sess_key.length); 432 479 if (lm_sess_key.data) { 433 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(user_info_dc->lm_session_key.data, 434 user_info_dc); 480 if (user_info_dc->lm_session_key.data == NULL) { 481 TALLOC_FREE(user_info_dc); 482 return NT_STATUS_NO_MEMORY; 483 } 435 484 } 436 485 … … 442 491 struct dom_sid, 443 492 user_info_dc->num_sids+1); 444 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(user_info_dc->sids, user_info_dc); 493 if (user_info_dc->sids == NULL) { 494 TALLOC_FREE(user_info_dc); 495 return NT_STATUS_NO_MEMORY; 496 } 445 497 user_info_dc->sids[user_info_dc->num_sids] = global_sid_Enterprise_DCs; 446 498 user_info_dc->num_sids++; … … 454 506 struct dom_sid, 455 507 user_info_dc->num_sids+1); 456 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(user_info_dc->sids, user_info_dc); 508 if (user_info_dc->sids == NULL) { 509 TALLOC_FREE(user_info_dc); 510 return NT_STATUS_NO_MEMORY; 511 } 457 512 user_info_dc->sids[user_info_dc->num_sids] = *domain_sid; 458 513 sid_append_rid(&user_info_dc->sids[user_info_dc->num_sids], … … 493 548 /* pull the user attributes */ 494 549 ret = dsdb_search_one(sam_ctx, tmp_ctx, msg, user_dn, 495 LDB_SCOPE_BASE, attrs, DSDB_SEARCH_SHOW_EXTENDED_DN, "(objectClass=*)"); 550 LDB_SCOPE_BASE, attrs, 551 DSDB_SEARCH_SHOW_EXTENDED_DN | DSDB_SEARCH_NO_GLOBAL_CATALOG, 552 "(objectClass=*)"); 496 553 if (ret != LDB_SUCCESS) { 497 554 talloc_free(tmp_ctx); … … 540 597 /* pull the user attributes */ 541 598 ret = dsdb_search_one(sam_ctx, tmp_ctx, &msg, user_dn, 542 LDB_SCOPE_BASE, user_attrs, DSDB_SEARCH_SHOW_EXTENDED_DN, "(objectClass=*)"); 599 LDB_SCOPE_BASE, user_attrs, 600 DSDB_SEARCH_SHOW_EXTENDED_DN | DSDB_SEARCH_NO_GLOBAL_CATALOG, 601 "(objectClass=*)"); 543 602 if (ret == LDB_ERR_NO_SUCH_OBJECT) { 544 603 talloc_free(tmp_ctx); … … 586 645 return NT_STATUS_OK; 587 646 } 647 648 NTSTATUS authsam_update_bad_pwd_count(struct ldb_context *sam_ctx, 649 struct ldb_message *msg, 650 struct ldb_dn *domain_dn) 651 { 652 const char *attrs[] = { "lockoutThreshold", 653 "lockOutObservationWindow", 654 "lockoutDuration", 655 "pwdProperties", 656 NULL }; 657 int ret; 658 NTSTATUS status; 659 struct ldb_result *domain_res; 660 struct ldb_message *msg_mod = NULL; 661 TALLOC_CTX *mem_ctx; 662 663 mem_ctx = talloc_new(msg); 664 if (mem_ctx == NULL) { 665 return NT_STATUS_NO_MEMORY; 666 } 667 668 ret = dsdb_search_dn(sam_ctx, mem_ctx, &domain_res, domain_dn, attrs, 0); 669 if (ret != LDB_SUCCESS) { 670 TALLOC_FREE(mem_ctx); 671 return NT_STATUS_INTERNAL_DB_CORRUPTION; 672 } 673 674 status = dsdb_update_bad_pwd_count(mem_ctx, sam_ctx, 675 msg, domain_res->msgs[0], &msg_mod); 676 if (!NT_STATUS_IS_OK(status)) { 677 TALLOC_FREE(mem_ctx); 678 return status; 679 } 680 681 if (msg_mod != NULL) { 682 ret = dsdb_modify(sam_ctx, msg_mod, 0); 683 if (ret != LDB_SUCCESS) { 684 DEBUG(0, ("Failed to update badPwdCount, badPasswordTime or set lockoutTime on %s: %s\n", 685 ldb_dn_get_linearized(msg_mod->dn), ldb_errstring(sam_ctx))); 686 TALLOC_FREE(mem_ctx); 687 return NT_STATUS_INTERNAL_ERROR; 688 } 689 } 690 691 TALLOC_FREE(mem_ctx); 692 return NT_STATUS_OK; 693 } 694 695 696 static NTSTATUS authsam_update_lastlogon_timestamp(struct ldb_context *sam_ctx, 697 struct ldb_message *msg_mod, 698 struct ldb_dn *domain_dn, 699 NTTIME old_timestamp, 700 NTTIME now) 701 { 702 /* 703 * We only set lastLogonTimestamp if the current value is older than 704 * now - msDS-LogonTimeSyncInterval days. 705 * 706 * msDS-LogonTimeSyncInterval is an int32_t number of days, while 707 * lastLogonTimestamp is in the 64 bit 100ns NTTIME format. 708 * 709 * The docs say: "the initial update, after the domain functional 710 * level is raised to DS_BEHAVIOR_WIN2003 or higher, is calculated as 711 * 14 days minus a random percentage of 5 days", but we aren't doing 712 * that. The blogosphere seems to think that this randomised update 713 * happens everytime, but [MS-ADA1] doesn't agree. 714 * 715 * Dochelp referred us to the following blog post: 716 * http://blogs.technet.com/b/askds/archive/2009/04/15/the-lastlogontimestamp-attribute-what-it-was-designed-for-and-how-it-works.aspx 717 * 718 * en msDS-LogonTimeSyncInterval is zero, the lastLogonTimestamp is 719 * not changed. 720 */ 721 static const char *attrs[] = { "msDS-LogonTimeSyncInterval", 722 NULL }; 723 int ret; 724 struct ldb_result *domain_res = NULL; 725 TALLOC_CTX *mem_ctx = NULL; 726 int32_t sync_interval; 727 NTTIME sync_interval_nt; 728 729 mem_ctx = talloc_new(msg_mod); 730 if (mem_ctx == NULL) { 731 return NT_STATUS_NO_MEMORY; 732 } 733 734 ret = dsdb_search_dn(sam_ctx, mem_ctx, &domain_res, domain_dn, attrs, 735 0); 736 if (ret != LDB_SUCCESS || domain_res->count != 1) { 737 TALLOC_FREE(mem_ctx); 738 return NT_STATUS_INTERNAL_DB_CORRUPTION; 739 } 740 741 sync_interval = ldb_msg_find_attr_as_int(domain_res->msgs[0], 742 "msDS-LogonTimeSyncInterval", 743 14); 744 DEBUG(5, ("sync interval is %d\n", sync_interval)); 745 if (sync_interval == 0){ 746 /* 747 * Setting msDS-LogonTimeSyncInterval to zero is how you ask 748 * that nothing happens here. 749 */ 750 TALLOC_FREE(mem_ctx); 751 return NT_STATUS_OK; 752 } 753 else if (sync_interval >= 5){ 754 /* 755 * Subtract "a random percentage of 5" days. Presumably this 756 * percentage is between 0 and 100, and modulus is accurate 757 * enough. 758 */ 759 uint32_t r = generate_random() % 6; 760 sync_interval -= r; 761 DEBUG(5, ("randomised sync interval is %d (-%d)\n", sync_interval, r)); 762 } 763 /* In the case where sync_interval < 5 there is no randomisation */ 764 765 sync_interval_nt = sync_interval * 24LL * 3600LL * 10000000LL; 766 767 DEBUG(5, ("old timestamp is %lld, threshold %lld, diff %lld\n", 768 (long long int)old_timestamp, 769 (long long int)(now - sync_interval_nt), 770 (long long int)(old_timestamp - now + sync_interval_nt))); 771 772 if (old_timestamp > now){ 773 DEBUG(0, ("lastLogonTimestamp is in the future! (%lld > %lld)\n", 774 (long long int)old_timestamp, (long long int)now)); 775 /* then what? */ 776 777 } else if (old_timestamp < now - sync_interval_nt){ 778 DEBUG(5, ("updating lastLogonTimestamp to %lld\n", 779 (long long int)now)); 780 781 /* The time has come to update lastLogonTimestamp */ 782 ret = samdb_msg_add_int64(sam_ctx, msg_mod, msg_mod, 783 "lastLogonTimestamp", now); 784 785 if (ret != LDB_SUCCESS) { 786 TALLOC_FREE(mem_ctx); 787 return NT_STATUS_NO_MEMORY; 788 } 789 } 790 TALLOC_FREE(mem_ctx); 791 return NT_STATUS_OK; 792 } 793 794 795 796 /* Reset the badPwdCount to zero and update the lastLogon time. */ 797 NTSTATUS authsam_logon_success_accounting(struct ldb_context *sam_ctx, 798 const struct ldb_message *msg, 799 struct ldb_dn *domain_dn, 800 bool interactive_or_kerberos) 801 { 802 int ret; 803 NTSTATUS status; 804 int badPwdCount; 805 int64_t lockoutTime; 806 struct ldb_message *msg_mod; 807 TALLOC_CTX *mem_ctx; 808 struct timeval tv_now; 809 NTTIME now; 810 NTTIME lastLogonTimestamp; 811 NTTIME lastLogon; 812 813 lockoutTime = ldb_msg_find_attr_as_int64(msg, "lockoutTime", 0); 814 badPwdCount = ldb_msg_find_attr_as_int(msg, "badPwdCount", 0); 815 lastLogonTimestamp = \ 816 ldb_msg_find_attr_as_int64(msg, "lastLogonTimestamp", 0); 817 lastLogon = ldb_msg_find_attr_as_int64(msg, "lastLogon", 0); 818 819 DEBUG(5, ("lastLogonTimestamp is %lld\n", 820 (long long int)lastLogonTimestamp)); 821 822 mem_ctx = talloc_new(msg); 823 if (mem_ctx == NULL) { 824 return NT_STATUS_NO_MEMORY; 825 } 826 msg_mod = ldb_msg_new(mem_ctx); 827 if (msg_mod == NULL) { 828 TALLOC_FREE(mem_ctx); 829 return NT_STATUS_NO_MEMORY; 830 } 831 msg_mod->dn = msg->dn; 832 833 if (lockoutTime != 0) { 834 /* 835 * This implies "badPwdCount" = 0, see samldb_lockout_time() 836 */ 837 ret = samdb_msg_add_int(sam_ctx, msg_mod, msg_mod, "lockoutTime", 0); 838 if (ret != LDB_SUCCESS) { 839 TALLOC_FREE(mem_ctx); 840 return NT_STATUS_NO_MEMORY; 841 } 842 } else if (badPwdCount != 0) { 843 ret = samdb_msg_add_int(sam_ctx, msg_mod, msg_mod, "badPwdCount", 0); 844 if (ret != LDB_SUCCESS) { 845 TALLOC_FREE(mem_ctx); 846 return NT_STATUS_NO_MEMORY; 847 } 848 } 849 850 tv_now = timeval_current(); 851 now = timeval_to_nttime(&tv_now); 852 853 if (interactive_or_kerberos || lastLogon == 0 || 854 (badPwdCount != 0 && lockoutTime == 0)) { 855 ret = samdb_msg_add_int64(sam_ctx, msg_mod, msg_mod, 856 "lastLogon", now); 857 if (ret != LDB_SUCCESS) { 858 TALLOC_FREE(mem_ctx); 859 return NT_STATUS_NO_MEMORY; 860 } 861 } 862 status = authsam_update_lastlogon_timestamp(sam_ctx, msg_mod, domain_dn, 863 lastLogonTimestamp, now); 864 if (!NT_STATUS_IS_OK(status)) { 865 TALLOC_FREE(mem_ctx); 866 return NT_STATUS_NO_MEMORY; 867 } 868 869 if (msg_mod->num_elements > 0) { 870 ret = dsdb_replace(sam_ctx, msg_mod, 0); 871 if (ret != LDB_SUCCESS) { 872 DEBUG(0, ("Failed to set badPwdCount and lockoutTime " 873 "to 0 and/or lastlogon to now (%lld) " 874 "%s: %s\n", (long long int)now, 875 ldb_dn_get_linearized(msg_mod->dn), 876 ldb_errstring(sam_ctx))); 877 TALLOC_FREE(mem_ctx); 878 return NT_STATUS_INTERNAL_ERROR; 879 } 880 } 881 TALLOC_FREE(mem_ctx); 882 return NT_STATUS_OK; 883 }
Note:
See TracChangeset
for help on using the changeset viewer.