Changeset 745 for trunk/server/source3/winbindd/winbindd_pam.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source3/winbindd/winbindd_pam.c
r599 r745 26 26 #include "winbindd.h" 27 27 #include "../libcli/auth/libcli_auth.h" 28 #include "../librpc/gen_ndr/cli_samr.h" 28 #include "../librpc/gen_ndr/ndr_samr_c.h" 29 #include "rpc_client/cli_pipe.h" 30 #include "rpc_client/cli_samr.h" 31 #include "../librpc/gen_ndr/ndr_netlogon.h" 32 #include "rpc_client/cli_netlogon.h" 29 33 #include "smb_krb5.h" 34 #include "../lib/crypto/arcfour.h" 35 #include "../libcli/security/security.h" 36 #include "ads.h" 37 #include "../librpc/gen_ndr/krb5pac.h" 38 #include "passdb/machine_sid.h" 39 #include "auth.h" 30 40 31 41 #undef DBGC_CLASS … … 35 45 36 46 static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, 37 struct winbindd_ cli_state *state,47 struct winbindd_response *resp, 38 48 struct netr_SamInfo3 *info3) 39 49 { … … 41 51 uint32_t i; 42 52 43 state->response->data.auth.info3.logon_time =53 resp->data.auth.info3.logon_time = 44 54 nt_time_to_unix(info3->base.last_logon); 45 state->response->data.auth.info3.logoff_time =55 resp->data.auth.info3.logoff_time = 46 56 nt_time_to_unix(info3->base.last_logoff); 47 state->response->data.auth.info3.kickoff_time =57 resp->data.auth.info3.kickoff_time = 48 58 nt_time_to_unix(info3->base.acct_expiry); 49 state->response->data.auth.info3.pass_last_set_time =59 resp->data.auth.info3.pass_last_set_time = 50 60 nt_time_to_unix(info3->base.last_password_change); 51 state->response->data.auth.info3.pass_can_change_time =61 resp->data.auth.info3.pass_can_change_time = 52 62 nt_time_to_unix(info3->base.allow_password_change); 53 state->response->data.auth.info3.pass_must_change_time =63 resp->data.auth.info3.pass_must_change_time = 54 64 nt_time_to_unix(info3->base.force_password_change); 55 65 56 state->response->data.auth.info3.logon_count = info3->base.logon_count;57 state->response->data.auth.info3.bad_pw_count = info3->base.bad_password_count;58 59 state->response->data.auth.info3.user_rid = info3->base.rid;60 state->response->data.auth.info3.group_rid = info3->base.primary_gid;61 sid_to_fstring( state->response->data.auth.info3.dom_sid, info3->base.domain_sid);62 63 state->response->data.auth.info3.num_groups = info3->base.groups.count;64 state->response->data.auth.info3.user_flgs = info3->base.user_flags;65 66 state->response->data.auth.info3.acct_flags = info3->base.acct_flags;67 state->response->data.auth.info3.num_other_sids = info3->sidcount;68 69 fstrcpy( state->response->data.auth.info3.user_name,66 resp->data.auth.info3.logon_count = info3->base.logon_count; 67 resp->data.auth.info3.bad_pw_count = info3->base.bad_password_count; 68 69 resp->data.auth.info3.user_rid = info3->base.rid; 70 resp->data.auth.info3.group_rid = info3->base.primary_gid; 71 sid_to_fstring(resp->data.auth.info3.dom_sid, info3->base.domain_sid); 72 73 resp->data.auth.info3.num_groups = info3->base.groups.count; 74 resp->data.auth.info3.user_flgs = info3->base.user_flags; 75 76 resp->data.auth.info3.acct_flags = info3->base.acct_flags; 77 resp->data.auth.info3.num_other_sids = info3->sidcount; 78 79 fstrcpy(resp->data.auth.info3.user_name, 70 80 info3->base.account_name.string); 71 fstrcpy( state->response->data.auth.info3.full_name,81 fstrcpy(resp->data.auth.info3.full_name, 72 82 info3->base.full_name.string); 73 fstrcpy( state->response->data.auth.info3.logon_script,83 fstrcpy(resp->data.auth.info3.logon_script, 74 84 info3->base.logon_script.string); 75 fstrcpy( state->response->data.auth.info3.profile_path,85 fstrcpy(resp->data.auth.info3.profile_path, 76 86 info3->base.profile_path.string); 77 fstrcpy( state->response->data.auth.info3.home_dir,87 fstrcpy(resp->data.auth.info3.home_dir, 78 88 info3->base.home_directory.string); 79 fstrcpy( state->response->data.auth.info3.dir_drive,89 fstrcpy(resp->data.auth.info3.dir_drive, 80 90 info3->base.home_drive.string); 81 91 82 fstrcpy( state->response->data.auth.info3.logon_srv,92 fstrcpy(resp->data.auth.info3.logon_srv, 83 93 info3->base.logon_server.string); 84 fstrcpy( state->response->data.auth.info3.logon_dom,94 fstrcpy(resp->data.auth.info3.logon_dom, 85 95 info3->base.domain.string); 86 96 87 ex = talloc_strdup( state->mem_ctx, "");97 ex = talloc_strdup(mem_ctx, ""); 88 98 NT_STATUS_HAVE_NO_MEMORY(ex); 89 99 … … 109 119 } 110 120 111 state->response->extra_data.data = ex;112 state->response->length += talloc_get_size(ex);121 resp->extra_data.data = ex; 122 resp->length += talloc_get_size(ex); 113 123 114 124 return NT_STATUS_OK; … … 116 126 117 127 static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, 118 struct winbindd_ cli_state *state,128 struct winbindd_response *resp, 119 129 struct netr_SamInfo3 *info3) 120 130 { … … 122 132 enum ndr_err_code ndr_err; 123 133 124 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL,info3,134 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, info3, 125 135 (ndr_push_flags_fn_t)ndr_push_netr_SamInfo3); 126 136 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { … … 129 139 } 130 140 131 state->response->extra_data.data = blob.data;132 state->response->length += blob.length;141 resp->extra_data.data = blob.data; 142 resp->length += blob.length; 133 143 134 144 return NT_STATUS_OK; … … 136 146 137 147 static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx, 138 struct winbindd_ cli_state *state,148 struct winbindd_response *resp, 139 149 const struct netr_SamInfo3 *info3, 140 150 const char *name_domain, … … 160 170 } 161 171 162 fill_domain_username( state->response->data.auth.unix_username,172 fill_domain_username(resp->data.auth.unix_username, 163 173 nt_domain, nt_username, true); 164 174 165 DEBUG(5, ("Setting unix username to [%s]\n",166 state->response->data.auth.unix_username));175 DEBUG(5, ("Setting unix username to [%s]\n", 176 resp->data.auth.unix_username)); 167 177 168 178 return NT_STATUS_OK; … … 170 180 171 181 static NTSTATUS append_afs_token(TALLOC_CTX *mem_ctx, 172 struct winbindd_ cli_state *state,182 struct winbindd_response *resp, 173 183 const struct netr_SamInfo3 *info3, 174 184 const char *name_domain, … … 193 203 194 204 { 195 DOM_SIDuser_sid;205 struct dom_sid user_sid; 196 206 fstring sidstr; 197 207 198 sid_co py(&user_sid, info3->base.domain_sid);199 sid_append_rid(&user_sid,info3->base.rid);208 sid_compose(&user_sid, info3->base.domain_sid, 209 info3->base.rid); 200 210 sid_to_fstring(sidstr, &user_sid); 201 211 afsname = talloc_string_sub(mem_ctx, afsname, … … 224 234 return NT_STATUS_OK; 225 235 } 226 state->response->extra_data.data = talloc_strdup(state->mem_ctx, 227 token); 228 if (state->response->extra_data.data == NULL) { 236 resp->extra_data.data = talloc_strdup(mem_ctx, token); 237 if (resp->extra_data.data == NULL) { 229 238 return NT_STATUS_NO_MEMORY; 230 239 } 231 state->response->length += 232 strlen((const char *)state->response->extra_data.data)+1; 240 resp->length += strlen((const char *)resp->extra_data.data)+1; 233 241 234 242 return NT_STATUS_OK; 235 243 } 236 244 237 NTSTATUS check_info3_in_group(struct netr_SamInfo3 *info3,238 245 static NTSTATUS check_info3_in_group(struct netr_SamInfo3 *info3, 246 const char *group_sid) 239 247 /** 240 248 * Check whether a user belongs to a group or list of groups. … … 249 257 */ 250 258 { 251 DOM_SID*require_membership_of_sid;252 size_t num_require_membership_of_sid;259 struct dom_sid *require_membership_of_sid; 260 uint32_t num_require_membership_of_sid; 253 261 char *req_sid; 254 262 const char *p; 255 DOM_SIDsid;263 struct dom_sid sid; 256 264 size_t i; 257 struct nt_user_token *token;265 struct security_token *token; 258 266 TALLOC_CTX *frame = talloc_stackframe(); 259 267 NTSTATUS status; … … 266 274 } 267 275 268 token = talloc_zero(talloc_tos(), struct nt_user_token);276 token = talloc_zero(talloc_tos(), struct security_token); 269 277 if (token == NULL) { 270 278 DEBUG(0, ("talloc failed\n")); … … 297 305 298 306 status = sid_array_from_info3(talloc_tos(), info3, 299 &token-> user_sids,307 &token->sids, 300 308 &token->num_sids, 301 309 true, false); … … 315 323 } 316 324 317 debug_nt_user_token(DBGC_CLASS, 10, token);325 security_token_debug(DBGC_CLASS, 10, token); 318 326 319 327 for (i=0; i<num_require_membership_of_sid; i++) { … … 349 357 } 350 358 351 if (is_myname(domain_name)) { 352 DEBUG(3, ("Authentication for domain %s (local domain " 353 "to this server) not supported at this " 354 "stage\n", domain_name)); 355 return NULL; 359 if (strequal(domain_name, get_global_sam_name())) { 360 return find_domain_from_name_noinit(domain_name); 356 361 } 357 362 … … 387 392 388 393 static NTSTATUS fillup_password_policy(struct winbindd_domain *domain, 389 struct winbindd_cli_state *state) 394 struct winbindd_response *response) 395 { 396 TALLOC_CTX *frame = talloc_stackframe(); 397 struct winbindd_methods *methods; 398 NTSTATUS status; 399 struct samr_DomInfo1 password_policy; 400 401 if ( !winbindd_can_contact_domain( domain ) ) { 402 DEBUG(5,("fillup_password_policy: No inbound trust to " 403 "contact domain %s\n", domain->name)); 404 status = NT_STATUS_NOT_SUPPORTED; 405 goto done; 406 } 407 408 methods = domain->methods; 409 410 status = methods->password_policy(domain, talloc_tos(), &password_policy); 411 if (NT_STATUS_IS_ERR(status)) { 412 goto done; 413 } 414 415 fill_in_password_policy(response, &password_policy); 416 417 done: 418 TALLOC_FREE(frame); 419 return NT_STATUS_OK; 420 } 421 422 static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain, 423 TALLOC_CTX *mem_ctx, 424 uint16 *lockout_threshold) 425 { 426 struct winbindd_methods *methods; 427 NTSTATUS status = NT_STATUS_UNSUCCESSFUL; 428 struct samr_DomInfo12 lockout_policy; 429 430 *lockout_threshold = 0; 431 432 methods = domain->methods; 433 434 status = methods->lockout_policy(domain, mem_ctx, &lockout_policy); 435 if (NT_STATUS_IS_ERR(status)) { 436 return status; 437 } 438 439 *lockout_threshold = lockout_policy.lockout_threshold; 440 441 return NT_STATUS_OK; 442 } 443 444 static NTSTATUS get_pwd_properties(struct winbindd_domain *domain, 445 TALLOC_CTX *mem_ctx, 446 uint32 *password_properties) 390 447 { 391 448 struct winbindd_methods *methods; … … 393 450 struct samr_DomInfo1 password_policy; 394 451 395 if ( !winbindd_can_contact_domain( domain ) ) {396 DEBUG(5,("fillup_password_policy: No inbound trust to "397 "contact domain %s\n", domain->name));398 return NT_STATUS_NOT_SUPPORTED;399 }400 401 methods = domain->methods;402 403 status = methods->password_policy(domain, state->mem_ctx, &password_policy);404 if (NT_STATUS_IS_ERR(status)) {405 return status;406 }407 408 fill_in_password_policy(state->response, &password_policy);409 410 return NT_STATUS_OK;411 }412 413 static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain,414 TALLOC_CTX *mem_ctx,415 uint16 *lockout_threshold)416 {417 struct winbindd_methods *methods;418 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;419 struct samr_DomInfo12 lockout_policy;420 421 *lockout_threshold = 0;422 423 methods = domain->methods;424 425 status = methods->lockout_policy(domain, mem_ctx, &lockout_policy);426 if (NT_STATUS_IS_ERR(status)) {427 return status;428 }429 430 *lockout_threshold = lockout_policy.lockout_threshold;431 432 return NT_STATUS_OK;433 }434 435 static NTSTATUS get_pwd_properties(struct winbindd_domain *domain,436 TALLOC_CTX *mem_ctx,437 uint32 *password_properties)438 {439 struct winbindd_methods *methods;440 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;441 struct samr_DomInfo1 password_policy;442 443 452 *password_properties = 0; 444 453 … … 460 469 const char *type, 461 470 uid_t uid, 462 bool *internal_ccache)471 const char **user_ccache_file) 463 472 { 464 473 /* accept FILE and WRFILE as krb5_cc_type from the client and then … … 468 477 const char *gen_cc = NULL; 469 478 470 *internal_ccache = true; 471 472 if (uid == -1) { 473 goto memory_ccache; 474 } 475 476 if (!type || type[0] == '\0') { 477 goto memory_ccache; 478 } 479 480 if (strequal(type, "FILE")) { 481 gen_cc = talloc_asprintf(mem_ctx, "FILE:/tmp/krb5cc_%d", uid); 482 } else if (strequal(type, "WRFILE")) { 483 gen_cc = talloc_asprintf(mem_ctx, "WRFILE:/tmp/krb5cc_%d", uid); 484 } else { 485 DEBUG(10,("we don't allow to set a %s type ccache\n", type)); 486 goto memory_ccache; 487 } 488 489 *internal_ccache = false; 490 goto done; 491 492 memory_ccache: 493 gen_cc = talloc_strdup(mem_ctx, "MEMORY:winbindd_pam_ccache"); 494 495 done: 479 if (uid != -1) { 480 if (strequal(type, "FILE")) { 481 gen_cc = talloc_asprintf( 482 mem_ctx, "FILE:/tmp/krb5cc_%d", uid); 483 } 484 if (strequal(type, "WRFILE")) { 485 gen_cc = talloc_asprintf( 486 mem_ctx, "WRFILE:/tmp/krb5cc_%d", uid); 487 } 488 } 489 490 *user_ccache_file = gen_cc; 491 492 if (gen_cc == NULL) { 493 gen_cc = talloc_strdup(mem_ctx, "MEMORY:winbindd_pam_ccache"); 494 } 496 495 if (gen_cc == NULL) { 497 496 DEBUG(0,("out of memory\n")); … … 499 498 } 500 499 501 DEBUG(10,("using ccache: %s %s\n", gen_cc, *internal_ccache ? "(internal)":"")); 500 DEBUG(10, ("using ccache: %s%s\n", gen_cc, 501 (*user_ccache_file == NULL) ? " (internal)":"")); 502 502 503 503 return gen_cc; 504 504 } 505 505 506 static void setup_return_cc_name(struct winbindd_cli_state *state, const char *cc)507 {508 const char *type = state->request->data.auth.krb5_cc_type;509 510 state->response->data.auth.krb5ccname[0] = '\0';511 512 if (type[0] == '\0') {513 return;514 }515 516 if (!strequal(type, "FILE") &&517 !strequal(type, "WRFILE")) {518 DEBUG(10,("won't return krbccname for a %s type ccache\n",519 type));520 return;521 }522 523 fstrcpy(state->response->data.auth.krb5ccname, cc);524 }525 526 506 #endif 527 507 528 static uid_t get_uid_from_state(struct winbindd_cli_state *state)508 uid_t get_uid_from_request(struct winbindd_request *request) 529 509 { 530 510 uid_t uid; 531 511 532 uid = state->request->data.auth.uid;512 uid = request->data.auth.uid; 533 513 534 514 if (uid < 0) { … … 544 524 **********************************************************************/ 545 525 546 static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, 547 struct winbindd_cli_state *state, 548 struct netr_SamInfo3 **info3) 526 static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx, 527 struct winbindd_domain *domain, 528 const char *user, 529 const char *pass, 530 const char *krb5_cc_type, 531 uid_t uid, 532 struct netr_SamInfo3 **info3, 533 fstring krb5ccname) 549 534 { 550 535 #ifdef HAVE_KRB5 … … 558 543 time_t ticket_lifetime = 0; 559 544 time_t renewal_until = 0; 560 uid_t uid = -1;561 545 ADS_STRUCT *ads; 562 546 time_t time_offset = 0; 563 bool internal_ccache = true; 564 565 ZERO_STRUCTP(info3); 547 const char *user_ccache_file; 548 struct PAC_LOGON_INFO *logon_info = NULL; 566 549 567 550 *info3 = NULL; … … 570 553 * prepare a krb5_cc_cache string for the user */ 571 554 572 uid = get_uid_from_state(state);573 555 if (uid == -1) { 574 556 DEBUG(0,("no valid uid\n")); 575 557 } 576 558 577 cc = generate_krb5_ccache( state->mem_ctx,578 state->request->data.auth.krb5_cc_type,579 state->request->data.auth.uid,580 & internal_ccache);559 cc = generate_krb5_ccache(mem_ctx, 560 krb5_cc_type, 561 uid, 562 &user_ccache_file); 581 563 if (cc == NULL) { 582 564 return NT_STATUS_NO_MEMORY; … … 596 578 * do kerberos auth and setup ccache as the user */ 597 579 598 parse_domain_user( state->request->data.auth.user, name_domain, name_user);580 parse_domain_user(user, name_domain, name_user); 599 581 600 582 realm = domain->alt_name; 601 583 strupper_m(realm); 602 584 603 principal_s = talloc_asprintf( state->mem_ctx, "%s@%s", name_user, realm);585 principal_s = talloc_asprintf(mem_ctx, "%s@%s", name_user, realm); 604 586 if (principal_s == NULL) { 605 587 return NT_STATUS_NO_MEMORY; 606 588 } 607 589 608 service = talloc_asprintf( state->mem_ctx, "%s/%s@%s", KRB5_TGS_NAME, realm, realm);590 service = talloc_asprintf(mem_ctx, "%s/%s@%s", KRB5_TGS_NAME, realm, realm); 609 591 if (service == NULL) { 610 592 return NT_STATUS_NO_MEMORY; … … 616 598 /************************ ENTERING NON-ROOT **********************/ 617 599 618 if ( !internal_ccache) {600 if (user_ccache_file != NULL) { 619 601 set_effective_uid(uid); 620 602 DEBUG(10,("winbindd_raw_kerberos_login: uid is %d\n", uid)); 621 603 } 622 604 623 result = kerberos_return_ info3_from_pac(state->mem_ctx,624 625 state->request->data.auth.pass,626 627 628 629 630 631 632 633 634 info3);635 if ( !internal_ccache) {605 result = kerberos_return_pac(mem_ctx, 606 principal_s, 607 pass, 608 time_offset, 609 &ticket_lifetime, 610 &renewal_until, 611 cc, 612 true, 613 true, 614 WINBINDD_PAM_AUTH_KRB5_RENEW_TIME, 615 NULL, 616 &logon_info); 617 if (user_ccache_file != NULL) { 636 618 gain_root_privilege(); 637 619 } … … 643 625 } 644 626 627 *info3 = &logon_info->info3; 628 645 629 DEBUG(10,("winbindd_raw_kerberos_login: winbindd validated ticket of %s\n", 646 630 principal_s)); … … 649 633 * environment */ 650 634 651 if ( !internal_ccache) {652 653 setup_return_cc_name(state, cc);635 if (user_ccache_file != NULL) { 636 637 fstrcpy(krb5ccname, user_ccache_file); 654 638 655 639 result = add_ccache_to_list(principal_s, 656 640 cc, 657 641 service, 658 state->request->data.auth.user,642 user, 659 643 realm, 660 644 uid, … … 697 681 } 698 682 699 if (!NT_STATUS_IS_OK(remove_ccache( state->request->data.auth.user))) {683 if (!NT_STATUS_IS_OK(remove_ccache(user))) { 700 684 DEBUG(3,("winbindd_raw_kerberos_login: " 701 685 "could not remove ccache for user %s\n", 702 state->request->data.auth.user));686 user)); 703 687 } 704 688 … … 734 718 ****************************************************************/ 735 719 736 NTSTATUS append_auth_data(struct winbindd_cli_state *state, 737 struct netr_SamInfo3 *info3, 738 const char *name_domain, 739 const char *name_user) 720 static NTSTATUS append_auth_data(TALLOC_CTX *mem_ctx, 721 struct winbindd_response *resp, 722 uint32_t request_flags, 723 struct netr_SamInfo3 *info3, 724 const char *name_domain, 725 const char *name_user) 740 726 { 741 727 NTSTATUS result; 742 uint32_t flags = state->request->flags; 743 744 if (flags & WBFLAG_PAM_USER_SESSION_KEY) { 745 memcpy(state->response->data.auth.user_session_key, 728 729 if (request_flags & WBFLAG_PAM_USER_SESSION_KEY) { 730 memcpy(resp->data.auth.user_session_key, 746 731 info3->base.key.key, 747 sizeof( state->response->data.auth.user_session_key)732 sizeof(resp->data.auth.user_session_key) 748 733 /* 16 */); 749 734 } 750 735 751 if ( flags & WBFLAG_PAM_LMKEY) {752 memcpy( state->response->data.auth.first_8_lm_hash,736 if (request_flags & WBFLAG_PAM_LMKEY) { 737 memcpy(resp->data.auth.first_8_lm_hash, 753 738 info3->base.LMSessKey.key, 754 sizeof( state->response->data.auth.first_8_lm_hash)739 sizeof(resp->data.auth.first_8_lm_hash) 755 740 /* 8 */); 756 741 } 757 742 758 if (flags & WBFLAG_PAM_INFO3_TEXT) { 759 result = append_info3_as_txt(state->mem_ctx, state, info3); 743 if (request_flags & WBFLAG_PAM_UNIX_NAME) { 744 result = append_unix_username(mem_ctx, resp, 745 info3, name_domain, name_user); 746 if (!NT_STATUS_IS_OK(result)) { 747 DEBUG(10,("Failed to append Unix Username: %s\n", 748 nt_errstr(result))); 749 return result; 750 } 751 } 752 753 /* currently, anything from here on potentially overwrites extra_data. */ 754 755 if (request_flags & WBFLAG_PAM_INFO3_NDR) { 756 result = append_info3_as_ndr(mem_ctx, resp, info3); 757 if (!NT_STATUS_IS_OK(result)) { 758 DEBUG(10,("Failed to append INFO3 (NDR): %s\n", 759 nt_errstr(result))); 760 return result; 761 } 762 } 763 764 if (request_flags & WBFLAG_PAM_INFO3_TEXT) { 765 result = append_info3_as_txt(mem_ctx, resp, info3); 760 766 if (!NT_STATUS_IS_OK(result)) { 761 767 DEBUG(10,("Failed to append INFO3 (TXT): %s\n", … … 765 771 } 766 772 767 /* currently, anything from here on potentially overwrites extra_data. */ 768 769 if (flags & WBFLAG_PAM_INFO3_NDR) { 770 result = append_info3_as_ndr(state->mem_ctx, state, info3); 771 if (!NT_STATUS_IS_OK(result)) { 772 DEBUG(10,("Failed to append INFO3 (NDR): %s\n", 773 nt_errstr(result))); 774 return result; 775 } 776 } 777 778 if (flags & WBFLAG_PAM_UNIX_NAME) { 779 result = append_unix_username(state->mem_ctx, state, info3, 780 name_domain, name_user); 781 if (!NT_STATUS_IS_OK(result)) { 782 DEBUG(10,("Failed to append Unix Username: %s\n", 783 nt_errstr(result))); 784 return result; 785 } 786 } 787 788 if (flags & WBFLAG_PAM_AFS_TOKEN) { 789 result = append_afs_token(state->mem_ctx, state, info3, 790 name_domain, name_user); 773 if (request_flags & WBFLAG_PAM_AFS_TOKEN) { 774 result = append_afs_token(mem_ctx, resp, 775 info3, name_domain, name_user); 791 776 if (!NT_STATUS_IS_OK(result)) { 792 777 DEBUG(10,("Failed to append AFS token: %s\n", … … 799 784 } 800 785 801 void winbindd_pam_auth(struct winbindd_cli_state *state)802 {803 struct winbindd_domain *domain;804 fstring name_domain, name_user;805 char *mapped = NULL;806 NTSTATUS result;807 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;808 809 /* Ensure null termination */810 state->request->data.auth.user811 [sizeof(state->request->data.auth.user)-1]='\0';812 813 /* Ensure null termination */814 state->request->data.auth.pass815 [sizeof(state->request->data.auth.pass)-1]='\0';816 817 DEBUG(3, ("[%5lu]: pam auth %s\n", (unsigned long)state->pid,818 state->request->data.auth.user));819 820 if (!check_request_flags(state->request->flags)) {821 result = NT_STATUS_INVALID_PARAMETER_MIX;822 goto done;823 }824 825 /* Parse domain and username */826 827 name_map_status = normalize_name_unmap(state->mem_ctx,828 state->request->data.auth.user,829 &mapped);830 831 /* Update the auth name if we did any mapping */832 833 if (NT_STATUS_IS_OK(name_map_status) ||834 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))835 {836 fstrcpy(state->request->data.auth.user, mapped);837 }838 839 if (!canonicalize_username(state->request->data.auth.user, name_domain, name_user)) {840 result = NT_STATUS_NO_SUCH_USER;841 goto done;842 }843 844 domain = find_auth_domain(state->request->flags, name_domain);845 846 if (domain == NULL) {847 result = NT_STATUS_NO_SUCH_USER;848 goto done;849 }850 851 sendto_domain(state, domain);852 return;853 done:854 set_auth_errors(state->response, result);855 DEBUG(5, ("Plain text authentication for %s returned %s "856 "(PAM: %d)\n",857 state->request->data.auth.user,858 state->response->data.auth.nt_status_string,859 state->response->data.auth.pam_error));860 request_error(state);861 }862 863 786 static NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain, 864 787 struct winbindd_cli_state *state, … … 868 791 uint16 max_allowed_bad_attempts; 869 792 fstring name_domain, name_user; 870 DOM_SIDsid;793 struct dom_sid sid; 871 794 enum lsa_SidType type; 872 795 uchar new_nt_pass[NT_HASH_LEN]; … … 891 814 892 815 893 if (!lookup_cached_name(state->mem_ctx, 894 name_domain, 816 if (!lookup_cached_name(name_domain, 895 817 name_user, 896 818 &sid, … … 998 920 const char *principal_s = NULL; 999 921 const char *service = NULL; 1000 bool internal_ccache = false;1001 1002 uid = get_uid_from_ state(state);922 const char *user_ccache_file; 923 924 uid = get_uid_from_request(state->request); 1003 925 if (uid == -1) { 1004 926 DEBUG(0,("winbindd_dual_pam_auth_cached: invalid uid\n")); … … 1009 931 state->request->data.auth.krb5_cc_type, 1010 932 state->request->data.auth.uid, 1011 & internal_ccache);933 &user_ccache_file); 1012 934 if (cc == NULL) { 1013 935 return NT_STATUS_NO_MEMORY; … … 1027 949 } 1028 950 1029 if (!internal_ccache) { 1030 1031 setup_return_cc_name(state, cc); 951 if (user_ccache_file != NULL) { 952 953 fstrcpy(state->response->data.auth.krb5ccname, 954 user_ccache_file); 1032 955 1033 956 result = add_ccache_to_list(principal_s, … … 1058 981 1059 982 result = winbindd_update_creds_by_info3(domain, 1060 state->mem_ctx,1061 983 state->request->data.auth.user, 1062 984 state->request->data.auth.pass, … … 1101 1023 } 1102 1024 1103 if ((my_info3->base.rid != DOMAIN_ USER_RID_ADMIN) ||1025 if ((my_info3->base.rid != DOMAIN_RID_ADMINISTRATOR) || 1104 1026 (password_properties & DOMAIN_PASSWORD_LOCKOUT_ADMINS)) { 1105 1027 my_info3->base.acct_flags |= ACB_AUTOLOCK; … … 1109 1031 failed: 1110 1032 result = winbindd_update_creds_by_info3(domain, 1111 state->mem_ctx,1112 1033 state->request->data.auth.user, 1113 1034 NULL, … … 1176 1097 } 1177 1098 try_login: 1178 result = winbindd_raw_kerberos_login(contact_domain, state, info3); 1099 result = winbindd_raw_kerberos_login( 1100 state->mem_ctx, contact_domain, 1101 state->request->data.auth.user, 1102 state->request->data.auth.pass, 1103 state->request->data.auth.krb5_cc_type, 1104 get_uid_from_request(state->request), 1105 info3, state->response->data.auth.krb5ccname); 1179 1106 done: 1180 1107 return result; 1181 1108 } 1182 1109 1183 typedef NTSTATUS (*netlogon_fn_t)(struct rpc_pipe_client *cli, 1184 TALLOC_CTX *mem_ctx, 1185 uint32 logon_parameters, 1186 const char *server, 1187 const char *username, 1188 const char *domain, 1189 const char *workstation, 1190 const uint8 chal[8], 1191 uint16_t validation_level, 1192 DATA_BLOB lm_response, 1193 DATA_BLOB nt_response, 1194 struct netr_SamInfo3 **info3); 1195 1196 static NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, 1197 struct winbindd_cli_state *state, 1198 struct netr_SamInfo3 **info3) 1199 { 1200 1201 struct rpc_pipe_client *netlogon_pipe; 1202 uchar chal[8]; 1203 DATA_BLOB lm_resp; 1204 DATA_BLOB nt_resp; 1110 static NTSTATUS winbindd_dual_auth_passdb(TALLOC_CTX *mem_ctx, 1111 const char *domain, const char *user, 1112 const DATA_BLOB *challenge, 1113 const DATA_BLOB *lm_resp, 1114 const DATA_BLOB *nt_resp, 1115 struct netr_SamInfo3 **pinfo3) 1116 { 1117 struct auth_usersupplied_info *user_info = NULL; 1118 NTSTATUS status; 1119 1120 status = make_user_info(&user_info, user, user, domain, domain, 1121 global_myname(), lm_resp, nt_resp, NULL, NULL, 1122 NULL, AUTH_PASSWORD_RESPONSE); 1123 if (!NT_STATUS_IS_OK(status)) { 1124 DEBUG(10, ("make_user_info failed: %s\n", nt_errstr(status))); 1125 return status; 1126 } 1127 1128 /* We don't want any more mapping of the username */ 1129 user_info->mapped_state = True; 1130 1131 status = check_sam_security_info3(challenge, talloc_tos(), user_info, 1132 pinfo3); 1133 free_user_info(&user_info); 1134 DEBUG(10, ("Authenticaticating user %s\\%s returned %s\n", domain, 1135 user, nt_errstr(status))); 1136 return status; 1137 } 1138 1139 static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, 1140 TALLOC_CTX *mem_ctx, 1141 uint32_t logon_parameters, 1142 const char *server, 1143 const char *username, 1144 const char *domainname, 1145 const char *workstation, 1146 const uint8_t chal[8], 1147 DATA_BLOB lm_response, 1148 DATA_BLOB nt_response, 1149 struct netr_SamInfo3 **info3) 1150 { 1205 1151 int attempts = 0; 1206 unsigned char local_lm_response[24]; 1207 unsigned char local_nt_response[24]; 1208 struct winbindd_domain *contact_domain; 1209 fstring name_domain, name_user; 1210 bool retry; 1152 bool retry = false; 1211 1153 NTSTATUS result; 1212 struct netr_SamInfo3 *my_info3 = NULL;1213 1214 *info3 = NULL;1215 1216 DEBUG(10,("winbindd_dual_pam_auth_samlogon\n"));1217 1218 /* Parse domain and username */1219 1220 parse_domain_user(state->request->data.auth.user, name_domain, name_user);1221 1222 /* do password magic */1223 1224 1225 generate_random_buffer(chal, 8);1226 if (lp_client_ntlmv2_auth()) {1227 DATA_BLOB server_chal;1228 DATA_BLOB names_blob;1229 DATA_BLOB nt_response;1230 DATA_BLOB lm_response;1231 server_chal = data_blob_talloc(state->mem_ctx, chal, 8);1232 1233 /* note that the 'workgroup' here is a best guess - we don't know1234 the server's domain at this point. The 'server name' is also1235 dodgy...1236 */1237 names_blob = NTLMv2_generate_names_blob(state->mem_ctx, global_myname(), lp_workgroup());1238 1239 if (!SMBNTLMv2encrypt(NULL, name_user, name_domain,1240 state->request->data.auth.pass,1241 &server_chal,1242 &names_blob,1243 &lm_response, &nt_response, NULL, NULL)) {1244 data_blob_free(&names_blob);1245 data_blob_free(&server_chal);1246 DEBUG(0, ("winbindd_pam_auth: SMBNTLMv2encrypt() failed!\n"));1247 result = NT_STATUS_NO_MEMORY;1248 goto done;1249 }1250 data_blob_free(&names_blob);1251 data_blob_free(&server_chal);1252 lm_resp = data_blob_talloc(state->mem_ctx, lm_response.data,1253 lm_response.length);1254 nt_resp = data_blob_talloc(state->mem_ctx, nt_response.data,1255 nt_response.length);1256 data_blob_free(&lm_response);1257 data_blob_free(&nt_response);1258 1259 } else {1260 if (lp_client_lanman_auth()1261 && SMBencrypt(state->request->data.auth.pass,1262 chal,1263 local_lm_response)) {1264 lm_resp = data_blob_talloc(state->mem_ctx,1265 local_lm_response,1266 sizeof(local_lm_response));1267 } else {1268 lm_resp = data_blob_null;1269 }1270 SMBNTencrypt(state->request->data.auth.pass,1271 chal,1272 local_nt_response);1273 1274 nt_resp = data_blob_talloc(state->mem_ctx,1275 local_nt_response,1276 sizeof(local_nt_response));1277 }1278 1279 /* what domain should we contact? */1280 1281 if ( IS_DC ) {1282 if (!(contact_domain = find_domain_from_name(name_domain))) {1283 DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",1284 state->request->data.auth.user, name_domain, name_user, name_domain));1285 result = NT_STATUS_NO_SUCH_USER;1286 goto done;1287 }1288 1289 } else {1290 if (is_myname(name_domain)) {1291 DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain));1292 result = NT_STATUS_NO_SUCH_USER;1293 goto done;1294 }1295 1296 contact_domain = find_our_domain();1297 }1298 1299 /* check authentication loop */1300 1154 1301 1155 do { 1302 netlogon_fn_t logon_fn;1303 const struct cli_pipe_auth_data *auth;1156 struct rpc_pipe_client *netlogon_pipe; 1157 const struct pipe_auth_data *auth; 1304 1158 uint32_t neg_flags = 0; 1305 1159 1306 ZERO_STRUCTP( my_info3);1160 ZERO_STRUCTP(info3); 1307 1161 retry = false; 1308 1162 1309 result = cm_connect_netlogon( contact_domain, &netlogon_pipe);1163 result = cm_connect_netlogon(domain, &netlogon_pipe); 1310 1164 1311 1165 if (!NT_STATUS_IS_OK(result)) { 1312 DEBUG(3, ("could not open handle to NETLOGON pipe\n")); 1313 goto done; 1166 DEBUG(3,("could not open handle to NETLOGON pipe (error: %s)\n", 1167 nt_errstr(result))); 1168 return result; 1314 1169 } 1315 1170 auth = netlogon_pipe->auth; … … 1348 1203 * NETLOGON_NEG_AUTHENTICATED_RPC set together 1349 1204 * are the indication that the server supports 1350 * NetlogonValidationSamInfo4 (6). And must only1205 * NetlogonValidationSamInfo4 (6). And it must only 1351 1206 * be used if "SealSecureChannel" is used. 1352 1207 * … … 1356 1211 if (auth == NULL) { 1357 1212 domain->can_do_validation6 = false; 1358 } else if (auth->auth_type != PIPE_AUTH_TYPE_SCHANNEL) {1213 } else if (auth->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { 1359 1214 domain->can_do_validation6 = false; 1360 1215 } else if (auth->auth_level != DCERPC_AUTH_LEVEL_PRIVACY) { … … 1366 1221 } 1367 1222 1368 logon_fn = contact_domain->can_do_samlogon_ex 1369 ? rpccli_netlogon_sam_network_logon_ex 1370 : rpccli_netlogon_sam_network_logon; 1371 1372 result = logon_fn(netlogon_pipe, 1373 state->mem_ctx, 1374 0, 1375 contact_domain->dcname, /* server name */ 1376 name_user, /* user name */ 1377 name_domain, /* target domain */ 1378 global_myname(), /* workstation */ 1379 chal, 1380 domain->can_do_validation6 ? 6 : 3, 1381 lm_resp, 1382 nt_resp, 1383 &my_info3); 1384 1385 if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) 1386 && contact_domain->can_do_samlogon_ex) { 1387 DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " 1388 "retrying with NetSamLogon\n")); 1389 contact_domain->can_do_samlogon_ex = false; 1223 if (domain->can_do_samlogon_ex) { 1224 result = rpccli_netlogon_sam_network_logon_ex( 1225 netlogon_pipe, 1226 mem_ctx, 1227 0, 1228 server, /* server name */ 1229 username, /* user name */ 1230 domainname, /* target domain */ 1231 workstation, /* workstation */ 1232 chal, 1233 domain->can_do_validation6 ? 6 : 3, 1234 lm_response, 1235 nt_response, 1236 info3); 1237 } else { 1238 result = rpccli_netlogon_sam_network_logon( 1239 netlogon_pipe, 1240 mem_ctx, 1241 0, 1242 server, /* server name */ 1243 username, /* user name */ 1244 domainname, /* target domain */ 1245 workstation, /* workstation */ 1246 chal, 1247 domain->can_do_validation6 ? 6 : 3, 1248 lm_response, 1249 nt_response, 1250 info3); 1251 } 1252 1253 if (NT_STATUS_EQUAL(result, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { 1254 1390 1255 /* 1391 1256 * It's likely that the server also does not support … … 1393 1258 */ 1394 1259 domain->can_do_validation6 = false; 1395 retry = true; 1396 continue; 1260 1261 if (domain->can_do_samlogon_ex) { 1262 DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " 1263 "retrying with NetSamLogon\n")); 1264 domain->can_do_samlogon_ex = false; 1265 retry = true; 1266 continue; 1267 } 1268 1269 1270 /* Got DCERPC_FAULT_OP_RNG_ERROR for SamLogon 1271 * (no Ex). This happens against old Samba 1272 * DCs. Drop the connection. 1273 */ 1274 invalidate_cm_connection(&domain->conn); 1275 result = NT_STATUS_LOGON_FAILURE; 1276 break; 1397 1277 } 1398 1278 … … 1433 1313 "password was changed and we didn't know it. " 1434 1314 "Killing connections to domain %s\n", 1435 name_domain));1436 invalidate_cm_connection(& contact_domain->conn);1315 domainname)); 1316 invalidate_cm_connection(&domain->conn); 1437 1317 retry = true; 1438 1318 } 1439 1319 1440 1320 } while ( (attempts < 2) && retry ); 1321 1322 return result; 1323 } 1324 1325 static NTSTATUS winbindd_dual_pam_auth_samlogon(TALLOC_CTX *mem_ctx, 1326 struct winbindd_domain *domain, 1327 const char *user, 1328 const char *pass, 1329 uint32_t request_flags, 1330 struct netr_SamInfo3 **info3) 1331 { 1332 1333 uchar chal[8]; 1334 DATA_BLOB lm_resp; 1335 DATA_BLOB nt_resp; 1336 unsigned char local_nt_response[24]; 1337 fstring name_domain, name_user; 1338 NTSTATUS result; 1339 struct netr_SamInfo3 *my_info3 = NULL; 1340 1341 *info3 = NULL; 1342 1343 DEBUG(10,("winbindd_dual_pam_auth_samlogon\n")); 1344 1345 /* Parse domain and username */ 1346 1347 parse_domain_user(user, name_domain, name_user); 1348 1349 /* do password magic */ 1350 1351 generate_random_buffer(chal, sizeof(chal)); 1352 1353 if (lp_client_ntlmv2_auth()) { 1354 DATA_BLOB server_chal; 1355 DATA_BLOB names_blob; 1356 server_chal = data_blob_const(chal, 8); 1357 1358 /* note that the 'workgroup' here is for the local 1359 machine. The 'server name' must match the 1360 'workstation' passed to the actual SamLogon call. 1361 */ 1362 names_blob = NTLMv2_generate_names_blob( 1363 mem_ctx, global_myname(), lp_workgroup()); 1364 1365 if (!SMBNTLMv2encrypt(mem_ctx, name_user, name_domain, 1366 pass, 1367 &server_chal, 1368 &names_blob, 1369 &lm_resp, &nt_resp, NULL, NULL)) { 1370 data_blob_free(&names_blob); 1371 DEBUG(0, ("winbindd_pam_auth: SMBNTLMv2encrypt() failed!\n")); 1372 result = NT_STATUS_NO_MEMORY; 1373 goto done; 1374 } 1375 data_blob_free(&names_blob); 1376 } else { 1377 lm_resp = data_blob_null; 1378 SMBNTencrypt(pass, chal, local_nt_response); 1379 1380 nt_resp = data_blob_talloc(mem_ctx, local_nt_response, 1381 sizeof(local_nt_response)); 1382 } 1383 1384 if (strequal(name_domain, get_global_sam_name())) { 1385 DATA_BLOB chal_blob = data_blob_const(chal, sizeof(chal)); 1386 1387 result = winbindd_dual_auth_passdb( 1388 mem_ctx, name_domain, name_user, 1389 &chal_blob, &lm_resp, &nt_resp, info3); 1390 goto done; 1391 } 1392 1393 /* check authentication loop */ 1394 1395 result = winbind_samlogon_retry_loop(domain, 1396 mem_ctx, 1397 0, 1398 domain->dcname, 1399 name_user, 1400 name_domain, 1401 global_myname(), 1402 chal, 1403 lm_resp, 1404 nt_resp, 1405 &my_info3); 1406 if (!NT_STATUS_IS_OK(result)) { 1407 goto done; 1408 } 1441 1409 1442 1410 /* handle the case where a NT4 DC does not fill in the acct_flags in … … 1444 1412 * caller, we look up the account flags ourselve - gd */ 1445 1413 1446 if (( state->request->flags & WBFLAG_PAM_INFO3_TEXT) &&1414 if ((request_flags & WBFLAG_PAM_INFO3_TEXT) && 1447 1415 NT_STATUS_IS_OK(result) && (my_info3->base.acct_flags == 0)) { 1448 1416 … … 1450 1418 struct policy_handle samr_domain_handle, user_pol; 1451 1419 union samr_UserInfo *info = NULL; 1452 NTSTATUS status_tmp ;1420 NTSTATUS status_tmp, result_tmp; 1453 1421 uint32 acct_flags; 1454 1455 status_tmp = cm_connect_sam(contact_domain, state->mem_ctx, 1422 struct dcerpc_binding_handle *b; 1423 1424 status_tmp = cm_connect_sam(domain, mem_ctx, 1456 1425 &samr_pipe, &samr_domain_handle); 1457 1426 … … 1462 1431 } 1463 1432 1464 status_tmp = rpccli_samr_OpenUser(samr_pipe, state->mem_ctx, 1433 b = samr_pipe->binding_handle; 1434 1435 status_tmp = dcerpc_samr_OpenUser(b, mem_ctx, 1465 1436 &samr_domain_handle, 1466 1437 MAXIMUM_ALLOWED_ACCESS, 1467 1438 my_info3->base.rid, 1468 &user_pol); 1439 &user_pol, 1440 &result_tmp); 1469 1441 1470 1442 if (!NT_STATUS_IS_OK(status_tmp)) { … … 1473 1445 goto done; 1474 1446 } 1475 1476 status_tmp = rpccli_samr_QueryUserInfo(samr_pipe, state->mem_ctx, 1447 if (!NT_STATUS_IS_OK(result_tmp)) { 1448 DEBUG(3, ("could not open user handle on SAMR pipe: %s\n", 1449 nt_errstr(result_tmp))); 1450 goto done; 1451 } 1452 1453 status_tmp = dcerpc_samr_QueryUserInfo(b, mem_ctx, 1477 1454 &user_pol, 1478 1455 16, 1479 &info); 1456 &info, 1457 &result_tmp); 1480 1458 1481 1459 if (!NT_STATUS_IS_OK(status_tmp)) { 1482 1460 DEBUG(3, ("could not query user info on SAMR pipe: %s\n", 1483 1461 nt_errstr(status_tmp))); 1484 rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol);1462 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result_tmp); 1485 1463 goto done; 1486 1464 } 1465 if (!NT_STATUS_IS_OK(result_tmp)) { 1466 DEBUG(3, ("could not query user info on SAMR pipe: %s\n", 1467 nt_errstr(result_tmp))); 1468 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result_tmp); 1469 goto done; 1470 } 1487 1471 1488 1472 acct_flags = info->info16.acct_flags; 1489 1473 1490 1474 if (acct_flags == 0) { 1491 rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol);1475 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result_tmp); 1492 1476 goto done; 1493 1477 } … … 1497 1481 DEBUG(10,("successfully retrieved acct_flags 0x%x\n", acct_flags)); 1498 1482 1499 rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol);1483 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result_tmp); 1500 1484 } 1501 1485 … … 1525 1509 state->request->data.auth.user)); 1526 1510 1527 if (!check_request_flags(state->request->flags)) {1528 result = NT_STATUS_INVALID_PARAMETER_MIX;1529 goto done;1530 }1531 1532 1511 /* Parse domain and username */ 1533 1512 … … 1548 1527 1549 1528 if ( mapped_user != state->request->data.auth.user ) { 1550 fstr_sprintf( domain_user, "%s\\%s", name_domain, name_user ); 1529 fstr_sprintf( domain_user, "%s%c%s", name_domain, 1530 *lp_winbind_separator(), 1531 name_user ); 1551 1532 safe_strcpy( state->request->data.auth.user, domain_user, 1552 1533 sizeof(state->request->data.auth.user)-1 ); 1553 1534 } 1554 1535 1555 if ( domain->online == false) {1536 if (!domain->online) { 1556 1537 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; 1557 1538 if (domain->startup) { … … 1607 1588 NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_MUST_CHANGE) || 1608 1589 NT_STATUS_EQUAL(result, NT_STATUS_WRONG_PASSWORD)) { 1609 goto process_result;1590 goto done; 1610 1591 } 1611 1592 … … 1621 1602 /* Check for Samlogon authentication */ 1622 1603 if (domain->online) { 1623 result = winbindd_dual_pam_auth_samlogon(domain, state, &info3); 1604 result = winbindd_dual_pam_auth_samlogon( 1605 state->mem_ctx, domain, 1606 state->request->data.auth.user, 1607 state->request->data.auth.pass, 1608 state->request->flags, 1609 &info3); 1624 1610 1625 1611 if (NT_STATUS_IS_OK(result)) { … … 1670 1656 if (NT_STATUS_IS_OK(result)) { 1671 1657 1672 DOM_SIDuser_sid;1658 struct dom_sid user_sid; 1673 1659 1674 1660 /* In all codepaths where result == NT_STATUS_OK info3 must have … … 1679 1665 } 1680 1666 1681 wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3); 1667 sid_compose(&user_sid, info3->base.domain_sid, 1668 info3->base.rid); 1669 1670 wcache_invalidate_samlogon(find_domain_from_name(name_domain), 1671 &user_sid); 1682 1672 netsamlogon_cache_store(name_user, info3); 1683 1673 … … 1687 1677 domain). */ 1688 1678 if ( domain->primary ) { 1689 sid_compose(&user_sid, info3->base.domain_sid,1690 info3->base.rid);1691 1679 cache_name2sid(domain, name_domain, name_user, 1692 1680 SID_NAME_USER, &user_sid); … … 1705 1693 } 1706 1694 1707 result = append_auth_data(state, info3, name_domain, 1708 name_user); 1695 result = append_auth_data(state->mem_ctx, state->response, 1696 state->request->flags, info3, 1697 name_domain, name_user); 1709 1698 if (!NT_STATUS_IS_OK(result)) { 1710 1699 goto done; 1711 1700 } 1712 1701 1713 if ((state->request->flags & WBFLAG_PAM_CACHED_LOGIN)) { 1714 1715 /* Store in-memory creds for single-signon using ntlm_auth. */ 1716 result = winbindd_add_memory_creds(state->request->data.auth.user, 1717 get_uid_from_state(state), 1718 state->request->data.auth.pass); 1719 1720 if (!NT_STATUS_IS_OK(result)) { 1721 DEBUG(10,("Failed to store memory creds: %s\n", nt_errstr(result))); 1722 goto done; 1723 } 1724 1725 if (lp_winbind_offline_logon()) { 1726 result = winbindd_store_creds(domain, 1727 state->mem_ctx, 1702 if ((state->request->flags & WBFLAG_PAM_CACHED_LOGIN) 1703 && lp_winbind_offline_logon()) { 1704 1705 result = winbindd_store_creds(domain, 1728 1706 state->request->data.auth.user, 1729 1707 state->request->data.auth.pass, 1730 info3, NULL); 1731 if (!NT_STATUS_IS_OK(result)) { 1732 1733 /* Release refcount. */ 1734 winbindd_delete_memory_creds(state->request->data.auth.user); 1735 1736 DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result))); 1737 goto done; 1738 } 1739 } 1740 } 1741 1708 info3); 1709 } 1742 1710 1743 1711 if (state->request->flags & WBFLAG_PAM_GET_PWD_POLICY) { … … 1752 1720 result = NT_STATUS_NOT_SUPPORTED; 1753 1721 if (our_domain == domain ) { 1754 result = fillup_password_policy(our_domain, state); 1722 result = fillup_password_policy( 1723 our_domain, state->response); 1755 1724 } 1756 1725 … … 1784 1753 } 1785 1754 1786 1787 /**********************************************************************1788 Challenge Response Authentication Protocol1789 **********************************************************************/1790 1791 void winbindd_pam_auth_crap(struct winbindd_cli_state *state)1792 {1793 struct winbindd_domain *domain = NULL;1794 const char *domain_name = NULL;1795 NTSTATUS result;1796 1797 if (!check_request_flags(state->request->flags)) {1798 result = NT_STATUS_INVALID_PARAMETER_MIX;1799 goto done;1800 }1801 1802 if (!state->privileged) {1803 DEBUG(2, ("winbindd_pam_auth_crap: non-privileged access "1804 "denied. !\n"));1805 DEBUGADD(2, ("winbindd_pam_auth_crap: Ensure permissions "1806 "on %s are set correctly.\n",1807 get_winbind_priv_pipe_dir()));1808 /* send a better message than ACCESS_DENIED */1809 fstr_sprintf(state->response->data.auth.error_string,1810 "winbind client not authorized to use "1811 "winbindd_pam_auth_crap. Ensure permissions on "1812 "%s are set correctly.",1813 get_winbind_priv_pipe_dir());1814 result = NT_STATUS_ACCESS_DENIED;1815 goto done;1816 }1817 1818 /* Ensure null termination */1819 state->request->data.auth_crap.user1820 [sizeof(state->request->data.auth_crap.user)-1]=0;1821 state->request->data.auth_crap.domain1822 [sizeof(state->request->data.auth_crap.domain)-1]=0;1823 1824 DEBUG(3, ("[%5lu]: pam auth crap domain: [%s] user: %s\n",1825 (unsigned long)state->pid,1826 state->request->data.auth_crap.domain,1827 state->request->data.auth_crap.user));1828 1829 if (*state->request->data.auth_crap.domain != '\0') {1830 domain_name = state->request->data.auth_crap.domain;1831 } else if (lp_winbind_use_default_domain()) {1832 domain_name = lp_workgroup();1833 }1834 1835 if (domain_name != NULL)1836 domain = find_auth_domain(state->request->flags, domain_name);1837 1838 if (domain != NULL) {1839 sendto_domain(state, domain);1840 return;1841 }1842 1843 result = NT_STATUS_NO_SUCH_USER;1844 1845 done:1846 set_auth_errors(state->response, result);1847 DEBUG(5, ("CRAP authentication for %s\\%s returned %s (PAM: %d)\n",1848 state->request->data.auth_crap.domain,1849 state->request->data.auth_crap.user,1850 state->response->data.auth.nt_status_string,1851 state->response->data.auth.pam_error));1852 request_error(state);1853 return;1854 }1855 1856 1857 1755 enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, 1858 1756 struct winbindd_cli_state *state) … … 1860 1758 NTSTATUS result; 1861 1759 struct netr_SamInfo3 *info3 = NULL; 1862 struct rpc_pipe_client *netlogon_pipe;1863 1760 const char *name_user = NULL; 1864 1761 const char *name_domain = NULL; 1865 1762 const char *workstation; 1866 struct winbindd_domain *contact_domain;1867 int attempts = 0;1868 bool retry;1869 1763 1870 1764 DATA_BLOB lm_resp, nt_resp; … … 1877 1771 state->request->data.auth_crap.domain[sizeof(state->request->data.auth_crap.domain)-1]=0; 1878 1772 1879 if (!check_request_flags(state->request->flags)) {1880 result = NT_STATUS_INVALID_PARAMETER_MIX;1881 goto done;1882 }1883 1884 1773 name_user = state->request->data.auth_crap.user; 1885 1886 if (*state->request->data.auth_crap.domain) { 1887 name_domain = state->request->data.auth_crap.domain; 1888 } else if (lp_winbind_use_default_domain()) { 1889 name_domain = lp_workgroup(); 1890 } else { 1891 DEBUG(5,("no domain specified with username (%s) - failing auth\n", 1892 name_user)); 1893 result = NT_STATUS_NO_SUCH_USER; 1894 goto done; 1895 } 1774 name_domain = state->request->data.auth_crap.domain; 1775 workstation = state->request->data.auth_crap.workstation; 1896 1776 1897 1777 DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", (unsigned long)state->pid, 1898 1778 name_domain, name_user)); 1899 1900 if (*state->request->data.auth_crap.workstation) {1901 workstation = state->request->data.auth_crap.workstation;1902 } else {1903 workstation = global_myname();1904 }1905 1779 1906 1780 if (state->request->data.auth_crap.lm_resp_len > sizeof(state->request->data.auth_crap.lm_resp) … … 1929 1803 } 1930 1804 1931 /* what domain should we contact? */ 1932 1933 if ( IS_DC ) { 1934 if (!(contact_domain = find_domain_from_name(name_domain))) { 1935 DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", 1936 state->request->data.auth_crap.user, name_domain, name_user, name_domain)); 1937 result = NT_STATUS_NO_SUCH_USER; 1938 goto done; 1939 } 1940 } else { 1941 if (is_myname(name_domain)) { 1942 DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain)); 1943 result = NT_STATUS_NO_SUCH_USER; 1944 goto done; 1945 } 1946 contact_domain = find_our_domain(); 1947 } 1948 1949 do { 1950 netlogon_fn_t logon_fn; 1951 const struct cli_pipe_auth_data *auth; 1952 uint32_t neg_flags = 0; 1953 1954 retry = false; 1955 1956 netlogon_pipe = NULL; 1957 result = cm_connect_netlogon(contact_domain, &netlogon_pipe); 1958 1959 if (!NT_STATUS_IS_OK(result)) { 1960 DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n", 1961 nt_errstr(result))); 1962 goto done; 1963 } 1964 auth = netlogon_pipe->auth; 1965 if (netlogon_pipe->dc) { 1966 neg_flags = netlogon_pipe->dc->negotiate_flags; 1967 } 1968 1969 if (auth == NULL) { 1970 domain->can_do_validation6 = false; 1971 } else if (auth->auth_type != PIPE_AUTH_TYPE_SCHANNEL) { 1972 domain->can_do_validation6 = false; 1973 } else if (auth->auth_level != DCERPC_AUTH_LEVEL_PRIVACY) { 1974 domain->can_do_validation6 = false; 1975 } else if (!(neg_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) { 1976 domain->can_do_validation6 = false; 1977 } else if (!(neg_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { 1978 domain->can_do_validation6 = false; 1979 } 1980 1981 logon_fn = contact_domain->can_do_samlogon_ex 1982 ? rpccli_netlogon_sam_network_logon_ex 1983 : rpccli_netlogon_sam_network_logon; 1984 1985 result = logon_fn(netlogon_pipe, 1986 state->mem_ctx, 1987 state->request->data.auth_crap.logon_parameters, 1988 contact_domain->dcname, 1989 name_user, 1990 name_domain, 1991 /* Bug #3248 - found by Stefan Burkei. */ 1992 workstation, /* We carefully set this above so use it... */ 1993 state->request->data.auth_crap.chal, 1994 domain->can_do_validation6 ? 6 : 3, 1995 lm_resp, 1996 nt_resp, 1997 &info3); 1998 1999 if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) 2000 && contact_domain->can_do_samlogon_ex) { 2001 DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " 2002 "retrying with NetSamLogon\n")); 2003 contact_domain->can_do_samlogon_ex = false; 2004 /* 2005 * It's likely that the server also does not support 2006 * validation level 6 2007 */ 2008 domain->can_do_validation6 = false; 2009 retry = true; 2010 continue; 2011 } 2012 2013 if (domain->can_do_validation6 && 2014 (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS) || 2015 NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PARAMETER) || 2016 NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL))) { 2017 DEBUG(3,("Got a DC that can not do validation level 6, " 2018 "retrying with level 3\n")); 2019 domain->can_do_validation6 = false; 2020 retry = true; 2021 continue; 2022 } 2023 2024 /* 2025 * we increment this after the "feature negotiation" 2026 * for can_do_samlogon_ex and can_do_validation6 2027 */ 2028 attempts += 1; 2029 2030 /* We have to try a second time as cm_connect_netlogon 2031 might not yet have noticed that the DC has killed 2032 our connection. */ 2033 2034 if (!rpccli_is_connected(netlogon_pipe)) { 2035 retry = true; 2036 continue; 2037 } 2038 2039 /* if we get access denied, a possible cause was that we had and open 2040 connection to the DC, but someone changed our machine account password 2041 out from underneath us using 'net rpc changetrustpw' */ 2042 2043 if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) { 2044 DEBUG(3,("winbindd_pam_auth: sam_logon returned " 2045 "ACCESS_DENIED. Maybe the trust account " 2046 "password was changed and we didn't know it. " 2047 "Killing connections to domain %s\n", 2048 name_domain)); 2049 invalidate_cm_connection(&contact_domain->conn); 2050 retry = true; 2051 } 2052 2053 } while ( (attempts < 2) && retry ); 1805 if (strequal(name_domain, get_global_sam_name())) { 1806 DATA_BLOB chal_blob = data_blob_const( 1807 state->request->data.auth_crap.chal, 1808 sizeof(state->request->data.auth_crap.chal)); 1809 1810 result = winbindd_dual_auth_passdb( 1811 state->mem_ctx, name_domain, name_user, 1812 &chal_blob, &lm_resp, &nt_resp, &info3); 1813 goto process_result; 1814 } 1815 1816 result = winbind_samlogon_retry_loop(domain, 1817 state->mem_ctx, 1818 state->request->data.auth_crap.logon_parameters, 1819 domain->dcname, 1820 name_user, 1821 name_domain, 1822 /* Bug #3248 - found by Stefan Burkei. */ 1823 workstation, /* We carefully set this above so use it... */ 1824 state->request->data.auth_crap.chal, 1825 lm_resp, 1826 nt_resp, 1827 &info3); 1828 if (!NT_STATUS_IS_OK(result)) { 1829 goto done; 1830 } 1831 1832 process_result: 2054 1833 2055 1834 if (NT_STATUS_IS_OK(result)) { 2056 2057 wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3); 1835 struct dom_sid user_sid; 1836 1837 sid_compose(&user_sid, info3->base.domain_sid, 1838 info3->base.rid); 1839 wcache_invalidate_samlogon(find_domain_from_name(name_domain), 1840 &user_sid); 2058 1841 netsamlogon_cache_store(name_user, info3); 2059 1842 … … 2071 1854 } 2072 1855 2073 result = append_auth_data(state, info3, name_domain, 2074 name_user); 1856 result = append_auth_data(state->mem_ctx, state->response, 1857 state->request->flags, info3, 1858 name_domain, name_user); 2075 1859 if (!NT_STATUS_IS_OK(result)) { 2076 1860 goto done; … … 2102 1886 } 2103 1887 2104 /* Change a user password */2105 2106 void winbindd_pam_chauthtok(struct winbindd_cli_state *state)2107 {2108 fstring domain, user;2109 char *mapped_user;2110 struct winbindd_domain *contact_domain;2111 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;2112 2113 DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)state->pid,2114 state->request->data.chauthtok.user));2115 2116 /* Setup crap */2117 2118 nt_status = normalize_name_unmap(state->mem_ctx,2119 state->request->data.chauthtok.user,2120 &mapped_user);2121 2122 /* Update the chauthtok name if we did any mapping */2123 2124 if (NT_STATUS_IS_OK(nt_status) ||2125 NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED))2126 {2127 fstrcpy(state->request->data.chauthtok.user, mapped_user);2128 }2129 2130 /* Must pass in state->...chauthtok.user because2131 canonicalize_username() assumes an fstring(). Since2132 we have already copied it (if necessary), this is ok. */2133 2134 if (!canonicalize_username(state->request->data.chauthtok.user, domain, user)) {2135 set_auth_errors(state->response, NT_STATUS_NO_SUCH_USER);2136 DEBUG(5, ("winbindd_pam_chauthtok: canonicalize_username %s failed with %s"2137 "(PAM: %d)\n",2138 state->request->data.auth.user,2139 state->response->data.auth.nt_status_string,2140 state->response->data.auth.pam_error));2141 request_error(state);2142 return;2143 }2144 2145 contact_domain = find_domain_from_name(domain);2146 if (!contact_domain) {2147 set_auth_errors(state->response, NT_STATUS_NO_SUCH_USER);2148 DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n",2149 state->request->data.chauthtok.user, domain, user, domain));2150 request_error(state);2151 return;2152 }2153 2154 sendto_domain(state, contact_domain);2155 }2156 2157 1888 enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact_domain, 2158 1889 struct winbindd_cli_state *state) … … 2161 1892 char *newpass = NULL; 2162 1893 struct policy_handle dom_pol; 2163 struct rpc_pipe_client *cli ;1894 struct rpc_pipe_client *cli = NULL; 2164 1895 bool got_info = false; 2165 1896 struct samr_DomInfo1 *info = NULL; 2166 struct samr_ChangeReject*reject = NULL;1897 struct userPwdChangeFailureInformation *reject = NULL; 2167 1898 NTSTATUS result = NT_STATUS_UNSUCCESSFUL; 2168 1899 fstring domain, user; 1900 struct dcerpc_binding_handle *b = NULL; 1901 1902 ZERO_STRUCT(dom_pol); 2169 1903 2170 1904 DEBUG(3, ("[%5lu]: dual pam chauthtok %s\n", (unsigned long)state->pid, … … 2191 1925 goto done; 2192 1926 } 1927 1928 b = cli->binding_handle; 2193 1929 2194 1930 result = rpccli_samr_chgpasswd_user3(cli, state->mem_ctx, … … 2206 1942 2207 1943 state->response->data.auth.reject_reason = 2208 reject-> reason;1944 reject->extendedFailureReason; 2209 1945 2210 1946 got_info = true; … … 2217 1953 2218 1954 /* only fallback when the chgpasswd_user3 call is not supported */ 2219 if ( (NT_STATUS_EQUAL(result, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR))) ||2220 (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) ||2221 (NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL)) ||2222 (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED))) {1955 if (NT_STATUS_EQUAL(result, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE) || 1956 NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) || 1957 NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL) || 1958 NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) { 2223 1959 2224 1960 DEBUG(10,("Password change with chgpasswd_user3 failed with: %s, retrying chgpasswd_user2\n", … … 2237 1973 done: 2238 1974 2239 if (NT_STATUS_IS_OK(result) && (state->request->flags & WBFLAG_PAM_CACHED_LOGIN)) {2240 2241 /* Update the single sign-on memory creds. */2242 result = winbindd_ replace_memory_creds(state->request->data.chauthtok.user,2243 2244 2245 /* When we login from gdm or xdm and password expires,2246 * we change password, but there are no memory crendentials2247 * So, winbindd_replace_memory_creds() returns2248 * NT_STATUS_OBJECT_NAME_NOT_FOUND.This is not a failure.1975 if (NT_STATUS_IS_OK(result) 1976 && (state->request->flags & WBFLAG_PAM_CACHED_LOGIN) 1977 && lp_winbind_offline_logon()) { 1978 result = winbindd_update_creds_by_name(contact_domain, user, 1979 newpass); 1980 /* Again, this happens when we login from gdm or xdm 1981 * and the password expires, *BUT* cached crendentials 1982 * doesn't exist. winbindd_update_creds_by_name() 1983 * returns NT_STATUS_NO_SUCH_USER. 1984 * This is not a failure. 2249 1985 * --- BoYang 2250 1986 * */ 2251 if (NT_STATUS_EQUAL(result, NT_STATUS_ OBJECT_NAME_NOT_FOUND)) {1987 if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER)) { 2252 1988 result = NT_STATUS_OK; 2253 1989 } 2254 1990 2255 1991 if (!NT_STATUS_IS_OK(result)) { 2256 DEBUG(10,("Failed to replace memory creds: %s\n", nt_errstr(result))); 1992 DEBUG(10, ("Failed to store creds: %s\n", 1993 nt_errstr(result))); 2257 1994 goto process_result; 2258 1995 } 2259 2260 if (lp_winbind_offline_logon()) {2261 result = winbindd_update_creds_by_name(contact_domain,2262 state->mem_ctx, user,2263 newpass);2264 /* Again, this happens when we login from gdm or xdm2265 * and the password expires, *BUT* cached crendentials2266 * doesn't exist. winbindd_update_creds_by_name()2267 * returns NT_STATUS_NO_SUCH_USER.2268 * This is not a failure.2269 * --- BoYang2270 * */2271 if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER)) {2272 result = NT_STATUS_OK;2273 }2274 2275 if (!NT_STATUS_IS_OK(result)) {2276 DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result)));2277 goto process_result;2278 }2279 }2280 1996 } 2281 1997 … … 2284 2000 NTSTATUS policy_ret; 2285 2001 2286 policy_ret = fillup_password_policy(contact_domain, state); 2002 policy_ret = fillup_password_policy( 2003 contact_domain, state->response); 2287 2004 2288 2005 /* failure of this is non critical, it will just provide no … … 2297 2014 2298 2015 process_result: 2016 2017 if (strequal(contact_domain->name, get_global_sam_name())) { 2018 /* FIXME: internal rpc pipe does not cache handles yet */ 2019 if (b) { 2020 if (is_valid_policy_hnd(&dom_pol)) { 2021 NTSTATUS _result; 2022 dcerpc_samr_Close(b, state->mem_ctx, &dom_pol, &_result); 2023 } 2024 TALLOC_FREE(cli); 2025 } 2026 } 2299 2027 2300 2028 set_auth_errors(state->response, result); … … 2310 2038 } 2311 2039 2312 void winbindd_pam_logoff(struct winbindd_cli_state *state)2313 {2314 struct winbindd_domain *domain;2315 fstring name_domain, user;2316 uid_t caller_uid = (uid_t)-1;2317 uid_t request_uid = state->request->data.logoff.uid;2318 2319 DEBUG(3, ("[%5lu]: pam logoff %s\n", (unsigned long)state->pid,2320 state->request->data.logoff.user));2321 2322 /* Ensure null termination */2323 state->request->data.logoff.user2324 [sizeof(state->request->data.logoff.user)-1]='\0';2325 2326 state->request->data.logoff.krb5ccname2327 [sizeof(state->request->data.logoff.krb5ccname)-1]='\0';2328 2329 if (request_uid == (gid_t)-1) {2330 goto failed;2331 }2332 2333 if (!canonicalize_username(state->request->data.logoff.user, name_domain, user)) {2334 goto failed;2335 }2336 2337 if ((domain = find_auth_domain(state->request->flags,2338 name_domain)) == NULL) {2339 goto failed;2340 }2341 2342 if ((sys_getpeereid(state->sock, &caller_uid)) != 0) {2343 DEBUG(1,("winbindd_pam_logoff: failed to check peerid: %s\n",2344 strerror(errno)));2345 goto failed;2346 }2347 2348 switch (caller_uid) {2349 case -1:2350 goto failed;2351 case 0:2352 /* root must be able to logoff any user - gd */2353 state->request->data.logoff.uid = request_uid;2354 break;2355 default:2356 if (caller_uid != request_uid) {2357 DEBUG(1,("winbindd_pam_logoff: caller requested invalid uid\n"));2358 goto failed;2359 }2360 state->request->data.logoff.uid = caller_uid;2361 break;2362 }2363 2364 sendto_domain(state, domain);2365 return;2366 2367 failed:2368 set_auth_errors(state->response, NT_STATUS_NO_SUCH_USER);2369 DEBUG(5, ("Pam Logoff for %s returned %s "2370 "(PAM: %d)\n",2371 state->request->data.logoff.user,2372 state->response->data.auth.nt_status_string,2373 state->response->data.auth.pam_error));2374 request_error(state);2375 return;2376 }2377 2378 2040 enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain, 2379 2041 struct winbindd_cli_state *state) … … 2430 2092 process_result: 2431 2093 2432 winbindd_delete_memory_creds(state->request->data.logoff.user);2433 2094 2434 2095 set_auth_errors(state->response, result); … … 2438 2099 2439 2100 /* Change user password with auth crap*/ 2440 2441 void winbindd_pam_chng_pswd_auth_crap(struct winbindd_cli_state *state)2442 {2443 struct winbindd_domain *domain = NULL;2444 const char *domain_name = NULL;2445 2446 /* Ensure null termination */2447 state->request->data.chng_pswd_auth_crap.user[2448 sizeof(state->request->data.chng_pswd_auth_crap.user)-1]=0;2449 state->request->data.chng_pswd_auth_crap.domain[2450 sizeof(state->request->data.chng_pswd_auth_crap.domain)-1]=0;2451 2452 DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n",2453 (unsigned long)state->pid,2454 state->request->data.chng_pswd_auth_crap.domain,2455 state->request->data.chng_pswd_auth_crap.user));2456 2457 if (*state->request->data.chng_pswd_auth_crap.domain != '\0') {2458 domain_name = state->request->data.chng_pswd_auth_crap.domain;2459 } else if (lp_winbind_use_default_domain()) {2460 domain_name = lp_workgroup();2461 }2462 2463 if (domain_name != NULL)2464 domain = find_domain_from_name(domain_name);2465 2466 if (domain != NULL) {2467 DEBUG(7, ("[%5lu]: pam auth crap changing pswd in domain: "2468 "%s\n", (unsigned long)state->pid,domain->name));2469 sendto_domain(state, domain);2470 return;2471 }2472 2473 set_auth_errors(state->response, NT_STATUS_NO_SUCH_USER);2474 DEBUG(5, ("CRAP change password for %s\\%s returned %s (PAM: %d)\n",2475 state->request->data.chng_pswd_auth_crap.domain,2476 state->request->data.chng_pswd_auth_crap.user,2477 state->response->data.auth.nt_status_string,2478 state->response->data.auth.pam_error));2479 request_error(state);2480 return;2481 }2482 2101 2483 2102 enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domain *domainSt, struct winbindd_cli_state *state) … … 2491 2110 struct policy_handle dom_pol; 2492 2111 struct winbindd_domain *contact_domain = domainSt; 2493 struct rpc_pipe_client *cli; 2112 struct rpc_pipe_client *cli = NULL; 2113 struct dcerpc_binding_handle *b = NULL; 2114 2115 ZERO_STRUCT(dom_pol); 2494 2116 2495 2117 /* Ensure null termination */ … … 2540 2162 2541 2163 /* Change password */ 2542 new_nt_password = data_blob_talloc( 2543 state->mem_ctx, 2164 new_nt_password = data_blob_const( 2544 2165 state->request->data.chng_pswd_auth_crap.new_nt_pswd, 2545 2166 state->request->data.chng_pswd_auth_crap.new_nt_pswd_len); 2546 2167 2547 old_nt_hash_enc = data_blob_talloc( 2548 state->mem_ctx, 2168 old_nt_hash_enc = data_blob_const( 2549 2169 state->request->data.chng_pswd_auth_crap.old_nt_hash_enc, 2550 2170 state->request->data.chng_pswd_auth_crap.old_nt_hash_enc_len); 2551 2171 2552 2172 if(state->request->data.chng_pswd_auth_crap.new_lm_pswd_len > 0) { 2553 new_lm_password = data_blob_talloc( 2554 state->mem_ctx, 2173 new_lm_password = data_blob_const( 2555 2174 state->request->data.chng_pswd_auth_crap.new_lm_pswd, 2556 2175 state->request->data.chng_pswd_auth_crap.new_lm_pswd_len); 2557 2176 2558 old_lm_hash_enc = data_blob_talloc( 2559 state->mem_ctx, 2177 old_lm_hash_enc = data_blob_const( 2560 2178 state->request->data.chng_pswd_auth_crap.old_lm_hash_enc, 2561 2179 state->request->data.chng_pswd_auth_crap.old_lm_hash_enc_len); … … 2573 2191 } 2574 2192 2193 b = cli->binding_handle; 2194 2575 2195 result = rpccli_samr_chng_pswd_auth_crap( 2576 2196 cli, state->mem_ctx, user, new_nt_password, old_nt_hash_enc, … … 2578 2198 2579 2199 done: 2200 2201 if (strequal(contact_domain->name, get_global_sam_name())) { 2202 /* FIXME: internal rpc pipe does not cache handles yet */ 2203 if (b) { 2204 if (is_valid_policy_hnd(&dom_pol)) { 2205 NTSTATUS _result; 2206 dcerpc_samr_Close(b, state->mem_ctx, &dom_pol, &_result); 2207 } 2208 TALLOC_FREE(cli); 2209 } 2210 } 2580 2211 2581 2212 set_auth_errors(state->response, result);
Note:
See TracChangeset
for help on using the changeset viewer.