static NTSTATUS append_info3_as_txt | ( | TALLOC_CTX * | mem_ctx, | |
struct winbindd_cli_state * | state, | |||
NET_USER_INFO_3 * | info3 | |||
) | [static] |
winbindd_pam.c の 31 行で定義されています。
参照先 net_user_info_3::acct_flags・winbindd_response::auth・net_user_info_3::bad_pw_count・winbindd_response::data・net_user_info_3::dom_sid・net_user_info_3::group_rid・net_user_info_3::kickoff_time・net_user_info_3::logoff_time・net_user_info_3::logon_count・net_user_info_3::logon_time・nt_time_to_unix()・net_user_info_3::num_groups・net_user_info_3::num_other_sids・net_user_info_3::pass_can_change_time・net_user_info_3::pass_last_set_time・net_user_info_3::pass_must_change_time・winbindd_cli_state::response・DOM_SID2::sid・sid_to_string()・net_user_info_3::uni_dir_drive・net_user_info_3::uni_full_name・net_user_info_3::uni_home_dir・net_user_info_3::uni_logon_dom・net_user_info_3::uni_logon_script・net_user_info_3::uni_logon_srv・net_user_info_3::uni_profile_path・net_user_info_3::uni_user_name・unistr2_to_ascii()・net_user_info_3::user_flgs・net_user_info_3::user_rid.
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 }
static NTSTATUS append_info3_as_ndr | ( | TALLOC_CTX * | mem_ctx, | |
struct winbindd_cli_state * | state, | |||
NET_USER_INFO_3 * | info3 | |||
) | [static] |
winbindd_pam.c の 85 行で定義されています。
参照先 winbindd_response::data・winbindd_response::extra_data・winbindd_response::length・net_io_user_info3()・prs_init()・prs_mem_free()・winbindd_cli_state::response・size.
参照元 winbindd_dual_pam_auth()・winbindd_dual_pam_auth_crap().
00088 { 00089 prs_struct ps; 00090 uint32 size; 00091 if (!prs_init(&ps, 256 /* Random, non-zero number */, 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 }
static NTSTATUS check_info3_in_group | ( | TALLOC_CTX * | mem_ctx, | |
NET_USER_INFO_3 * | info3, | |||
const char * | group_sid | |||
) | [static] |
Check whether a user belongs to a group or list of groups.
mem_ctx | talloc memory context. | |
info3 | user information, including group membership info. | |
group_sid | One or more groups , separated by commas. |
winbindd_pam.c の 113 行で定義されています。
参照先 net_user_info_3::dom_sid・DOM_GID::g_rid・net_user_info_3::gids・net_user_info_3::group_rid・net_user_info_3::num_groups2・net_user_info_3::num_other_sids・require_membership_of_sid・DOM_SID2::sid・sid_append_rid()・sid_copy()・string_to_sid()・net_user_info_3::user_rid.
参照元 winbindd_dual_pam_auth()・winbindd_dual_pam_auth_crap().
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 /* Parse the 'required group' SID */ 00139 00140 if (!group_sid || !group_sid[0]) { 00141 /* NO sid supplied, all users may access */ 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 /* Allocate the maximum possible size */ 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 /* and create (by appending rids) the 'domain' sids */ 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 /* Copy 'other' sids. We need to do sid filtering here to 00230 prevent possible elevation of privileges. See: 00231 00232 http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp 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 /* Do not distinguish this error from a wrong username/pw */ 00255 00256 return NT_STATUS_LOGON_FAILURE; 00257 }
struct winbindd_domain* find_auth_domain | ( | struct winbindd_cli_state * | state, | |
const char * | domain_name | |||
) |
winbindd_pam.c の 259 行で定義されています。
参照先 find_domain_from_name_noinit()・find_our_domain()・winbindd_request::flags・is_myname()・winbindd_cli_state::request.
参照元 winbindd_ccache_ntlm_auth()・winbindd_pam_auth()・winbindd_pam_auth_crap()・winbindd_pam_logoff().
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 /* we can auth against trusted domains */ 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 }
static void set_auth_errors | ( | struct winbindd_response * | resp, | |
NTSTATUS | result | |||
) | [static] |
winbindd_pam.c の 296 行で定義されています。
参照先 winbindd_response::auth・winbindd_response::data・get_friendly_nt_error_msg()・nt_errstr()・nt_status_to_pam()・result.
参照元 winbindd_pam_auth()・winbindd_pam_auth_crap()・winbindd_pam_chauthtok()・winbindd_pam_chng_pswd_auth_crap()・winbindd_pam_logoff().
00297 { 00298 resp->data.auth.nt_status = NT_STATUS_V(result); 00299 fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result)); 00300 00301 /* we might have given a more useful error above */ 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 }
static NTSTATUS fillup_password_policy | ( | struct winbindd_domain * | domain, | |
struct winbindd_cli_state * | state | |||
) | [static] |
winbindd_pam.c の 308 行で定義されています。
参照先 winbindd_response::auth・winbindd_response::data・winbindd_cli_state::mem_ctx・winbindd_domain::methods・methods・nt_time_to_unix_abs()・password_policy()・winbindd_cli_state::response・status.
参照元 winbindd_dual_pam_auth()・winbindd_dual_pam_chauthtok().
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 }
static NTSTATUS get_max_bad_attempts_from_lockout_policy | ( | struct winbindd_domain * | domain, | |
TALLOC_CTX * | mem_ctx, | |||
uint16 * | max_allowed_bad_attempts | |||
) | [static] |
winbindd_pam.c の 336 行で定義されています。
参照先 lockout_policy()・winbindd_domain::methods・methods・status.
参照元 winbindd_dual_pam_auth_cached().
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 }
static NTSTATUS get_pwd_properties | ( | struct winbindd_domain * | domain, | |
TALLOC_CTX * | mem_ctx, | |||
uint32 * | password_properties | |||
) | [static] |
winbindd_pam.c の 358 行で定義されています。
参照先 winbindd_domain::methods・methods・password_policy()・status.
参照元 winbindd_dual_pam_auth_cached().
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 }
static const char* generate_krb5_ccache | ( | TALLOC_CTX * | mem_ctx, | |
const char * | type, | |||
uid_t | uid, | |||
BOOL * | internal_ccache | |||
) | [static] |
winbindd_pam.c の 382 行で定義されています。
参照先 strequal()・talloc_asprintf()・talloc_strdup().
参照元 winbindd_dual_pam_auth_cached()・winbindd_raw_kerberos_login().
00386 { 00387 /* accept FILE and WRFILE as krb5_cc_type from the client and then 00388 * build the full ccname string based on the user's uid here - 00389 * Guenther*/ 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 }
static void setup_return_cc_name | ( | struct winbindd_cli_state * | state, | |
const char * | cc | |||
) | [static] |
winbindd_pam.c の 429 行で定義されています。
参照先 winbindd_response::auth・winbindd_request::auth・winbindd_response::data・winbindd_request::data・winbindd_cli_state::request・winbindd_cli_state::response・strequal()・type.
参照元 winbindd_dual_pam_auth_cached()・winbindd_raw_kerberos_login().
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 }
static uid_t get_uid_from_state | ( | struct winbindd_cli_state * | state | ) | [static] |
winbindd_pam.c の 451 行で定義されています。
参照先 winbindd_request::auth・winbindd_request::data・winbindd_cli_state::request.
参照元 winbindd_dual_pam_auth()・winbindd_dual_pam_auth_cached()・winbindd_raw_kerberos_login().
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 }
static NTSTATUS winbindd_raw_kerberos_login | ( | struct winbindd_domain * | domain, | |
struct winbindd_cli_state * | state, | |||
NET_USER_INFO_3 ** | info3 | |||
) | [static] |
winbindd_pam.c の 469 行で定義されています。
参照先 add_ccache_to_list()・ads_kdestroy()・ads_verify_ticket()・winbindd_domain::alt_name・ADS_STRUCT::auth・winbindd_request::auth・cli_krb5_get_ticket()・winbindd_request::data・data_blob_free()・failed・gain_root_privilege()・generate_krb5_ccache()・get_logon_info_from_pac()・get_uid_from_state()・global_myname・http_timestring()・pac_logon_info::info3・kerberos_kinit_password_ext()・krb5_to_nt_status()・winbindd_cli_state::mem_ctx・nt_errstr()・parse_domain_user()・winbindd_domain::private_data・remove_ccache()・winbindd_cli_state::request・result・set_effective_uid()・setup_return_cc_name()・strlower_m()・strupper_m()・talloc_asprintf()・talloc_strdup()・ADS_STRUCT::time_offset.
参照元 winbindd_dual_pam_auth_kerberos().
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 /* 1st step: 00505 * prepare a krb5_cc_cache string for the user */ 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 /* 2nd step: 00522 * get kerberos properties */ 00523 00524 if (domain->private_data) { 00525 ads = (ADS_STRUCT *)domain->private_data; 00526 time_offset = ads->auth.time_offset; 00527 } 00528 00529 00530 /* 3rd step: 00531 * do kerberos auth and setup ccache as the user */ 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 /* if this is a user ccache, we need to act as the user to let the krb5 00549 * library handle the chown, etc. */ 00550 00551 /************************ NON-ROOT **********************/ 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 /* does http_timestring use heimdals libroken strftime?? - Guenther */ 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 /* we cannot continue with krb5 when UF_DONT_REQUIRE_PREAUTH is set, 00583 * in that case fallback to NTLM - gd */ 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 /************************ NON-ROOT **********************/ 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 /* last step: 00656 * put results together */ 00657 00658 *info3 = &logon_info->info3; 00659 00660 /* if we had a user's ccache then return that string for the pam 00661 * environment */ 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 /* need to delete the memory cred cache, it is not used anymore */ 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 /* we could have created a new credential cache with a valid tgt in it 00702 * but we werent able to get or verify the service ticket for this 00703 * local host and therefor didn't get the PAC, we need to remove that 00704 * cache entirely now */ 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 /* HAVE_KRB5 */ 00735 }
void winbindd_pam_auth | ( | struct winbindd_cli_state * | state | ) |
winbindd_pam.c の 737 行で定義されています。
参照先 winbindd_response::auth・winbindd_request::auth・canonicalize_username()・winbindd_response::data・winbindd_request::data・find_auth_domain()・winbindd_cli_state::pid・winbindd_cli_state::request・request_error()・winbindd_cli_state::response・sendto_domain()・set_auth_errors()・ws_name_return().
00738 { 00739 struct winbindd_domain *domain; 00740 fstring name_domain, name_user; 00741 00742 /* Ensure null termination */ 00743 state->request.data.auth.user 00744 [sizeof(state->request.data.auth.user)-1]='\0'; 00745 00746 /* Ensure null termination */ 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 /* Parse domain and username */ 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 }
NTSTATUS winbindd_dual_pam_auth_cached | ( | struct winbindd_domain * | domain, | |
struct winbindd_cli_state * | state, | |||
NET_USER_INFO_3 ** | info3 | |||
) |
winbindd_pam.c の 785 行で定義されています。
参照先 net_user_info_3::acct_flags・add_ccache_to_list()・winbindd_domain::alt_name・winbindd_request::auth・net_user_info_3::bad_pw_count・winbindd_request::data・dump_data()・E_md4hash()・E_md5hash()・failed・winbindd_request::flags・generate_krb5_ccache()・get_max_bad_attempts_from_lockout_policy()・get_pwd_properties()・get_uid_from_state()・net_user_info_3::kickoff_time・net_user_info_3::logon_time・lookup_cached_name()・winbindd_cli_state::mem_ctx・winbindd_domain::name・nt_errstr()・nt_time_to_unix()・parse_domain_user()・net_user_info_3::pass_must_change_time・winbindd_cli_state::request・result・setup_return_cc_name()・winbindd_domain::sid・SID_NAME_USER・sid_type_lookup()・strequal()・strupper_m()・talloc_asprintf()・type・unix_to_nt_time()・net_user_info_3::user_flgs・net_user_info_3::user_rid・winbindd_get_creds()・winbindd_update_creds_by_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 /* Parse domain and username */ 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 /* In this case we didn't store the nt_hash itself, 00851 but the MD5 combination of salt + nt_hash. */ 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 /* Old cached cred - direct store of nt_hash (bad bad bad !). */ 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 /* User *DOES* know the password, update logon_time and reset 00866 * bad_pw_count */ 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 /* we allow grace logons when the password has expired */ 00904 my_info3->user_flgs |= LOGON_GRACE_LOGON; 00905 /* return NT_STATUS_PASSWORD_EXPIRED; */ 00906 goto success; 00907 } 00908 00909 #ifdef HAVE_KRB5 00910 /* FIXME: what else points out that the remote domain is AD ? */ 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 /* HAVE_KRB5 */ 00971 success: 00972 /* FIXME: we possibly should handle logon hours as well (does xp when 00973 * offline?) see auth/auth_sam.c:sam_account_ok for details */ 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 /* User does *NOT* know the correct password, modify info3 accordingly */ 00994 00995 /* failure of this is not critical */ 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 /* increase counter */ 01003 my_info3->bad_pw_count++; 01004 01005 if (max_allowed_bad_attempts == 0) { 01006 goto failed; 01007 } 01008 01009 /* lockout user */ 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 }
NTSTATUS winbindd_dual_pam_auth_kerberos | ( | struct winbindd_domain * | domain, | |
struct winbindd_cli_state * | state, | |||
NET_USER_INFO_3 ** | info3 | |||
) |
winbindd_pam.c の 1040 行で定義されています。
参照先 winbindd_domain::active_directory・winbindd_request::auth・winbindd_request::data・find_domain_from_name()・find_our_domain()・init_dc_connection()・winbindd_domain::initialized・is_myname()・parse_domain_user()・winbindd_cli_state::request・result・winbindd_raw_kerberos_login().
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 /* Parse domain and username */ 01051 01052 parse_domain_user(state->request.data.auth.user, name_domain, name_user); 01053 01054 /* what domain should we contact? */ 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 }
NTSTATUS winbindd_dual_pam_auth_samlogon | ( | struct winbindd_domain * | domain, | |
struct winbindd_cli_state * | state, | |||
NET_USER_INFO_3 ** | info3 | |||
) |
winbindd_pam.c の 1099 行で定義されています。
参照先 sam_user_info_16::acb_info・net_user_info_3::acct_flags・winbindd_request::auth・cm_connect_netlogon()・cm_connect_sam()・winbindd_domain::conn・data_blob_::data・winbindd_request::data・data_blob()・data_blob_free()・data_blob_talloc()・winbindd_domain::dcname・find_domain_from_name()・find_our_domain()・winbindd_request::flags・generate_random_buffer()・global_myname・sam_userinfo_ctr_info::id16・sam_userinfo_ctr_info::info・invalidate_cm_connection()・is_myname()・data_blob_::length・lp_workgroup()・winbindd_cli_state::mem_ctx・nt_errstr()・NTLMv2_generate_names_blob()・parse_domain_user()・winbindd_cli_state::request・result・rpccli_netlogon_sam_network_logon()・rpccli_samr_close()・rpccli_samr_open_user()・rpccli_samr_query_userinfo()・SMBencrypt()・SMBNTencrypt()・SMBNTLMv2encrypt()・net_user_info_3::user_rid.
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 /* Parse domain and username */ 01130 01131 parse_domain_user(state->request.data.auth.user, name_domain, name_user); 01132 01133 /* do password magic */ 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 /* note that the 'workgroup' here is a best guess - we don't know 01145 the server's domain at this point. The 'server name' is also 01146 dodgy... 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 /* what domain should we contact? */ 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 /* check authentication loop */ 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, /* server name */ 01228 name_user, /* user name */ 01229 name_domain, /* target domain */ 01230 global_myname(), /* workstation */ 01231 chal, 01232 lm_resp, 01233 nt_resp, 01234 my_info3); 01235 attempts += 1; 01236 01237 /* We have to try a second time as cm_connect_netlogon 01238 might not yet have noticed that the DC has killed 01239 our connection. */ 01240 01241 if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { 01242 retry = True; 01243 continue; 01244 } 01245 01246 /* if we get access denied, a possible cause was that we had 01247 and open connection to the DC, but someone changed our 01248 machine account password out from underneath us using 'net 01249 rpc changetrustpw' */ 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 /* handle the case where a NT4 DC does not fill in the acct_flags in 01264 * the samlogon reply info3. When accurate info3 is required by the 01265 * caller, we look up the account flags ourselve - gd */ 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 }
enum winbindd_result winbindd_dual_pam_auth | ( | struct winbindd_domain * | domain, | |
struct winbindd_cli_state * | state | |||
) |
winbindd_pam.c の 1327 行で定義されています。
参照先 afs_createtoken_str()・append_info3_as_ndr()・append_info3_as_txt()・winbindd_response::auth・winbindd_request::auth・cache_name2sid()・check_info3_in_group()・winbindd_response::data・winbindd_request::data・net_user_info_3::dom_sid・rpc_pipe_client::domain・winbindd_response::extra_data・fill_domain_username()・fillup_password_policy()・find_domain_from_name()・winbindd_request::flags・get_friendly_nt_error_msg()・get_uid_from_state()・init_dc_connection()・winbindd_response::length・winbindd_cli_state::mem_ctx・netsamlogon_cache_store()・nt_errstr()・nt_status_to_pam()・parse_domain_user()・winbindd_cli_state::pid・winbindd_cli_state::request・winbindd_cli_state::response・result・set_domain_offline()・DOM_SID2::sid・sid_append_rid()・sid_compose()・sid_copy()・SID_NAME_USER・sid_to_string()・strlower_m()・talloc_strdup()・talloc_string_sub()・net_user_info_3::uni_logon_dom・net_user_info_3::uni_user_name・unistr2_tdup()・net_user_info_3::user_rid・wcache_invalidate_samlogon()・winbindd_add_memory_creds()・winbindd_delete_memory_creds()・winbindd_dual_pam_auth_cached()・winbindd_dual_pam_auth_kerberos()・winbindd_dual_pam_auth_samlogon()・WINBINDD_ERROR・winbindd_flush_negative_conn_cache()・WINBINDD_OK・winbindd_store_creds()・ws_name_return().
01329 { 01330 NTSTATUS result = NT_STATUS_LOGON_FAILURE; 01331 fstring name_domain, name_user; 01332 NET_USER_INFO_3 *info3 = NULL; 01333 01334 /* Ensure null termination */ 01335 state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0'; 01336 01337 /* Ensure null termination */ 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 /* Parse domain and username */ 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 /* Logons are very important to users. If we're offline and 01353 we get a request within the first 30 seconds of startup, 01354 try very hard to find a DC and go online. */ 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 /* Check for Kerberos authentication */ 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 /* Use set_domain_offline() instead of 01383 * just set status offline, otherwise, 01384 * domain will never goes online again 01385 * --- BoYang */ 01386 set_domain_offline(domain); 01387 } 01388 01389 /* there are quite some NT_STATUS errors where there is no 01390 * point in retrying with a samlogon, we explictly have to take 01391 * care not to increase the bad logon counter on the DC */ 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 /* Check for Samlogon authentication */ 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 /* We're still online - fail. */ 01426 goto done; 01427 } 01428 /* Else drop through and see if we can check offline.... */ 01429 } 01430 } 01431 01432 cached_logon: 01433 /* Check for Cached logons */ 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 /* In all codepaths where result == NT_STATUS_OK info3 must have 01455 been initialized. */ 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 /* save name_to_sid info as early as possible */ 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 /* Check if the user is in the right group */ 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 /* Store in-memory creds for single-signon using ntlm_auth. */ 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 /* Release refcount. */ 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 /* We've been asked to return the unix username, per 01535 'winbind use default domain' settings and the like */ 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 /* If the server didn't give us one, just use the one we sent them */ 01542 nt_username = name_user; 01543 } 01544 01545 if (!(nt_domain = unistr2_tdup(state->mem_ctx, &info3->uni_logon_dom))) { 01546 /* If the server didn't give us one, just use the one we sent them */ 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 /* give us a more useful (more correct?) error code */ 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 /* we might have given a more useful error above */ 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 /* Append an AFS token string */ 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 }
void winbindd_pam_auth_crap | ( | struct winbindd_cli_state * | state | ) |
winbindd_pam.c の 1655 行で定義されています。
参照先 winbindd_response::auth・winbindd_request::auth_crap・winbindd_request::data・winbindd_response::data・domain_name・find_auth_domain()・get_winbind_priv_pipe_dir()・lp_workgroup()・winbindd_cli_state::mem_ctx・winbindd_cli_state::pid・winbindd_cli_state::privileged・winbindd_cli_state::request・request_error()・winbindd_cli_state::response・result・sendto_domain()・set_auth_errors()・talloc_asprintf().
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 /* send a better message than ACCESS_DENIED */ 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 /* Ensure null termination */ 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 }
enum winbindd_result winbindd_dual_pam_auth_crap | ( | struct winbindd_domain * | domain, | |
struct winbindd_cli_state * | state | |||
) |
winbindd_pam.c の 1719 行で定義されています。
参照先 append_info3_as_ndr()・winbindd_response::auth・winbindd_request::auth_crap・check_info3_in_group()・cm_connect_netlogon()・winbindd_domain::conn・winbindd_response::data・winbindd_request::data・data_blob_talloc()・winbindd_domain::dcname・winbindd_response::extra_data・fill_domain_username()・find_domain_from_name()・find_our_domain()・winbindd_request::flags・get_friendly_nt_error_msg()・global_myname・invalidate_cm_connection()・is_myname()・winbindd_response::length・net_user_info_3::lm_sess_key・lp_workgroup()・winbindd_cli_state::mem_ctx・netsamlogon_cache_store()・nt_errstr()・nt_status_squash()・nt_status_to_pam()・winbindd_cli_state::pid・winbindd_cli_state::request・winbindd_cli_state::response・result・rpccli_netlogon_sam_network_logon()・net_user_info_3::uni_logon_dom・net_user_info_3::uni_user_name・unistr2_tdup()・net_user_info_3::user_sess_key・wcache_invalidate_samlogon()・WINBINDD_ERROR・WINBINDD_OK.
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 /* This is child-only, so no check for privileged access is needed 01735 anymore */ 01736 01737 /* Ensure null termination */ 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 /* what domain should we contact? */ 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 /* Bug #3248 - found by Stefan Burkei. */ 01815 workstation, /* We carefully set this above so use it... */ 01816 state->request.data.auth_crap.chal, 01817 lm_resp, 01818 nt_resp, 01819 &info3); 01820 01821 attempts += 1; 01822 01823 /* We have to try a second time as cm_connect_netlogon 01824 might not yet have noticed that the DC has killed 01825 our connection. */ 01826 01827 if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { 01828 retry = True; 01829 continue; 01830 } 01831 01832 /* if we get access denied, a possible cause was that we had and open 01833 connection to the DC, but someone changed our machine account password 01834 out from underneath us using 'net rpc changetrustpw' */ 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 /* Check if the user is in the right group */ 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 /* ntlm_auth should return the unix username, per 01867 'winbind use default domain' settings and the like */ 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 /* If the server didn't give us one, just use the one we sent them */ 01873 nt_username = name_user; 01874 } 01875 01876 if (!(nt_domain = unistr2_tdup(state->mem_ctx, &(info3.uni_logon_dom)))) { 01877 /* If the server didn't give us one, just use the one we sent them */ 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) /* 16 */); 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) /* 8 */); 01902 } 01903 } 01904 01905 done: 01906 01907 /* give us a more useful (more correct?) error code */ 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 /* we might have given a more useful error above */ 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 }
void winbindd_pam_chauthtok | ( | struct winbindd_cli_state * | state | ) |
winbindd_pam.c の 1938 行で定義されています。
参照先 winbindd_response::auth・winbindd_request::auth・canonicalize_username()・winbindd_request::chauthtok・winbindd_response::data・winbindd_request::data・find_domain_from_name()・winbindd_cli_state::pid・winbindd_cli_state::request・request_error()・winbindd_cli_state::response・sendto_domain()・set_auth_errors().
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 /* Setup crap */ 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 }
enum winbindd_result winbindd_dual_pam_chauthtok | ( | struct winbindd_domain * | contact_domain, | |
struct winbindd_cli_state * | state | |||
) |
winbindd_pam.c の 1971 行で定義されています。
参照先 winbindd_response::auth・winbindd_request::auth・winbindd_request::chauthtok・cli・cm_connect_sam()・winbindd_response::data・winbindd_request::data・rpc_pipe_client::domain・sam_unknown_info_1_inf::expire・fillup_password_policy()・winbindd_request::flags・get_friendly_nt_error_msg()・winbindd_cli_state::mem_ctx・sam_unknown_info_1_inf::min_length_password・sam_unknown_info_1_inf::min_passwordage・nt_errstr()・nt_status_to_pam()・nt_time_to_unix_abs()・parse_domain_user()・sam_unknown_info_1_inf::password_history・sam_unknown_info_1_inf::password_properties・winbindd_cli_state::pid・samr_change_reject::reject_reason・winbindd_cli_state::request・winbindd_cli_state::response・result・rpccli_samr_chgpasswd3()・rpccli_samr_chgpasswd_user()・WINBINDD_ERROR・WINBINDD_OK・winbindd_replace_memory_creds()・winbindd_update_creds_by_name().
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 /* Change password */ 01992 01993 oldpass = state->request.data.chauthtok.oldpass; 01994 newpass = state->request.data.chauthtok.newpass; 01995 01996 /* Initialize reject reason */ 01997 state->response.data.auth.reject_reason = Undefined; 01998 01999 /* Get sam handle */ 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 /* Windows 2003 returns NT_STATUS_PASSWORD_RESTRICTION */ 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 /* only fallback when the chgpasswd3 call is not supported */ 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 /* Windows 2000 returns NT_STATUS_ACCOUNT_RESTRICTION. 02041 Map to the same status code as Windows 2003. */ 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 /* Update the single sign-on memory creds. */ 02053 result = winbindd_replace_memory_creds(state->request.data.chauthtok.user, 02054 newpass); 02055 02056 /* When we login from gdm or xdm and password expires, 02057 * we change the password, but there are no memory crendentials. 02058 * So, winbindd_replace_memory_creds() returns 02059 * NT_STATUS_OBJECT_NAME_NOT_FOUND. This is not a failure. 02060 * --- BoYang 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 /* Again, this happens when we login from gdm or xdm 02076 * and the password expires, *BUT* cached crendentials 02077 * don't exist. winbindd_update_creds_by_name() 02078 * returns NT_STATUS_NO_SUCH_USER. 02079 * This is not a failure. 02080 * --- BoYang 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 /* failure of this is non critical, it will just provide no 02099 * additional information to the client why the change has 02100 * failed - Guenther */ 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 }
void winbindd_pam_logoff | ( | struct winbindd_cli_state * | state | ) |
winbindd_pam.c の 2125 行で定義されています。
参照先 winbindd_response::auth・canonicalize_username()・winbindd_response::data・winbindd_request::data・errno・failed・find_auth_domain()・winbindd_request::logoff・winbindd_cli_state::pid・winbindd_cli_state::request・request_error()・winbindd_cli_state::response・sendto_domain()・set_auth_errors()・winbindd_cli_state::sock・strerror()・sys_getpeereid().
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 /* Ensure null termination */ 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 /* root must be able to logoff any user - gd */ 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 }
enum winbindd_result winbindd_dual_pam_logoff | ( | struct winbindd_domain * | domain, | |
struct winbindd_cli_state * | state | |||
) |
winbindd_pam.c の 2190 行で定義されています。
参照先 winbindd_response::auth・ccache_entry_exists()・ccache_entry_identical()・winbindd_response::data・winbindd_request::data・winbindd_request::flags・get_friendly_nt_error_msg()・winbindd_request::logoff・nt_errstr()・nt_status_to_pam()・winbindd_cli_state::pid・remove_ccache()・winbindd_cli_state::request・winbindd_cli_state::response・result・winbindd_delete_memory_creds()・WINBINDD_ERROR・WINBINDD_OK.
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 /* what we need here is to find the corresponding krb5 ccache name *we* 02216 * created for a given username and destroy it */ 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 }
void winbindd_pam_chng_pswd_auth_crap | ( | struct winbindd_cli_state * | state | ) |
winbindd_pam.c の 2256 行で定義されています。
参照先 winbindd_response::auth・winbindd_request::chng_pswd_auth_crap・winbindd_response::data・winbindd_request::data・domain_name・find_domain_from_name()・lp_workgroup()・winbindd_domain::name・winbindd_cli_state::pid・winbindd_cli_state::request・request_error()・winbindd_cli_state::response・sendto_domain()・set_auth_errors().
02257 { 02258 struct winbindd_domain *domain = NULL; 02259 const char *domain_name = NULL; 02260 02261 /* Ensure null termination */ 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 }
enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap | ( | struct winbindd_domain * | domainSt, | |
struct winbindd_cli_state * | state | |||
) |
winbindd_pam.c の 2298 行で定義されています。
参照先 winbindd_response::auth・winbindd_request::chng_pswd_auth_crap・cli・cm_connect_sam()・winbindd_response::data・winbindd_request::data・data_blob_talloc()・get_friendly_nt_error_msg()・data_blob_::length・lp_workgroup()・winbindd_cli_state::mem_ctx・nt_errstr()・nt_status_to_pam()・parse_domain_user()・winbindd_cli_state::pid・winbindd_cli_state::request・winbindd_cli_state::response・result・rpccli_samr_chng_pswd_auth_crap()・WINBINDD_ERROR・WINBINDD_OK.
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 /* Ensure null termination */ 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 /* Change password */ 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 /* Get sam handle */ 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 }