00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "includes.h"
00027 #include "winbindd.h"
00028 #undef DBGC_CLASS
00029 #define DBGC_CLASS DBGC_WINBIND
00030
00031 static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx,
00032 struct winbindd_cli_state *state,
00033 NET_USER_INFO_3 *info3)
00034 {
00035 fstring str_sid;
00036
00037 state->response.data.auth.info3.logon_time =
00038 nt_time_to_unix(info3->logon_time);
00039 state->response.data.auth.info3.logoff_time =
00040 nt_time_to_unix(info3->logoff_time);
00041 state->response.data.auth.info3.kickoff_time =
00042 nt_time_to_unix(info3->kickoff_time);
00043 state->response.data.auth.info3.pass_last_set_time =
00044 nt_time_to_unix(info3->pass_last_set_time);
00045 state->response.data.auth.info3.pass_can_change_time =
00046 nt_time_to_unix(info3->pass_can_change_time);
00047 state->response.data.auth.info3.pass_must_change_time =
00048 nt_time_to_unix(info3->pass_must_change_time);
00049
00050 state->response.data.auth.info3.logon_count = info3->logon_count;
00051 state->response.data.auth.info3.bad_pw_count = info3->bad_pw_count;
00052
00053 state->response.data.auth.info3.user_rid = info3->user_rid;
00054 state->response.data.auth.info3.group_rid = info3->group_rid;
00055 sid_to_string(str_sid, &(info3->dom_sid.sid));
00056 fstrcpy(state->response.data.auth.info3.dom_sid, str_sid);
00057
00058 state->response.data.auth.info3.num_groups = info3->num_groups;
00059 state->response.data.auth.info3.user_flgs = info3->user_flgs;
00060
00061 state->response.data.auth.info3.acct_flags = info3->acct_flags;
00062 state->response.data.auth.info3.num_other_sids = info3->num_other_sids;
00063
00064 unistr2_to_ascii(state->response.data.auth.info3.user_name,
00065 &info3->uni_user_name, -1);
00066 unistr2_to_ascii(state->response.data.auth.info3.full_name,
00067 &info3->uni_full_name, -1);
00068 unistr2_to_ascii(state->response.data.auth.info3.logon_script,
00069 &info3->uni_logon_script, -1);
00070 unistr2_to_ascii(state->response.data.auth.info3.profile_path,
00071 &info3->uni_profile_path, -1);
00072 unistr2_to_ascii(state->response.data.auth.info3.home_dir,
00073 &info3->uni_home_dir, -1);
00074 unistr2_to_ascii(state->response.data.auth.info3.dir_drive,
00075 &info3->uni_dir_drive, -1);
00076
00077 unistr2_to_ascii(state->response.data.auth.info3.logon_srv,
00078 &info3->uni_logon_srv, -1);
00079 unistr2_to_ascii(state->response.data.auth.info3.logon_dom,
00080 &info3->uni_logon_dom, -1);
00081
00082 return NT_STATUS_OK;
00083 }
00084
00085 static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx,
00086 struct winbindd_cli_state *state,
00087 NET_USER_INFO_3 *info3)
00088 {
00089 prs_struct ps;
00090 uint32 size;
00091 if (!prs_init(&ps, 256 , mem_ctx, MARSHALL)) {
00092 return NT_STATUS_NO_MEMORY;
00093 }
00094 if (!net_io_user_info3("", info3, &ps, 1, 3, False)) {
00095 prs_mem_free(&ps);
00096 return NT_STATUS_UNSUCCESSFUL;
00097 }
00098
00099 size = prs_data_size(&ps);
00100 SAFE_FREE(state->response.extra_data.data);
00101 state->response.extra_data.data = SMB_MALLOC(size);
00102 if (!state->response.extra_data.data) {
00103 prs_mem_free(&ps);
00104 return NT_STATUS_NO_MEMORY;
00105 }
00106 memset( state->response.extra_data.data, '\0', size );
00107 prs_copy_all_data_out((char *)state->response.extra_data.data, &ps);
00108 state->response.length += size;
00109 prs_mem_free(&ps);
00110 return NT_STATUS_OK;
00111 }
00112
00113 static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx,
00114 NET_USER_INFO_3 *info3,
00115 const char *group_sid)
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 {
00128 DOM_SID *require_membership_of_sid;
00129 size_t num_require_membership_of_sid;
00130 DOM_SID *all_sids;
00131 size_t num_all_sids = (2 + info3->num_groups2 + info3->num_other_sids);
00132 size_t i, j = 0, k;
00133 size_t group_sid_length;
00134 const char *search_location;
00135 char *single_group_sid;
00136 const char *comma;
00137
00138
00139
00140 if (!group_sid || !group_sid[0]) {
00141
00142 return NT_STATUS_OK;
00143 }
00144
00145 num_require_membership_of_sid = 1;
00146 group_sid_length = strlen(group_sid);
00147 for (i = 0; i < group_sid_length; i++) {
00148 if (',' == group_sid[i]) {
00149 num_require_membership_of_sid++;
00150 }
00151 }
00152
00153 require_membership_of_sid = TALLOC_ARRAY(mem_ctx, DOM_SID, num_require_membership_of_sid);
00154 if (!require_membership_of_sid)
00155 return NT_STATUS_NO_MEMORY;
00156
00157 i = 0;
00158 search_location = group_sid;
00159
00160 if (num_require_membership_of_sid > 1) {
00161
00162
00163 single_group_sid = TALLOC(mem_ctx, group_sid_length);
00164 if (!single_group_sid)
00165 return NT_STATUS_NO_MEMORY;
00166
00167 while ( (comma = strstr(search_location, ",")) != NULL ) {
00168
00169 strncpy(single_group_sid, search_location, comma - search_location);
00170 single_group_sid[comma - search_location] = 0;
00171
00172 if (!string_to_sid(&require_membership_of_sid[i++], single_group_sid)) {
00173 DEBUG(0, ("check_info3_in_group: could not parse %s as a SID!",
00174 single_group_sid));
00175
00176 return NT_STATUS_INVALID_PARAMETER;
00177 }
00178
00179 search_location = comma + 1;
00180 }
00181 }
00182
00183 if (!string_to_sid(&require_membership_of_sid[i++], search_location)) {
00184 DEBUG(0, ("check_info3_in_group: could not parse %s as a SID!",
00185 search_location));
00186
00187 return NT_STATUS_INVALID_PARAMETER;
00188 }
00189
00190 all_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_all_sids);
00191 if (!all_sids)
00192 return NT_STATUS_NO_MEMORY;
00193
00194
00195
00196 sid_copy(&all_sids[0], &(info3->dom_sid.sid));
00197
00198 if (!sid_append_rid(&all_sids[0], info3->user_rid)) {
00199 DEBUG(3,("could not append user's primary RID 0x%x\n",
00200 info3->user_rid));
00201
00202 return NT_STATUS_INVALID_PARAMETER;
00203 }
00204 j++;
00205
00206 sid_copy(&all_sids[1], &(info3->dom_sid.sid));
00207
00208 if (!sid_append_rid(&all_sids[1], info3->group_rid)) {
00209 DEBUG(3,("could not append additional group rid 0x%x\n",
00210 info3->group_rid));
00211
00212 return NT_STATUS_INVALID_PARAMETER;
00213 }
00214 j++;
00215
00216 for (i = 0; i < info3->num_groups2; i++) {
00217
00218 sid_copy(&all_sids[j], &(info3->dom_sid.sid));
00219
00220 if (!sid_append_rid(&all_sids[j], info3->gids[i].g_rid)) {
00221 DEBUG(3,("could not append additional group rid 0x%x\n",
00222 info3->gids[i].g_rid));
00223
00224 return NT_STATUS_INVALID_PARAMETER;
00225 }
00226 j++;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235 for (i = 0; i < info3->num_other_sids; i++) {
00236 sid_copy(&all_sids[info3->num_groups2 + i + 2],
00237 &info3->other_sids[i].sid);
00238 j++;
00239 }
00240
00241 for (i = 0; i < j; i++) {
00242 fstring sid1, sid2;
00243 DEBUG(10, ("User has SID: %s\n",
00244 sid_to_string(sid1, &all_sids[i])));
00245 for (k = 0; k < num_require_membership_of_sid; k++) {
00246 if (sid_equal(&require_membership_of_sid[k], &all_sids[i])) {
00247 DEBUG(10, ("SID %s matches %s - user permitted to authenticate!\n",
00248 sid_to_string(sid1, &require_membership_of_sid[k]), sid_to_string(sid2, &all_sids[i])));
00249 return NT_STATUS_OK;
00250 }
00251 }
00252 }
00253
00254
00255
00256 return NT_STATUS_LOGON_FAILURE;
00257 }
00258
00259 struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state,
00260 const char *domain_name)
00261 {
00262 struct winbindd_domain *domain;
00263
00264 if (IS_DC) {
00265 domain = find_domain_from_name_noinit(domain_name);
00266 if (domain == NULL) {
00267 DEBUG(3, ("Authentication for domain [%s] refused"
00268 "as it is not a trusted domain\n",
00269 domain_name));
00270 }
00271 return domain;
00272 }
00273
00274 if (is_myname(domain_name)) {
00275 DEBUG(3, ("Authentication for domain %s (local domain "
00276 "to this server) not supported at this "
00277 "stage\n", domain_name));
00278 return NULL;
00279 }
00280
00281
00282 if (state->request.flags & WBFLAG_PAM_CONTACT_TRUSTDOM) {
00283 domain = find_domain_from_name_noinit(domain_name);
00284 if (domain == NULL) {
00285 DEBUG(3, ("Authentication for domain [%s] skipped "
00286 "as it is not a trusted domain\n",
00287 domain_name));
00288 } else {
00289 return domain;
00290 }
00291 }
00292
00293 return find_our_domain();
00294 }
00295
00296 static void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
00297 {
00298 resp->data.auth.nt_status = NT_STATUS_V(result);
00299 fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
00300
00301
00302 if (*resp->data.auth.error_string == '\0')
00303 fstrcpy(resp->data.auth.error_string,
00304 get_friendly_nt_error_msg(result));
00305 resp->data.auth.pam_error = nt_status_to_pam(result);
00306 }
00307
00308 static NTSTATUS fillup_password_policy(struct winbindd_domain *domain,
00309 struct winbindd_cli_state *state)
00310 {
00311 struct winbindd_methods *methods;
00312 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
00313 SAM_UNK_INFO_1 password_policy;
00314
00315 methods = domain->methods;
00316
00317 status = methods->password_policy(domain, state->mem_ctx, &password_policy);
00318 if (NT_STATUS_IS_ERR(status)) {
00319 return status;
00320 }
00321
00322 state->response.data.auth.policy.min_length_password =
00323 password_policy.min_length_password;
00324 state->response.data.auth.policy.password_history =
00325 password_policy.password_history;
00326 state->response.data.auth.policy.password_properties =
00327 password_policy.password_properties;
00328 state->response.data.auth.policy.expire =
00329 nt_time_to_unix_abs(&(password_policy.expire));
00330 state->response.data.auth.policy.min_passwordage =
00331 nt_time_to_unix_abs(&(password_policy.min_passwordage));
00332
00333 return NT_STATUS_OK;
00334 }
00335
00336 static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain,
00337 TALLOC_CTX *mem_ctx,
00338 uint16 *max_allowed_bad_attempts)
00339 {
00340 struct winbindd_methods *methods;
00341 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
00342 SAM_UNK_INFO_12 lockout_policy;
00343
00344 *max_allowed_bad_attempts = 0;
00345
00346 methods = domain->methods;
00347
00348 status = methods->lockout_policy(domain, mem_ctx, &lockout_policy);
00349 if (NT_STATUS_IS_ERR(status)) {
00350 return status;
00351 }
00352
00353 *max_allowed_bad_attempts = lockout_policy.bad_attempt_lockout;
00354
00355 return NT_STATUS_OK;
00356 }
00357
00358 static NTSTATUS get_pwd_properties(struct winbindd_domain *domain,
00359 TALLOC_CTX *mem_ctx,
00360 uint32 *password_properties)
00361 {
00362 struct winbindd_methods *methods;
00363 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
00364 SAM_UNK_INFO_1 password_policy;
00365
00366 *password_properties = 0;
00367
00368 methods = domain->methods;
00369
00370 status = methods->password_policy(domain, mem_ctx, &password_policy);
00371 if (NT_STATUS_IS_ERR(status)) {
00372 return status;
00373 }
00374
00375 *password_properties = password_policy.password_properties;
00376
00377 return NT_STATUS_OK;
00378 }
00379
00380 #ifdef HAVE_KRB5
00381
00382 static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx,
00383 const char *type,
00384 uid_t uid,
00385 BOOL *internal_ccache)
00386 {
00387
00388
00389
00390
00391 const char *gen_cc = NULL;
00392
00393 *internal_ccache = True;
00394
00395 if (uid == -1) {
00396 goto memory_ccache;
00397 }
00398
00399 if (!type || type[0] == '\0') {
00400 goto memory_ccache;
00401 }
00402
00403 if (strequal(type, "FILE")) {
00404 gen_cc = talloc_asprintf(mem_ctx, "FILE:/tmp/krb5cc_%d", uid);
00405 } else if (strequal(type, "WRFILE")) {
00406 gen_cc = talloc_asprintf(mem_ctx, "WRFILE:/tmp/krb5cc_%d", uid);
00407 } else {
00408 DEBUG(10,("we don't allow to set a %s type ccache\n", type));
00409 goto memory_ccache;
00410 }
00411
00412 *internal_ccache = False;
00413 goto done;
00414
00415 memory_ccache:
00416 gen_cc = talloc_strdup(mem_ctx, "MEMORY:winbindd_pam_ccache");
00417
00418 done:
00419 if (gen_cc == NULL) {
00420 DEBUG(0,("out of memory\n"));
00421 return NULL;
00422 }
00423
00424 DEBUG(10,("using ccache: %s %s\n", gen_cc, *internal_ccache ? "(internal)":""));
00425
00426 return gen_cc;
00427 }
00428
00429 static void setup_return_cc_name(struct winbindd_cli_state *state, const char *cc)
00430 {
00431 const char *type = state->request.data.auth.krb5_cc_type;
00432
00433 state->response.data.auth.krb5ccname[0] = '\0';
00434
00435 if (type[0] == '\0') {
00436 return;
00437 }
00438
00439 if (!strequal(type, "FILE") &&
00440 !strequal(type, "WRFILE")) {
00441 DEBUG(10,("won't return krbccname for a %s type ccache\n",
00442 type));
00443 return;
00444 }
00445
00446 fstrcpy(state->response.data.auth.krb5ccname, cc);
00447 }
00448
00449 #endif
00450
00451 static uid_t get_uid_from_state(struct winbindd_cli_state *state)
00452 {
00453 uid_t uid = -1;
00454
00455 uid = state->request.data.auth.uid;
00456
00457 if (uid < 0) {
00458 DEBUG(1,("invalid uid: '%d'\n", uid));
00459 return -1;
00460 }
00461 return uid;
00462 }
00463
00464
00465
00466
00467
00468
00469 static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain,
00470 struct winbindd_cli_state *state,
00471 NET_USER_INFO_3 **info3)
00472 {
00473 #ifdef HAVE_KRB5
00474 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
00475 krb5_error_code krb5_ret;
00476 DATA_BLOB tkt, session_key_krb5;
00477 DATA_BLOB ap_rep, session_key;
00478 PAC_DATA *pac_data = NULL;
00479 PAC_LOGON_INFO *logon_info = NULL;
00480 char *client_princ = NULL;
00481 char *client_princ_out = NULL;
00482 char *local_service = NULL;
00483 const char *cc = NULL;
00484 const char *principal_s = NULL;
00485 const char *service = NULL;
00486 char *realm = NULL;
00487 fstring name_domain, name_user;
00488 time_t ticket_lifetime = 0;
00489 time_t renewal_until = 0;
00490 uid_t uid = -1;
00491 ADS_STRUCT *ads;
00492 time_t time_offset = 0;
00493 BOOL internal_ccache = True;
00494
00495 ZERO_STRUCT(session_key);
00496 ZERO_STRUCT(session_key_krb5);
00497 ZERO_STRUCT(tkt);
00498 ZERO_STRUCT(ap_rep);
00499
00500 ZERO_STRUCTP(info3);
00501
00502 *info3 = NULL;
00503
00504
00505
00506
00507 uid = get_uid_from_state(state);
00508 if (uid == -1) {
00509 DEBUG(0,("no valid uid\n"));
00510 }
00511
00512 cc = generate_krb5_ccache(state->mem_ctx,
00513 state->request.data.auth.krb5_cc_type,
00514 state->request.data.auth.uid,
00515 &internal_ccache);
00516 if (cc == NULL) {
00517 return NT_STATUS_NO_MEMORY;
00518 }
00519
00520
00521
00522
00523
00524 if (domain->private_data) {
00525 ads = (ADS_STRUCT *)domain->private_data;
00526 time_offset = ads->auth.time_offset;
00527 }
00528
00529
00530
00531
00532
00533 parse_domain_user(state->request.data.auth.user, name_domain, name_user);
00534
00535 realm = domain->alt_name;
00536 strupper_m(realm);
00537
00538 principal_s = talloc_asprintf(state->mem_ctx, "%s@%s", name_user, realm);
00539 if (principal_s == NULL) {
00540 return NT_STATUS_NO_MEMORY;
00541 }
00542
00543 service = talloc_asprintf(state->mem_ctx, "%s/%s@%s", KRB5_TGS_NAME, realm, realm);
00544 if (service == NULL) {
00545 return NT_STATUS_NO_MEMORY;
00546 }
00547
00548
00549
00550
00551
00552
00553 if (!internal_ccache) {
00554
00555 set_effective_uid(uid);
00556 DEBUG(10,("winbindd_raw_kerberos_login: uid is %d\n", uid));
00557 }
00558
00559 krb5_ret = kerberos_kinit_password_ext(principal_s,
00560 state->request.data.auth.pass,
00561 time_offset,
00562 &ticket_lifetime,
00563 &renewal_until,
00564 cc,
00565 True,
00566 True,
00567 WINBINDD_PAM_AUTH_KRB5_RENEW_TIME);
00568
00569 if (krb5_ret) {
00570 DEBUG(1,("winbindd_raw_kerberos_login: kinit failed for '%s' with: %s (%d)\n",
00571 principal_s, error_message(krb5_ret), krb5_ret));
00572 result = krb5_to_nt_status(krb5_ret);
00573 goto failed;
00574 }
00575
00576
00577 DEBUG(10,("got TGT for %s in %s (valid until: %s (%d), renewable till: %s (%d))\n",
00578 principal_s, cc,
00579 http_timestring(ticket_lifetime), (int)ticket_lifetime,
00580 http_timestring(renewal_until), (int)renewal_until));
00581
00582
00583
00584
00585 if ((ticket_lifetime == 0) && (renewal_until == 0)) {
00586 result = NT_STATUS_INVALID_LOGON_TYPE;
00587 goto failed;
00588 }
00589
00590 client_princ = talloc_strdup(state->mem_ctx, global_myname());
00591 if (client_princ == NULL) {
00592 result = NT_STATUS_NO_MEMORY;
00593 goto failed;
00594 }
00595 strlower_m(client_princ);
00596
00597 local_service = talloc_asprintf(state->mem_ctx, "%s$@%s", client_princ, lp_realm());
00598 if (local_service == NULL) {
00599 DEBUG(0,("winbindd_raw_kerberos_login: out of memory\n"));
00600 result = NT_STATUS_NO_MEMORY;
00601 goto failed;
00602 }
00603
00604 krb5_ret = cli_krb5_get_ticket(local_service,
00605 time_offset,
00606 &tkt,
00607 &session_key_krb5,
00608 0,
00609 cc,
00610 NULL);
00611 if (krb5_ret) {
00612 DEBUG(1,("winbindd_raw_kerberos_login: failed to get ticket for %s: %s\n",
00613 local_service, error_message(krb5_ret)));
00614 result = krb5_to_nt_status(krb5_ret);
00615 goto failed;
00616 }
00617
00618 if (!internal_ccache) {
00619 gain_root_privilege();
00620 }
00621
00622
00623
00624 result = ads_verify_ticket(state->mem_ctx,
00625 lp_realm(),
00626 time_offset,
00627 &tkt,
00628 &client_princ_out,
00629 &pac_data,
00630 &ap_rep,
00631 &session_key);
00632 if (!NT_STATUS_IS_OK(result)) {
00633 DEBUG(0,("winbindd_raw_kerberos_login: ads_verify_ticket failed: %s\n",
00634 nt_errstr(result)));
00635 goto failed;
00636 }
00637
00638 if (!pac_data) {
00639 DEBUG(3,("winbindd_raw_kerberos_login: no pac data\n"));
00640 result = NT_STATUS_INVALID_PARAMETER;
00641 goto failed;
00642 }
00643
00644 logon_info = get_logon_info_from_pac(pac_data);
00645 if (logon_info == NULL) {
00646 DEBUG(1,("winbindd_raw_kerberos_login: no logon info\n"));
00647 result = NT_STATUS_INVALID_PARAMETER;
00648 goto failed;
00649 }
00650
00651 DEBUG(10,("winbindd_raw_kerberos_login: winbindd validated ticket of %s\n",
00652 local_service));
00653
00654
00655
00656
00657
00658 *info3 = &logon_info->info3;
00659
00660
00661
00662
00663 if (!internal_ccache) {
00664
00665 setup_return_cc_name(state, cc);
00666
00667 result = add_ccache_to_list(principal_s,
00668 cc,
00669 service,
00670 state->request.data.auth.user,
00671 realm,
00672 uid,
00673 time(NULL),
00674 ticket_lifetime,
00675 renewal_until,
00676 False);
00677
00678 if (!NT_STATUS_IS_OK(result)) {
00679 DEBUG(10,("winbindd_raw_kerberos_login: failed to add ccache to list: %s\n",
00680 nt_errstr(result)));
00681 }
00682 } else {
00683
00684
00685
00686 krb5_ret = ads_kdestroy(cc);
00687 if (krb5_ret) {
00688 DEBUG(3,("winbindd_raw_kerberos_login: "
00689 "could not destroy krb5 credential cache: "
00690 "%s\n", error_message(krb5_ret)));
00691 }
00692
00693 }
00694
00695 result = NT_STATUS_OK;
00696
00697 goto done;
00698
00699 failed:
00700
00701
00702
00703
00704
00705
00706 krb5_ret = ads_kdestroy(cc);
00707 if (krb5_ret) {
00708 DEBUG(3,("winbindd_raw_kerberos_login: "
00709 "could not destroy krb5 credential cache: "
00710 "%s\n", error_message(krb5_ret)));
00711 }
00712
00713 if (!NT_STATUS_IS_OK(remove_ccache(state->request.data.auth.user))) {
00714 DEBUG(3,("winbindd_raw_kerberos_login: "
00715 "could not remove ccache for user %s\n",
00716 state->request.data.auth.user));
00717 }
00718
00719 done:
00720 data_blob_free(&session_key);
00721 data_blob_free(&session_key_krb5);
00722 data_blob_free(&ap_rep);
00723 data_blob_free(&tkt);
00724
00725 SAFE_FREE(client_princ_out);
00726
00727 if (!internal_ccache) {
00728 gain_root_privilege();
00729 }
00730
00731 return result;
00732 #else
00733 return NT_STATUS_NOT_SUPPORTED;
00734 #endif
00735 }
00736
00737 void winbindd_pam_auth(struct winbindd_cli_state *state)
00738 {
00739 struct winbindd_domain *domain;
00740 fstring name_domain, name_user;
00741
00742
00743 state->request.data.auth.user
00744 [sizeof(state->request.data.auth.user)-1]='\0';
00745
00746
00747 state->request.data.auth.pass
00748 [sizeof(state->request.data.auth.pass)-1]='\0';
00749
00750 DEBUG(3, ("[%5lu]: pam auth %s\n", (unsigned long)state->pid,
00751 state->request.data.auth.user));
00752
00753
00754
00755 ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR );
00756
00757 if (!canonicalize_username(state->request.data.auth.user,
00758 name_domain, name_user)) {
00759 set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
00760 DEBUG(5, ("Plain text authentication for %s returned %s "
00761 "(PAM: %d)\n",
00762 state->request.data.auth.user,
00763 state->response.data.auth.nt_status_string,
00764 state->response.data.auth.pam_error));
00765 request_error(state);
00766 return;
00767 }
00768
00769 domain = find_auth_domain(state, name_domain);
00770
00771 if (domain == NULL) {
00772 set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
00773 DEBUG(5, ("Plain text authentication for %s returned %s "
00774 "(PAM: %d)\n",
00775 state->request.data.auth.user,
00776 state->response.data.auth.nt_status_string,
00777 state->response.data.auth.pam_error));
00778 request_error(state);
00779 return;
00780 }
00781
00782 sendto_domain(state, domain);
00783 }
00784
00785 NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
00786 struct winbindd_cli_state *state,
00787 NET_USER_INFO_3 **info3)
00788 {
00789 NTSTATUS result = NT_STATUS_LOGON_FAILURE;
00790 uint16 max_allowed_bad_attempts;
00791 fstring name_domain, name_user;
00792 DOM_SID sid;
00793 enum lsa_SidType type;
00794 uchar new_nt_pass[NT_HASH_LEN];
00795 const uint8 *cached_nt_pass;
00796 const uint8 *cached_salt;
00797 NET_USER_INFO_3 *my_info3;
00798 time_t kickoff_time, must_change_time;
00799 BOOL password_good = False;
00800
00801 *info3 = NULL;
00802
00803 ZERO_STRUCTP(info3);
00804
00805 DEBUG(10,("winbindd_dual_pam_auth_cached\n"));
00806
00807
00808
00809 parse_domain_user(state->request.data.auth.user, name_domain, name_user);
00810
00811
00812 if (!lookup_cached_name(state->mem_ctx,
00813 name_domain,
00814 name_user,
00815 &sid,
00816 &type)) {
00817 DEBUG(10,("winbindd_dual_pam_auth_cached: no such user in the cache\n"));
00818 return NT_STATUS_NO_SUCH_USER;
00819 }
00820
00821 if (type != SID_NAME_USER) {
00822 DEBUG(10,("winbindd_dual_pam_auth_cached: not a user (%s)\n", sid_type_lookup(type)));
00823 return NT_STATUS_LOGON_FAILURE;
00824 }
00825
00826 result = winbindd_get_creds(domain,
00827 state->mem_ctx,
00828 &sid,
00829 &my_info3,
00830 &cached_nt_pass,
00831 &cached_salt);
00832 if (!NT_STATUS_IS_OK(result)) {
00833 DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get creds: %s\n", nt_errstr(result)));
00834 return result;
00835 }
00836
00837 *info3 = my_info3;
00838
00839 E_md4hash(state->request.data.auth.pass, new_nt_pass);
00840
00841 #if DEBUG_PASSWORD
00842 dump_data(100, (const char *)new_nt_pass, NT_HASH_LEN);
00843 dump_data(100, (const char *)cached_nt_pass, NT_HASH_LEN);
00844 if (cached_salt) {
00845 dump_data(100, (const char *)cached_salt, NT_HASH_LEN);
00846 }
00847 #endif
00848
00849 if (cached_salt) {
00850
00851
00852 uchar salted_hash[NT_HASH_LEN];
00853 E_md5hash(cached_salt, new_nt_pass, salted_hash);
00854
00855 password_good = (memcmp(cached_nt_pass, salted_hash, NT_HASH_LEN) == 0) ?
00856 True : False;
00857 } else {
00858
00859 password_good = (memcmp(cached_nt_pass, new_nt_pass, NT_HASH_LEN) == 0) ?
00860 True : False;
00861 }
00862
00863 if (password_good) {
00864
00865
00866
00867
00868 my_info3->user_flgs |= LOGON_CACHED_ACCOUNT;
00869
00870 if (my_info3->acct_flags & ACB_AUTOLOCK) {
00871 return NT_STATUS_ACCOUNT_LOCKED_OUT;
00872 }
00873
00874 if (my_info3->acct_flags & ACB_DISABLED) {
00875 return NT_STATUS_ACCOUNT_DISABLED;
00876 }
00877
00878 if (my_info3->acct_flags & ACB_WSTRUST) {
00879 return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
00880 }
00881
00882 if (my_info3->acct_flags & ACB_SVRTRUST) {
00883 return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT;
00884 }
00885
00886 if (my_info3->acct_flags & ACB_DOMTRUST) {
00887 return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT;
00888 }
00889
00890 if (!(my_info3->acct_flags & ACB_NORMAL)) {
00891 DEBUG(0,("winbindd_dual_pam_auth_cached: whats wrong with that one?: 0x%08x\n",
00892 my_info3->acct_flags));
00893 return NT_STATUS_LOGON_FAILURE;
00894 }
00895
00896 kickoff_time = nt_time_to_unix(my_info3->kickoff_time);
00897 if (kickoff_time != 0 && time(NULL) > kickoff_time) {
00898 return NT_STATUS_ACCOUNT_EXPIRED;
00899 }
00900
00901 must_change_time = nt_time_to_unix(my_info3->pass_must_change_time);
00902 if (must_change_time != 0 && must_change_time < time(NULL)) {
00903
00904 my_info3->user_flgs |= LOGON_GRACE_LOGON;
00905
00906 goto success;
00907 }
00908
00909 #ifdef HAVE_KRB5
00910
00911 if (!strequal(domain->name, domain->alt_name) &&
00912 (state->request.flags & WBFLAG_PAM_KRB5)) {
00913
00914 uid_t uid = -1;
00915 const char *cc = NULL;
00916 char *realm = NULL;
00917 const char *principal_s = NULL;
00918 const char *service = NULL;
00919 BOOL internal_ccache = False;
00920
00921 uid = get_uid_from_state(state);
00922 if (uid == -1) {
00923 DEBUG(0,("winbindd_dual_pam_auth_cached: invalid uid\n"));
00924 return NT_STATUS_INVALID_PARAMETER;
00925 }
00926
00927 cc = generate_krb5_ccache(state->mem_ctx,
00928 state->request.data.auth.krb5_cc_type,
00929 state->request.data.auth.uid,
00930 &internal_ccache);
00931 if (cc == NULL) {
00932 return NT_STATUS_NO_MEMORY;
00933 }
00934
00935 realm = domain->alt_name;
00936 strupper_m(realm);
00937
00938 principal_s = talloc_asprintf(state->mem_ctx, "%s@%s", name_user, realm);
00939 if (principal_s == NULL) {
00940 return NT_STATUS_NO_MEMORY;
00941 }
00942
00943 service = talloc_asprintf(state->mem_ctx, "%s/%s@%s", KRB5_TGS_NAME, realm, realm);
00944 if (service == NULL) {
00945 return NT_STATUS_NO_MEMORY;
00946 }
00947
00948 if (!internal_ccache) {
00949
00950 setup_return_cc_name(state, cc);
00951
00952 result = add_ccache_to_list(principal_s,
00953 cc,
00954 service,
00955 state->request.data.auth.user,
00956 domain->alt_name,
00957 uid,
00958 time(NULL),
00959 time(NULL) + lp_winbind_cache_time(),
00960 time(NULL) + WINBINDD_PAM_AUTH_KRB5_RENEW_TIME,
00961 True);
00962
00963 if (!NT_STATUS_IS_OK(result)) {
00964 DEBUG(10,("winbindd_dual_pam_auth_cached: failed "
00965 "to add ccache to list: %s\n",
00966 nt_errstr(result)));
00967 }
00968 }
00969 }
00970 #endif
00971 success:
00972
00973
00974
00975 unix_to_nt_time(&my_info3->logon_time, time(NULL));
00976 my_info3->bad_pw_count = 0;
00977
00978 result = winbindd_update_creds_by_info3(domain,
00979 state->mem_ctx,
00980 state->request.data.auth.user,
00981 state->request.data.auth.pass,
00982 my_info3);
00983 if (!NT_STATUS_IS_OK(result)) {
00984 DEBUG(1,("winbindd_dual_pam_auth_cached: failed to update creds: %s\n",
00985 nt_errstr(result)));
00986 return result;
00987 }
00988
00989 return NT_STATUS_OK;
00990
00991 }
00992
00993
00994
00995
00996 result = get_max_bad_attempts_from_lockout_policy(domain, state->mem_ctx, &max_allowed_bad_attempts);
00997 if (!NT_STATUS_IS_OK(result)) {
00998 DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get max_allowed_bad_attempts. "
00999 "Won't be able to honour account lockout policies\n"));
01000 }
01001
01002
01003 my_info3->bad_pw_count++;
01004
01005 if (max_allowed_bad_attempts == 0) {
01006 goto failed;
01007 }
01008
01009
01010 if (my_info3->bad_pw_count >= max_allowed_bad_attempts) {
01011
01012 uint32 password_properties;
01013
01014 result = get_pwd_properties(domain, state->mem_ctx, &password_properties);
01015 if (!NT_STATUS_IS_OK(result)) {
01016 DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get password properties.\n"));
01017 }
01018
01019 if ((my_info3->user_rid != DOMAIN_USER_RID_ADMIN) ||
01020 (password_properties & DOMAIN_LOCKOUT_ADMINS)) {
01021 my_info3->acct_flags |= ACB_AUTOLOCK;
01022 }
01023 }
01024
01025 failed:
01026 result = winbindd_update_creds_by_info3(domain,
01027 state->mem_ctx,
01028 state->request.data.auth.user,
01029 NULL,
01030 my_info3);
01031
01032 if (!NT_STATUS_IS_OK(result)) {
01033 DEBUG(0,("winbindd_dual_pam_auth_cached: failed to update creds %s\n",
01034 nt_errstr(result)));
01035 }
01036
01037 return NT_STATUS_LOGON_FAILURE;
01038 }
01039
01040 NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain,
01041 struct winbindd_cli_state *state,
01042 NET_USER_INFO_3 **info3)
01043 {
01044 struct winbindd_domain *contact_domain;
01045 fstring name_domain, name_user;
01046 NTSTATUS result;
01047
01048 DEBUG(10,("winbindd_dual_pam_auth_kerberos\n"));
01049
01050
01051
01052 parse_domain_user(state->request.data.auth.user, name_domain, name_user);
01053
01054
01055
01056 if ( IS_DC ) {
01057 if (!(contact_domain = find_domain_from_name(name_domain))) {
01058 DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",
01059 state->request.data.auth.user, name_domain, name_user, name_domain));
01060 result = NT_STATUS_NO_SUCH_USER;
01061 goto done;
01062 }
01063
01064 } else {
01065 if (is_myname(name_domain)) {
01066 DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain));
01067 result = NT_STATUS_NO_SUCH_USER;
01068 goto done;
01069 }
01070
01071 contact_domain = find_domain_from_name(name_domain);
01072 if (contact_domain == NULL) {
01073 DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",
01074 state->request.data.auth.user, name_domain, name_user, name_domain));
01075
01076 contact_domain = find_our_domain();
01077 }
01078 }
01079
01080 if (contact_domain->initialized &&
01081 contact_domain->active_directory) {
01082 goto try_login;
01083 }
01084
01085 if (!contact_domain->initialized) {
01086 init_dc_connection(contact_domain);
01087 }
01088
01089 if (!contact_domain->active_directory) {
01090 DEBUG(3,("krb5 auth requested but domain is not Active Directory\n"));
01091 return NT_STATUS_INVALID_LOGON_TYPE;
01092 }
01093 try_login:
01094 result = winbindd_raw_kerberos_login(contact_domain, state, info3);
01095 done:
01096 return result;
01097 }
01098
01099 NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain,
01100 struct winbindd_cli_state *state,
01101 NET_USER_INFO_3 **info3)
01102 {
01103
01104 struct rpc_pipe_client *netlogon_pipe;
01105 uchar chal[8];
01106 DATA_BLOB lm_resp;
01107 DATA_BLOB nt_resp;
01108 int attempts = 0;
01109 unsigned char local_lm_response[24];
01110 unsigned char local_nt_response[24];
01111 struct winbindd_domain *contact_domain;
01112 fstring name_domain, name_user;
01113 BOOL retry;
01114 NTSTATUS result;
01115 NET_USER_INFO_3 *my_info3;
01116
01117 ZERO_STRUCTP(info3);
01118
01119 *info3 = NULL;
01120
01121 my_info3 = TALLOC_ZERO_P(state->mem_ctx, NET_USER_INFO_3);
01122 if (my_info3 == NULL) {
01123 return NT_STATUS_NO_MEMORY;
01124 }
01125
01126
01127 DEBUG(10,("winbindd_dual_pam_auth_samlogon\n"));
01128
01129
01130
01131 parse_domain_user(state->request.data.auth.user, name_domain, name_user);
01132
01133
01134
01135
01136 generate_random_buffer(chal, 8);
01137 if (lp_client_ntlmv2_auth()) {
01138 DATA_BLOB server_chal;
01139 DATA_BLOB names_blob;
01140 DATA_BLOB nt_response;
01141 DATA_BLOB lm_response;
01142 server_chal = data_blob_talloc(state->mem_ctx, chal, 8);
01143
01144
01145
01146
01147
01148 names_blob = NTLMv2_generate_names_blob(global_myname(), lp_workgroup());
01149
01150 if (!SMBNTLMv2encrypt(name_user, name_domain,
01151 state->request.data.auth.pass,
01152 &server_chal,
01153 &names_blob,
01154 &lm_response, &nt_response, NULL)) {
01155 data_blob_free(&names_blob);
01156 data_blob_free(&server_chal);
01157 DEBUG(0, ("winbindd_pam_auth: SMBNTLMv2encrypt() failed!\n"));
01158 result = NT_STATUS_NO_MEMORY;
01159 goto done;
01160 }
01161 data_blob_free(&names_blob);
01162 data_blob_free(&server_chal);
01163 lm_resp = data_blob_talloc(state->mem_ctx, lm_response.data,
01164 lm_response.length);
01165 nt_resp = data_blob_talloc(state->mem_ctx, nt_response.data,
01166 nt_response.length);
01167 data_blob_free(&lm_response);
01168 data_blob_free(&nt_response);
01169
01170 } else {
01171 if (lp_client_lanman_auth()
01172 && SMBencrypt(state->request.data.auth.pass,
01173 chal,
01174 local_lm_response)) {
01175 lm_resp = data_blob_talloc(state->mem_ctx,
01176 local_lm_response,
01177 sizeof(local_lm_response));
01178 } else {
01179 lm_resp = data_blob(NULL, 0);
01180 }
01181 SMBNTencrypt(state->request.data.auth.pass,
01182 chal,
01183 local_nt_response);
01184
01185 nt_resp = data_blob_talloc(state->mem_ctx,
01186 local_nt_response,
01187 sizeof(local_nt_response));
01188 }
01189
01190
01191
01192 if ( IS_DC ) {
01193 if (!(contact_domain = find_domain_from_name(name_domain))) {
01194 DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",
01195 state->request.data.auth.user, name_domain, name_user, name_domain));
01196 result = NT_STATUS_NO_SUCH_USER;
01197 goto done;
01198 }
01199
01200 } else {
01201 if (is_myname(name_domain)) {
01202 DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain));
01203 result = NT_STATUS_NO_SUCH_USER;
01204 goto done;
01205 }
01206
01207 contact_domain = find_our_domain();
01208 }
01209
01210
01211
01212 do {
01213
01214 ZERO_STRUCTP(my_info3);
01215 retry = False;
01216
01217 result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
01218
01219 if (!NT_STATUS_IS_OK(result)) {
01220 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
01221 goto done;
01222 }
01223
01224 result = rpccli_netlogon_sam_network_logon(netlogon_pipe,
01225 state->mem_ctx,
01226 0,
01227 contact_domain->dcname,
01228 name_user,
01229 name_domain,
01230 global_myname(),
01231 chal,
01232 lm_resp,
01233 nt_resp,
01234 my_info3);
01235 attempts += 1;
01236
01237
01238
01239
01240
01241 if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) {
01242 retry = True;
01243 continue;
01244 }
01245
01246
01247
01248
01249
01250
01251 if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) {
01252 DEBUG(3,("winbindd_pam_auth: sam_logon returned "
01253 "ACCESS_DENIED. Maybe the trust account "
01254 "password was changed and we didn't know it. "
01255 "Killing connections to domain %s\n",
01256 name_domain));
01257 invalidate_cm_connection(&contact_domain->conn);
01258 retry = True;
01259 }
01260
01261 } while ( (attempts < 2) && retry );
01262
01263
01264
01265
01266
01267 if ((state->request.flags & WBFLAG_PAM_INFO3_TEXT) &&
01268 (my_info3->acct_flags == 0) && NT_STATUS_IS_OK(result)) {
01269
01270 struct rpc_pipe_client *samr_pipe;
01271 POLICY_HND samr_domain_handle, user_pol;
01272 SAM_USERINFO_CTR *user_ctr;
01273 NTSTATUS status_tmp;
01274 uint32 acct_flags;
01275
01276 ZERO_STRUCT(user_ctr);
01277
01278 status_tmp = cm_connect_sam(contact_domain, state->mem_ctx,
01279 &samr_pipe, &samr_domain_handle);
01280
01281 if (!NT_STATUS_IS_OK(status_tmp)) {
01282 DEBUG(3, ("could not open handle to SAMR pipe: %s\n",
01283 nt_errstr(status_tmp)));
01284 goto done;
01285 }
01286
01287 status_tmp = rpccli_samr_open_user(samr_pipe, state->mem_ctx,
01288 &samr_domain_handle,
01289 MAXIMUM_ALLOWED_ACCESS,
01290 my_info3->user_rid, &user_pol);
01291
01292 if (!NT_STATUS_IS_OK(status_tmp)) {
01293 DEBUG(3, ("could not open user handle on SAMR pipe: %s\n",
01294 nt_errstr(status_tmp)));
01295 goto done;
01296 }
01297
01298 status_tmp = rpccli_samr_query_userinfo(samr_pipe, state->mem_ctx,
01299 &user_pol, 16, &user_ctr);
01300
01301 if (!NT_STATUS_IS_OK(status_tmp)) {
01302 DEBUG(3, ("could not query user info on SAMR pipe: %s\n",
01303 nt_errstr(status_tmp)));
01304 rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol);
01305 goto done;
01306 }
01307
01308 acct_flags = user_ctr->info.id16->acb_info;
01309
01310 if (acct_flags == 0) {
01311 rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol);
01312 goto done;
01313 }
01314
01315 my_info3->acct_flags = acct_flags;
01316
01317 DEBUG(10,("successfully retrieved acct_flags 0x%x\n", acct_flags));
01318
01319 rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol);
01320 }
01321
01322 *info3 = my_info3;
01323 done:
01324 return result;
01325 }
01326
01327 enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
01328 struct winbindd_cli_state *state)
01329 {
01330 NTSTATUS result = NT_STATUS_LOGON_FAILURE;
01331 fstring name_domain, name_user;
01332 NET_USER_INFO_3 *info3 = NULL;
01333
01334
01335 state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0';
01336
01337
01338 state->request.data.auth.pass[sizeof(state->request.data.auth.pass)-1]='\0';
01339
01340 DEBUG(3, ("[%5lu]: dual pam auth %s\n", (unsigned long)state->pid,
01341 state->request.data.auth.user));
01342
01343
01344
01345 ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR );
01346
01347 parse_domain_user(state->request.data.auth.user, name_domain, name_user);
01348
01349 if (domain->online == False) {
01350 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
01351 if (domain->startup) {
01352
01353
01354
01355
01356 DEBUG(10,("winbindd_dual_pam_auth: domain: %s offline and auth "
01357 "request in startup mode.\n", domain->name ));
01358
01359 winbindd_flush_negative_conn_cache(domain);
01360 result = init_dc_connection(domain);
01361 }
01362 }
01363
01364 DEBUG(10,("winbindd_dual_pam_auth: domain: %s last was %s\n", domain->name, domain->online ? "online":"offline"));
01365
01366
01367 if (domain->online && (state->request.flags & WBFLAG_PAM_KRB5)) {
01368
01369 result = winbindd_dual_pam_auth_kerberos(domain, state, &info3);
01370
01371 if (NT_STATUS_IS_OK(result)) {
01372 DEBUG(10,("winbindd_dual_pam_auth_kerberos succeeded\n"));
01373 goto process_result;
01374 } else {
01375 DEBUG(10,("winbindd_dual_pam_auth_kerberos failed: %s\n", nt_errstr(result)));
01376 }
01377
01378 if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS) ||
01379 NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) ||
01380 NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
01381 DEBUG(10,("winbindd_dual_pam_auth_kerberos setting domain to offline\n"));
01382
01383
01384
01385
01386 set_domain_offline(domain);
01387 }
01388
01389
01390
01391
01392
01393 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_DISABLED) ||
01394 NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_EXPIRED) ||
01395 NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_LOCKED_OUT) ||
01396 NT_STATUS_EQUAL(result, NT_STATUS_INVALID_LOGON_HOURS) ||
01397 NT_STATUS_EQUAL(result, NT_STATUS_INVALID_WORKSTATION) ||
01398 NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE) ||
01399 NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER) ||
01400 NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_EXPIRED) ||
01401 NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_MUST_CHANGE) ||
01402 NT_STATUS_EQUAL(result, NT_STATUS_WRONG_PASSWORD)) {
01403 goto process_result;
01404 }
01405
01406 if (state->request.flags & WBFLAG_PAM_FALLBACK_AFTER_KRB5) {
01407 DEBUG(3,("falling back to samlogon\n"));
01408 goto sam_logon;
01409 } else {
01410 goto cached_logon;
01411 }
01412 }
01413
01414 sam_logon:
01415
01416 if (domain->online) {
01417 result = winbindd_dual_pam_auth_samlogon(domain, state, &info3);
01418
01419 if (NT_STATUS_IS_OK(result)) {
01420 DEBUG(10,("winbindd_dual_pam_auth_samlogon succeeded\n"));
01421 goto process_result;
01422 } else {
01423 DEBUG(10,("winbindd_dual_pam_auth_samlogon failed: %s\n", nt_errstr(result)));
01424 if (domain->online) {
01425
01426 goto done;
01427 }
01428
01429 }
01430 }
01431
01432 cached_logon:
01433
01434 if (!domain->online && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN) &&
01435 lp_winbind_offline_logon()) {
01436
01437 result = winbindd_dual_pam_auth_cached(domain, state, &info3);
01438
01439 if (NT_STATUS_IS_OK(result)) {
01440 DEBUG(10,("winbindd_dual_pam_auth_cached succeeded\n"));
01441 goto process_result;
01442 } else {
01443 DEBUG(10,("winbindd_dual_pam_auth_cached failed: %s\n", nt_errstr(result)));
01444 goto done;
01445 }
01446 }
01447
01448 process_result:
01449
01450 if (NT_STATUS_IS_OK(result)) {
01451
01452 DOM_SID user_sid;
01453
01454
01455
01456 if (!info3) {
01457 result = NT_STATUS_INTERNAL_ERROR;
01458 goto done;
01459 }
01460
01461 netsamlogon_cache_store(name_user, info3);
01462 wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3);
01463
01464
01465 sid_compose(&user_sid, &info3->dom_sid.sid, info3->user_rid);
01466 cache_name2sid(domain, name_domain, name_user, SID_NAME_USER, &user_sid);
01467
01468
01469
01470 if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, info3,
01471 state->request.data.auth.require_membership_of_sid))) {
01472 DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n",
01473 state->request.data.auth.user,
01474 state->request.data.auth.require_membership_of_sid));
01475 goto done;
01476 }
01477
01478 if (state->request.flags & WBFLAG_PAM_INFO3_NDR) {
01479 result = append_info3_as_ndr(state->mem_ctx, state, info3);
01480 if (!NT_STATUS_IS_OK(result)) {
01481 DEBUG(10,("Failed to append INFO3 (NDR): %s\n", nt_errstr(result)));
01482 goto done;
01483 }
01484 }
01485
01486 if (state->request.flags & WBFLAG_PAM_INFO3_TEXT) {
01487 result = append_info3_as_txt(state->mem_ctx, state, info3);
01488 if (!NT_STATUS_IS_OK(result)) {
01489 DEBUG(10,("Failed to append INFO3 (TXT): %s\n", nt_errstr(result)));
01490 goto done;
01491 }
01492
01493 }
01494
01495 if ((state->request.flags & WBFLAG_PAM_CACHED_LOGIN)) {
01496
01497
01498 result = winbindd_add_memory_creds(state->request.data.auth.user,
01499 get_uid_from_state(state),
01500 state->request.data.auth.pass);
01501
01502 if (!NT_STATUS_IS_OK(result)) {
01503 DEBUG(10,("Failed to store memory creds: %s\n", nt_errstr(result)));
01504 goto done;
01505 }
01506
01507 if (lp_winbind_offline_logon()) {
01508 result = winbindd_store_creds(domain,
01509 state->mem_ctx,
01510 state->request.data.auth.user,
01511 state->request.data.auth.pass,
01512 info3, NULL);
01513 if (!NT_STATUS_IS_OK(result)) {
01514
01515
01516 winbindd_delete_memory_creds(state->request.data.auth.user);
01517
01518 DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result)));
01519 goto done;
01520 }
01521 }
01522 }
01523
01524 if (state->request.flags & WBFLAG_PAM_GET_PWD_POLICY) {
01525 result = fillup_password_policy(domain, state);
01526
01527 if (!NT_STATUS_IS_OK(result)) {
01528 DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(result)));
01529 goto done;
01530 }
01531 }
01532
01533 if (state->request.flags & WBFLAG_PAM_UNIX_NAME) {
01534
01535
01536
01537 fstring username_out;
01538 const char *nt_username, *nt_domain;
01539
01540 if (!(nt_username = unistr2_tdup(state->mem_ctx, &info3->uni_user_name))) {
01541
01542 nt_username = name_user;
01543 }
01544
01545 if (!(nt_domain = unistr2_tdup(state->mem_ctx, &info3->uni_logon_dom))) {
01546
01547 nt_domain = name_domain;
01548 }
01549
01550 fill_domain_username(username_out, nt_domain, nt_username, True);
01551
01552 DEBUG(5, ("Setting unix username to [%s]\n", username_out));
01553
01554 SAFE_FREE(state->response.extra_data.data);
01555 state->response.extra_data.data = SMB_STRDUP(username_out);
01556 if (!state->response.extra_data.data) {
01557 result = NT_STATUS_NO_MEMORY;
01558 goto done;
01559 }
01560 state->response.length +=
01561 strlen((const char *)state->response.extra_data.data)+1;
01562 }
01563 }
01564
01565
01566 done:
01567
01568 if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ||
01569 (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
01570 result = NT_STATUS_NO_LOGON_SERVERS;
01571 }
01572
01573 state->response.data.auth.nt_status = NT_STATUS_V(result);
01574 fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
01575
01576
01577 if (!*state->response.data.auth.error_string)
01578 fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
01579 state->response.data.auth.pam_error = nt_status_to_pam(result);
01580
01581 DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n",
01582 state->request.data.auth.user,
01583 state->response.data.auth.nt_status_string,
01584 state->response.data.auth.pam_error));
01585
01586 if ( NT_STATUS_IS_OK(result) && info3 &&
01587 (state->request.flags & WBFLAG_PAM_AFS_TOKEN) ) {
01588
01589 char *afsname = talloc_strdup(state->mem_ctx,
01590 lp_afs_username_map());
01591 char *cell;
01592
01593 if (afsname == NULL) {
01594 goto no_token;
01595 }
01596
01597 afsname = talloc_string_sub(state->mem_ctx,
01598 lp_afs_username_map(),
01599 "%D", name_domain);
01600 afsname = talloc_string_sub(state->mem_ctx, afsname,
01601 "%u", name_user);
01602 afsname = talloc_string_sub(state->mem_ctx, afsname,
01603 "%U", name_user);
01604
01605 {
01606 DOM_SID user_sid;
01607 fstring sidstr;
01608
01609 sid_copy(&user_sid, &info3->dom_sid.sid);
01610 sid_append_rid(&user_sid, info3->user_rid);
01611 sid_to_string(sidstr, &user_sid);
01612 afsname = talloc_string_sub(state->mem_ctx, afsname,
01613 "%s", sidstr);
01614 }
01615
01616 if (afsname == NULL) {
01617 goto no_token;
01618 }
01619
01620 strlower_m(afsname);
01621
01622 DEBUG(10, ("Generating token for user %s\n", afsname));
01623
01624 cell = strchr(afsname, '@');
01625
01626 if (cell == NULL) {
01627 goto no_token;
01628 }
01629
01630 *cell = '\0';
01631 cell += 1;
01632
01633
01634 SAFE_FREE(state->response.extra_data.data);
01635 state->response.extra_data.data =
01636 afs_createtoken_str(afsname, cell);
01637
01638 if (state->response.extra_data.data != NULL) {
01639 state->response.length +=
01640 strlen((const char *)state->response.extra_data.data)+1;
01641 }
01642
01643 no_token:
01644 TALLOC_FREE(afsname);
01645 }
01646
01647 return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
01648 }
01649
01650
01651
01652
01653
01654
01655 void winbindd_pam_auth_crap(struct winbindd_cli_state *state)
01656 {
01657 struct winbindd_domain *domain = NULL;
01658 const char *domain_name = NULL;
01659 NTSTATUS result;
01660
01661 if (!state->privileged) {
01662 char *error_string = NULL;
01663 DEBUG(2, ("winbindd_pam_auth_crap: non-privileged access "
01664 "denied. !\n"));
01665 DEBUGADD(2, ("winbindd_pam_auth_crap: Ensure permissions "
01666 "on %s are set correctly.\n",
01667 get_winbind_priv_pipe_dir()));
01668
01669 error_string = talloc_asprintf(state->mem_ctx,
01670 "winbind client not authorized "
01671 "to use winbindd_pam_auth_crap."
01672 " Ensure permissions on %s "
01673 "are set correctly.",
01674 get_winbind_priv_pipe_dir());
01675 fstrcpy(state->response.data.auth.error_string, error_string);
01676 result = NT_STATUS_ACCESS_DENIED;
01677 goto done;
01678 }
01679
01680
01681 state->request.data.auth_crap.user
01682 [sizeof(state->request.data.auth_crap.user)-1]=0;
01683 state->request.data.auth_crap.domain
01684 [sizeof(state->request.data.auth_crap.domain)-1]=0;
01685
01686 DEBUG(3, ("[%5lu]: pam auth crap domain: [%s] user: %s\n",
01687 (unsigned long)state->pid,
01688 state->request.data.auth_crap.domain,
01689 state->request.data.auth_crap.user));
01690
01691 if (*state->request.data.auth_crap.domain != '\0') {
01692 domain_name = state->request.data.auth_crap.domain;
01693 } else if (lp_winbind_use_default_domain()) {
01694 domain_name = lp_workgroup();
01695 }
01696
01697 if (domain_name != NULL)
01698 domain = find_auth_domain(state, domain_name);
01699
01700 if (domain != NULL) {
01701 sendto_domain(state, domain);
01702 return;
01703 }
01704
01705 result = NT_STATUS_NO_SUCH_USER;
01706
01707 done:
01708 set_auth_errors(&state->response, result);
01709 DEBUG(5, ("CRAP authentication for %s\\%s returned %s (PAM: %d)\n",
01710 state->request.data.auth_crap.domain,
01711 state->request.data.auth_crap.user,
01712 state->response.data.auth.nt_status_string,
01713 state->response.data.auth.pam_error));
01714 request_error(state);
01715 return;
01716 }
01717
01718
01719 enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
01720 struct winbindd_cli_state *state)
01721 {
01722 NTSTATUS result;
01723 NET_USER_INFO_3 info3;
01724 struct rpc_pipe_client *netlogon_pipe;
01725 const char *name_user = NULL;
01726 const char *name_domain = NULL;
01727 const char *workstation;
01728 struct winbindd_domain *contact_domain;
01729 int attempts = 0;
01730 BOOL retry;
01731
01732 DATA_BLOB lm_resp, nt_resp;
01733
01734
01735
01736
01737
01738 state->request.data.auth_crap.user[sizeof(state->request.data.auth_crap.user)-1]=0;
01739 state->request.data.auth_crap.domain[sizeof(state->request.data.auth_crap.domain)-1]=0;
01740
01741 name_user = state->request.data.auth_crap.user;
01742
01743 if (*state->request.data.auth_crap.domain) {
01744 name_domain = state->request.data.auth_crap.domain;
01745 } else if (lp_winbind_use_default_domain()) {
01746 name_domain = lp_workgroup();
01747 } else {
01748 DEBUG(5,("no domain specified with username (%s) - failing auth\n",
01749 name_user));
01750 result = NT_STATUS_NO_SUCH_USER;
01751 goto done;
01752 }
01753
01754 DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", (unsigned long)state->pid,
01755 name_domain, name_user));
01756
01757 if (*state->request.data.auth_crap.workstation) {
01758 workstation = state->request.data.auth_crap.workstation;
01759 } else {
01760 workstation = global_myname();
01761 }
01762
01763 if (state->request.data.auth_crap.lm_resp_len > sizeof(state->request.data.auth_crap.lm_resp)
01764 || state->request.data.auth_crap.nt_resp_len > sizeof(state->request.data.auth_crap.nt_resp)) {
01765 DEBUG(0, ("winbindd_pam_auth_crap: invalid password length %u/%u\n",
01766 state->request.data.auth_crap.lm_resp_len,
01767 state->request.data.auth_crap.nt_resp_len));
01768 result = NT_STATUS_INVALID_PARAMETER;
01769 goto done;
01770 }
01771
01772 lm_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.lm_resp,
01773 state->request.data.auth_crap.lm_resp_len);
01774 nt_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.nt_resp,
01775 state->request.data.auth_crap.nt_resp_len);
01776
01777
01778
01779 if ( IS_DC ) {
01780 if (!(contact_domain = find_domain_from_name(name_domain))) {
01781 DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",
01782 state->request.data.auth_crap.user, name_domain, name_user, name_domain));
01783 result = NT_STATUS_NO_SUCH_USER;
01784 goto done;
01785 }
01786 } else {
01787 if (is_myname(name_domain)) {
01788 DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain));
01789 result = NT_STATUS_NO_SUCH_USER;
01790 goto done;
01791 }
01792 contact_domain = find_our_domain();
01793 }
01794
01795 do {
01796 ZERO_STRUCT(info3);
01797 retry = False;
01798
01799 netlogon_pipe = NULL;
01800 result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
01801
01802 if (!NT_STATUS_IS_OK(result)) {
01803 DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n",
01804 nt_errstr(result)));
01805 goto done;
01806 }
01807
01808 result = rpccli_netlogon_sam_network_logon(netlogon_pipe,
01809 state->mem_ctx,
01810 state->request.data.auth_crap.logon_parameters,
01811 contact_domain->dcname,
01812 name_user,
01813 name_domain,
01814
01815 workstation,
01816 state->request.data.auth_crap.chal,
01817 lm_resp,
01818 nt_resp,
01819 &info3);
01820
01821 attempts += 1;
01822
01823
01824
01825
01826
01827 if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) {
01828 retry = True;
01829 continue;
01830 }
01831
01832
01833
01834
01835
01836 if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) {
01837 DEBUG(3,("winbindd_pam_auth: sam_logon returned "
01838 "ACCESS_DENIED. Maybe the trust account "
01839 "password was changed and we didn't know it. "
01840 "Killing connections to domain %s\n",
01841 name_domain));
01842 invalidate_cm_connection(&contact_domain->conn);
01843 retry = True;
01844 }
01845
01846 } while ( (attempts < 2) && retry );
01847
01848 if (NT_STATUS_IS_OK(result)) {
01849
01850 netsamlogon_cache_store(name_user, &info3);
01851 wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3);
01852
01853
01854
01855 if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3,
01856 state->request.data.auth_crap.require_membership_of_sid))) {
01857 DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n",
01858 state->request.data.auth_crap.user,
01859 state->request.data.auth_crap.require_membership_of_sid));
01860 goto done;
01861 }
01862
01863 if (state->request.flags & WBFLAG_PAM_INFO3_NDR) {
01864 result = append_info3_as_ndr(state->mem_ctx, state, &info3);
01865 } else if (state->request.flags & WBFLAG_PAM_UNIX_NAME) {
01866
01867
01868
01869 fstring username_out;
01870 const char *nt_username, *nt_domain;
01871 if (!(nt_username = unistr2_tdup(state->mem_ctx, &(info3.uni_user_name)))) {
01872
01873 nt_username = name_user;
01874 }
01875
01876 if (!(nt_domain = unistr2_tdup(state->mem_ctx, &(info3.uni_logon_dom)))) {
01877
01878 nt_domain = name_domain;
01879 }
01880
01881 fill_domain_username(username_out, nt_domain, nt_username, True);
01882
01883 DEBUG(5, ("Setting unix username to [%s]\n", username_out));
01884
01885 SAFE_FREE(state->response.extra_data.data);
01886 state->response.extra_data.data = SMB_STRDUP(username_out);
01887 if (!state->response.extra_data.data) {
01888 result = NT_STATUS_NO_MEMORY;
01889 goto done;
01890 }
01891 state->response.length +=
01892 strlen((const char *)state->response.extra_data.data)+1;
01893 }
01894
01895 if (state->request.flags & WBFLAG_PAM_USER_SESSION_KEY) {
01896 memcpy(state->response.data.auth.user_session_key, info3.user_sess_key,
01897 sizeof(state->response.data.auth.user_session_key) );
01898 }
01899 if (state->request.flags & WBFLAG_PAM_LMKEY) {
01900 memcpy(state->response.data.auth.first_8_lm_hash, info3.lm_sess_key,
01901 sizeof(state->response.data.auth.first_8_lm_hash) );
01902 }
01903 }
01904
01905 done:
01906
01907
01908 if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ||
01909 (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
01910 result = NT_STATUS_NO_LOGON_SERVERS;
01911 }
01912
01913 if (state->request.flags & WBFLAG_PAM_NT_STATUS_SQUASH) {
01914 result = nt_status_squash(result);
01915 }
01916
01917 state->response.data.auth.nt_status = NT_STATUS_V(result);
01918 fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
01919
01920
01921 if (!*state->response.data.auth.error_string) {
01922 fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
01923 }
01924 state->response.data.auth.pam_error = nt_status_to_pam(result);
01925
01926 DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
01927 ("NTLM CRAP authentication for user [%s]\\[%s] returned %s (PAM: %d)\n",
01928 name_domain,
01929 name_user,
01930 state->response.data.auth.nt_status_string,
01931 state->response.data.auth.pam_error));
01932
01933 return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
01934 }
01935
01936
01937
01938 void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
01939 {
01940 fstring domain, user;
01941 struct winbindd_domain *contact_domain;
01942
01943 DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)state->pid,
01944 state->request.data.chauthtok.user));
01945
01946
01947
01948 if (!canonicalize_username(state->request.data.chauthtok.user, domain, user)) {
01949 set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
01950 DEBUG(5, ("winbindd_pam_chauthtok: canonicalize_username %s failed with %s"
01951 "(PAM: %d)\n",
01952 state->request.data.auth.user,
01953 state->response.data.auth.nt_status_string,
01954 state->response.data.auth.pam_error));
01955 request_error(state);
01956 return;
01957 }
01958
01959 contact_domain = find_domain_from_name(domain);
01960 if (!contact_domain) {
01961 set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
01962 DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n",
01963 state->request.data.chauthtok.user, domain, user, domain));
01964 request_error(state);
01965 return;
01966 }
01967
01968 sendto_domain(state, contact_domain);
01969 }
01970
01971 enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact_domain,
01972 struct winbindd_cli_state *state)
01973 {
01974 char *oldpass;
01975 char *newpass = NULL;
01976 POLICY_HND dom_pol;
01977 struct rpc_pipe_client *cli;
01978 BOOL got_info = False;
01979 SAM_UNK_INFO_1 info;
01980 SAMR_CHANGE_REJECT reject;
01981 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
01982 fstring domain, user;
01983
01984 DEBUG(3, ("[%5lu]: dual pam chauthtok %s\n", (unsigned long)state->pid,
01985 state->request.data.auth.user));
01986
01987 if (!parse_domain_user(state->request.data.chauthtok.user, domain, user)) {
01988 goto done;
01989 }
01990
01991
01992
01993 oldpass = state->request.data.chauthtok.oldpass;
01994 newpass = state->request.data.chauthtok.newpass;
01995
01996
01997 state->response.data.auth.reject_reason = Undefined;
01998
01999
02000
02001 result = cm_connect_sam(contact_domain, state->mem_ctx, &cli,
02002 &dom_pol);
02003 if (!NT_STATUS_IS_OK(result)) {
02004 DEBUG(1, ("could not get SAM handle on DC for %s\n", domain));
02005 goto done;
02006 }
02007
02008 result = rpccli_samr_chgpasswd3(cli, state->mem_ctx, user, newpass, oldpass, &info, &reject);
02009
02010
02011
02012 if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION) ) {
02013 state->response.data.auth.policy.min_length_password =
02014 info.min_length_password;
02015 state->response.data.auth.policy.password_history =
02016 info.password_history;
02017 state->response.data.auth.policy.password_properties =
02018 info.password_properties;
02019 state->response.data.auth.policy.expire =
02020 nt_time_to_unix_abs(&info.expire);
02021 state->response.data.auth.policy.min_passwordage =
02022 nt_time_to_unix_abs(&info.min_passwordage);
02023
02024 state->response.data.auth.reject_reason =
02025 reject.reject_reason;
02026
02027 got_info = True;
02028 }
02029
02030
02031 if ((NT_STATUS_EQUAL(result, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR))) ||
02032 (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) ||
02033 (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED))) {
02034
02035 DEBUG(10,("Password change with chgpasswd3 failed with: %s, retrying chgpasswd_user\n",
02036 nt_errstr(result)));
02037
02038 result = rpccli_samr_chgpasswd_user(cli, state->mem_ctx, user, newpass, oldpass);
02039
02040
02041
02042
02043 if ( NT_STATUS_EQUAL(NT_STATUS_ACCOUNT_RESTRICTION, result ) ) {
02044 result = NT_STATUS_PASSWORD_RESTRICTION;
02045 }
02046 }
02047
02048 done:
02049
02050 if (NT_STATUS_IS_OK(result) && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN)) {
02051
02052
02053 result = winbindd_replace_memory_creds(state->request.data.chauthtok.user,
02054 newpass);
02055
02056
02057
02058
02059
02060
02061
02062 if (NT_STATUS_EQUAL(result, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
02063 result = NT_STATUS_OK;
02064 }
02065
02066 if (!NT_STATUS_IS_OK(result)) {
02067 DEBUG(10,("Failed to replace memory creds: %s\n", nt_errstr(result)));
02068 goto process_result;
02069 }
02070
02071 if (lp_winbind_offline_logon()) {
02072 result = winbindd_update_creds_by_name(contact_domain,
02073 state->mem_ctx, user,
02074 newpass);
02075
02076
02077
02078
02079
02080
02081
02082 if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER)) {
02083 result = NT_STATUS_OK;
02084 }
02085 if (!NT_STATUS_IS_OK(result)) {
02086 DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result)));
02087 goto process_result;
02088 }
02089 }
02090 }
02091
02092 if (!NT_STATUS_IS_OK(result) && !got_info && contact_domain) {
02093
02094 NTSTATUS policy_ret;
02095
02096 policy_ret = fillup_password_policy(contact_domain, state);
02097
02098
02099
02100
02101
02102 if (!NT_STATUS_IS_OK(policy_ret)) {
02103 DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(policy_ret)));
02104 goto process_result;
02105 }
02106 }
02107
02108 process_result:
02109
02110 state->response.data.auth.nt_status = NT_STATUS_V(result);
02111 fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
02112 fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
02113 state->response.data.auth.pam_error = nt_status_to_pam(result);
02114
02115 DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
02116 ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n",
02117 domain,
02118 user,
02119 state->response.data.auth.nt_status_string,
02120 state->response.data.auth.pam_error));
02121
02122 return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
02123 }
02124
02125 void winbindd_pam_logoff(struct winbindd_cli_state *state)
02126 {
02127 struct winbindd_domain *domain;
02128 fstring name_domain, user;
02129 uid_t caller_uid = (uid_t)-1;
02130 uid_t request_uid = state->request.data.logoff.uid;
02131
02132 DEBUG(3, ("[%5lu]: pam logoff %s\n", (unsigned long)state->pid,
02133 state->request.data.logoff.user));
02134
02135
02136 state->request.data.logoff.user
02137 [sizeof(state->request.data.logoff.user)-1]='\0';
02138
02139 state->request.data.logoff.krb5ccname
02140 [sizeof(state->request.data.logoff.krb5ccname)-1]='\0';
02141
02142 if (request_uid == (gid_t)-1) {
02143 goto failed;
02144 }
02145
02146 if (!canonicalize_username(state->request.data.logoff.user, name_domain, user)) {
02147 goto failed;
02148 }
02149
02150 if ((domain = find_auth_domain(state, name_domain)) == NULL) {
02151 goto failed;
02152 }
02153
02154 if ((sys_getpeereid(state->sock, &caller_uid)) != 0) {
02155 DEBUG(1,("winbindd_pam_logoff: failed to check peerid: %s\n",
02156 strerror(errno)));
02157 goto failed;
02158 }
02159
02160 switch (caller_uid) {
02161 case -1:
02162 goto failed;
02163 case 0:
02164
02165 state->request.data.logoff.uid = request_uid;
02166 break;
02167 default:
02168 if (caller_uid != request_uid) {
02169 DEBUG(1,("winbindd_pam_logoff: caller requested invalid uid\n"));
02170 goto failed;
02171 }
02172 state->request.data.logoff.uid = caller_uid;
02173 break;
02174 }
02175
02176 sendto_domain(state, domain);
02177 return;
02178
02179 failed:
02180 set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
02181 DEBUG(5, ("Pam Logoff for %s returned %s "
02182 "(PAM: %d)\n",
02183 state->request.data.logoff.user,
02184 state->response.data.auth.nt_status_string,
02185 state->response.data.auth.pam_error));
02186 request_error(state);
02187 return;
02188 }
02189
02190 enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain,
02191 struct winbindd_cli_state *state)
02192 {
02193 NTSTATUS result = NT_STATUS_NOT_SUPPORTED;
02194
02195 DEBUG(3, ("[%5lu]: pam dual logoff %s\n", (unsigned long)state->pid,
02196 state->request.data.logoff.user));
02197
02198 if (!(state->request.flags & WBFLAG_PAM_KRB5)) {
02199 result = NT_STATUS_OK;
02200 goto process_result;
02201 }
02202
02203 if (state->request.data.logoff.krb5ccname[0] == '\0') {
02204 result = NT_STATUS_OK;
02205 goto process_result;
02206 }
02207
02208 #ifdef HAVE_KRB5
02209
02210 if (state->request.data.logoff.uid < 0) {
02211 DEBUG(0,("winbindd_pam_logoff: invalid uid\n"));
02212 goto process_result;
02213 }
02214
02215
02216
02217
02218 if (!ccache_entry_exists(state->request.data.logoff.user)) {
02219 result = NT_STATUS_OK;
02220 DEBUG(10,("winbindd_pam_logoff: no entry found.\n"));
02221 goto process_result;
02222 }
02223
02224 if (!ccache_entry_identical(state->request.data.logoff.user,
02225 state->request.data.logoff.uid,
02226 state->request.data.logoff.krb5ccname)) {
02227 DEBUG(0,("winbindd_pam_logoff: cached entry differs.\n"));
02228 goto process_result;
02229 }
02230
02231 result = remove_ccache(state->request.data.logoff.user);
02232 if (!NT_STATUS_IS_OK(result)) {
02233 DEBUG(0,("winbindd_pam_logoff: failed to remove ccache: %s\n",
02234 nt_errstr(result)));
02235 goto process_result;
02236 }
02237
02238 #else
02239 result = NT_STATUS_NOT_SUPPORTED;
02240 #endif
02241
02242 process_result:
02243
02244 winbindd_delete_memory_creds(state->request.data.logoff.user);
02245
02246 state->response.data.auth.nt_status = NT_STATUS_V(result);
02247 fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
02248 fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
02249 state->response.data.auth.pam_error = nt_status_to_pam(result);
02250
02251 return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
02252 }
02253
02254
02255
02256 void winbindd_pam_chng_pswd_auth_crap(struct winbindd_cli_state *state)
02257 {
02258 struct winbindd_domain *domain = NULL;
02259 const char *domain_name = NULL;
02260
02261
02262 state->request.data.chng_pswd_auth_crap.user[
02263 sizeof(state->request.data.chng_pswd_auth_crap.user)-1]=0;
02264 state->request.data.chng_pswd_auth_crap.domain[
02265 sizeof(state->request.data.chng_pswd_auth_crap.domain)-1]=0;
02266
02267 DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n",
02268 (unsigned long)state->pid,
02269 state->request.data.chng_pswd_auth_crap.domain,
02270 state->request.data.chng_pswd_auth_crap.user));
02271
02272 if (*state->request.data.chng_pswd_auth_crap.domain != '\0') {
02273 domain_name = state->request.data.chng_pswd_auth_crap.domain;
02274 } else if (lp_winbind_use_default_domain()) {
02275 domain_name = lp_workgroup();
02276 }
02277
02278 if (domain_name != NULL)
02279 domain = find_domain_from_name(domain_name);
02280
02281 if (domain != NULL) {
02282 DEBUG(7, ("[%5lu]: pam auth crap changing pswd in domain: "
02283 "%s\n", (unsigned long)state->pid,domain->name));
02284 sendto_domain(state, domain);
02285 return;
02286 }
02287
02288 set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
02289 DEBUG(5, ("CRAP change password for %s\\%s returned %s (PAM: %d)\n",
02290 state->request.data.chng_pswd_auth_crap.domain,
02291 state->request.data.chng_pswd_auth_crap.user,
02292 state->response.data.auth.nt_status_string,
02293 state->response.data.auth.pam_error));
02294 request_error(state);
02295 return;
02296 }
02297
02298 enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domain *domainSt, struct winbindd_cli_state *state)
02299 {
02300 NTSTATUS result;
02301 DATA_BLOB new_nt_password;
02302 DATA_BLOB old_nt_hash_enc;
02303 DATA_BLOB new_lm_password;
02304 DATA_BLOB old_lm_hash_enc;
02305 fstring domain,user;
02306 POLICY_HND dom_pol;
02307 struct winbindd_domain *contact_domain = domainSt;
02308 struct rpc_pipe_client *cli;
02309
02310
02311 state->request.data.chng_pswd_auth_crap.user[
02312 sizeof(state->request.data.chng_pswd_auth_crap.user)-1]=0;
02313 state->request.data.chng_pswd_auth_crap.domain[
02314 sizeof(state->request.data.chng_pswd_auth_crap.domain)-1]=0;
02315 *domain = 0;
02316 *user = 0;
02317
02318 DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n",
02319 (unsigned long)state->pid,
02320 state->request.data.chng_pswd_auth_crap.domain,
02321 state->request.data.chng_pswd_auth_crap.user));
02322
02323 if (lp_winbind_offline_logon()) {
02324 DEBUG(0,("Refusing password change as winbind offline logons are enabled. "));
02325 DEBUGADD(0,("Changing passwords here would risk inconsistent logons\n"));
02326 result = NT_STATUS_ACCESS_DENIED;
02327 goto done;
02328 }
02329
02330 if (*state->request.data.chng_pswd_auth_crap.domain) {
02331 fstrcpy(domain,state->request.data.chng_pswd_auth_crap.domain);
02332 } else {
02333 parse_domain_user(state->request.data.chng_pswd_auth_crap.user,
02334 domain, user);
02335
02336 if(!*domain) {
02337 DEBUG(3,("no domain specified with username (%s) - "
02338 "failing auth\n",
02339 state->request.data.chng_pswd_auth_crap.user));
02340 result = NT_STATUS_NO_SUCH_USER;
02341 goto done;
02342 }
02343 }
02344
02345 if (!*domain && lp_winbind_use_default_domain()) {
02346 fstrcpy(domain,(char *)lp_workgroup());
02347 }
02348
02349 if(!*user) {
02350 fstrcpy(user, state->request.data.chng_pswd_auth_crap.user);
02351 }
02352
02353 DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n",
02354 (unsigned long)state->pid, domain, user));
02355
02356
02357 new_nt_password = data_blob_talloc(
02358 state->mem_ctx,
02359 state->request.data.chng_pswd_auth_crap.new_nt_pswd,
02360 state->request.data.chng_pswd_auth_crap.new_nt_pswd_len);
02361
02362 old_nt_hash_enc = data_blob_talloc(
02363 state->mem_ctx,
02364 state->request.data.chng_pswd_auth_crap.old_nt_hash_enc,
02365 state->request.data.chng_pswd_auth_crap.old_nt_hash_enc_len);
02366
02367 if(state->request.data.chng_pswd_auth_crap.new_lm_pswd_len > 0) {
02368 new_lm_password = data_blob_talloc(
02369 state->mem_ctx,
02370 state->request.data.chng_pswd_auth_crap.new_lm_pswd,
02371 state->request.data.chng_pswd_auth_crap.new_lm_pswd_len);
02372
02373 old_lm_hash_enc = data_blob_talloc(
02374 state->mem_ctx,
02375 state->request.data.chng_pswd_auth_crap.old_lm_hash_enc,
02376 state->request.data.chng_pswd_auth_crap.old_lm_hash_enc_len);
02377 } else {
02378 new_lm_password.length = 0;
02379 old_lm_hash_enc.length = 0;
02380 }
02381
02382
02383
02384 result = cm_connect_sam(contact_domain, state->mem_ctx, &cli, &dom_pol);
02385 if (!NT_STATUS_IS_OK(result)) {
02386 DEBUG(1, ("could not get SAM handle on DC for %s\n", domain));
02387 goto done;
02388 }
02389
02390 result = rpccli_samr_chng_pswd_auth_crap(
02391 cli, state->mem_ctx, user, new_nt_password, old_nt_hash_enc,
02392 new_lm_password, old_lm_hash_enc);
02393
02394 done:
02395 state->response.data.auth.nt_status = NT_STATUS_V(result);
02396 fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
02397 fstrcpy(state->response.data.auth.error_string,
02398 get_friendly_nt_error_msg(result));
02399 state->response.data.auth.pam_error = nt_status_to_pam(result);
02400
02401 DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
02402 ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n",
02403 domain, user,
02404 state->response.data.auth.nt_status_string,
02405 state->response.data.auth.pam_error));
02406
02407 return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
02408 }