diff options
-rw-r--r-- | source3/nsswitch/pam_winbind.c | 1111 |
1 files changed, 697 insertions, 414 deletions
diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index f4793f77c8..fde5b03611 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -5,22 +5,24 @@ Copyright Andrew Bartlett <abartlet@samba.org> 2002 Copyright Guenther Deschner <gd@samba.org> 2005-2007 - largely based on pam_userdb by Cristian Gafton <gafton@redhat.com> - also contains large slabs of code from pam_unix by Elliot Lee <sopwith@redhat.com> - (see copyright below for full details) + largely based on pam_userdb by Cristian Gafton <gafton@redhat.com> also + contains large slabs of code from pam_unix by Elliot Lee + <sopwith@redhat.com> (see copyright below for full details) */ #include "pam_winbind.h" #define _PAM_LOG_FUNCTION_ENTER(function, pamh, ctrl, flags) \ do { \ - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] ENTER: " function " (flags: 0x%04x)", pamh, flags); \ + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] ENTER: " \ + function " (flags: 0x%04x)", pamh, flags); \ _pam_log_state(pamh, ctrl); \ } while (0) #define _PAM_LOG_FUNCTION_LEAVE(function, pamh, ctrl, retval) \ do { \ - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] LEAVE: " function " returning %d", pamh, retval); \ + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] LEAVE: " \ + function " returning %d", pamh, retval); \ _pam_log_state(pamh, ctrl); \ } while (0) @@ -29,17 +31,19 @@ #define MAX_PASSWD_TRIES 3 /* - * Work around the pam API that has functions with void ** as parameters. + * Work around the pam API that has functions with void ** as parameters * These lead to strict aliasing warnings with gcc. */ -static int _pam_get_item(const pam_handle_t *pamh, int item_type, +static int _pam_get_item(const pam_handle_t *pamh, + int item_type, const void *_item) { const void **item = (const void **)_item; return pam_get_item(pamh, item_type, item); } static int _pam_get_data(const pam_handle_t *pamh, - const char *module_data_name, const void *_data) + const char *module_data_name, + const void *_data) { const void **data = (const void **)_data; return pam_get_data(pamh, module_data_name, data); @@ -48,12 +52,18 @@ static int _pam_get_data(const pam_handle_t *pamh, /* some syslogging */ #ifdef HAVE_PAM_VSYSLOG -static void _pam_log_int(const pam_handle_t *pamh, int err, const char *format, va_list args) +static void _pam_log_int(const pam_handle_t *pamh, + int err, + const char *format, + va_list args) { pam_vsyslog(pamh, err, format, args); } #else -static void _pam_log_int(const pam_handle_t *pamh, int err, const char *format, va_list args) +static void _pam_log_int(const pam_handle_t *pamh, + int err, + const char *format, + va_list args) { char *format2 = NULL; const char *service; @@ -132,7 +142,11 @@ static void _pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const ch va_end(args); } -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_datum(const pam_handle_t *pamh, + int ctrl, + int item_type, + const char *key, + int is_string) { const void *data = NULL; if (item_type != 0) { @@ -143,9 +157,14 @@ static void _pam_log_state_datum(const pam_handle_t *pamh, int ctrl, int item_ty if (data != NULL) { const char *type = (item_type != 0) ? "ITEM" : "DATA"; if (is_string != 0) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] STATE: %s(%s) = \"%s\" (%p)", pamh, type, key, (const char *) data, data); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "[pamh: %p] STATE: %s(%s) = \"%s\" (%p)", + pamh, type, key, (const char *)data, + data); } else { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] STATE: %s(%s) = %p", pamh, type, key, data); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "[pamh: %p] STATE: %s(%s) = %p", + pamh, type, key, data); } } } @@ -169,7 +188,8 @@ static void _pam_log_state_datum(const pam_handle_t *pamh, int ctrl, int item_ty #endif #define _PAM_LOG_STATE_ITEM_PASSWORD(pamh, ctrl, item_type) \ - _pam_log_state_datum(pamh, ctrl, item_type, #item_type, _LOG_PASSWORD_AS_STRING) + _pam_log_state_datum(pamh, ctrl, item_type, #item_type, \ + _LOG_PASSWORD_AS_STRING) static void _pam_log_state(const pam_handle_t *pamh, int ctrl) { @@ -197,12 +217,19 @@ static void _pam_log_state(const pam_handle_t *pamh, int ctrl) _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_LOGONSCRIPT); _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_LOGONSERVER); _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_PROFILEPATH); - _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_NEW_AUTHTOK_REQD); /* Use atoi to get PAM result code */ - _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH); + _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, + PAM_WINBIND_NEW_AUTHTOK_REQD); + /* Use atoi to get PAM result code */ + _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, + PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH); _PAM_LOG_STATE_DATA_POINTER(pamh, ctrl, PAM_WINBIND_PWD_LAST_SET); } -static int _pam_parse(const pam_handle_t *pamh, int flags, int argc, const char **argv, dictionary **result_d) +static int _pam_parse(const pam_handle_t *pamh, + int flags, + int argc, + const char **argv, + dictionary **result_d) { int ctrl = 0; const char *config_file = NULL; @@ -287,18 +314,22 @@ config_from_pam: ctrl |= WINBIND_TRY_FIRST_PASS_ARG; else if (!strcasecmp(*v, "unknown_ok")) ctrl |= WINBIND_UNKNOWN_OK_ARG; - else if (!strncasecmp(*v, "require_membership_of", strlen("require_membership_of"))) + else if (!strncasecmp(*v, "require_membership_of", + strlen("require_membership_of"))) ctrl |= WINBIND_REQUIRED_MEMBERSHIP; - else if (!strncasecmp(*v, "require-membership-of", strlen("require-membership-of"))) + else if (!strncasecmp(*v, "require-membership-of", + strlen("require-membership-of"))) ctrl |= WINBIND_REQUIRED_MEMBERSHIP; else if (!strcasecmp(*v, "krb5_auth")) ctrl |= WINBIND_KRB5_AUTH; - else if (!strncasecmp(*v, "krb5_ccache_type", strlen("krb5_ccache_type"))) + else if (!strncasecmp(*v, "krb5_ccache_type", + strlen("krb5_ccache_type"))) ctrl |= WINBIND_KRB5_CCACHE_TYPE; else if (!strcasecmp(*v, "cached_login")) ctrl |= WINBIND_CACHED_LOGIN; else { - _pam_log(pamh, ctrl, LOG_ERR, "pam_parse: unknown option: %s", *v); + _pam_log(pamh, ctrl, LOG_ERR, + "pam_parse: unknown option: %s", *v); return -1; } @@ -315,11 +346,16 @@ config_from_pam: return ctrl; }; -static void _pam_winbind_cleanup_func(pam_handle_t *pamh, void *data, int error_status) +static void _pam_winbind_cleanup_func(pam_handle_t *pamh, + void *data, + int error_status) { int ctrl = _pam_parse(pamh, 0, 0, NULL, NULL); if (_pam_log_is_debug_state_enabled(ctrl)) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] CLEAN: cleaning up PAM data %p (error_status = %d)", pamh, data, error_status); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "[pamh: %p] CLEAN: cleaning up PAM data %p " + "(error_status = %d)", pamh, data, + error_status); } SAFE_FREE(data); } @@ -329,32 +365,54 @@ static const struct ntstatus_errors { const char *ntstatus_string; const char *error_string; } ntstatus_errors[] = { - {"NT_STATUS_OK", "Success"}, - {"NT_STATUS_BACKUP_CONTROLLER", "No primary Domain Controler available"}, - {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", "No domain controllers found"}, - {"NT_STATUS_NO_LOGON_SERVERS", "No logon servers"}, - {"NT_STATUS_PWD_TOO_SHORT", "Password too short"}, - {"NT_STATUS_PWD_TOO_RECENT", "The password of this user is too recent to change"}, - {"NT_STATUS_PWD_HISTORY_CONFLICT", "Password is already in password history"}, - {"NT_STATUS_PASSWORD_EXPIRED", "Your password has expired"}, - {"NT_STATUS_PASSWORD_MUST_CHANGE", "You need to change your password now"}, - {"NT_STATUS_INVALID_WORKSTATION", "You are not allowed to logon from this workstation"}, - {"NT_STATUS_INVALID_LOGON_HOURS", "You are not allowed to logon at this time"}, - {"NT_STATUS_ACCOUNT_EXPIRED", "Your account has expired. Please contact your System administrator"}, /* SCNR */ - {"NT_STATUS_ACCOUNT_DISABLED", "Your account is disabled. Please contact your System administrator"}, /* SCNR */ - {"NT_STATUS_ACCOUNT_LOCKED_OUT", "Your account has been locked. Please contact your System administrator"}, /* SCNR */ - {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT", "Invalid Trust Account"}, - {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT", "Invalid Trust Account"}, - {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT", "Invalid Trust Account"}, - {"NT_STATUS_ACCESS_DENIED", "Access is denied"}, + {"NT_STATUS_OK", + "Success"}, + {"NT_STATUS_BACKUP_CONTROLLER", + "No primary Domain Controler available"}, + {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", + "No domain controllers found"}, + {"NT_STATUS_NO_LOGON_SERVERS", + "No logon servers"}, + {"NT_STATUS_PWD_TOO_SHORT", + "Password too short"}, + {"NT_STATUS_PWD_TOO_RECENT", + "The password of this user is too recent to change"}, + {"NT_STATUS_PWD_HISTORY_CONFLICT", + "Password is already in password history"}, + {"NT_STATUS_PASSWORD_EXPIRED", + "Your password has expired"}, + {"NT_STATUS_PASSWORD_MUST_CHANGE", + "You need to change your password now"}, + {"NT_STATUS_INVALID_WORKSTATION", + "You are not allowed to logon from this workstation"}, + {"NT_STATUS_INVALID_LOGON_HOURS", + "You are not allowed to logon at this time"}, + {"NT_STATUS_ACCOUNT_EXPIRED", + "Your account has expired. " + "Please contact your System administrator"}, /* SCNR */ + {"NT_STATUS_ACCOUNT_DISABLED", + "Your account is disabled. " + "Please contact your System administrator"}, /* SCNR */ + {"NT_STATUS_ACCOUNT_LOCKED_OUT", + "Your account has been locked. " + "Please contact your System administrator"}, /* SCNR */ + {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT", + "Invalid Trust Account"}, + {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT", + "Invalid Trust Account"}, + {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT", + "Invalid Trust Account"}, + {"NT_STATUS_ACCESS_DENIED", + "Access is denied"}, {NULL, NULL} }; -const char *_get_ntstatus_error_string(const char *nt_status_string) +const char *_get_ntstatus_error_string(const char *nt_status_string) { int i; for (i=0; ntstatus_errors[i].ntstatus_string != NULL; i++) { - if (!strcasecmp(ntstatus_errors[i].ntstatus_string, nt_status_string)) { + if (!strcasecmp(ntstatus_errors[i].ntstatus_string, + nt_status_string)) { return ntstatus_errors[i].error_string; } } @@ -365,30 +423,35 @@ const char *_get_ntstatus_error_string(const char *nt_status_string) /* Attempt a conversation */ -static int converse(pam_handle_t *pamh, int nargs, +static int converse(pam_handle_t *pamh, + int nargs, struct pam_message **message, struct pam_response **response) { int retval; struct pam_conv *conv; - retval = _pam_get_item(pamh, PAM_CONV, &conv ); + retval = _pam_get_item(pamh, PAM_CONV, &conv); if (retval == PAM_SUCCESS) { - retval = conv->conv(nargs, (const struct pam_message **)message, + retval = conv->conv(nargs, + (const struct pam_message **)message, response, conv->appdata_ptr); } - + return retval; /* propagate error status */ } -static int _make_remark(pam_handle_t * pamh, int flags, int type, const char *text) +static int _make_remark(pam_handle_t * pamh, + int flags, + int type, + const char *text) { int retval = PAM_SUCCESS; struct pam_message *pmsg[1], msg[1]; struct pam_response *resp; - + if (flags & WINBIND_SILENT) { return PAM_SUCCESS; } @@ -396,17 +459,21 @@ static int _make_remark(pam_handle_t * pamh, int flags, int type, const char *te pmsg[0] = &msg[0]; msg[0].msg = discard_const_p(char, text); msg[0].msg_style = type; - + resp = NULL; retval = converse(pamh, 1, pmsg, &resp); - + if (resp) { _pam_drop_reply(resp, 1); } return retval; } -static int _make_remark_v(pam_handle_t * pamh, int flags, int type, const char *format, va_list args) +static int _make_remark_v(pam_handle_t *pamh, + int flags, + int type, + const char *format, + va_list args) { char *var; int ret; @@ -434,23 +501,26 @@ static int _make_remark_format(pam_handle_t * pamh, int flags, int type, const c return ret; } -static int pam_winbind_request(pam_handle_t * pamh, int ctrl, +static int pam_winbind_request(pam_handle_t *pamh, + int ctrl, enum winbindd_cmd req_type, struct winbindd_request *request, struct winbindd_response *response) { /* Fill in request and send down pipe */ winbindd_init_request(request, req_type); - + if (winbind_write_sock(request, sizeof(*request), 0, 0) == -1) { - _pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: write to socket failed!"); + _pam_log(pamh, ctrl, LOG_ERR, + "pam_winbind_request: write to socket failed!"); winbind_close_sock(); return PAM_SERVICE_ERR; } - + /* Wait for reply */ if (winbindd_read_reply(response) == -1) { - _pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: read from socket failed!"); + _pam_log(pamh, ctrl, LOG_ERR, + "pam_winbind_request: read from socket failed!"); winbind_close_sock(); return PAM_SERVICE_ERR; } @@ -469,8 +539,9 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl, case WINBINDD_GETPWNAM: case WINBINDD_LOOKUPNAME: if (strlen(response->data.auth.nt_status_string) > 0) { - _pam_log(pamh, ctrl, LOG_ERR, "request failed, NT error was %s", - response->data.auth.nt_status_string); + _pam_log(pamh, ctrl, LOG_ERR, + "request failed, NT error was %s", + response->data.auth.nt_status_string); } else { _pam_log(pamh, ctrl, LOG_ERR, "request failed"); } @@ -480,20 +551,22 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl, } if (response->data.auth.pam_error != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_ERR, "request failed: %s, PAM error was %s (%d), NT error was %s", + _pam_log(pamh, ctrl, LOG_ERR, + "request failed: %s, " + "PAM error was %s (%d), NT error was %s", response->data.auth.error_string, pam_strerror(pamh, response->data.auth.pam_error), response->data.auth.pam_error, response->data.auth.nt_status_string); return response->data.auth.pam_error; - } - + } + _pam_log(pamh, ctrl, LOG_ERR, "request failed, but PAM error 0!"); return PAM_SERVICE_ERR; } -static int pam_winbind_request_log(pam_handle_t * pamh, +static int pam_winbind_request_log(pam_handle_t *pamh, int ctrl, enum winbindd_cmd req_type, struct winbindd_request *request, @@ -507,26 +580,31 @@ static int pam_winbind_request_log(pam_handle_t * pamh, switch (retval) { case PAM_AUTH_ERR: /* incorrect password */ - _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' denied access (incorrect password or invalid membership)", user); + _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' denied access " + "(incorrect password or invalid membership)", user); return retval; case PAM_ACCT_EXPIRED: /* account expired */ - _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' account expired", user); + _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' account expired", + user); return retval; case PAM_AUTHTOK_EXPIRED: /* password expired */ - _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' password expired", user); + _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' password expired", + user); return retval; case PAM_NEW_AUTHTOK_REQD: /* new password required */ - _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' new password required", user); + _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' new password " + "required", user); return retval; case PAM_USER_UNKNOWN: /* the user does not exist */ - _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", user); + _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", + user); if (ctrl & WINBIND_UNKNOWN_OK_ARG) { return PAM_IGNORE; - } + } return retval; case PAM_SUCCESS: /* Otherwise, the authentication looked good */ @@ -534,20 +612,24 @@ static int pam_winbind_request_log(pam_handle_t * pamh, case WINBINDD_INFO: break; case WINBINDD_PAM_AUTH: - _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", user); + _pam_log(pamh, ctrl, LOG_NOTICE, + "user '%s' granted access", user); break; case WINBINDD_PAM_CHAUTHTOK: - _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' password changed", user); + _pam_log(pamh, ctrl, LOG_NOTICE, + "user '%s' password changed", user); break; default: - _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' OK", user); + _pam_log(pamh, ctrl, LOG_NOTICE, + "user '%s' OK", user); break; } - + return retval; default: /* we don't know anything about this return value */ - _pam_log(pamh, ctrl, LOG_ERR, "internal module error (retval = %d, user = '%s')", + _pam_log(pamh, ctrl, LOG_ERR, + "internal module error (retval = %d, user = '%s')", retval, user); return retval; } @@ -555,7 +637,7 @@ static int pam_winbind_request_log(pam_handle_t * pamh, /** * send a password expiry message if required - * + * * @param pamh PAM handle * @param ctrl PAM winbind options. * @param next_change expected (calculated) next expiry date. @@ -592,21 +674,24 @@ static bool _pam_send_password_expiry_message(pam_handle_t *pamh, return false; } - if ((localtime_r(&now, &tm_now) == NULL) || + if ((localtime_r(&now, &tm_now) == NULL) || (localtime_r(&next_change, &tm_next_change) == NULL)) { return false; } - days = (tm_next_change.tm_yday+tm_next_change.tm_year*365) - (tm_now.tm_yday+tm_now.tm_year*365); + days = (tm_next_change.tm_yday+tm_next_change.tm_year*365) - + (tm_now.tm_yday+tm_now.tm_year*365); if (days == 0) { - _make_remark(pamh, ctrl, PAM_TEXT_INFO, "Your password expires today"); + _make_remark(pamh, ctrl, PAM_TEXT_INFO, + "Your password expires today"); return true; - } - + } + if (days > 0 && days < warn_pwd_expire) { - _make_remark_format(pamh, ctrl, PAM_TEXT_INFO, "Your password will expire in %d %s", - days, (days > 1) ? "days":"day"); + _make_remark_format(pamh, ctrl, PAM_TEXT_INFO, + "Your password will expire in %d %s", + days, (days > 1) ? "days":"day"); return true; } @@ -624,8 +709,8 @@ static bool _pam_send_password_expiry_message(pam_handle_t *pamh, * @return void. */ -static void _pam_warn_password_expiry(pam_handle_t *pamh, - int flags, +static void _pam_warn_password_expiry(pam_handle_t *pamh, + int flags, const struct winbindd_response *response, int warn_pwd_expire, bool *already_expired) @@ -663,7 +748,7 @@ static void _pam_warn_password_expiry(pam_handle_t *pamh, return; } - next_change = response->data.auth.info3.pass_last_set_time + + next_change = response->data.auth.info3.pass_last_set_time + response->data.auth.policy.expire; if (_pam_send_password_expiry_message(pamh, flags, next_change, now, @@ -677,24 +762,26 @@ static void _pam_warn_password_expiry(pam_handle_t *pamh, #define IS_SID_STRING(name) (strncmp("S-", name, 2) == 0) -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. + * Append a string, making sure not to overflow and to always return a + * NULL-terminated string. * * @param dest Destination string buffer (must already be NULL-terminated). * @param src Source string buffer. * @param dest_buffer_size Size of dest buffer in bytes. * - * @return false if dest buffer is not big enough (no bytes copied), true on success. + * @return false if dest buffer is not big enough (no bytes copied), true on + * success. */ + +static bool safe_append_string(char *dest, + const char *src, + int dest_buffer_size) { int dest_length = strlen(dest); int src_length = strlen(src); - if ( dest_length + src_length + 1 > dest_buffer_size ) { + if (dest_length + src_length + 1 > dest_buffer_size) { return false; } @@ -702,12 +789,6 @@ static bool safe_append_string(char *dest, return true; } -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. * @@ -720,11 +801,17 @@ static bool winbind_name_to_sid_string(pam_handle_t *pamh, * * @return false on failure, true on success. */ +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) { const char* sid_string; struct winbindd_response sid_response; - /* lookup name? */ + /* lookup name? */ if (IS_SID_STRING(name)) { sid_string = name; } else { @@ -733,33 +820,32 @@ static bool winbind_name_to_sid_string(pam_handle_t *pamh, ZERO_STRUCT(sid_request); ZERO_STRUCT(sid_response); - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "no sid given, looking up: %s\n", name); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "no sid given, looking up: %s\n", name); /* fortunatly winbindd can handle non-separated names */ strncpy(sid_request.data.name.name, name, sizeof(sid_request.data.name.name) - 1); - if (pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, &sid_request, &sid_response, user)) { - _pam_log(pamh, ctrl, LOG_INFO, "could not lookup name: %s\n", name); + if (pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, + &sid_request, &sid_response, + user)) { + _pam_log(pamh, ctrl, LOG_INFO, + "could not lookup name: %s\n", name); return false; } sid_string = sid_response.data.sid.sid; } - if (!safe_append_string(sid_list_buffer, sid_string, sid_list_buffer_size)) { + if (!safe_append_string(sid_list_buffer, sid_string, + sid_list_buffer_size)) { return false; } return true; } -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. * @@ -772,37 +858,50 @@ static bool winbind_name_list_to_sid_string_list(pam_handle_t *pamh, * * @return false on failure, true on success. */ +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) { bool result = false; char *current_name = NULL; const char *search_location; const char *comma; - if ( sid_list_buffer_size > 0 ) { + if (sid_list_buffer_size > 0) { sid_list_buffer[0] = 0; } search_location = name_list; - while ( (comma = strstr(search_location, ",")) != NULL ) { - current_name = strndup(search_location, comma - search_location); + while ((comma = strstr(search_location, ",")) != NULL) { + current_name = strndup(search_location, + comma - search_location); if (NULL == current_name) { goto out; } - if (!winbind_name_to_sid_string(pamh, ctrl, user, current_name, sid_list_buffer, sid_list_buffer_size)) { + if (!winbind_name_to_sid_string(pamh, ctrl, user, + current_name, + sid_list_buffer, + sid_list_buffer_size)) { goto out; } SAFE_FREE(current_name); - if (!safe_append_string(sid_list_buffer, ",", sid_list_buffer_size)) { + if (!safe_append_string(sid_list_buffer, ",", + sid_list_buffer_size)) { goto out; } search_location = comma + 1; } - if (!winbind_name_to_sid_string(pamh, ctrl, user, search_location, sid_list_buffer, sid_list_buffer_size)) { + if (!winbind_name_to_sid_string(pamh, ctrl, user, search_location, + sid_list_buffer, + sid_list_buffer_size)) { goto out; } @@ -823,7 +922,9 @@ out: * @return void. */ -static void _pam_setup_krb5_env(pam_handle_t *pamh, int ctrl, const char *krb5ccname) +static void _pam_setup_krb5_env(pam_handle_t *pamh, + int ctrl, + const char *krb5ccname) { char var[PATH_MAX]; int ret; @@ -836,18 +937,20 @@ static void _pam_setup_krb5_env(pam_handle_t *pamh, int ctrl, const char *krb5cc return; } - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "request returned KRB5CCNAME: %s", krb5ccname); - + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "request returned KRB5CCNAME: %s", krb5ccname); + if (snprintf(var, sizeof(var), "KRB5CCNAME=%s", krb5ccname) == -1) { return; } - + ret = pam_putenv(pamh, var); if (ret) { - _pam_log(pamh, ctrl, LOG_ERR, "failed to set KRB5CCNAME to %s: %s", - var, pam_strerror(pamh, ret)); + _pam_log(pamh, ctrl, LOG_ERR, + "failed to set KRB5CCNAME to %s: %s", + var, pam_strerror(pamh, ret)); } -} +} /** * Set string into the PAM stack. @@ -860,18 +963,24 @@ static void _pam_setup_krb5_env(pam_handle_t *pamh, int ctrl, const char *krb5cc * @return void. */ -static void _pam_set_data_string(pam_handle_t *pamh, int ctrl, const char *data_name, const char *value) +static void _pam_set_data_string(pam_handle_t *pamh, + int ctrl, + const char *data_name, + const char *value) { int ret; - if ( !data_name || !value || (strlen(data_name) == 0) || (strlen(value) == 0) ) { + if (!data_name || !value || (strlen(data_name) == 0) || + (strlen(value) == 0)) { return; } - ret = pam_set_data(pamh, data_name, (void *)strdup(value), _pam_winbind_cleanup_func); + ret = pam_set_data(pamh, data_name, (void *)strdup(value), + _pam_winbind_cleanup_func); if (ret) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Could not set data %s: %s\n", - data_name, pam_strerror(pamh, ret)); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "Could not set data %s: %s\n", + data_name, pam_strerror(pamh, ret)); } } @@ -887,12 +996,18 @@ static void _pam_set_data_string(pam_handle_t *pamh, int ctrl, const char *data_ * @return void. */ -static void _pam_set_data_info3(pam_handle_t *pamh, int ctrl, struct winbindd_response *response) +static void _pam_set_data_info3(pam_handle_t *pamh, + int ctrl, + struct winbindd_response *response) { - _pam_set_data_string(pamh, ctrl, PAM_WINBIND_HOMEDIR, response->data.auth.info3.home_dir); - _pam_set_data_string(pamh, ctrl, PAM_WINBIND_LOGONSCRIPT, response->data.auth.info3.logon_script); - _pam_set_data_string(pamh, ctrl, PAM_WINBIND_LOGONSERVER, response->data.auth.info3.logon_srv); - _pam_set_data_string(pamh, ctrl, PAM_WINBIND_PROFILEPATH, response->data.auth.info3.profile_path); + _pam_set_data_string(pamh, ctrl, PAM_WINBIND_HOMEDIR, + response->data.auth.info3.home_dir); + _pam_set_data_string(pamh, ctrl, PAM_WINBIND_LOGONSCRIPT, + response->data.auth.info3.logon_script); + _pam_set_data_string(pamh, ctrl, PAM_WINBIND_LOGONSERVER, + response->data.auth.info3.logon_srv); + _pam_set_data_string(pamh, ctrl, PAM_WINBIND_PROFILEPATH, + response->data.auth.info3.profile_path); } /** @@ -922,22 +1037,31 @@ static void _pam_free_data_info3(pam_handle_t *pamh) * @return void. */ -static void _pam_warn_logon_type(pam_handle_t *pamh, int ctrl, const char *username, uint32_t info3_user_flgs) +static void _pam_warn_logon_type(pam_handle_t *pamh, + int ctrl, + const char *username, + uint32_t info3_user_flgs) { /* inform about logon type */ if (PAM_WB_GRACE_LOGON(info3_user_flgs)) { - _make_remark(pamh, ctrl, PAM_ERROR_MSG, - "Grace login. Please change your password as soon you're online again"); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "Grace login. " + "Please change your password as soon you're " + "online again"); _pam_log_debug(pamh, ctrl, LOG_DEBUG, - "User %s logged on using grace logon\n", username); + "User %s logged on using grace logon\n", + username); } else if (PAM_WB_CACHED_LOGON(info3_user_flgs)) { - _make_remark(pamh, ctrl, PAM_ERROR_MSG, - "Domain Controller unreachable, using cached credentials instead. Network resources may be unavailable"); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "Domain Controller unreachable, " + "using cached credentials instead. " + "Network resources may be unavailable"); _pam_log_debug(pamh, ctrl, LOG_DEBUG, - "User %s logged on using cached credentials\n", username); + "User %s logged on using cached credentials\n", + username); } } @@ -952,16 +1076,20 @@ static void _pam_warn_logon_type(pam_handle_t *pamh, int ctrl, const char *usern * @return void. */ -static void _pam_warn_krb5_failure(pam_handle_t *pamh, int ctrl, const char *username, uint32_t info3_user_flgs) +static void _pam_warn_krb5_failure(pam_handle_t *pamh, + int ctrl, + const char *username, + uint32_t info3_user_flgs) { if (PAM_WB_KRB5_CLOCK_SKEW(info3_user_flgs)) { - _make_remark(pamh, ctrl, PAM_ERROR_MSG, + _make_remark(pamh, ctrl, PAM_ERROR_MSG, "Failed to establish your Kerberos Ticket cache " - "due time differences\n" + "due time differences\n" "with the domain controller. " - "Please verify the system time.\n"); + "Please verify the system time.\n"); _pam_log_debug(pamh, ctrl, LOG_DEBUG, - "User %s: Clock skew when getting Krb5 TGT\n", username); + "User %s: Clock skew when getting Krb5 TGT\n", + username); } } @@ -992,37 +1120,42 @@ static char *_pam_compose_pwd_restriction_string(struct winbindd_response *respo if (response->data.auth.policy.min_length_password > 0) { ret = snprintf(str+offset, str_size-offset, - "must be at least %d characters; ", - response->data.auth.policy.min_length_password); + "must be at least %d characters; ", + response->data.auth.policy.min_length_password); if (ret == -1) { goto failed; } offset += ret; } - + if (response->data.auth.policy.password_history > 0) { ret = snprintf(str+offset, str_size-offset, - "cannot repeat any of your previous %d passwords; ", - response->data.auth.policy.password_history); + "cannot repeat any of your previous %d " + "passwords; ", + response->data.auth.policy.password_history); if (ret == -1) { goto failed; } offset += ret; } - - if (response->data.auth.policy.password_properties & DOMAIN_PASSWORD_COMPLEX) { + + if (response->data.auth.policy.password_properties & + DOMAIN_PASSWORD_COMPLEX) { ret = snprintf(str+offset, str_size-offset, - "must contain capitals, numerals or punctuation; " - "and cannot contain your account or full name; "); + "must contain capitals, numerals " + "or punctuation; " + "and cannot contain your account " + "or full name; "); if (ret == -1) { goto failed; } offset += ret; } - ret = snprintf(str+offset, str_size-offset, - "Please type a different password. " - "Type a password which meets these requirements in both text boxes."); + ret = snprintf(str+offset, str_size-offset, + "Please type a different password. " + "Type a password which meets these requirements in " + "both text boxes."); if (ret == -1) { goto failed; } @@ -1036,10 +1169,10 @@ static char *_pam_compose_pwd_restriction_string(struct winbindd_response *respo /* talk to winbindd */ static int winbind_auth_request(pam_handle_t * pamh, - int ctrl, - const char *user, - const char *pass, - const char *member, + int ctrl, + const char *user, + const char *pass, + const char *member, const char *cctype, const int warn_pwd_expire, struct winbindd_response *p_response, @@ -1058,16 +1191,17 @@ static int winbind_auth_request(pam_handle_t * pamh, *pwd_last_set = 0; } - strncpy(request.data.auth.user, user, + strncpy(request.data.auth.user, user, sizeof(request.data.auth.user)-1); - strncpy(request.data.auth.pass, pass, + strncpy(request.data.auth.pass, pass, sizeof(request.data.auth.pass)-1); request.data.auth.krb5_cc_type[0] = '\0'; request.data.auth.uid = -1; - - request.flags = WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_CONTACT_TRUSTDOM; + + request.flags = WBFLAG_PAM_INFO3_TEXT | + WBFLAG_PAM_CONTACT_TRUSTDOM; if (ctrl & (WINBIND_KRB5_AUTH|WINBIND_CACHED_LOGIN)) { struct passwd *pwd = NULL; @@ -1081,13 +1215,16 @@ static int winbind_auth_request(pam_handle_t * pamh, if (ctrl & WINBIND_KRB5_AUTH) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling krb5 login flag\n"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "enabling krb5 login flag\n"); - request.flags |= WBFLAG_PAM_KRB5 | WBFLAG_PAM_FALLBACK_AFTER_KRB5; + request.flags |= WBFLAG_PAM_KRB5 | + WBFLAG_PAM_FALLBACK_AFTER_KRB5; } if (ctrl & WINBIND_CACHED_LOGIN) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling cached login flag\n"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "enabling cached login flag\n"); request.flags |= WBFLAG_PAM_CACHED_LOGIN; } @@ -1097,25 +1234,31 @@ static int winbind_auth_request(pam_handle_t * pamh, } if (cctype != NULL) { - strncpy(request.data.auth.krb5_cc_type, cctype, + strncpy(request.data.auth.krb5_cc_type, cctype, sizeof(request.data.auth.krb5_cc_type) - 1); - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling request for a %s krb5 ccache\n", cctype); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "enabling request for a %s krb5 ccache\n", + cctype); } request.data.auth.require_membership_of_sid[0] = '\0'; if (member != NULL) { - if (!winbind_name_list_to_sid_string_list(pamh, ctrl, user, member, + if (!winbind_name_list_to_sid_string_list(pamh, ctrl, user, + member, request.data.auth.require_membership_of_sid, sizeof(request.data.auth.require_membership_of_sid))) { - _pam_log_debug(pamh, ctrl, LOG_ERR, "failed to serialize membership of sid \"%s\"\n", member); + _pam_log_debug(pamh, ctrl, LOG_ERR, + "failed to serialize membership of sid " + "\"%s\"\n", member); return PAM_AUTH_ERR; } } - ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_AUTH, &request, &response, user); + ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_AUTH, + &request, &response, user); if (pwd_last_set) { *pwd_last_set = response.data.auth.info3.pass_last_set_time; @@ -1128,20 +1271,34 @@ static int winbind_auth_request(pam_handle_t * pamh, } if (ret) { - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PASSWORD_EXPIRED"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PASSWORD_MUST_CHANGE"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_INVALID_WORKSTATION"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_INVALID_LOGON_HOURS"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCOUNT_EXPIRED"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCOUNT_DISABLED"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCOUNT_LOCKED_OUT"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_WRONG_PASSWORD"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_PASSWORD_EXPIRED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_PASSWORD_MUST_CHANGE"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_INVALID_WORKSTATION"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_INVALID_LOGON_HOURS"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_ACCOUNT_EXPIRED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_ACCOUNT_DISABLED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_ACCOUNT_LOCKED_OUT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_NO_LOGON_SERVERS"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_WRONG_PASSWORD"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_ACCESS_DENIED"); } if (ret == PAM_SUCCESS) { @@ -1152,11 +1309,15 @@ static int winbind_auth_request(pam_handle_t * pamh, &already_expired); if (already_expired == true) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Password has expired " - "(Password was last set: %lld, the policy says " - "it should expire here %lld (now it's: %lu))\n", - response.data.auth.info3.pass_last_set_time, - response.data.auth.info3.pass_last_set_time + + SMB_TIME_T last_set; + last_set = response.data.auth.info3.pass_last_set_time; + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "Password has expired " + "(Password was last set: %lld, " + "the policy says it should expire here " + "%lld (now it's: %lu))\n", + (long long int)last_set, + (long long int)last_set + response.data.auth.policy.expire, time(NULL)); @@ -1164,10 +1325,12 @@ static int winbind_auth_request(pam_handle_t * pamh, } /* inform about logon type */ - _pam_warn_logon_type(pamh, ctrl, user, response.data.auth.info3.user_flgs); + _pam_warn_logon_type(pamh, ctrl, user, + response.data.auth.info3.user_flgs); /* inform about krb5 failures */ - _pam_warn_krb5_failure(pamh, ctrl, user, response.data.auth.info3.user_flgs); + _pam_warn_krb5_failure(pamh, ctrl, user, + response.data.auth.info3.user_flgs); /* set some info3 info for other modules in the stack */ _pam_set_data_info3(pamh, ctrl, &response); @@ -1175,7 +1338,8 @@ static int winbind_auth_request(pam_handle_t * pamh, /* put krb5ccname into env */ _pam_setup_krb5_env(pamh, ctrl, response.data.auth.krb5ccname); - /* If winbindd returned a username, return the pointer to it here. */ + /* If winbindd returned a username, return the pointer to it + * here. */ if (user_ret && response.extra_data.data) { /* We have to trust it's a null terminated string. */ *user_ret = (char *)response.extra_data.data; @@ -1188,10 +1352,10 @@ static int winbind_auth_request(pam_handle_t * pamh, /* talk to winbindd */ static int winbind_chauthtok_request(pam_handle_t * pamh, int ctrl, - const char *user, + const char *user, const char *oldpass, const char *newpass, - time_t pwd_last_set) + time_t pwd_last_set) { struct winbindd_request request; struct winbindd_response response; @@ -1200,82 +1364,105 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, ZERO_STRUCT(request); ZERO_STRUCT(response); - if (request.data.chauthtok.user == NULL) return -2; + if (request.data.chauthtok.user == NULL) { + return -2; + } - strncpy(request.data.chauthtok.user, user, + strncpy(request.data.chauthtok.user, user, sizeof(request.data.chauthtok.user) - 1); if (oldpass != NULL) { - strncpy(request.data.chauthtok.oldpass, oldpass, + strncpy(request.data.chauthtok.oldpass, oldpass, sizeof(request.data.chauthtok.oldpass) - 1); } else { request.data.chauthtok.oldpass[0] = '\0'; } - + if (newpass != NULL) { - strncpy(request.data.chauthtok.newpass, newpass, + strncpy(request.data.chauthtok.newpass, newpass, sizeof(request.data.chauthtok.newpass) - 1); } else { request.data.chauthtok.newpass[0] = '\0'; } if (ctrl & WINBIND_KRB5_AUTH) { - request.flags = WBFLAG_PAM_KRB5 | WBFLAG_PAM_CONTACT_TRUSTDOM; + request.flags = WBFLAG_PAM_KRB5 | + WBFLAG_PAM_CONTACT_TRUSTDOM; } - ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_CHAUTHTOK, &request, &response, user); + ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_CHAUTHTOK, + &request, &response, user); if (ret == PAM_SUCCESS) { return ret; } - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_BACKUP_CONTROLLER"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_BACKUP_CONTROLLER"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_NO_LOGON_SERVERS"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_ACCESS_DENIED"); /* TODO: tell the min pwd length ? */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PWD_TOO_SHORT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_PWD_TOO_SHORT"); /* TODO: tell the minage ? */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PWD_TOO_RECENT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_PWD_TOO_RECENT"); /* TODO: tell the history length ? */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PWD_HISTORY_CONFLICT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_PWD_HISTORY_CONFLICT"); - if (!strcasecmp(response.data.auth.nt_status_string, "NT_STATUS_PASSWORD_RESTRICTION")) { + if (!strcasecmp(response.data.auth.nt_status_string, + "NT_STATUS_PASSWORD_RESTRICTION")) { char *pwd_restriction_string = NULL; + SMB_TIME_T min_pwd_age; + uint32_t reject_reason = response.data.auth.reject_reason; + min_pwd_age = response.data.auth.policy.min_passwordage; /* FIXME: avoid to send multiple PAM messages after another */ - switch (response.data.auth.reject_reason) { + switch (reject_reason) { case -1: break; case REJECT_REASON_OTHER: - if ((response.data.auth.policy.min_passwordage > 0) && - (pwd_last_set + response.data.auth.policy.min_passwordage > time(NULL))) { - PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_TOO_RECENT"); + if ((min_pwd_age > 0) && + (pwd_last_set + min_pwd_age > time(NULL))) { + PAM_WB_REMARK_DIRECT(pamh, ctrl, + "NT_STATUS_PWD_TOO_RECENT"); } break; case REJECT_REASON_TOO_SHORT: - PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_TOO_SHORT"); + PAM_WB_REMARK_DIRECT(pamh, ctrl, + "NT_STATUS_PWD_TOO_SHORT"); break; case REJECT_REASON_IN_HISTORY: - PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_HISTORY_CONFLICT"); + PAM_WB_REMARK_DIRECT(pamh, ctrl, + "NT_STATUS_PWD_HISTORY_CONFLICT"); break; case REJECT_REASON_NOT_COMPLEX: - _make_remark(pamh, ctrl, PAM_ERROR_MSG, "Password does not meet complexity requirements"); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "Password does not meet " + "complexity requirements"); break; default: _pam_log_debug(pamh, ctrl, LOG_DEBUG, - "unknown password change reject reason: %d", - response.data.auth.reject_reason); + "unknown password change " + "reject reason: %d", + reject_reason); break; } - pwd_restriction_string = _pam_compose_pwd_restriction_string(&response); + pwd_restriction_string = + _pam_compose_pwd_restriction_string(&response); if (pwd_restriction_string) { - _make_remark(pamh, ctrl, PAM_ERROR_MSG, pwd_restriction_string); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + pwd_restriction_string); SAFE_FREE(pwd_restriction_string); } } @@ -1291,7 +1478,9 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, * 0 = OK * -1 = System error */ -static int valid_user(pam_handle_t *pamh, int ctrl, const char *user) +static int valid_user(pam_handle_t *pamh, + int ctrl, + const char *user) { /* check not only if the user is available over NSS calls, also make * sure it's really a winbind user, this is important when stacking PAM @@ -1313,7 +1502,8 @@ static int valid_user(pam_handle_t *pamh, int ctrl, const char *user) strncpy(request.data.username, user, sizeof(request.data.username) - 1); - ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_GETPWNAM, &request, &response, user); + ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_GETPWNAM, + &request, &response, user); switch (ret) { case PAM_USER_UNKNOWN: @@ -1361,28 +1551,33 @@ static int _winbind_read_password(pam_handle_t * pamh, * which authentication token are we getting? */ - authtok_flag = on(WINBIND__OLD_PASSWORD, ctrl) ? PAM_OLDAUTHTOK : PAM_AUTHTOK; + if (on(WINBIND__OLD_PASSWORD, ctrl)) { + authtok_flag = PAM_OLDAUTHTOK; + } else { + authtok_flag = PAM_AUTHTOK; + } /* * should we obtain the password from a PAM item ? */ - if (on(WINBIND_TRY_FIRST_PASS_ARG, ctrl) || on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { + if (on(WINBIND_TRY_FIRST_PASS_ARG, ctrl) || + on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { retval = _pam_get_item(pamh, authtok_flag, &item); if (retval != PAM_SUCCESS) { /* very strange. */ - _pam_log(pamh, ctrl, LOG_ALERT, - "pam_get_item returned error to unix-read-password" - ); + _pam_log(pamh, ctrl, LOG_ALERT, + "pam_get_item returned error " + "to unix-read-password"); return retval; } else if (item != NULL) { /* we have a password! */ *pass = item; item = NULL; - _pam_log(pamh, ctrl, LOG_DEBUG, + _pam_log(pamh, ctrl, LOG_DEBUG, "pam_get_item returned a password"); return PAM_SUCCESS; } else if (on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { - return PAM_AUTHTOK_RECOVER_ERR; /* didn't work */ + return PAM_AUTHTOK_RECOVER_ERR; /* didn't work */ } else if (on(WINBIND_USE_AUTHTOK_ARG, ctrl) && off(WINBIND__OLD_PASSWORD, ctrl)) { return PAM_AUTHTOK_RECOVER_ERR; @@ -1423,60 +1618,64 @@ static int _winbind_read_password(pam_handle_t * pamh, /* so call the conversation expecting i responses */ resp = NULL; retval = converse(pamh, i, pmsg, &resp); - - if (resp != NULL) { - - /* interpret the response */ - - if (retval == PAM_SUCCESS) { /* a good conversation */ - - token = x_strdup(resp[i - replies].resp); - if (token != NULL) { - if (replies == 2) { - /* verify that password entered correctly */ - if (!resp[i - 1].resp - || strcmp(token, resp[i - 1].resp)) { - _pam_delete(token); /* mistyped */ - retval = PAM_AUTHTOK_RECOVER_ERR; - _make_remark(pamh, ctrl, PAM_ERROR_MSG, MISTYPED_PASS); - } - } - } else { - _pam_log(pamh, ctrl, LOG_NOTICE, "could not recover authentication token"); - retval = PAM_AUTHTOK_RECOVER_ERR; - } - + if (resp == NULL) { + if (retval == PAM_SUCCESS) { + retval = PAM_AUTHTOK_RECOVER_ERR; } - /* - * tidy up the conversation (resp_retcode) is ignored - * -- what is it for anyway? AGM - */ - + goto done; + } + if (retval != PAM_SUCCESS) { _pam_drop_reply(resp, i); + goto done; + } - } else { - retval = (retval == PAM_SUCCESS) - ? PAM_AUTHTOK_RECOVER_ERR : retval; + /* interpret the response */ + + token = x_strdup(resp[i - replies].resp); + if (!token) { + _pam_log(pamh, ctrl, LOG_NOTICE, + "could not recover " + "authentication token"); + retval = PAM_AUTHTOK_RECOVER_ERR; + goto done; + } + + if (replies == 2) { + /* verify that password entered correctly */ + if (!resp[i - 1].resp || + strcmp(token, resp[i - 1].resp)) { + _pam_delete(token); /* mistyped */ + retval = PAM_AUTHTOK_RECOVER_ERR; + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + MISTYPED_PASS); + } } + + /* + * tidy up the conversation (resp_retcode) is ignored + * -- what is it for anyway? AGM + */ + _pam_drop_reply(resp, i); } + done: if (retval != PAM_SUCCESS) { _pam_log_debug(pamh, ctrl, LOG_DEBUG, - "unable to obtain a password"); + "unable to obtain a password"); return retval; } /* 'token' is the entered password */ /* we store this password as an item */ - + retval = pam_set_item(pamh, authtok_flag, token); _pam_delete(token); /* clean it up */ - if (retval != PAM_SUCCESS || + if (retval != PAM_SUCCESS || (retval = _pam_get_item(pamh, authtok_flag, &item)) != PAM_SUCCESS) { - + _pam_log(pamh, ctrl, LOG_CRIT, "error manipulating password"); return retval; - + } *pass = item; @@ -1486,11 +1685,11 @@ static int _winbind_read_password(pam_handle_t * pamh, } const char *get_conf_item_string(const pam_handle_t *pamh, - int argc, - const char **argv, + int argc, + const char **argv, int ctrl, dictionary *d, - const char *item, + const char *item, int config_flag) { int i = 0; @@ -1501,16 +1700,19 @@ const char *get_conf_item_string(const pam_handle_t *pamh, } /* let the pam opt take precedence over the pam_winbind.conf option */ - for ( i=0; i<argc; i++ ) { + for (i=0; i<argc; i++) { if ((strncmp(argv[i], item, strlen(item)) == 0)) { char *p; - if ( (p = strchr( argv[i], '=' )) == NULL) { - _pam_log(pamh, ctrl, LOG_INFO, "no \"=\" delimiter for \"%s\" found\n", item); + if ((p = strchr(argv[i], '=')) == NULL) { + _pam_log(pamh, ctrl, LOG_INFO, + "no \"=\" delimiter for \"%s\" found\n", + item); goto out; } - _pam_log_debug(pamh, ctrl, LOG_INFO, "PAM config: %s '%s'\n", item, p+1); + _pam_log_debug(pamh, ctrl, LOG_INFO, + "PAM config: %s '%s'\n", item, p+1); return p + 1; } } @@ -1525,7 +1727,8 @@ const char *get_conf_item_string(const pam_handle_t *pamh, parm_opt = iniparser_getstr(d, key); SAFE_FREE(key); - _pam_log_debug(pamh, ctrl, LOG_INFO, "CONFIG file: %s '%s'\n", item, parm_opt); + _pam_log_debug(pamh, ctrl, LOG_INFO, "CONFIG file: %s '%s'\n", + item, parm_opt); } out: return parm_opt; @@ -1551,7 +1754,7 @@ int get_config_item_int(const pam_handle_t *pamh, if ((strncmp(argv[i], item, strlen(item)) == 0)) { char *p; - if ( (p = strchr( argv[i], '=' )) == NULL) { + if ((p = strchr(argv[i], '=')) == NULL) { _pam_log(pamh, ctrl, LOG_INFO, "no \"=\" delimiter for \"%s\" found\n", item); @@ -1583,30 +1786,45 @@ out: return parm_opt; } -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_krb5_cc_type_from_config(const pam_handle_t *pamh, + int argc, + const char **argv, + int ctrl, + dictionary *d) { - return get_conf_item_string(pamh, argc, argv, ctrl, d, "krb5_ccache_type", WINBIND_KRB5_CCACHE_TYPE); + return get_conf_item_string(pamh, argc, argv, ctrl, d, + "krb5_ccache_type", + WINBIND_KRB5_CCACHE_TYPE); } -const char *get_member_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) { const char *ret = NULL; - ret = get_conf_item_string(pamh, argc, argv, ctrl, d, "require_membership_of", WINBIND_REQUIRED_MEMBERSHIP); + ret = get_conf_item_string(pamh, argc, argv, ctrl, d, + "require_membership_of", + WINBIND_REQUIRED_MEMBERSHIP); if (ret) { return ret; } - return get_conf_item_string(pamh, argc, argv, ctrl, d, "require-membership-of", WINBIND_REQUIRED_MEMBERSHIP); + return get_conf_item_string(pamh, argc, argv, ctrl, d, + "require-membership-of", + WINBIND_REQUIRED_MEMBERSHIP); } int get_warn_pwd_expire_from_config(const pam_handle_t *pamh, - int argc, - const char **argv, - int ctrl, - dictionary *d) + int argc, + const char **argv, + int ctrl, + dictionary *d) { int ret; ret = get_config_item_int(pamh, argc, argv, ctrl, d, - "warn_pwd_expire", WINBIND_WARN_PWD_EXPIRE); + "warn_pwd_expire", + WINBIND_WARN_PWD_EXPIRE); /* no or broken setting */ if (ret <= 0) { return DEFAULT_DAYS_TO_WARN_BEFORE_PWD_EXPIRES; @@ -1623,7 +1841,8 @@ int get_warn_pwd_expire_from_config(const pam_handle_t *pamh, * @return string separator character. NULL on failure. */ -static char winbind_get_separator(pam_handle_t *pamh, int ctrl) +static char winbind_get_separator(pam_handle_t *pamh, + int ctrl) { struct winbindd_request request; struct winbindd_response response; @@ -1631,7 +1850,8 @@ static char winbind_get_separator(pam_handle_t *pamh, int ctrl) ZERO_STRUCT(request); ZERO_STRUCT(response); - if (pam_winbind_request_log(pamh, ctrl, WINBINDD_INFO, &request, &response, NULL)) { + if (pam_winbind_request_log(pamh, ctrl, WINBINDD_INFO, + &request, &response, NULL)) { return '\0'; } @@ -1648,14 +1868,16 @@ static char winbind_get_separator(pam_handle_t *pamh, int ctrl) * @return converted name. NULL pointer on failure. Caller needs to free. */ -static char* winbind_upn_to_username(pam_handle_t *pamh, int ctrl, const char *upn) +static char* winbind_upn_to_username(pam_handle_t *pamh, + int ctrl, + const char *upn) { struct winbindd_request req; struct winbindd_response resp; - int retval; - char *account_name; + int retval; + char *account_name; int account_name_len; - char sep; + char sep; /* This cannot work when the winbind separator = @ */ @@ -1663,7 +1885,7 @@ static char* winbind_upn_to_username(pam_handle_t *pamh, int ctrl, const char *u if (!sep || sep == '@') { return NULL; } - + /* Convert the UPN to a SID */ ZERO_STRUCT(req); @@ -1673,24 +1895,24 @@ static char* winbind_upn_to_username(pam_handle_t *pamh, int ctrl, const char *u sizeof(req.data.name.dom_name) - 1); strncpy(req.data.name.name, upn, sizeof(req.data.name.name) - 1); - retval = pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, + retval = pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, &req, &resp, upn); - if ( retval != PAM_SUCCESS ) { + if (retval != PAM_SUCCESS) { return NULL; } - + /* Convert the the SID back to the sAMAccountName */ - + ZERO_STRUCT(req); strncpy(req.data.sid, resp.data.sid.sid, sizeof(req.data.sid)-1); ZERO_STRUCT(resp); - retval = pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPSID, + retval = pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPSID, &req, &resp, upn); - if ( retval != PAM_SUCCESS ) { + if (retval != PAM_SUCCESS) { return NULL; } - - account_name_len = asprintf(&account_name, "%s\\%s", + + account_name_len = asprintf(&account_name, "%s\\%s", resp.data.name.dom_name, resp.data.name.name); @@ -1724,7 +1946,8 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, /* Get the username */ retval = pam_get_user(pamh, &username, NULL); if ((retval != PAM_SUCCESS) || (!username)) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "can not get the username"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "can not get the username"); retval = PAM_SERVICE_ERR; goto out; } @@ -1734,32 +1957,33 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, /* Decode the user name since AIX does not support logn user names by default. The name is encoded as _#uid. */ - if ( username[0] == '_' ) { - uid_t id = atoi( &username[1] ); - struct passwd *pw = NULL; + if (username[0] == '_') { + uid_t id = atoi(&username[1]); + struct passwd *pw = NULL; - if ( (id!=0) && ((pw = getpwuid( id )) != NULL) ) { - real_username = strdup( pw->pw_name ); + if ((id!=0) && ((pw = getpwuid(id)) != NULL)) { + real_username = strdup(pw->pw_name); } } #endif - if ( !real_username ) { + if (!real_username) { /* Just making a copy of the username we got from PAM */ - if ( (real_username = strdup( username )) == NULL ) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, - "memory allocation failure when copying username"); + if ((real_username = strdup(username)) == NULL) { + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "memory allocation failure when copying " + "username"); retval = PAM_SERVICE_ERR; goto out; } - } + } /* Maybe this was a UPN */ if (strchr(real_username, '@') != NULL) { char *samaccountname = NULL; - - samaccountname = winbind_upn_to_username(pamh, ctrl, + + samaccountname = winbind_upn_to_username(pamh, ctrl, real_username); if (samaccountname) { free(real_username); @@ -1767,12 +1991,13 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, } } - retval = _winbind_read_password(pamh, ctrl, NULL, + retval = _winbind_read_password(pamh, ctrl, NULL, "Password: ", NULL, &password); if (retval != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_ERR, "Could not retrieve user's password"); + _pam_log(pamh, ctrl, LOG_ERR, + "Could not retrieve user's password"); retval = PAM_AUTHTOK_ERR; goto out; } @@ -1780,10 +2005,12 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, /* Let's not give too much away in the log file */ #ifdef DEBUG_PASSWORD - _pam_log_debug(pamh, ctrl, LOG_INFO, "Verify user '%s' with password '%s'", + _pam_log_debug(pamh, ctrl, LOG_INFO, + "Verify user '%s' with password '%s'", real_username, password); #else - _pam_log_debug(pamh, ctrl, LOG_INFO, "Verify user '%s'", real_username); + _pam_log_debug(pamh, ctrl, LOG_INFO, + "Verify user '%s'", real_username); #endif member = get_member_from_config(pamh, argc, argv, ctrl, d); @@ -1794,9 +2021,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, ctrl, d); /* Now use the username to look up password */ - retval = winbind_auth_request(pamh, ctrl, real_username, password, member, - cctype, warn_pwd_expire, NULL, NULL, - &username_ret); + retval = winbind_auth_request(pamh, ctrl, real_username, password, + member, cctype, warn_pwd_expire, NULL, + NULL, &username_ret); if (retval == PAM_NEW_AUTHTOK_REQD || retval == PAM_AUTHTOK_EXPIRED) { @@ -1808,7 +2035,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, goto out; } - pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, new_authtok_required, _pam_winbind_cleanup_func); + pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, + new_authtok_required, + _pam_winbind_cleanup_func); retval = PAM_SUCCESS; @@ -1817,8 +2046,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, goto out; } - pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, - new_authtok_required_during_auth, _pam_winbind_cleanup_func); + pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, + new_authtok_required_during_auth, + _pam_winbind_cleanup_func); goto out; } @@ -1826,14 +2056,15 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, out: if (username_ret) { pam_set_item (pamh, PAM_USER, username_ret); - _pam_log_debug(pamh, ctrl, LOG_INFO, "Returned user was '%s'", username_ret); + _pam_log_debug(pamh, ctrl, LOG_INFO, + "Returned user was '%s'", username_ret); free(username_ret); } - if ( real_username ) { - free( real_username ); - } - + if (real_username) { + free(real_username); + } + if (d) { iniparser_freedict(d); } @@ -1873,15 +2104,18 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, ret = pam_sm_close_session(pamh, flags, argc, argv); break; case PAM_REFRESH_CRED: - _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_REFRESH_CRED not implemented"); + _pam_log_debug(pamh, ctrl, LOG_WARNING, + "PAM_REFRESH_CRED not implemented"); ret = PAM_SUCCESS; break; case PAM_REINITIALIZE_CRED: - _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_REINITIALIZE_CRED not implemented"); + _pam_log_debug(pamh, ctrl, LOG_WARNING, + "PAM_REINITIALIZE_CRED not implemented"); ret = PAM_SUCCESS; break; case PAM_ESTABLISH_CRED: - _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_ESTABLISH_CRED not implemented"); + _pam_log_debug(pamh, ctrl, LOG_WARNING, + "PAM_ESTABLISH_CRED not implemented"); ret = PAM_SUCCESS; break; default: @@ -1895,12 +2129,12 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, } _PAM_LOG_FUNCTION_LEAVE("pam_sm_setcred", pamh, ctrl, ret); - + return ret; } /* - * Account management. We want to verify that the account exists + * Account management. We want to verify that the account exists * before returning PAM_SUCCESS */ PAM_EXTERN @@ -1924,7 +2158,8 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, /* Get the username */ ret = pam_get_user(pamh, &username, NULL); if ((ret != PAM_SUCCESS) || (!username)) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG,"can not get the username"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "can not get the username"); ret = PAM_SERVICE_ERR; goto out; } @@ -1938,7 +2173,8 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, goto out; case 1: /* the user does not exist */ - _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", username); + _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", + username); if (ctrl & WINBIND_UNKNOWN_OK_ARG) { ret = PAM_IGNORE; goto out; @@ -1946,34 +2182,42 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, ret = PAM_USER_UNKNOWN; goto out; case 0: - pam_get_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (const void **)&tmp); + pam_get_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, + (const void **)&tmp); if (tmp != NULL) { ret = atoi((const char *)tmp); switch (ret) { case PAM_AUTHTOK_EXPIRED: /* fall through, since new token is required in this case */ case PAM_NEW_AUTHTOK_REQD: - _pam_log(pamh, ctrl, LOG_WARNING, "pam_sm_acct_mgmt success but %s is set", + _pam_log(pamh, ctrl, LOG_WARNING, + "pam_sm_acct_mgmt success but %s is set", PAM_WINBIND_NEW_AUTHTOK_REQD); - _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' needs new password", username); + _pam_log(pamh, ctrl, LOG_NOTICE, + "user '%s' needs new password", + username); /* PAM_AUTHTOKEN_REQD does not exist, but is documented in the manpage */ ret = PAM_NEW_AUTHTOK_REQD; goto out; default: - _pam_log(pamh, ctrl, LOG_WARNING, "pam_sm_acct_mgmt success"); - _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", username); + _pam_log(pamh, ctrl, LOG_WARNING, + "pam_sm_acct_mgmt success"); + _pam_log(pamh, ctrl, LOG_NOTICE, + "user '%s' granted access", username); ret = PAM_SUCCESS; goto out; } } /* Otherwise, the authentication looked good */ - _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", username); + _pam_log(pamh, ctrl, LOG_NOTICE, + "user '%s' granted access", username); ret = PAM_SUCCESS; goto out; default: /* we don't know anything about this return value */ - _pam_log(pamh, ctrl, LOG_ERR, "internal module error (ret = %d, user = '%s')", + _pam_log(pamh, ctrl, LOG_ERR, + "internal module error (ret = %d, user = '%s')", ret, username); ret = PAM_SERVICE_ERR; goto out; @@ -1989,7 +2233,7 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, } _PAM_LOG_FUNCTION_LEAVE("pam_sm_acct_mgmt", pamh, ctrl, ret); - + return ret; } @@ -2017,7 +2261,7 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, } _PAM_LOG_FUNCTION_LEAVE("pam_sm_open_session", pamh, ctrl, ret); - + return ret; } @@ -2056,21 +2300,25 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, retval = pam_get_user(pamh, &user, "Username: "); if (retval) { - _pam_log(pamh, ctrl, LOG_ERR, "could not identify user"); + _pam_log(pamh, ctrl, LOG_ERR, + "could not identify user"); goto out; } if (user == NULL) { - _pam_log(pamh, ctrl, LOG_ERR, "username was NULL!"); + _pam_log(pamh, ctrl, LOG_ERR, + "username was NULL!"); retval = PAM_USER_UNKNOWN; goto out; } - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "username [%s] obtained", user); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "username [%s] obtained", user); ccname = pam_getenv(pamh, "KRB5CCNAME"); if (ccname == NULL) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "user has no KRB5CCNAME environment"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "user has no KRB5CCNAME environment"); } strncpy(request.data.logoff.user, user, @@ -2088,9 +2336,12 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, } request.data.logoff.uid = pwd->pw_uid; - request.flags = WBFLAG_PAM_KRB5 | WBFLAG_PAM_CONTACT_TRUSTDOM; + request.flags = WBFLAG_PAM_KRB5 | + WBFLAG_PAM_CONTACT_TRUSTDOM; - retval = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_LOGOFF, &request, &response, user); + retval = pam_winbind_request_log(pamh, ctrl, + WINBINDD_PAM_LOGOFF, + &request, &response, user); } out: @@ -2099,13 +2350,14 @@ out: } _PAM_LOG_FUNCTION_LEAVE("pam_sm_close_session", pamh, ctrl, retval); - + return retval; } /** - * evaluate whether we need to re-authenticate with kerberos after a password change - * + * evaluate whether we need to re-authenticate with kerberos after a + * password change + * * @param pamh PAM handle * @param ctrl PAM winbind options. * @param user The username @@ -2113,14 +2365,16 @@ out: * @return boolean Returns true if required, false if not. */ -static bool _pam_require_krb5_auth_after_chauthtok(pam_handle_t *pamh, int ctrl, const char *user) +static bool _pam_require_krb5_auth_after_chauthtok(pam_handle_t *pamh, + int ctrl, + const char *user) { - /* Make sure that we only do this if - * a) the chauthtok got initiated during a logon attempt (authenticate->acct_mgmt->chauthtok) - * b) any later password change via the "passwd" command if done by the user itself - */ - + /* Make sure that we only do this if a) the chauthtok got initiated + * during a logon attempt (authenticate->acct_mgmt->chauthtok) b) any + * later password change via the "passwd" command if done by the user + * itself */ + char *new_authtok_reqd_during_auth = NULL; struct passwd *pwd = NULL; @@ -2128,8 +2382,10 @@ static bool _pam_require_krb5_auth_after_chauthtok(pam_handle_t *pamh, int ctrl, return false; } - _pam_get_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, &new_authtok_reqd_during_auth); - pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, NULL, NULL); + _pam_get_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, + &new_authtok_reqd_during_auth); + pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, + NULL, NULL); if (new_authtok_reqd_during_auth) { return true; @@ -2148,7 +2404,7 @@ static bool _pam_require_krb5_auth_after_chauthtok(pam_handle_t *pamh, int ctrl, } -PAM_EXTERN +PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, int argc, const char **argv) { @@ -2162,7 +2418,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, /* </DO NOT free() THESE> */ char *Announce; - + int retry = 0; dictionary *d = NULL; char *username_ret = NULL; @@ -2211,7 +2467,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, default: break; } - + /* * obtain and verify the current password (OLDAUTHTOK) for * the user. @@ -2219,19 +2475,20 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, if (flags & PAM_PRELIM_CHECK) { time_t pwdlastset_prelim = 0; - + /* instruct user what is happening */ #define greeting "Changing password for " Announce = (char *) malloc(sizeof(greeting) + strlen(user)); if (Announce == NULL) { - _pam_log(pamh, ctrl, LOG_CRIT, "password - out of memory"); + _pam_log(pamh, ctrl, LOG_CRIT, + "password - out of memory"); ret = PAM_BUF_ERR; goto out; } (void) strcpy(Announce, greeting); (void) strcpy(Announce + sizeof(greeting) - 1, user); #undef greeting - + lctrl = ctrl | WINBIND__OLD_PASSWORD; ret = _winbind_read_password(pamh, lctrl, Announce, @@ -2239,52 +2496,57 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, NULL, (const char **) &pass_old); if (ret != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_NOTICE, "password - (old) token not obtained"); + _pam_log(pamh, ctrl, LOG_NOTICE, + "password - (old) token not obtained"); goto out; } /* verify that this is the password for this user */ - + ret = winbind_auth_request(pamh, ctrl, user, pass_old, NULL, NULL, 0, &response, &pwdlastset_prelim, NULL); - if (ret != PAM_ACCT_EXPIRED && + if (ret != PAM_ACCT_EXPIRED && ret != PAM_AUTHTOK_EXPIRED && ret != PAM_NEW_AUTHTOK_REQD && ret != PAM_SUCCESS) { pass_old = NULL; goto out; } - - pam_set_data(pamh, PAM_WINBIND_PWD_LAST_SET, (void *)pwdlastset_prelim, NULL); - ret = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); + pam_set_data(pamh, PAM_WINBIND_PWD_LAST_SET, + (void *)pwdlastset_prelim, NULL); + + ret = pam_set_item(pamh, PAM_OLDAUTHTOK, + (const void *) pass_old); pass_old = NULL; if (ret != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_CRIT, "failed to set PAM_OLDAUTHTOK"); + _pam_log(pamh, ctrl, LOG_CRIT, + "failed to set PAM_OLDAUTHTOK"); } } else if (flags & PAM_UPDATE_AUTHTOK) { - + time_t pwdlastset_update = 0; - + /* * obtain the proposed password */ - + /* - * get the old token back. + * get the old token back. */ - + ret = _pam_get_item(pamh, PAM_OLDAUTHTOK, &pass_old); - + if (ret != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_NOTICE, "user not authenticated"); + _pam_log(pamh, ctrl, LOG_NOTICE, + "user not authenticated"); goto out; } - + lctrl = ctrl & ~WINBIND_TRY_FIRST_PASS_ARG; - + if (on(WINBIND_USE_AUTHTOK_ARG, lctrl)) { lctrl |= WINBIND_USE_FIRST_PASS_ARG; } @@ -2295,16 +2557,17 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * use_authtok is to force the use of a previously entered * password -- needed for pluggable password strength checking */ - + ret = _winbind_read_password(pamh, lctrl, - NULL, - "Enter new NT password: ", - "Retype new NT password: ", - (const char **) &pass_new); - + NULL, + "Enter new NT password: ", + "Retype new NT password: ", + (const char **)&pass_new); + if (ret != PAM_SUCCESS) { - _pam_log_debug(pamh, ctrl, LOG_ALERT - ,"password - new password not obtained"); + _pam_log_debug(pamh, ctrl, LOG_ALERT, + "password - " + "new password not obtained"); pass_old = NULL;/* tidy up */ goto out; } @@ -2314,20 +2577,21 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * propose as their new password. Verify that the new * password is acceptable. */ - + if (pass_new[0] == '\0') {/* "\0" password = NULL */ pass_new = NULL; } } - + /* * By reaching here we have approved the passwords and must now * rebuild the password database file. */ - _pam_get_data( pamh, PAM_WINBIND_PWD_LAST_SET, - &pwdlastset_update); + _pam_get_data(pamh, PAM_WINBIND_PWD_LAST_SET, + &pwdlastset_update); - ret = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new, pwdlastset_update); + ret = winbind_chauthtok_request(pamh, ctrl, user, pass_old, + pass_new, pwdlastset_update); if (ret) { _pam_overwrite(pass_new); _pam_overwrite(pass_old); @@ -2337,11 +2601,20 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, if (_pam_require_krb5_auth_after_chauthtok(pamh, ctrl, user)) { - const char *member = get_member_from_config(pamh, argc, argv, ctrl, d); - const char *cctype = get_krb5_cc_type_from_config(pamh, argc, argv, ctrl, d); - const int warn_pwd_expire = - get_warn_pwd_expire_from_config(pamh, argc, argv, ctrl, - d); + const char *member = NULL; + const char *cctype = NULL; + int warn_pwd_expire; + + member = get_member_from_config(pamh, argc, argv, + ctrl, d); + cctype = get_krb5_cc_type_from_config(pamh, argc, argv, + ctrl, d); + warn_pwd_expire = get_warn_pwd_expire_from_config(pamh, + argc, + argv, + ctrl, + d); + ret = winbind_auth_request(pamh, ctrl, user, pass_new, member, cctype, 0, &response, @@ -2351,20 +2624,27 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, pass_old = pass_new = NULL; if (ret == PAM_SUCCESS) { - - /* warn a user if the password is about to expire soon */ + + /* warn a user if the password is about to + * expire soon */ _pam_warn_password_expiry(pamh, ctrl, &response, - warn_pwd_expire , NULL); + warn_pwd_expire, + NULL); - /* set some info3 info for other modules in the stack */ + /* set some info3 info for other modules in the + * stack */ _pam_set_data_info3(pamh, ctrl, &response); /* put krb5ccname into env */ - _pam_setup_krb5_env(pamh, ctrl, response.data.auth.krb5ccname); + _pam_setup_krb5_env(pamh, ctrl, + response.data.auth.krb5ccname); if (username_ret) { - pam_set_item (pamh, PAM_USER, username_ret); - _pam_log_debug(pamh, ctrl, LOG_INFO, "Returned user was '%s'", username_ret); + pam_set_item(pamh, PAM_USER, + username_ret); + _pam_log_debug(pamh, ctrl, LOG_INFO, + "Returned user was '%s'", + username_ret); free(username_ret); } } @@ -2381,12 +2661,15 @@ out: } /* Deal with offline errors. */ - PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS"); - PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); - PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED"); + PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, + "NT_STATUS_NO_LOGON_SERVERS"); + PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, + "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); + PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, + "NT_STATUS_ACCESS_DENIED"); _PAM_LOG_FUNCTION_LEAVE("pam_sm_chauthtok", pamh, ctrl, ret); - + return ret; } @@ -2415,7 +2698,7 @@ struct pam_module _pam_winbind_modstruct = { * Copyright (c) Andrew G. Morgan 1996-8. * Copyright (c) Alex O. Yuriev, 1996. * Copyright (c) Cristian Gafton 1996. - * Copyright (C) Elliot Lee <sopwith@redhat.com> 1996, Red Hat Software. + * Copyright (C) Elliot Lee <sopwith@redhat.com> 1996, Red Hat Software. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions |