nsswitch/pam_winbind.c

ソースコードを見る。

データ構造

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.c35 行で定義されています。

参照元 _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.c41 行で定義されています。

参照元 _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.c51 行で定義されています。

参照元 _pam_log()_pam_log_debug().

00052 {
00053         pam_vsyslog(pamh, err, format, args);
00054 }

static BOOL _pam_log_is_silent ( int  ctrl  )  [static]

pam_winbind.c76 行で定義されています。

参照元 _pam_log()_pam_log_is_debug_enabled().

00077 {
00078         return on(ctrl, WINBIND_SILENT);
00079 }

static void static void _pam_log ( const pam_handle_t *  pamh,
int  ctrl,
int  err,
const char *  format,
  ... 
) [static]

pam_winbind.c82 行で定義されています。

参照先 _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.c95 行で定義されています。

参照先 _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.c112 行で定義されています。

参照先 _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.c122 行で定義されています。

参照先 _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.c135 行で定義されています。

参照先 _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.c174 行で定義されています。

参照先 _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.c205 行で定義されています。

参照先 _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.c312 行で定義されています。

参照先 _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.c347 行で定義されています。

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.c362 行で定義されています。

参照先 _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.c379 行で定義されています。

参照先 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.c403 行で定義されています。

参照先 _make_remark()_pam_log()vasprintf().

参照元 _make_remark_format().

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.c420 行で定義されています。

参照先 _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.c431 行で定義されています。

参照先 _pam_log()winbindd_response::authclose_sock()winbindd_response::datainit_request()read_reply()winbindd_response::resultWINBINDD_GETPWNAMWINBINDD_LOOKUPNAMEWINBINDD_OKwrite_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.c490 行で定義されています。

参照先 _pam_log()_pam_log_debug()pam_winbind_request()WINBINDD_INFOWINBINDD_PAM_AUTHWINBINDD_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.
戻り値:
boolean Returns True if message has been sent, False if not.

pam_winbind.c562 行で定義されています。

参照先 _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?
戻り値:
void.

pam_winbind.c616 行で定義されています。

参照先 _pam_send_password_expiry_message()winbindd_response::authwinbindd_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.
戻り値:
False if dest buffer is not big enough (no bytes copied), True on success.

pam_winbind.c666 行で定義されています。

参照元 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).
戻り値:
False on failure, True on success.

pam_winbind.c691 行で定義されています。

参照先 _pam_log()_pam_log_debug()winbindd_response::datawinbindd_request::datawinbindd_request::namepam_winbind_request_log()safe_append_string()winbindd_response::sidWINBINDD_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).
戻り値:
False on failure, True on success.

pam_winbind.c743 行で定義されています。

参照先 resultsafe_append_string()winbind_name_to_sid_string().

参照元 winbind_auth_request().

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.
戻り値:
void.

pam_winbind.c812 行で定義されています。

参照先 _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.
戻り値:
void.

pam_winbind.c849 行で定義されています。

参照先 _pam_log_debug()_pam_winbind_cleanup_func()strdup().

参照元 _pam_set_data_info3().

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.
戻り値:
void.

pam_winbind.c876 行で定義されています。

参照先 _pam_set_data_string()winbindd_response::authwinbindd_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
戻り値:
void.

pam_winbind.c892 行で定義されています。

参照元 pam_sm_authenticate().

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.
戻り値:
void.

pam_winbind.c911 行で定義されています。

参照先 _make_remark()_pam_log_debug().

参照元 winbind_auth_request().

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.
戻り値:
string (caller needs to free).

pam_winbind.c938 行で定義されています。

参照先 winbindd_response::authwinbindd_response::datafailedsnprintf().

参照元 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.c1000 行で定義されています。

参照先 _pam_log_debug()_pam_set_data_info3()_pam_setup_krb5_env()_pam_warn_logon_type()_pam_warn_password_expiry()winbindd_response::authwinbindd_request::authwinbindd_response::datawinbindd_request::datawinbindd_response::extra_datawinbindd_request::flagspam_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.c1147 行で定義されています。

参照先 _make_remark()_pam_compose_pwd_restriction_string()_pam_log_debug()winbindd_response::authwinbindd_request::chauthtokwinbindd_response::datawinbindd_request::datawinbindd_request::flagspam_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.c1256 行で定義されています。

参照先 winbindd_request::datapam_winbind_request_log()winbindd_request::usernameWINBINDD_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]

pam_winbind.c1291 行で定義されています。

参照元 _cleanup()_cleanup_failures()_winbind_read_password().

01292 {
01293         _pam_overwrite(xx);
01294         _pam_drop(xx);
01295         return NULL;
01296 }

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.c1302 行で定義されています。

参照先 _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.c1450 行で定義されています。

参照先 _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.c1499 行で定義されています。

参照先 get_conf_item_string().

参照元 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.c1504 行で定義されています。

参照先 get_conf_item_string().

参照元 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.c1515 行で定義されています。

参照先 _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()passwordstrdup()usernamewinbind_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.c1650 行で定義されています。

参照先 _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.c1702 行で定義されています。

参照先 _pam_log()_pam_log_debug()_pam_parse()iniparser_freedict()usernamevalid_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.c1792 行で定義されています。

参照先 _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.c1820 行で定義されています。

参照先 _pam_log()_pam_log_debug()_pam_parse()winbindd_request::datawinbindd_request::flagsiniparser_freedict()winbindd_request::logoffpam_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
戻り値:
boolean Returns True if required, False if not.

pam_winbind.c1911 行で定義されています。

参照先 _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.c1949 行で定義されています。

参照先 _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::authwinbindd_response::dataget_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

初期値:

pam_winbind.c2208 行で定義されています。


Sambaに対してSat Aug 29 21:23:55 2009に生成されました。  doxygen 1.4.7