データ構造 | |
struct | ntstatus_errors |
関数 | |
static int | _pam_get_item (const pam_handle_t *pamh, int item_type, const void *_item) |
static int | _pam_get_data (const pam_handle_t *pamh, const char *module_data_name, const void *_data) |
static void | _pam_log_int (const pam_handle_t *pamh, int err, const char *format, va_list args) |
static BOOL | _pam_log_is_silent (int ctrl) |
static void | _pam_log (const pam_handle_t *pamh, int ctrl, int err, const char *format,...) PRINTF_ATTRIBUTE(4 |
static BOOL | _pam_log_is_debug_enabled (int ctrl) |
static BOOL | _pam_log_is_debug_state_enabled (int ctrl) |
static void | _pam_log_debug (const pam_handle_t *pamh, int ctrl, int err, const char *format,...) PRINTF_ATTRIBUTE(4 |
static void | _pam_log_state_datum (const pam_handle_t *pamh, int ctrl, int item_type, const char *key, int is_string) |
static void | _pam_log_state (const pam_handle_t *pamh, int ctrl) |
static int | _pam_parse (const pam_handle_t *pamh, int flags, int argc, const char **argv, dictionary **result_d) |
static void | _pam_winbind_cleanup_func (pam_handle_t *pamh, void *data, int error_status) |
const char * | _get_ntstatus_error_string (const char *nt_status_string) |
static int | converse (pam_handle_t *pamh, int nargs, struct pam_message **message, struct pam_response **response) |
static int | _make_remark (pam_handle_t *pamh, int flags, int type, const char *text) |
static int | _make_remark_v (pam_handle_t *pamh, int flags, int type, const char *format, va_list args) |
static int | _make_remark_format (pam_handle_t *pamh, int flags, int type, const char *format,...) PRINTF_ATTRIBUTE(4 |
static int | pam_winbind_request (pam_handle_t *pamh, int ctrl, enum winbindd_cmd req_type, struct winbindd_request *request, struct winbindd_response *response) |
static int | pam_winbind_request_log (pam_handle_t *pamh, int ctrl, enum winbindd_cmd req_type, struct winbindd_request *request, struct winbindd_response *response, const char *user) |
static BOOL | _pam_send_password_expiry_message (pam_handle_t *pamh, int ctrl, time_t next_change, time_t now, BOOL *already_expired) |
send a password expiry message if required | |
static void | _pam_warn_password_expiry (pam_handle_t *pamh, int flags, const struct winbindd_response *response, BOOL *already_expired) |
Send a warning if the password expires in the near future | |
static BOOL | safe_append_string (char *dest, const char *src, int dest_buffer_size) |
Append a string, making sure not to overflow and to always return a NULL-terminated string. | |
static BOOL | winbind_name_to_sid_string (pam_handle_t *pamh, int ctrl, const char *user, const char *name, char *sid_list_buffer, int sid_list_buffer_size) |
Convert a names into a SID string, appending it to a buffer. | |
static BOOL | winbind_name_list_to_sid_string_list (pam_handle_t *pamh, int ctrl, const char *user, const char *name_list, char *sid_list_buffer, int sid_list_buffer_size) |
Convert a list of names into a list of sids. | |
static void | _pam_setup_krb5_env (pam_handle_t *pamh, int ctrl, const char *krb5ccname) |
put krb5ccname variable into environment | |
static void | _pam_set_data_string (pam_handle_t *pamh, int ctrl, const char *data_name, const char *value) |
Set string into the PAM stack. | |
static void | _pam_set_data_info3 (pam_handle_t *pamh, int ctrl, struct winbindd_response *response) |
Set info3 strings into the PAM stack. | |
static void | _pam_free_data_info3 (pam_handle_t *pamh) |
Free info3 strings in the PAM stack. | |
static void | _pam_warn_logon_type (pam_handle_t *pamh, int ctrl, const char *username, uint32 info3_user_flgs) |
Send PAM_ERROR_MSG for cached or grace logons. | |
static char * | _pam_compose_pwd_restriction_string (struct winbindd_response *response) |
Compose Password Restriction String for a PAM_ERROR_MSG conversation. | |
static int | winbind_auth_request (pam_handle_t *pamh, int ctrl, const char *user, const char *pass, const char *member, const char *cctype, struct winbindd_response *p_response, time_t *pwd_last_set, char **user_ret) |
static int | winbind_chauthtok_request (pam_handle_t *pamh, int ctrl, const char *user, const char *oldpass, const char *newpass, time_t pwd_last_set) |
static int | valid_user (pam_handle_t *pamh, int ctrl, const char *user) |
static char * | _pam_delete (register char *xx) |
static int | _winbind_read_password (pam_handle_t *pamh, unsigned int ctrl, const char *comment, const char *prompt1, const char *prompt2, const char **pass) |
const char * | get_conf_item_string (const pam_handle_t *pamh, int argc, const char **argv, int ctrl, dictionary *d, const char *item, int config_flag) |
const char * | get_krb5_cc_type_from_config (const pam_handle_t *pamh, int argc, const char **argv, int ctrl, dictionary *d) |
const char * | get_member_from_config (const pam_handle_t *pamh, int argc, const char **argv, int ctrl, dictionary *d) |
PAM_EXTERN int | pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, const char **argv) |
PAM_EXTERN int | pam_sm_setcred (pam_handle_t *pamh, int flags, int argc, const char **argv) |
PAM_EXTERN int | pam_sm_acct_mgmt (pam_handle_t *pamh, int flags, int argc, const char **argv) |
PAM_EXTERN int | pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv) |
PAM_EXTERN int | pam_sm_close_session (pam_handle_t *pamh, int flags, int argc, const char **argv) |
static BOOL | _pam_require_krb5_auth_after_chauthtok (pam_handle_t *pamh, int ctrl, const char *user) |
evaluate whether we need to re-authenticate with kerberos after a password change | |
PAM_EXTERN int | pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv) |
変数 | |
pam_module | _pam_winbind_modstruct |
static int _pam_get_item | ( | const pam_handle_t * | pamh, | |
int | item_type, | |||
const void * | _item | |||
) | [static] |
pam_winbind.c の 35 行で定義されています。
参照元 _winbind_read_password()・converse()・pam_sm_chauthtok().
00037 { 00038 const void **item = (const void **)_item; 00039 return pam_get_item(pamh, item_type, item); 00040 }
static int _pam_get_data | ( | const pam_handle_t * | pamh, | |
const char * | module_data_name, | |||
const void * | _data | |||
) | [static] |
pam_winbind.c の 41 行で定義されています。
参照元 _pam_require_krb5_auth_after_chauthtok()・pam_sm_chauthtok().
00043 { 00044 const void **data = (const void **)_data; 00045 return pam_get_data(pamh, module_data_name, data); 00046 }
static void _pam_log_int | ( | const pam_handle_t * | pamh, | |
int | err, | |||
const char * | format, | |||
va_list | args | |||
) | [static] |
pam_winbind.c の 51 行で定義されています。
参照元 _pam_log()・_pam_log_debug().
00052 { 00053 pam_vsyslog(pamh, err, format, args); 00054 }
static BOOL _pam_log_is_silent | ( | int | ctrl | ) | [static] |
static void static void _pam_log | ( | const pam_handle_t * | pamh, | |
int | ctrl, | |||
int | err, | |||
const char * | format, | |||
... | ||||
) | [static] |
pam_winbind.c の 82 行で定義されています。
参照先 _pam_log_int()・_pam_log_is_silent().
参照元 _make_remark_v()・_pam_parse()・_pam_setup_krb5_env()・_winbind_read_password()・get_conf_item_string()・pam_sm_acct_mgmt()・pam_sm_authenticate()・pam_sm_chauthtok()・pam_sm_close_session()・pam_winbind_request()・pam_winbind_request_log()・winbind_name_to_sid_string().
00083 { 00084 va_list args; 00085 00086 if (_pam_log_is_silent(ctrl)) { 00087 return; 00088 } 00089 00090 va_start(args, format); 00091 _pam_log_int(pamh, err, format, args); 00092 va_end(args); 00093 }
static BOOL _pam_log_is_debug_enabled | ( | int | ctrl | ) | [static] |
pam_winbind.c の 95 行で定義されています。
参照先 _pam_log_is_silent().
参照元 _pam_log_debug()・_pam_log_is_debug_state_enabled().
00096 { 00097 if (ctrl == -1) { 00098 return False; 00099 } 00100 00101 if (_pam_log_is_silent(ctrl)) { 00102 return False; 00103 } 00104 00105 if (!(ctrl & WINBIND_DEBUG_ARG)) { 00106 return False; 00107 } 00108 00109 return True; 00110 }
static BOOL _pam_log_is_debug_state_enabled | ( | int | ctrl | ) | [static] |
pam_winbind.c の 112 行で定義されています。
参照先 _pam_log_is_debug_enabled().
参照元 _pam_log_state()・_pam_winbind_cleanup_func().
00113 { 00114 if (!(ctrl & WINBIND_DEBUG_STATE)) { 00115 return False; 00116 } 00117 00118 return _pam_log_is_debug_enabled(ctrl); 00119 }
static void static void _pam_log_debug | ( | const pam_handle_t * | pamh, | |
int | ctrl, | |||
int | err, | |||
const char * | format, | |||
... | ||||
) | [static] |
pam_winbind.c の 122 行で定義されています。
参照先 _pam_log_int()・_pam_log_is_debug_enabled().
参照元 _pam_log_state_datum()・_pam_set_data_string()・_pam_setup_krb5_env()・_pam_warn_logon_type()・_pam_winbind_cleanup_func()・_winbind_read_password()・get_conf_item_string()・pam_sm_acct_mgmt()・pam_sm_authenticate()・pam_sm_chauthtok()・pam_sm_close_session()・pam_sm_setcred()・pam_winbind_request_log()・winbind_auth_request()・winbind_chauthtok_request()・winbind_name_to_sid_string().
00123 { 00124 va_list args; 00125 00126 if (!_pam_log_is_debug_enabled(ctrl)) { 00127 return; 00128 } 00129 00130 va_start(args, format); 00131 _pam_log_int(pamh, err, format, args); 00132 va_end(args); 00133 }
static void _pam_log_state_datum | ( | const pam_handle_t * | pamh, | |
int | ctrl, | |||
int | item_type, | |||
const char * | key, | |||
int | is_string | |||
) | [static] |
pam_winbind.c の 135 行で定義されています。
参照先 _pam_log_debug()・type.
00136 { 00137 const void *data = NULL; 00138 if (item_type != 0) { 00139 pam_get_item(pamh, item_type, &data); 00140 } else { 00141 pam_get_data(pamh, key, &data); 00142 } 00143 if (data != NULL) { 00144 const char *type = (item_type != 0) ? "ITEM" : "DATA"; 00145 if (is_string != 0) { 00146 _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] STATE: %s(%s) = \"%s\" (0x%08x)", (uint32) pamh, type, key, (const char *) data, (uint32) data); 00147 } else { 00148 _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] STATE: %s(%s) = 0x%08x", (uint32) pamh, type, key, (uint32) data); 00149 } 00150 } 00151 }
static void _pam_log_state | ( | const pam_handle_t * | pamh, | |
int | ctrl | |||
) | [static] |
pam_winbind.c の 174 行で定義されています。
参照先 _pam_log_is_debug_state_enabled().
00175 { 00176 if (!_pam_log_is_debug_state_enabled(ctrl)) { 00177 return; 00178 } 00179 00180 _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_SERVICE); 00181 _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_USER); 00182 _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_TTY); 00183 _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_RHOST); 00184 _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_RUSER); 00185 _PAM_LOG_STATE_ITEM_PASSWORD(pamh, ctrl, PAM_OLDAUTHTOK); 00186 _PAM_LOG_STATE_ITEM_PASSWORD(pamh, ctrl, PAM_AUTHTOK); 00187 _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_USER_PROMPT); 00188 _PAM_LOG_STATE_ITEM_POINTER(pamh, ctrl, PAM_CONV); 00189 #ifdef PAM_FAIL_DELAY 00190 _PAM_LOG_STATE_ITEM_POINTER(pamh, ctrl, PAM_FAIL_DELAY); 00191 #endif 00192 #ifdef PAM_REPOSITORY 00193 _PAM_LOG_STATE_ITEM_POINTER(pamh, ctrl, PAM_REPOSITORY); 00194 #endif 00195 00196 _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_HOMEDIR); 00197 _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_LOGONSCRIPT); 00198 _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_LOGONSERVER); 00199 _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_PROFILEPATH); 00200 _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_NEW_AUTHTOK_REQD); /* Use atoi to get PAM result code */ 00201 _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH); 00202 _PAM_LOG_STATE_DATA_POINTER(pamh, ctrl, PAM_WINBIND_PWD_LAST_SET); 00203 }
static int _pam_parse | ( | const pam_handle_t * | pamh, | |
int | flags, | |||
int | argc, | |||
const char ** | argv, | |||
dictionary ** | result_d | |||
) | [static] |
pam_winbind.c の 205 行で定義されています。
参照先 _pam_log()・iniparser_freedict()・iniparser_getboolean()・iniparser_getstr()・iniparser_load().
参照元 _pam_winbind_cleanup_func()・pam_sm_acct_mgmt()・pam_sm_authenticate()・pam_sm_chauthtok()・pam_sm_close_session()・pam_sm_open_session()・pam_sm_setcred().
00206 { 00207 int ctrl = 0; 00208 const char *config_file = NULL; 00209 int i; 00210 const char **v; 00211 dictionary *d = NULL; 00212 00213 if (flags & PAM_SILENT) { 00214 ctrl |= WINBIND_SILENT; 00215 } 00216 00217 for (i=argc,v=argv; i-- > 0; ++v) { 00218 if (!strncasecmp(*v, "config", strlen("config"))) { 00219 ctrl |= WINBIND_CONFIG_FILE; 00220 config_file = v[i]; 00221 break; 00222 } 00223 } 00224 00225 if (config_file == NULL) { 00226 config_file = PAM_WINBIND_CONFIG_FILE; 00227 } 00228 00229 d = iniparser_load(config_file); 00230 if (d == NULL) { 00231 goto config_from_pam; 00232 } 00233 00234 if (iniparser_getboolean(d, "global:debug", False)) { 00235 ctrl |= WINBIND_DEBUG_ARG; 00236 } 00237 00238 if (iniparser_getboolean(d, "global:debug_state", False)) { 00239 ctrl |= WINBIND_DEBUG_STATE; 00240 } 00241 00242 if (iniparser_getboolean(d, "global:cached_login", False)) { 00243 ctrl |= WINBIND_CACHED_LOGIN; 00244 } 00245 00246 if (iniparser_getboolean(d, "global:krb5_auth", False)) { 00247 ctrl |= WINBIND_KRB5_AUTH; 00248 } 00249 00250 if (iniparser_getboolean(d, "global:silent", False)) { 00251 ctrl |= WINBIND_SILENT; 00252 } 00253 00254 if (iniparser_getstr(d, "global:krb5_ccache_type") != NULL) { 00255 ctrl |= WINBIND_KRB5_CCACHE_TYPE; 00256 } 00257 00258 if ((iniparser_getstr(d, "global:require-membership-of") != NULL) || 00259 (iniparser_getstr(d, "global:require_membership_of") != NULL)) { 00260 ctrl |= WINBIND_REQUIRED_MEMBERSHIP; 00261 } 00262 00263 if (iniparser_getboolean(d, "global:try_first_pass", False)) { 00264 ctrl |= WINBIND_TRY_FIRST_PASS_ARG; 00265 } 00266 00267 config_from_pam: 00268 /* step through arguments */ 00269 for (i=argc,v=argv; i-- > 0; ++v) { 00270 00271 /* generic options */ 00272 if (!strcmp(*v,"debug")) 00273 ctrl |= WINBIND_DEBUG_ARG; 00274 else if (!strcasecmp(*v, "debug_state")) 00275 ctrl |= WINBIND_DEBUG_STATE; 00276 else if (!strcasecmp(*v, "use_authtok")) 00277 ctrl |= WINBIND_USE_AUTHTOK_ARG; 00278 else if (!strcasecmp(*v, "use_first_pass")) 00279 ctrl |= WINBIND_USE_FIRST_PASS_ARG; 00280 else if (!strcasecmp(*v, "try_first_pass")) 00281 ctrl |= WINBIND_TRY_FIRST_PASS_ARG; 00282 else if (!strcasecmp(*v, "unknown_ok")) 00283 ctrl |= WINBIND_UNKNOWN_OK_ARG; 00284 else if (!strncasecmp(*v, "require_membership_of", strlen("require_membership_of"))) 00285 ctrl |= WINBIND_REQUIRED_MEMBERSHIP; 00286 else if (!strncasecmp(*v, "require-membership-of", strlen("require-membership-of"))) 00287 ctrl |= WINBIND_REQUIRED_MEMBERSHIP; 00288 else if (!strcasecmp(*v, "krb5_auth")) 00289 ctrl |= WINBIND_KRB5_AUTH; 00290 else if (!strncasecmp(*v, "krb5_ccache_type", strlen("krb5_ccache_type"))) 00291 ctrl |= WINBIND_KRB5_CCACHE_TYPE; 00292 else if (!strcasecmp(*v, "cached_login")) 00293 ctrl |= WINBIND_CACHED_LOGIN; 00294 else { 00295 _pam_log(pamh, ctrl, LOG_ERR, "pam_parse: unknown option: %s", *v); 00296 return -1; 00297 } 00298 00299 } 00300 00301 if (result_d) { 00302 *result_d = d; 00303 } else { 00304 if (d) { 00305 iniparser_freedict(d); 00306 } 00307 } 00308 00309 return ctrl; 00310 };
static void _pam_winbind_cleanup_func | ( | pam_handle_t * | pamh, | |
void * | data, | |||
int | error_status | |||
) | [static] |
pam_winbind.c の 312 行で定義されています。
参照先 _pam_log_debug()・_pam_log_is_debug_state_enabled()・_pam_parse().
参照元 _pam_set_data_string()・pam_sm_authenticate().
00313 { 00314 int ctrl = _pam_parse(pamh, 0, 0, NULL, NULL); 00315 if (_pam_log_is_debug_state_enabled(ctrl)) { 00316 _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] CLEAN: cleaning up PAM data 0x%08x (error_status = %d)", (uint32) pamh, (uint32) data, error_status); 00317 } 00318 SAFE_FREE(data); 00319 }
const char* _get_ntstatus_error_string | ( | const char * | nt_status_string | ) |
pam_winbind.c の 347 行で定義されています。
00348 { 00349 int i; 00350 for (i=0; ntstatus_errors[i].ntstatus_string != NULL; i++) { 00351 if (!strcasecmp(ntstatus_errors[i].ntstatus_string, nt_status_string)) { 00352 return ntstatus_errors[i].error_string; 00353 } 00354 } 00355 return NULL; 00356 }
static int converse | ( | pam_handle_t * | pamh, | |
int | nargs, | |||
struct pam_message ** | message, | |||
struct pam_response ** | response | |||
) | [static] |
pam_winbind.c の 362 行で定義されています。
参照先 _pam_get_item().
参照元 _cleanup_failures()・_make_remark()・_winbind_read_password()・make_remark().
00365 { 00366 int retval; 00367 struct pam_conv *conv; 00368 00369 retval = _pam_get_item(pamh, PAM_CONV, &conv ); 00370 if (retval == PAM_SUCCESS) { 00371 retval = conv->conv(nargs, (const struct pam_message **)message, 00372 response, conv->appdata_ptr); 00373 } 00374 00375 return retval; /* propagate error status */ 00376 }
static int _make_remark | ( | pam_handle_t * | pamh, | |
int | flags, | |||
int | type, | |||
const char * | text | |||
) | [static] |
pam_winbind.c の 379 行で定義されています。
参照先 converse().
参照元 _make_remark_v()・_pam_send_password_expiry_message()・_pam_warn_logon_type()・_winbind_read_password()・winbind_chauthtok_request().
00380 { 00381 int retval = PAM_SUCCESS; 00382 00383 struct pam_message *pmsg[1], msg[1]; 00384 struct pam_response *resp; 00385 00386 if (flags & WINBIND_SILENT) { 00387 return PAM_SUCCESS; 00388 } 00389 00390 pmsg[0] = &msg[0]; 00391 msg[0].msg = CONST_DISCARD(char *, text); 00392 msg[0].msg_style = type; 00393 00394 resp = NULL; 00395 retval = converse(pamh, 1, pmsg, &resp); 00396 00397 if (resp) { 00398 _pam_drop_reply(resp, 1); 00399 } 00400 return retval; 00401 }
static int _make_remark_v | ( | pam_handle_t * | pamh, | |
int | flags, | |||
int | type, | |||
const char * | format, | |||
va_list | args | |||
) | [static] |
pam_winbind.c の 403 行で定義されています。
参照先 _make_remark()・_pam_log()・vasprintf().
00404 { 00405 char *var; 00406 int ret; 00407 00408 ret = vasprintf(&var, format, args); 00409 if (ret < 0) { 00410 _pam_log(pamh, 0, LOG_ERR, "memory allocation failure"); 00411 return ret; 00412 } 00413 00414 ret = _make_remark(pamh, flags, type, var); 00415 SAFE_FREE(var); 00416 return ret; 00417 }
static int static int _make_remark_format | ( | pam_handle_t * | pamh, | |
int | flags, | |||
int | type, | |||
const char * | format, | |||
... | ||||
) | [static] |
pam_winbind.c の 420 行で定義されています。
参照先 _make_remark_v().
参照元 _pam_send_password_expiry_message().
00421 { 00422 int ret; 00423 va_list args; 00424 00425 va_start(args, format); 00426 ret = _make_remark_v(pamh, flags, type, format, args); 00427 va_end(args); 00428 return ret; 00429 }
static int pam_winbind_request | ( | pam_handle_t * | pamh, | |
int | ctrl, | |||
enum winbindd_cmd | req_type, | |||
struct winbindd_request * | request, | |||
struct winbindd_response * | response | |||
) | [static] |
pam_winbind.c の 431 行で定義されています。
参照先 _pam_log()・winbindd_response::auth・close_sock()・winbindd_response::data・init_request()・read_reply()・winbindd_response::result・WINBINDD_GETPWNAM・WINBINDD_LOOKUPNAME・WINBINDD_OK・write_sock().
参照元 pam_winbind_request_log().
00435 { 00436 /* Fill in request and send down pipe */ 00437 init_request(request, req_type); 00438 00439 if (write_sock(request, sizeof(*request), 0, 0) == -1) { 00440 _pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: write to socket failed!"); 00441 close_sock(); 00442 return PAM_SERVICE_ERR; 00443 } 00444 00445 /* Wait for reply */ 00446 if (read_reply(response) == -1) { 00447 _pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: read from socket failed!"); 00448 close_sock(); 00449 return PAM_SERVICE_ERR; 00450 } 00451 00452 /* We are done with the socket - close it and avoid mischeif */ 00453 close_sock(); 00454 00455 /* Copy reply data from socket */ 00456 if (response->result == WINBINDD_OK) { 00457 return PAM_SUCCESS; 00458 } 00459 00460 /* no need to check for pam_error codes for getpwnam() */ 00461 switch (req_type) { 00462 00463 case WINBINDD_GETPWNAM: 00464 case WINBINDD_LOOKUPNAME: 00465 if (strlen(response->data.auth.nt_status_string) > 0) { 00466 _pam_log(pamh, ctrl, LOG_ERR, "request failed, NT error was %s", 00467 response->data.auth.nt_status_string); 00468 } else { 00469 _pam_log(pamh, ctrl, LOG_ERR, "request failed"); 00470 } 00471 return PAM_USER_UNKNOWN; 00472 default: 00473 break; 00474 } 00475 00476 if (response->data.auth.pam_error != PAM_SUCCESS) { 00477 _pam_log(pamh, ctrl, LOG_ERR, "request failed: %s, PAM error was %s (%d), NT error was %s", 00478 response->data.auth.error_string, 00479 pam_strerror(pamh, response->data.auth.pam_error), 00480 response->data.auth.pam_error, 00481 response->data.auth.nt_status_string); 00482 return response->data.auth.pam_error; 00483 } 00484 00485 _pam_log(pamh, ctrl, LOG_ERR, "request failed, but PAM error 0!"); 00486 00487 return PAM_SERVICE_ERR; 00488 }
static int pam_winbind_request_log | ( | pam_handle_t * | pamh, | |
int | ctrl, | |||
enum winbindd_cmd | req_type, | |||
struct winbindd_request * | request, | |||
struct winbindd_response * | response, | |||
const char * | user | |||
) | [static] |
pam_winbind.c の 490 行で定義されています。
参照先 _pam_log()・_pam_log_debug()・pam_winbind_request()・WINBINDD_INFO・WINBINDD_PAM_AUTH・WINBINDD_PAM_CHAUTHTOK.
参照元 pam_sm_close_session()・valid_user()・winbind_auth_request()・winbind_chauthtok_request()・winbind_name_to_sid_string().
00496 { 00497 int retval; 00498 00499 retval = pam_winbind_request(pamh, ctrl, req_type, request, response); 00500 00501 switch (retval) { 00502 case PAM_AUTH_ERR: 00503 /* incorrect password */ 00504 _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' denied access (incorrect password or invalid membership)", user); 00505 return retval; 00506 case PAM_ACCT_EXPIRED: 00507 /* account expired */ 00508 _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' account expired", user); 00509 return retval; 00510 case PAM_AUTHTOK_EXPIRED: 00511 /* password expired */ 00512 _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' password expired", user); 00513 return retval; 00514 case PAM_NEW_AUTHTOK_REQD: 00515 /* new password required */ 00516 _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' new password required", user); 00517 return retval; 00518 case PAM_USER_UNKNOWN: 00519 /* the user does not exist */ 00520 _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", user); 00521 if (ctrl & WINBIND_UNKNOWN_OK_ARG) { 00522 return PAM_IGNORE; 00523 } 00524 return retval; 00525 case PAM_SUCCESS: 00526 /* Otherwise, the authentication looked good */ 00527 switch (req_type) { 00528 case WINBINDD_INFO: 00529 break; 00530 case WINBINDD_PAM_AUTH: 00531 _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", user); 00532 break; 00533 case WINBINDD_PAM_CHAUTHTOK: 00534 _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' password changed", user); 00535 break; 00536 default: 00537 _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' OK", user); 00538 break; 00539 } 00540 00541 return retval; 00542 default: 00543 /* we don't know anything about this return value */ 00544 _pam_log(pamh, ctrl, LOG_ERR, "internal module error (retval = %d, user = '%s')", 00545 retval, user); 00546 return retval; 00547 } 00548 }
static BOOL _pam_send_password_expiry_message | ( | pam_handle_t * | pamh, | |
int | ctrl, | |||
time_t | next_change, | |||
time_t | now, | |||
BOOL * | already_expired | |||
) | [static] |
send a password expiry message if required
pamh | PAM handle | |
ctrl | PAM winbind options. | |
next_change | expected (calculated) next expiry date. | |
already_expired | pointer to a boolean to indicate if the password is already expired. |
pam_winbind.c の 562 行で定義されています。
参照先 _make_remark()・_make_remark_format()・localtime_r().
参照元 _pam_warn_password_expiry().
00563 { 00564 int days = 0; 00565 struct tm tm_now, tm_next_change; 00566 00567 if (already_expired) { 00568 *already_expired = False; 00569 } 00570 00571 if (next_change <= now) { 00572 PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PASSWORD_EXPIRED"); 00573 if (already_expired) { 00574 *already_expired = True; 00575 } 00576 return True; 00577 } 00578 00579 if ((next_change < 0) || 00580 (next_change > now + DAYS_TO_WARN_BEFORE_PWD_EXPIRES * SECONDS_PER_DAY)) { 00581 return False; 00582 } 00583 00584 if ((localtime_r(&now, &tm_now) == NULL) || 00585 (localtime_r(&next_change, &tm_next_change) == NULL)) { 00586 return False; 00587 } 00588 00589 days = (tm_next_change.tm_yday+tm_next_change.tm_year*365) - (tm_now.tm_yday+tm_now.tm_year*365); 00590 00591 if (days == 0) { 00592 _make_remark(pamh, ctrl, PAM_TEXT_INFO, "Your password expires today"); 00593 return True; 00594 } 00595 00596 if (days > 0 && days < DAYS_TO_WARN_BEFORE_PWD_EXPIRES) { 00597 _make_remark_format(pamh, ctrl, PAM_TEXT_INFO, "Your password will expire in %d %s", 00598 days, (days > 1) ? "days":"day"); 00599 return True; 00600 } 00601 00602 return False; 00603 }
static void _pam_warn_password_expiry | ( | pam_handle_t * | pamh, | |
int | flags, | |||
const struct winbindd_response * | response, | |||
BOOL * | already_expired | |||
) | [static] |
Send a warning if the password expires in the near future
pamh | PAM handle | |
ctrl | PAM winbind options. | |
response | The full authentication response structure. | |
already_expired | boolean, is the pwd already expired? |
pam_winbind.c の 616 行で定義されています。
参照先 _pam_send_password_expiry_message()・winbindd_response::auth・winbindd_response::data.
参照元 pam_sm_chauthtok()・winbind_auth_request().
00620 { 00621 time_t now = time(NULL); 00622 time_t next_change = 0; 00623 00624 if (already_expired) { 00625 *already_expired = False; 00626 } 00627 00628 /* accounts with ACB_PWNOEXP set never receive a warning */ 00629 if (response->data.auth.info3.acct_flags & ACB_PWNOEXP) { 00630 return; 00631 } 00632 00633 /* no point in sending a warning if this is a grace logon */ 00634 if (PAM_WB_GRACE_LOGON(response->data.auth.info3.user_flgs)) { 00635 return; 00636 } 00637 00638 /* check if the info3 must change timestamp has been set */ 00639 next_change = response->data.auth.info3.pass_must_change_time; 00640 00641 if (_pam_send_password_expiry_message(pamh, flags, next_change, now, 00642 already_expired)) { 00643 return; 00644 } 00645 00646 /* now check for the global password policy */ 00647 /* good catch from Ralf Haferkamp: an expiry of "never" is translated 00648 * to -1 */ 00649 if (response->data.auth.policy.expire <= 0) { 00650 return; 00651 } 00652 00653 next_change = response->data.auth.info3.pass_last_set_time + 00654 response->data.auth.policy.expire; 00655 00656 if (_pam_send_password_expiry_message(pamh, flags, next_change, now, 00657 already_expired)) { 00658 return; 00659 } 00660 00661 /* no warning sent */ 00662 }
static BOOL safe_append_string | ( | char * | dest, | |
const char * | src, | |||
int | dest_buffer_size | |||
) | [static] |
Append a string, making sure not to overflow and to always return a NULL-terminated string.
dest | Destination string buffer (must already be NULL-terminated). | |
src | Source string buffer. | |
dest_buffer_size | Size of dest buffer in bytes. |
pam_winbind.c の 666 行で定義されています。
参照元 winbind_name_list_to_sid_string_list()・winbind_name_to_sid_string().
00679 { 00680 int dest_length = strlen(dest); 00681 int src_length = strlen(src); 00682 00683 if ( dest_length + src_length + 1 > dest_buffer_size ) { 00684 return False; 00685 } 00686 00687 memcpy(dest + dest_length, src, src_length + 1); 00688 return True; 00689 }
static BOOL winbind_name_to_sid_string | ( | pam_handle_t * | pamh, | |
int | ctrl, | |||
const char * | user, | |||
const char * | name, | |||
char * | sid_list_buffer, | |||
int | sid_list_buffer_size | |||
) | [static] |
Convert a names into a SID string, appending it to a buffer.
pamh | PAM handle | |
ctrl | PAM winbind options. | |
user | User in PAM request. | |
name | Name to convert. | |
sid_list_buffer | Where to append the string sid. | |
sid_list_buffer | Size of sid_list_buffer (in bytes). |
pam_winbind.c の 691 行で定義されています。
参照先 _pam_log()・_pam_log_debug()・winbindd_response::data・winbindd_request::data・winbindd_request::name・pam_winbind_request_log()・safe_append_string()・winbindd_response::sid・WINBINDD_LOOKUPNAME.
参照元 winbind_name_list_to_sid_string_list().
00709 { 00710 const char* sid_string; 00711 struct winbindd_response sid_response; 00712 00713 /* lookup name? */ 00714 if (IS_SID_STRING(name)) { 00715 sid_string = name; 00716 } else { 00717 struct winbindd_request sid_request; 00718 00719 ZERO_STRUCT(sid_request); 00720 ZERO_STRUCT(sid_response); 00721 00722 _pam_log_debug(pamh, ctrl, LOG_DEBUG, "no sid given, looking up: %s\n", name); 00723 00724 /* fortunatly winbindd can handle non-separated names */ 00725 strncpy(sid_request.data.name.name, name, 00726 sizeof(sid_request.data.name.name) - 1); 00727 00728 if (pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, &sid_request, &sid_response, user)) { 00729 _pam_log(pamh, ctrl, LOG_INFO, "could not lookup name: %s\n", name); 00730 return False; 00731 } 00732 00733 sid_string = sid_response.data.sid.sid; 00734 } 00735 00736 if (!safe_append_string(sid_list_buffer, sid_string, sid_list_buffer_size)) { 00737 return False; 00738 } 00739 00740 return True; 00741 }
static BOOL winbind_name_list_to_sid_string_list | ( | pam_handle_t * | pamh, | |
int | ctrl, | |||
const char * | user, | |||
const char * | name_list, | |||
char * | sid_list_buffer, | |||
int | sid_list_buffer_size | |||
) | [static] |
Convert a list of names into a list of sids.
pamh | PAM handle | |
ctrl | PAM winbind options. | |
user | User in PAM request. | |
name_list | List of names or string sids, separated by commas. | |
sid_list_buffer | Where to put the list of string sids. | |
sid_list_buffer | Size of sid_list_buffer (in bytes). |
pam_winbind.c の 743 行で定義されています。
参照先 result・safe_append_string()・winbind_name_to_sid_string().
00761 { 00762 BOOL result = False; 00763 char *current_name = NULL; 00764 const char *search_location; 00765 const char *comma; 00766 00767 if ( sid_list_buffer_size > 0 ) { 00768 sid_list_buffer[0] = 0; 00769 } 00770 00771 search_location = name_list; 00772 while ( (comma = strstr(search_location, ",")) != NULL ) { 00773 current_name = strndup(search_location, comma - search_location); 00774 if (NULL == current_name) { 00775 goto out; 00776 } 00777 00778 if (!winbind_name_to_sid_string(pamh, ctrl, user, current_name, sid_list_buffer, sid_list_buffer_size)) { 00779 goto out; 00780 } 00781 00782 SAFE_FREE(current_name); 00783 00784 if (!safe_append_string(sid_list_buffer, ",", sid_list_buffer_size)) { 00785 goto out; 00786 } 00787 00788 search_location = comma + 1; 00789 } 00790 00791 if (!winbind_name_to_sid_string(pamh, ctrl, user, search_location, sid_list_buffer, sid_list_buffer_size)) { 00792 goto out; 00793 } 00794 00795 result = True; 00796 00797 out: 00798 SAFE_FREE(current_name); 00799 return result; 00800 }
static void _pam_setup_krb5_env | ( | pam_handle_t * | pamh, | |
int | ctrl, | |||
const char * | krb5ccname | |||
) | [static] |
put krb5ccname variable into environment
pamh | PAM handle | |
ctrl | PAM winbind options. | |
krb5ccname | env variable retrieved from winbindd. |
pam_winbind.c の 812 行で定義されています。
参照先 _pam_log()・_pam_log_debug()・snprintf().
参照元 pam_sm_chauthtok()・winbind_auth_request().
00813 { 00814 char var[PATH_MAX]; 00815 int ret; 00816 00817 if (off(ctrl, WINBIND_KRB5_AUTH)) { 00818 return; 00819 } 00820 00821 if (!krb5ccname || (strlen(krb5ccname) == 0)) { 00822 return; 00823 } 00824 00825 _pam_log_debug(pamh, ctrl, LOG_DEBUG, "request returned KRB5CCNAME: %s", krb5ccname); 00826 00827 if (snprintf(var, sizeof(var), "KRB5CCNAME=%s", krb5ccname) == -1) { 00828 return; 00829 } 00830 00831 ret = pam_putenv(pamh, var); 00832 if (ret) { 00833 _pam_log(pamh, ctrl, LOG_ERR, "failed to set KRB5CCNAME to %s: %s", 00834 var, pam_strerror(pamh, ret)); 00835 } 00836 }
static void _pam_set_data_string | ( | pam_handle_t * | pamh, | |
int | ctrl, | |||
const char * | data_name, | |||
const char * | value | |||
) | [static] |
Set string into the PAM stack.
pamh | PAM handle | |
ctrl | PAM winbind options. | |
data_name | Key name for pam_set_data. | |
value | String value. |
pam_winbind.c の 849 行で定義されています。
参照先 _pam_log_debug()・_pam_winbind_cleanup_func()・strdup().
00850 { 00851 int ret; 00852 00853 if ( !data_name || !value || (strlen(data_name) == 0) || (strlen(value) == 0) ) { 00854 return; 00855 } 00856 00857 ret = pam_set_data(pamh, data_name, (void *)strdup(value), _pam_winbind_cleanup_func); 00858 if (ret) { 00859 _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Could not set data %s: %s\n", 00860 data_name, pam_strerror(pamh, ret)); 00861 } 00862 00863 }
static void _pam_set_data_info3 | ( | pam_handle_t * | pamh, | |
int | ctrl, | |||
struct winbindd_response * | response | |||
) | [static] |
Set info3 strings into the PAM stack.
pamh | PAM handle | |
ctrl | PAM winbind options. | |
data_name | Key name for pam_set_data. | |
value | String value. |
pam_winbind.c の 876 行で定義されています。
参照先 _pam_set_data_string()・winbindd_response::auth・winbindd_response::data.
参照元 pam_sm_chauthtok()・winbind_auth_request().
00877 { 00878 _pam_set_data_string(pamh, ctrl, PAM_WINBIND_HOMEDIR, response->data.auth.info3.home_dir); 00879 _pam_set_data_string(pamh, ctrl, PAM_WINBIND_LOGONSCRIPT, response->data.auth.info3.logon_script); 00880 _pam_set_data_string(pamh, ctrl, PAM_WINBIND_LOGONSERVER, response->data.auth.info3.logon_srv); 00881 _pam_set_data_string(pamh, ctrl, PAM_WINBIND_PROFILEPATH, response->data.auth.info3.profile_path); 00882 }
static void _pam_free_data_info3 | ( | pam_handle_t * | pamh | ) | [static] |
Free info3 strings in the PAM stack.
pamh | PAM handle |
pam_winbind.c の 892 行で定義されています。
00893 { 00894 pam_set_data(pamh, PAM_WINBIND_HOMEDIR, NULL, NULL); 00895 pam_set_data(pamh, PAM_WINBIND_LOGONSCRIPT, NULL, NULL); 00896 pam_set_data(pamh, PAM_WINBIND_LOGONSERVER, NULL, NULL); 00897 pam_set_data(pamh, PAM_WINBIND_PROFILEPATH, NULL, NULL); 00898 }
static void _pam_warn_logon_type | ( | pam_handle_t * | pamh, | |
int | ctrl, | |||
const char * | username, | |||
uint32 | info3_user_flgs | |||
) | [static] |
Send PAM_ERROR_MSG for cached or grace logons.
pamh | PAM handle | |
ctrl | PAM winbind options. | |
username | User in PAM request. | |
info3_user_flgs | Info3 flags containing logon type bits. |
pam_winbind.c の 911 行で定義されています。
参照先 _make_remark()・_pam_log_debug().
00912 { 00913 /* inform about logon type */ 00914 if (PAM_WB_GRACE_LOGON(info3_user_flgs)) { 00915 00916 _make_remark(pamh, ctrl, PAM_ERROR_MSG, 00917 "Grace login. Please change your password as soon you're online again"); 00918 _pam_log_debug(pamh, ctrl, LOG_DEBUG, 00919 "User %s logged on using grace logon\n", username); 00920 00921 } else if (PAM_WB_CACHED_LOGON(info3_user_flgs)) { 00922 00923 _make_remark(pamh, ctrl, PAM_ERROR_MSG, 00924 "Domain Controller unreachable, using cached credentials instead. Network resources may be unavailable"); 00925 _pam_log_debug(pamh, ctrl, LOG_DEBUG, 00926 "User %s logged on using cached credentials\n", username); 00927 } 00928 }
static char* _pam_compose_pwd_restriction_string | ( | struct winbindd_response * | response | ) | [static] |
Compose Password Restriction String for a PAM_ERROR_MSG conversation.
response | The struct winbindd_response. |
pam_winbind.c の 938 行で定義されています。
参照先 winbindd_response::auth・winbindd_response::data・failed・snprintf().
参照元 winbind_chauthtok_request().
00939 { 00940 char *str = NULL; 00941 size_t offset = 0, ret = 0, str_size = 1024; 00942 00943 str = (char *)malloc(str_size); 00944 if (!str) { 00945 return NULL; 00946 } 00947 00948 memset(str, '\0', str_size); 00949 00950 offset = snprintf(str, str_size, "Your password "); 00951 if (offset == -1) { 00952 goto failed; 00953 } 00954 00955 if (response->data.auth.policy.min_length_password > 0) { 00956 ret = snprintf(str+offset, str_size-offset, 00957 "must be at least %d characters; ", 00958 response->data.auth.policy.min_length_password); 00959 if (ret == -1) { 00960 goto failed; 00961 } 00962 offset += ret; 00963 } 00964 00965 if (response->data.auth.policy.password_history > 0) { 00966 ret = snprintf(str+offset, str_size-offset, 00967 "cannot repeat any of your previous %d passwords; ", 00968 response->data.auth.policy.password_history); 00969 if (ret == -1) { 00970 goto failed; 00971 } 00972 offset += ret; 00973 } 00974 00975 if (response->data.auth.policy.password_properties & DOMAIN_PASSWORD_COMPLEX) { 00976 ret = snprintf(str+offset, str_size-offset, 00977 "must contain capitals, numerals or punctuation; " 00978 "and cannot contain your account or full name; "); 00979 if (ret == -1) { 00980 goto failed; 00981 } 00982 offset += ret; 00983 } 00984 00985 ret = snprintf(str+offset, str_size-offset, 00986 "Please type a different password. " 00987 "Type a password which meets these requirements in both text boxes."); 00988 if (ret == -1) { 00989 goto failed; 00990 } 00991 00992 return str; 00993 00994 failed: 00995 SAFE_FREE(str); 00996 return NULL; 00997 }
static int winbind_auth_request | ( | pam_handle_t * | pamh, | |
int | ctrl, | |||
const char * | user, | |||
const char * | pass, | |||
const char * | member, | |||
const char * | cctype, | |||
struct winbindd_response * | p_response, | |||
time_t * | pwd_last_set, | |||
char ** | user_ret | |||
) | [static] |
pam_winbind.c の 1000 行で定義されています。
参照先 _pam_log_debug()・_pam_set_data_info3()・_pam_setup_krb5_env()・_pam_warn_logon_type()・_pam_warn_password_expiry()・winbindd_response::auth・winbindd_request::auth・winbindd_response::data・winbindd_request::data・winbindd_response::extra_data・winbindd_request::flags・pam_winbind_request_log()・winbind_name_list_to_sid_string_list()・WINBINDD_PAM_AUTH.
参照元 pam_sm_authenticate()・pam_sm_chauthtok().
01009 { 01010 struct winbindd_request request; 01011 struct winbindd_response response; 01012 int ret; 01013 BOOL already_expired = False; 01014 01015 ZERO_STRUCT(request); 01016 ZERO_STRUCT(response); 01017 01018 if (pwd_last_set) { 01019 *pwd_last_set = 0; 01020 } 01021 01022 strncpy(request.data.auth.user, user, 01023 sizeof(request.data.auth.user)-1); 01024 01025 strncpy(request.data.auth.pass, pass, 01026 sizeof(request.data.auth.pass)-1); 01027 01028 request.data.auth.krb5_cc_type[0] = '\0'; 01029 request.data.auth.uid = -1; 01030 01031 request.flags = WBFLAG_PAM_INFO3_TEXT | 01032 WBFLAG_PAM_GET_PWD_POLICY | 01033 WBFLAG_PAM_CONTACT_TRUSTDOM; 01034 01035 if (ctrl & (WINBIND_KRB5_AUTH|WINBIND_CACHED_LOGIN)) { 01036 struct passwd *pwd = NULL; 01037 01038 pwd = getpwnam(user); 01039 if (pwd == NULL) { 01040 return PAM_USER_UNKNOWN; 01041 } 01042 request.data.auth.uid = pwd->pw_uid; 01043 } 01044 01045 if (ctrl & WINBIND_KRB5_AUTH) { 01046 01047 _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling krb5 login flag\n"); 01048 01049 request.flags |= WBFLAG_PAM_KRB5 | WBFLAG_PAM_FALLBACK_AFTER_KRB5; 01050 } 01051 01052 if (ctrl & WINBIND_CACHED_LOGIN) { 01053 _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling cached login flag\n"); 01054 request.flags |= WBFLAG_PAM_CACHED_LOGIN; 01055 } 01056 01057 if (user_ret) { 01058 *user_ret = NULL; 01059 request.flags |= WBFLAG_PAM_UNIX_NAME; 01060 } 01061 01062 if (cctype != NULL) { 01063 strncpy(request.data.auth.krb5_cc_type, cctype, 01064 sizeof(request.data.auth.krb5_cc_type) - 1); 01065 _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling request for a %s krb5 ccache\n", cctype); 01066 } 01067 01068 request.data.auth.require_membership_of_sid[0] = '\0'; 01069 01070 if (member != NULL) { 01071 01072 if (!winbind_name_list_to_sid_string_list(pamh, ctrl, user, member, 01073 request.data.auth.require_membership_of_sid, 01074 sizeof(request.data.auth.require_membership_of_sid))) { 01075 01076 _pam_log_debug(pamh, ctrl, LOG_ERR, "failed to serialize membership of sid \"%s\"\n", member); 01077 return PAM_AUTH_ERR; 01078 } 01079 } 01080 01081 ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_AUTH, &request, &response, user); 01082 01083 if (pwd_last_set) { 01084 *pwd_last_set = response.data.auth.info3.pass_last_set_time; 01085 } 01086 01087 if (p_response) { 01088 /* We want to process the response in the caller. */ 01089 *p_response = response; 01090 return ret; 01091 } 01092 01093 if (ret) { 01094 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PASSWORD_EXPIRED"); 01095 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PASSWORD_MUST_CHANGE"); 01096 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_INVALID_WORKSTATION"); 01097 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_INVALID_LOGON_HOURS"); 01098 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCOUNT_EXPIRED"); 01099 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCOUNT_DISABLED"); 01100 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCOUNT_LOCKED_OUT"); 01101 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT"); 01102 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"); 01103 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"); 01104 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); 01105 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS"); 01106 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_WRONG_PASSWORD"); 01107 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED"); 01108 } 01109 01110 if (ret == PAM_SUCCESS) { 01111 01112 /* warn a user if the password is about to expire soon */ 01113 _pam_warn_password_expiry(pamh, ctrl, &response, &already_expired); 01114 01115 if (already_expired == True) { 01116 _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Password has expired " 01117 "(Password was last set: %lld, the policy says " 01118 "it should expire here %lld (now it's: %lu))\n", 01119 response.data.auth.info3.pass_last_set_time, 01120 response.data.auth.info3.pass_last_set_time + 01121 response.data.auth.policy.expire, 01122 time(NULL)); 01123 01124 return PAM_AUTHTOK_EXPIRED; 01125 } 01126 01127 /* inform about logon type */ 01128 _pam_warn_logon_type(pamh, ctrl, user, response.data.auth.info3.user_flgs); 01129 01130 /* set some info3 info for other modules in the stack */ 01131 _pam_set_data_info3(pamh, ctrl, &response); 01132 01133 /* put krb5ccname into env */ 01134 _pam_setup_krb5_env(pamh, ctrl, response.data.auth.krb5ccname); 01135 01136 /* If winbindd returned a username, return the pointer to it here. */ 01137 if (user_ret && response.extra_data.data) { 01138 /* We have to trust it's a null terminated string. */ 01139 *user_ret = (char *)response.extra_data.data; 01140 } 01141 } 01142 01143 return ret; 01144 }
static int winbind_chauthtok_request | ( | pam_handle_t * | pamh, | |
int | ctrl, | |||
const char * | user, | |||
const char * | oldpass, | |||
const char * | newpass, | |||
time_t | pwd_last_set | |||
) | [static] |
pam_winbind.c の 1147 行で定義されています。
参照先 _make_remark()・_pam_compose_pwd_restriction_string()・_pam_log_debug()・winbindd_response::auth・winbindd_request::chauthtok・winbindd_response::data・winbindd_request::data・winbindd_request::flags・pam_winbind_request_log()・WINBINDD_PAM_CHAUTHTOK.
参照元 pam_sm_chauthtok().
01153 { 01154 struct winbindd_request request; 01155 struct winbindd_response response; 01156 int ret; 01157 01158 ZERO_STRUCT(request); 01159 ZERO_STRUCT(response); 01160 01161 if (request.data.chauthtok.user == NULL) return -2; 01162 01163 strncpy(request.data.chauthtok.user, user, 01164 sizeof(request.data.chauthtok.user) - 1); 01165 01166 if (oldpass != NULL) { 01167 strncpy(request.data.chauthtok.oldpass, oldpass, 01168 sizeof(request.data.chauthtok.oldpass) - 1); 01169 } else { 01170 request.data.chauthtok.oldpass[0] = '\0'; 01171 } 01172 01173 if (newpass != NULL) { 01174 strncpy(request.data.chauthtok.newpass, newpass, 01175 sizeof(request.data.chauthtok.newpass) - 1); 01176 } else { 01177 request.data.chauthtok.newpass[0] = '\0'; 01178 } 01179 01180 if (ctrl & WINBIND_KRB5_AUTH) { 01181 request.flags = WBFLAG_PAM_KRB5 | WBFLAG_PAM_CONTACT_TRUSTDOM; 01182 } 01183 01184 if (ctrl & WINBIND_CACHED_LOGIN) { 01185 request.flags |= WBFLAG_PAM_CACHED_LOGIN; 01186 } 01187 01188 ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_CHAUTHTOK, &request, &response, user); 01189 01190 if (ret == PAM_SUCCESS) { 01191 return ret; 01192 } 01193 01194 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_BACKUP_CONTROLLER"); 01195 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); 01196 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS"); 01197 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED"); 01198 01199 /* TODO: tell the min pwd length ? */ 01200 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PWD_TOO_SHORT"); 01201 01202 /* TODO: tell the minage ? */ 01203 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PWD_TOO_RECENT"); 01204 01205 /* TODO: tell the history length ? */ 01206 PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PWD_HISTORY_CONFLICT"); 01207 01208 if (!strcasecmp(response.data.auth.nt_status_string, "NT_STATUS_PASSWORD_RESTRICTION")) { 01209 01210 char *pwd_restriction_string = NULL; 01211 01212 /* FIXME: avoid to send multiple PAM messages after another */ 01213 switch (response.data.auth.reject_reason) { 01214 case -1: 01215 break; 01216 case REJECT_REASON_OTHER: 01217 if ((response.data.auth.policy.min_passwordage > 0) && 01218 (pwd_last_set + response.data.auth.policy.min_passwordage > time(NULL))) { 01219 PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_TOO_RECENT"); 01220 } 01221 break; 01222 case REJECT_REASON_TOO_SHORT: 01223 PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_TOO_SHORT"); 01224 break; 01225 case REJECT_REASON_IN_HISTORY: 01226 PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_HISTORY_CONFLICT"); 01227 break; 01228 case REJECT_REASON_NOT_COMPLEX: 01229 _make_remark(pamh, ctrl, PAM_ERROR_MSG, "Password does not meet complexity requirements"); 01230 break; 01231 default: 01232 _pam_log_debug(pamh, ctrl, LOG_DEBUG, 01233 "unknown password change reject reason: %d", 01234 response.data.auth.reject_reason); 01235 break; 01236 } 01237 01238 pwd_restriction_string = _pam_compose_pwd_restriction_string(&response); 01239 if (pwd_restriction_string) { 01240 _make_remark(pamh, ctrl, PAM_ERROR_MSG, pwd_restriction_string); 01241 SAFE_FREE(pwd_restriction_string); 01242 } 01243 } 01244 01245 return ret; 01246 }
static int valid_user | ( | pam_handle_t * | pamh, | |
int | ctrl, | |||
const char * | user | |||
) | [static] |
pam_winbind.c の 1256 行で定義されています。
参照先 winbindd_request::data・pam_winbind_request_log()・winbindd_request::username・WINBINDD_GETPWNAM.
参照元 pam_sm_acct_mgmt()・pam_sm_chauthtok().
01257 { 01258 /* check not only if the user is available over NSS calls, also make 01259 * sure it's really a winbind user, this is important when stacking PAM 01260 * modules in the 'account' or 'password' facility. */ 01261 01262 struct passwd *pwd = NULL; 01263 struct winbindd_request request; 01264 struct winbindd_response response; 01265 int ret; 01266 01267 ZERO_STRUCT(request); 01268 ZERO_STRUCT(response); 01269 01270 pwd = getpwnam(user); 01271 if (pwd == NULL) { 01272 return 1; 01273 } 01274 01275 strncpy(request.data.username, user, 01276 sizeof(request.data.username) - 1); 01277 01278 ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_GETPWNAM, &request, &response, user); 01279 01280 switch (ret) { 01281 case PAM_USER_UNKNOWN: 01282 return 1; 01283 case PAM_SUCCESS: 01284 return 0; 01285 default: 01286 break; 01287 } 01288 return -1; 01289 }
static char* _pam_delete | ( | register char * | xx | ) | [static] |
static int _winbind_read_password | ( | pam_handle_t * | pamh, | |
unsigned int | ctrl, | |||
const char * | comment, | |||
const char * | prompt1, | |||
const char * | prompt2, | |||
const char ** | pass | |||
) | [static] |
pam_winbind.c の 1302 行で定義されています。
参照先 _make_remark()・_pam_delete()・_pam_get_item()・_pam_log()・_pam_log_debug()・converse().
参照元 pam_sm_authenticate()・pam_sm_chauthtok().
01308 { 01309 int authtok_flag; 01310 int retval; 01311 const char *item; 01312 char *token; 01313 01314 _pam_log(pamh, ctrl, LOG_DEBUG, "getting password (0x%08x)", ctrl); 01315 01316 /* 01317 * make sure nothing inappropriate gets returned 01318 */ 01319 01320 *pass = token = NULL; 01321 01322 /* 01323 * which authentication token are we getting? 01324 */ 01325 01326 authtok_flag = on(WINBIND__OLD_PASSWORD, ctrl) ? PAM_OLDAUTHTOK : PAM_AUTHTOK; 01327 01328 /* 01329 * should we obtain the password from a PAM item ? 01330 */ 01331 01332 if (on(WINBIND_TRY_FIRST_PASS_ARG, ctrl) || on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { 01333 retval = _pam_get_item(pamh, authtok_flag, &item); 01334 if (retval != PAM_SUCCESS) { 01335 /* very strange. */ 01336 _pam_log(pamh, ctrl, LOG_ALERT, 01337 "pam_get_item returned error to unix-read-password" 01338 ); 01339 return retval; 01340 } else if (item != NULL) { /* we have a password! */ 01341 *pass = item; 01342 item = NULL; 01343 _pam_log(pamh, ctrl, LOG_DEBUG, 01344 "pam_get_item returned a password"); 01345 return PAM_SUCCESS; 01346 } else if (on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { 01347 return PAM_AUTHTOK_RECOVER_ERR; /* didn't work */ 01348 } else if (on(WINBIND_USE_AUTHTOK_ARG, ctrl) 01349 && off(WINBIND__OLD_PASSWORD, ctrl)) { 01350 return PAM_AUTHTOK_RECOVER_ERR; 01351 } 01352 } 01353 /* 01354 * getting here implies we will have to get the password from the 01355 * user directly. 01356 */ 01357 01358 { 01359 struct pam_message msg[3], *pmsg[3]; 01360 struct pam_response *resp; 01361 int i, replies; 01362 01363 /* prepare to converse */ 01364 01365 if (comment != NULL && off(ctrl, WINBIND_SILENT)) { 01366 pmsg[0] = &msg[0]; 01367 msg[0].msg_style = PAM_TEXT_INFO; 01368 msg[0].msg = CONST_DISCARD(char *, comment); 01369 i = 1; 01370 } else { 01371 i = 0; 01372 } 01373 01374 pmsg[i] = &msg[i]; 01375 msg[i].msg_style = PAM_PROMPT_ECHO_OFF; 01376 msg[i++].msg = CONST_DISCARD(char *, prompt1); 01377 replies = 1; 01378 01379 if (prompt2 != NULL) { 01380 pmsg[i] = &msg[i]; 01381 msg[i].msg_style = PAM_PROMPT_ECHO_OFF; 01382 msg[i++].msg = CONST_DISCARD(char *, prompt2); 01383 ++replies; 01384 } 01385 /* so call the conversation expecting i responses */ 01386 resp = NULL; 01387 retval = converse(pamh, i, pmsg, &resp); 01388 01389 if (resp != NULL) { 01390 01391 /* interpret the response */ 01392 01393 if (retval == PAM_SUCCESS) { /* a good conversation */ 01394 01395 token = x_strdup(resp[i - replies].resp); 01396 if (token != NULL) { 01397 if (replies == 2) { 01398 /* verify that password entered correctly */ 01399 if (!resp[i - 1].resp 01400 || strcmp(token, resp[i - 1].resp)) { 01401 _pam_delete(token); /* mistyped */ 01402 retval = PAM_AUTHTOK_RECOVER_ERR; 01403 _make_remark(pamh, ctrl, PAM_ERROR_MSG, MISTYPED_PASS); 01404 } 01405 } 01406 } else { 01407 _pam_log(pamh, ctrl, LOG_NOTICE, "could not recover authentication token"); 01408 retval = PAM_AUTHTOK_RECOVER_ERR; 01409 } 01410 01411 } 01412 /* 01413 * tidy up the conversation (resp_retcode) is ignored 01414 * -- what is it for anyway? AGM 01415 */ 01416 01417 _pam_drop_reply(resp, i); 01418 01419 } else { 01420 retval = (retval == PAM_SUCCESS) 01421 ? PAM_AUTHTOK_RECOVER_ERR : retval; 01422 } 01423 } 01424 01425 if (retval != PAM_SUCCESS) { 01426 _pam_log_debug(pamh, ctrl, LOG_DEBUG, 01427 "unable to obtain a password"); 01428 return retval; 01429 } 01430 /* 'token' is the entered password */ 01431 01432 /* we store this password as an item */ 01433 01434 retval = pam_set_item(pamh, authtok_flag, token); 01435 _pam_delete(token); /* clean it up */ 01436 if (retval != PAM_SUCCESS || 01437 (retval = _pam_get_item(pamh, authtok_flag, &item)) != PAM_SUCCESS) { 01438 01439 _pam_log(pamh, ctrl, LOG_CRIT, "error manipulating password"); 01440 return retval; 01441 01442 } 01443 01444 *pass = item; 01445 item = NULL; /* break link to password */ 01446 01447 return PAM_SUCCESS; 01448 }
const char* get_conf_item_string | ( | const pam_handle_t * | pamh, | |
int | argc, | |||
const char ** | argv, | |||
int | ctrl, | |||
dictionary * | d, | |||
const char * | item, | |||
int | config_flag | |||
) |
pam_winbind.c の 1450 行で定義されています。
参照先 _pam_log()・_pam_log_debug()・asprintf()・iniparser_getstr().
参照元 get_krb5_cc_type_from_config()・get_member_from_config().
01457 { 01458 int i = 0; 01459 const char *parm_opt = NULL; 01460 char *key = NULL; 01461 01462 if (!(ctrl & config_flag)) { 01463 goto out; 01464 } 01465 01466 /* let the pam opt take precedence over the pam_winbind.conf option */ 01467 01468 if (d != NULL) { 01469 01470 if (!asprintf(&key, "global:%s", item)) { 01471 goto out; 01472 } 01473 01474 parm_opt = iniparser_getstr(d, key); 01475 SAFE_FREE(key); 01476 } 01477 01478 for ( i=0; i<argc; i++ ) { 01479 01480 if ((strncmp(argv[i], item, strlen(item)) == 0)) { 01481 char *p; 01482 01483 if ( (p = strchr( argv[i], '=' )) == NULL) { 01484 _pam_log(pamh, ctrl, LOG_INFO, "no \"=\" delimiter for \"%s\" found\n", item); 01485 goto out; 01486 } 01487 _pam_log_debug(pamh, ctrl, LOG_INFO, "PAM config: %s '%s'\n", item, p+1); 01488 return p + 1; 01489 } 01490 } 01491 01492 if (d != NULL) { 01493 _pam_log_debug(pamh, ctrl, LOG_INFO, "CONFIG file: %s '%s'\n", item, parm_opt); 01494 } 01495 out: 01496 return parm_opt; 01497 }
const char* get_krb5_cc_type_from_config | ( | const pam_handle_t * | pamh, | |
int | argc, | |||
const char ** | argv, | |||
int | ctrl, | |||
dictionary * | d | |||
) |
pam_winbind.c の 1499 行で定義されています。
参照元 pam_sm_authenticate()・pam_sm_chauthtok().
01500 { 01501 return get_conf_item_string(pamh, argc, argv, ctrl, d, "krb5_ccache_type", WINBIND_KRB5_CCACHE_TYPE); 01502 }
const char* get_member_from_config | ( | const pam_handle_t * | pamh, | |
int | argc, | |||
const char ** | argv, | |||
int | ctrl, | |||
dictionary * | d | |||
) |
pam_winbind.c の 1504 行で定義されています。
参照元 pam_sm_authenticate()・pam_sm_chauthtok().
01505 { 01506 const char *ret = NULL; 01507 ret = get_conf_item_string(pamh, argc, argv, ctrl, d, "require_membership_of", WINBIND_REQUIRED_MEMBERSHIP); 01508 if (ret) { 01509 return ret; 01510 } 01511 return get_conf_item_string(pamh, argc, argv, ctrl, d, "require-membership-of", WINBIND_REQUIRED_MEMBERSHIP); 01512 }
PAM_EXTERN int pam_sm_authenticate | ( | pam_handle_t * | pamh, | |
int | flags, | |||
int | argc, | |||
const char ** | argv | |||
) |
pam_winbind.c の 1515 行で定義されています。
参照先 _pam_free_data_info3()・_pam_log()・_pam_log_debug()・_pam_parse()・_pam_winbind_cleanup_func()・_winbind_read_password()・asprintf()・get_krb5_cc_type_from_config()・get_member_from_config()・iniparser_freedict()・password・strdup()・username・winbind_auth_request().
01517 { 01518 const char *username; 01519 const char *password; 01520 const char *member = NULL; 01521 const char *cctype = NULL; 01522 int retval = PAM_AUTH_ERR; 01523 dictionary *d = NULL; 01524 char *username_ret = NULL; 01525 char *new_authtok_required = NULL; 01526 char *real_username = NULL; 01527 01528 /* parse arguments */ 01529 int ctrl = _pam_parse(pamh, flags, argc, argv, &d); 01530 if (ctrl == -1) { 01531 retval = PAM_SYSTEM_ERR; 01532 goto out; 01533 } 01534 01535 _PAM_LOG_FUNCTION_ENTER("pam_sm_authenticate", pamh, ctrl, flags); 01536 01537 /* Get the username */ 01538 retval = pam_get_user(pamh, &username, NULL); 01539 if ((retval != PAM_SUCCESS) || (!username)) { 01540 _pam_log_debug(pamh, ctrl, LOG_DEBUG, "can not get the username"); 01541 retval = PAM_SERVICE_ERR; 01542 goto out; 01543 } 01544 01545 #if defined(AIX) 01546 /* Decode the user name since AIX does not support logn user 01547 names by default. The name is encoded as _#uid. */ 01548 01549 if ( username[0] == '_' ) { 01550 uid_t id = atoi( &username[1] ); 01551 struct passwd *pw = NULL; 01552 01553 if ( (id!=0) && ((pw = getpwuid( id )) != NULL) ) { 01554 real_username = strdup( pw->pw_name ); 01555 } 01556 } 01557 #endif 01558 01559 if ( !real_username ) { 01560 /* Just making a copy of the username we got from PAM */ 01561 if ( (real_username = strdup( username )) == NULL ) { 01562 _pam_log_debug(pamh, ctrl, LOG_DEBUG, 01563 "memory allocation failure when copying username"); 01564 retval = PAM_SERVICE_ERR; 01565 goto out; 01566 } 01567 } 01568 01569 retval = _winbind_read_password(pamh, ctrl, NULL, 01570 "Password: ", NULL, 01571 &password); 01572 01573 if (retval != PAM_SUCCESS) { 01574 _pam_log(pamh, ctrl, LOG_ERR, "Could not retrieve user's password"); 01575 retval = PAM_AUTHTOK_ERR; 01576 goto out; 01577 } 01578 01579 /* Let's not give too much away in the log file */ 01580 01581 #ifdef DEBUG_PASSWORD 01582 _pam_log_debug(pamh, ctrl, LOG_INFO, "Verify user '%s' with password '%s'", 01583 real_username, password); 01584 #else 01585 _pam_log_debug(pamh, ctrl, LOG_INFO, "Verify user '%s'", real_username); 01586 #endif 01587 01588 member = get_member_from_config(pamh, argc, argv, ctrl, d); 01589 01590 cctype = get_krb5_cc_type_from_config(pamh, argc, argv, ctrl, d); 01591 01592 /* Now use the username to look up password */ 01593 retval = winbind_auth_request(pamh, ctrl, username, password, member, 01594 cctype, NULL, NULL, &username_ret); 01595 01596 if (retval == PAM_NEW_AUTHTOK_REQD || 01597 retval == PAM_AUTHTOK_EXPIRED) { 01598 01599 char *new_authtok_required_during_auth = NULL; 01600 01601 if (!asprintf(&new_authtok_required, "%d", retval)) { 01602 retval = PAM_BUF_ERR; 01603 goto out; 01604 } 01605 01606 pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, new_authtok_required, _pam_winbind_cleanup_func); 01607 01608 retval = PAM_SUCCESS; 01609 01610 if (!asprintf(&new_authtok_required_during_auth, "%d", True)) { 01611 retval = PAM_BUF_ERR; 01612 goto out; 01613 } 01614 01615 pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, 01616 new_authtok_required_during_auth, _pam_winbind_cleanup_func); 01617 01618 goto out; 01619 } 01620 01621 out: 01622 if (username_ret) { 01623 pam_set_item (pamh, PAM_USER, username_ret); 01624 _pam_log_debug(pamh, ctrl, LOG_INFO, "Returned user was '%s'", username_ret); 01625 free(username_ret); 01626 } 01627 01628 if ( real_username ) { 01629 free( real_username ); 01630 } 01631 01632 if (d) { 01633 iniparser_freedict(d); 01634 } 01635 01636 if (!new_authtok_required) { 01637 pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, NULL, NULL); 01638 } 01639 01640 if (retval != PAM_SUCCESS) { 01641 _pam_free_data_info3(pamh); 01642 } 01643 01644 _PAM_LOG_FUNCTION_LEAVE("pam_sm_authenticate", pamh, ctrl, retval); 01645 01646 return retval; 01647 }
PAM_EXTERN int pam_sm_setcred | ( | pam_handle_t * | pamh, | |
int | flags, | |||
int | argc, | |||
const char ** | argv | |||
) |
pam_winbind.c の 1650 行で定義されています。
参照先 _pam_log_debug()・_pam_parse()・iniparser_freedict()・pam_sm_close_session().
01652 { 01653 int ret = PAM_SYSTEM_ERR; 01654 dictionary *d = NULL; 01655 01656 /* parse arguments */ 01657 int ctrl = _pam_parse(pamh, flags, argc, argv, &d); 01658 if (ctrl == -1) { 01659 ret = PAM_SYSTEM_ERR; 01660 goto out; 01661 } 01662 01663 _PAM_LOG_FUNCTION_ENTER("pam_sm_setcred", pamh, ctrl, flags); 01664 01665 switch (flags & ~PAM_SILENT) { 01666 01667 case PAM_DELETE_CRED: 01668 ret = pam_sm_close_session(pamh, flags, argc, argv); 01669 break; 01670 case PAM_REFRESH_CRED: 01671 _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_REFRESH_CRED not implemented"); 01672 ret = PAM_SUCCESS; 01673 break; 01674 case PAM_REINITIALIZE_CRED: 01675 _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_REINITIALIZE_CRED not implemented"); 01676 ret = PAM_SUCCESS; 01677 break; 01678 case PAM_ESTABLISH_CRED: 01679 _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_ESTABLISH_CRED not implemented"); 01680 ret = PAM_SUCCESS; 01681 break; 01682 default: 01683 ret = PAM_SYSTEM_ERR; 01684 break; 01685 } 01686 01687 out: 01688 if (d) { 01689 iniparser_freedict(d); 01690 } 01691 01692 _PAM_LOG_FUNCTION_LEAVE("pam_sm_setcred", pamh, ctrl, ret); 01693 01694 return ret; 01695 }
PAM_EXTERN int pam_sm_acct_mgmt | ( | pam_handle_t * | pamh, | |
int | flags, | |||
int | argc, | |||
const char ** | argv | |||
) |
pam_winbind.c の 1702 行で定義されています。
参照先 _pam_log()・_pam_log_debug()・_pam_parse()・iniparser_freedict()・username・valid_user().
01704 { 01705 const char *username; 01706 int ret = PAM_USER_UNKNOWN; 01707 void *tmp = NULL; 01708 dictionary *d = NULL; 01709 01710 /* parse arguments */ 01711 int ctrl = _pam_parse(pamh, flags, argc, argv, &d); 01712 if (ctrl == -1) { 01713 return PAM_SYSTEM_ERR; 01714 } 01715 01716 _PAM_LOG_FUNCTION_ENTER("pam_sm_acct_mgmt", pamh, ctrl, flags); 01717 01718 01719 /* Get the username */ 01720 ret = pam_get_user(pamh, &username, NULL); 01721 if ((ret != PAM_SUCCESS) || (!username)) { 01722 _pam_log_debug(pamh, ctrl, LOG_DEBUG,"can not get the username"); 01723 ret = PAM_SERVICE_ERR; 01724 goto out; 01725 } 01726 01727 /* Verify the username */ 01728 ret = valid_user(pamh, ctrl, username); 01729 switch (ret) { 01730 case -1: 01731 /* some sort of system error. The log was already printed */ 01732 ret = PAM_SERVICE_ERR; 01733 goto out; 01734 case 1: 01735 /* the user does not exist */ 01736 _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", username); 01737 if (ctrl & WINBIND_UNKNOWN_OK_ARG) { 01738 ret = PAM_IGNORE; 01739 goto out; 01740 } 01741 ret = PAM_USER_UNKNOWN; 01742 goto out; 01743 case 0: 01744 pam_get_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (const void **)&tmp); 01745 if (tmp != NULL) { 01746 ret = atoi((const char *)tmp); 01747 switch (ret) { 01748 case PAM_AUTHTOK_EXPIRED: 01749 /* fall through, since new token is required in this case */ 01750 case PAM_NEW_AUTHTOK_REQD: 01751 _pam_log(pamh, ctrl, LOG_WARNING, "pam_sm_acct_mgmt success but %s is set", 01752 PAM_WINBIND_NEW_AUTHTOK_REQD); 01753 _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' needs new password", username); 01754 /* PAM_AUTHTOKEN_REQD does not exist, but is documented in the manpage */ 01755 ret = PAM_NEW_AUTHTOK_REQD; 01756 goto out; 01757 default: 01758 _pam_log(pamh, ctrl, LOG_WARNING, "pam_sm_acct_mgmt success"); 01759 _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", username); 01760 ret = PAM_SUCCESS; 01761 goto out; 01762 } 01763 } 01764 01765 /* Otherwise, the authentication looked good */ 01766 _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", username); 01767 ret = PAM_SUCCESS; 01768 goto out; 01769 default: 01770 /* we don't know anything about this return value */ 01771 _pam_log(pamh, ctrl, LOG_ERR, "internal module error (ret = %d, user = '%s')", 01772 ret, username); 01773 ret = PAM_SERVICE_ERR; 01774 goto out; 01775 } 01776 01777 /* should not be reached */ 01778 ret = PAM_IGNORE; 01779 01780 out: 01781 01782 if (d) { 01783 iniparser_freedict(d); 01784 } 01785 01786 _PAM_LOG_FUNCTION_LEAVE("pam_sm_acct_mgmt", pamh, ctrl, ret); 01787 01788 return ret; 01789 }
PAM_EXTERN int pam_sm_open_session | ( | pam_handle_t * | pamh, | |
int | flags, | |||
int | argc, | |||
const char ** | argv | |||
) |
pam_winbind.c の 1792 行で定義されています。
参照先 _pam_parse()・iniparser_freedict().
01794 { 01795 int ret = PAM_SYSTEM_ERR; 01796 dictionary *d = NULL; 01797 01798 /* parse arguments */ 01799 int ctrl = _pam_parse(pamh, flags, argc, argv, &d); 01800 if (ctrl == -1) { 01801 ret = PAM_SYSTEM_ERR; 01802 goto out; 01803 } 01804 01805 _PAM_LOG_FUNCTION_ENTER("pam_sm_open_session", pamh, ctrl, flags); 01806 01807 ret = PAM_SUCCESS; 01808 01809 out: 01810 if (d) { 01811 iniparser_freedict(d); 01812 } 01813 01814 _PAM_LOG_FUNCTION_LEAVE("pam_sm_open_session", pamh, ctrl, ret); 01815 01816 return ret; 01817 }
PAM_EXTERN int pam_sm_close_session | ( | pam_handle_t * | pamh, | |
int | flags, | |||
int | argc, | |||
const char ** | argv | |||
) |
pam_winbind.c の 1820 行で定義されています。
参照先 _pam_log()・_pam_log_debug()・_pam_parse()・winbindd_request::data・winbindd_request::flags・iniparser_freedict()・winbindd_request::logoff・pam_winbind_request_log()・WINBINDD_PAM_LOGOFF.
参照元 pam_sm_setcred().
01822 { 01823 dictionary *d = NULL; 01824 int retval = PAM_SUCCESS; 01825 01826 /* parse arguments */ 01827 int ctrl = _pam_parse(pamh, flags, argc, argv, &d); 01828 if (ctrl == -1) { 01829 retval = PAM_SYSTEM_ERR; 01830 goto out; 01831 } 01832 01833 _PAM_LOG_FUNCTION_ENTER("pam_sm_close_session", pamh, ctrl, flags); 01834 01835 if (!(flags & PAM_DELETE_CRED)) { 01836 retval = PAM_SUCCESS; 01837 goto out; 01838 } 01839 01840 if (ctrl & WINBIND_KRB5_AUTH) { 01841 01842 /* destroy the ccache here */ 01843 struct winbindd_request request; 01844 struct winbindd_response response; 01845 const char *user; 01846 const char *ccname = NULL; 01847 struct passwd *pwd = NULL; 01848 01849 ZERO_STRUCT(request); 01850 ZERO_STRUCT(response); 01851 01852 retval = pam_get_user(pamh, &user, "Username: "); 01853 if (retval) { 01854 _pam_log(pamh, ctrl, LOG_ERR, "could not identify user"); 01855 goto out; 01856 } 01857 01858 if (user == NULL) { 01859 _pam_log(pamh, ctrl, LOG_ERR, "username was NULL!"); 01860 retval = PAM_USER_UNKNOWN; 01861 goto out; 01862 } 01863 01864 _pam_log_debug(pamh, ctrl, LOG_DEBUG, "username [%s] obtained", user); 01865 01866 ccname = pam_getenv(pamh, "KRB5CCNAME"); 01867 if (ccname == NULL) { 01868 _pam_log_debug(pamh, ctrl, LOG_DEBUG, "user has no KRB5CCNAME environment"); 01869 } 01870 01871 strncpy(request.data.logoff.user, user, 01872 sizeof(request.data.logoff.user) - 1); 01873 01874 if (ccname) { 01875 strncpy(request.data.logoff.krb5ccname, ccname, 01876 sizeof(request.data.logoff.krb5ccname) - 1); 01877 } 01878 01879 pwd = getpwnam(user); 01880 if (pwd == NULL) { 01881 retval = PAM_USER_UNKNOWN; 01882 goto out; 01883 } 01884 request.data.logoff.uid = pwd->pw_uid; 01885 01886 request.flags = WBFLAG_PAM_KRB5 | WBFLAG_PAM_CONTACT_TRUSTDOM; 01887 01888 retval = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_LOGOFF, &request, &response, user); 01889 } 01890 01891 out: 01892 if (d) { 01893 iniparser_freedict(d); 01894 } 01895 01896 _PAM_LOG_FUNCTION_LEAVE("pam_sm_close_session", pamh, ctrl, retval); 01897 01898 return retval; 01899 }
static BOOL _pam_require_krb5_auth_after_chauthtok | ( | pam_handle_t * | pamh, | |
int | ctrl, | |||
const char * | user | |||
) | [static] |
evaluate whether we need to re-authenticate with kerberos after a password change
pamh | PAM handle | |
ctrl | PAM winbind options. | |
user | The username |
pam_winbind.c の 1911 行で定義されています。
参照先 _pam_get_data().
参照元 pam_sm_chauthtok().
01912 { 01913 01914 /* Make sure that we only do this if 01915 * a) the chauthtok got initiated during a logon attempt (authenticate->acct_mgmt->chauthtok) 01916 * b) any later password change via the "passwd" command if done by the user itself 01917 * 01918 * NB. If we login from gdm or xdm and the password expires, 01919 * we change the password, but there is no memory cache. 01920 * Thus, even for passthrough login, we should do the 01921 * authentication again to update memory cache. 01922 * --- BoYang 01923 * */ 01924 01925 char *new_authtok_reqd_during_auth = NULL; 01926 struct passwd *pwd = NULL; 01927 01928 _pam_get_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, &new_authtok_reqd_during_auth); 01929 pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, NULL, NULL); 01930 01931 if (new_authtok_reqd_during_auth) { 01932 return True; 01933 } 01934 01935 pwd = getpwnam(user); 01936 if (!pwd) { 01937 return False; 01938 } 01939 01940 if (getuid() == pwd->pw_uid) { 01941 return True; 01942 } 01943 01944 return False; 01945 }
PAM_EXTERN int pam_sm_chauthtok | ( | pam_handle_t * | pamh, | |
int | flags, | |||
int | argc, | |||
const char ** | argv | |||
) |
pam_winbind.c の 1949 行で定義されています。
参照先 _pam_get_data()・_pam_get_item()・_pam_log()・_pam_log_debug()・_pam_parse()・_pam_require_krb5_auth_after_chauthtok()・_pam_set_data_info3()・_pam_setup_krb5_env()・_pam_warn_password_expiry()・_winbind_read_password()・winbindd_response::auth・winbindd_response::data・get_krb5_cc_type_from_config()・get_member_from_config()・iniparser_freedict()・valid_user()・winbind_auth_request()・winbind_chauthtok_request().
01951 { 01952 unsigned int lctrl; 01953 int ret; 01954 unsigned int ctrl; 01955 bool cached_login = False; 01956 01957 /* <DO NOT free() THESE> */ 01958 const char *user; 01959 char *pass_old, *pass_new; 01960 /* </DO NOT free() THESE> */ 01961 01962 char *Announce; 01963 01964 int retry = 0; 01965 dictionary *d = NULL; 01966 char *username_ret = NULL; 01967 struct winbindd_response response; 01968 01969 ZERO_STRUCT(response); 01970 01971 ctrl = _pam_parse(pamh, flags, argc, argv, &d); 01972 if (ctrl == -1) { 01973 ret = PAM_SYSTEM_ERR; 01974 goto out; 01975 } 01976 01977 _PAM_LOG_FUNCTION_ENTER("pam_sm_chauthtok", pamh, ctrl, flags); 01978 01979 cached_login = (ctrl & WINBIND_CACHED_LOGIN); 01980 01981 /* clearing offline bit for auth */ 01982 ctrl &= ~WINBIND_CACHED_LOGIN; 01983 01984 /* 01985 * First get the name of a user 01986 */ 01987 ret = pam_get_user(pamh, &user, "Username: "); 01988 if (ret) { 01989 _pam_log(pamh, ctrl, LOG_ERR, 01990 "password - could not identify user"); 01991 goto out; 01992 } 01993 01994 if (user == NULL) { 01995 _pam_log(pamh, ctrl, LOG_ERR, "username was NULL!"); 01996 ret = PAM_USER_UNKNOWN; 01997 goto out; 01998 } 01999 02000 _pam_log_debug(pamh, ctrl, LOG_DEBUG, "username [%s] obtained", user); 02001 02002 /* check if this is really a user in winbindd, not only in NSS */ 02003 ret = valid_user(pamh, ctrl, user); 02004 switch (ret) { 02005 case 1: 02006 ret = PAM_USER_UNKNOWN; 02007 goto out; 02008 case -1: 02009 ret = PAM_SYSTEM_ERR; 02010 goto out; 02011 default: 02012 break; 02013 } 02014 02015 /* 02016 * obtain and verify the current password (OLDAUTHTOK) for 02017 * the user. 02018 */ 02019 02020 if (flags & PAM_PRELIM_CHECK) { 02021 time_t pwdlastset_prelim = 0; 02022 02023 /* instruct user what is happening */ 02024 #define greeting "Changing password for " 02025 Announce = (char *) malloc(sizeof(greeting) + strlen(user)); 02026 if (Announce == NULL) { 02027 _pam_log(pamh, ctrl, LOG_CRIT, "password - out of memory"); 02028 ret = PAM_BUF_ERR; 02029 goto out; 02030 } 02031 (void) strcpy(Announce, greeting); 02032 (void) strcpy(Announce + sizeof(greeting) - 1, user); 02033 #undef greeting 02034 02035 lctrl = ctrl | WINBIND__OLD_PASSWORD; 02036 ret = _winbind_read_password(pamh, lctrl, 02037 Announce, 02038 "(current) NT password: ", 02039 NULL, 02040 (const char **) &pass_old); 02041 if (ret != PAM_SUCCESS) { 02042 _pam_log(pamh, ctrl, LOG_NOTICE, "password - (old) token not obtained"); 02043 goto out; 02044 } 02045 02046 /* verify that this is the password for this user */ 02047 02048 ret = winbind_auth_request(pamh, ctrl, user, pass_old, 02049 NULL, NULL, &response, &pwdlastset_prelim, NULL); 02050 02051 if (ret != PAM_ACCT_EXPIRED && 02052 ret != PAM_AUTHTOK_EXPIRED && 02053 ret != PAM_NEW_AUTHTOK_REQD && 02054 ret != PAM_SUCCESS) { 02055 pass_old = NULL; 02056 goto out; 02057 } 02058 02059 pam_set_data(pamh, PAM_WINBIND_PWD_LAST_SET, (void *)pwdlastset_prelim, NULL); 02060 02061 ret = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); 02062 pass_old = NULL; 02063 if (ret != PAM_SUCCESS) { 02064 _pam_log(pamh, ctrl, LOG_CRIT, "failed to set PAM_OLDAUTHTOK"); 02065 } 02066 } else if (flags & PAM_UPDATE_AUTHTOK) { 02067 02068 time_t pwdlastset_update = 0; 02069 02070 /* 02071 * obtain the proposed password 02072 */ 02073 02074 /* 02075 * get the old token back. 02076 */ 02077 02078 ret = _pam_get_item(pamh, PAM_OLDAUTHTOK, &pass_old); 02079 02080 if (ret != PAM_SUCCESS) { 02081 _pam_log(pamh, ctrl, LOG_NOTICE, "user not authenticated"); 02082 goto out; 02083 } 02084 02085 lctrl = ctrl & ~WINBIND_TRY_FIRST_PASS_ARG; 02086 02087 if (on(WINBIND_USE_AUTHTOK_ARG, lctrl)) { 02088 lctrl |= WINBIND_USE_FIRST_PASS_ARG; 02089 } 02090 retry = 0; 02091 ret = PAM_AUTHTOK_ERR; 02092 while ((ret != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) { 02093 /* 02094 * use_authtok is to force the use of a previously entered 02095 * password -- needed for pluggable password strength checking 02096 */ 02097 02098 ret = _winbind_read_password(pamh, lctrl, 02099 NULL, 02100 "Enter new NT password: ", 02101 "Retype new NT password: ", 02102 (const char **) &pass_new); 02103 02104 if (ret != PAM_SUCCESS) { 02105 _pam_log_debug(pamh, ctrl, LOG_ALERT 02106 ,"password - new password not obtained"); 02107 pass_old = NULL;/* tidy up */ 02108 goto out; 02109 } 02110 02111 /* 02112 * At this point we know who the user is and what they 02113 * propose as their new password. Verify that the new 02114 * password is acceptable. 02115 */ 02116 02117 if (pass_new[0] == '\0') {/* "\0" password = NULL */ 02118 pass_new = NULL; 02119 } 02120 } 02121 02122 /* 02123 * By reaching here we have approved the passwords and must now 02124 * rebuild the password database file. 02125 */ 02126 _pam_get_data( pamh, PAM_WINBIND_PWD_LAST_SET, 02127 &pwdlastset_update); 02128 02129 /* 02130 * if cached creds were enabled, make sure to set the 02131 * WINBIND_CACHED_LOGIN bit here in order to have winbindd 02132 * update the cached creds storage - gd 02133 */ 02134 if (cached_login) { 02135 ctrl |= WINBIND_CACHED_LOGIN; 02136 } 02137 02138 ret = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new, pwdlastset_update); 02139 if (ret) { 02140 _pam_overwrite(pass_new); 02141 _pam_overwrite(pass_old); 02142 pass_old = pass_new = NULL; 02143 goto out; 02144 } 02145 02146 if (_pam_require_krb5_auth_after_chauthtok(pamh, ctrl, user)) { 02147 02148 const char *member = get_member_from_config(pamh, argc, argv, ctrl, d); 02149 const char *cctype = get_krb5_cc_type_from_config(pamh, argc, argv, ctrl, d); 02150 02151 /* Keep the WINBIND_CACHED_LOGIN bit for 02152 * authentication after changing the password. 02153 * This will update the cached credentials in case 02154 * that winbindd_dual_pam_chauthtok() fails 02155 * to update them. 02156 * --- BoYang 02157 * */ 02158 02159 ret = winbind_auth_request(pamh, ctrl, user, pass_new, 02160 member, cctype, &response, NULL, &username_ret); 02161 _pam_overwrite(pass_new); 02162 _pam_overwrite(pass_old); 02163 pass_old = pass_new = NULL; 02164 02165 if (ret == PAM_SUCCESS) { 02166 02167 /* warn a user if the password is about to expire soon */ 02168 _pam_warn_password_expiry(pamh, ctrl, &response, NULL); 02169 02170 /* set some info3 info for other modules in the stack */ 02171 _pam_set_data_info3(pamh, ctrl, &response); 02172 02173 /* put krb5ccname into env */ 02174 _pam_setup_krb5_env(pamh, ctrl, response.data.auth.krb5ccname); 02175 02176 if (username_ret) { 02177 pam_set_item (pamh, PAM_USER, username_ret); 02178 _pam_log_debug(pamh, ctrl, LOG_INFO, "Returned user was '%s'", username_ret); 02179 free(username_ret); 02180 } 02181 } 02182 02183 goto out; 02184 } 02185 } else { 02186 ret = PAM_SERVICE_ERR; 02187 } 02188 02189 out: 02190 if (d) { 02191 iniparser_freedict(d); 02192 } 02193 02194 /* Deal with offline errors. */ 02195 PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS"); 02196 PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); 02197 PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED"); 02198 02199 _PAM_LOG_FUNCTION_LEAVE("pam_sm_chauthtok", pamh, ctrl, ret); 02200 02201 return ret; 02202 }
struct pam_module _pam_winbind_modstruct |
初期値:
{ MODULE_NAME, pam_sm_authenticate, pam_sm_setcred, pam_sm_acct_mgmt, pam_sm_open_session, pam_sm_close_session, pam_sm_chauthtok }
pam_winbind.c の 2208 行で定義されています。