From 08347b649ee066dfba16f81dcb52e2b1777ca48c Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Mon, 8 Feb 2010 11:53:43 +0100 Subject: [PATCH] Make return values more specific during password change - return PAM_AUTHTOK_ERR instead of PAM_SYSTEM_ERR if the password change operation fails - send a message to the user if the system is offline and the password cannot be changed --- server/providers/krb5/krb5_child.c | 1 + server/providers/ldap/ldap_auth.c | 8 ++- server/responder/pam/pamsrv_cmd.c | 92 +++++++++++++++++++++-------------- sss_client/pam_sss.c | 24 +++++++++ sss_client/sss_cli.h | 3 +- 5 files changed, 87 insertions(+), 41 deletions(-) diff --git a/server/providers/krb5/krb5_child.c b/server/providers/krb5/krb5_child.c index 08e16b4..b730326 100644 --- a/server/providers/krb5/krb5_child.c +++ b/server/providers/krb5/krb5_child.c @@ -579,6 +579,7 @@ static errno_t changepw_child(int fd, struct krb5_req *kr) result_string.length, result_string.data)); } + pam_status = PAM_AUTHTOK_ERR; goto sendresponse; } diff --git a/server/providers/ldap/ldap_auth.c b/server/providers/ldap/ldap_auth.c index fbb4e53..1d1346c 100644 --- a/server/providers/ldap/ldap_auth.c +++ b/server/providers/ldap/ldap_auth.c @@ -772,7 +772,7 @@ static void sdap_auth4chpass_done(struct tevent_req *req) if (pw_expire_type == PWEXPIRE_SHADOW) { /* TODO: implement async ldap modify request */ DEBUG(1, ("Changing shadow password attributes not implemented.\n")); - state->pd->pam_status = PAM_SYSTEM_ERR; + state->pd->pam_status = PAM_MODULE_UNKNOWN; goto done; } else { subreq = sdap_exop_modify_passwd_send(state, @@ -791,7 +791,9 @@ static void sdap_auth4chpass_done(struct tevent_req *req) return; } break; - + case SDAP_AUTH_FAILED: + state->pd->pam_status = PAM_AUTH_ERR; + break; default: state->pd->pam_status = PAM_SYSTEM_ERR; } @@ -821,7 +823,7 @@ static void sdap_pam_chpass_done(struct tevent_req *req) dp_err = DP_ERR_OK; break; default: - state->pd->pam_status = PAM_SYSTEM_ERR; + state->pd->pam_status = PAM_AUTHTOK_ERR; } done: diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c index 3172a97..c204e0a 100644 --- a/server/responder/pam/pamsrv_cmd.c +++ b/server/responder/pam/pamsrv_cmd.c @@ -484,50 +484,68 @@ static void pam_reply(struct pam_auth_req *preq) struct tevent_req *req; struct sysdb_ctx *sysdb; struct pam_ctx *pctx; + uint32_t user_info_type; pd = preq->pd; DEBUG(4, ("pam_reply get called.\n")); - if ((pd->cmd == SSS_PAM_AUTHENTICATE) && - (preq->domain != NULL) && - (preq->domain->cache_credentials == true) && - (pd->offline_auth == false)) { + if (pd->pam_status == PAM_AUTHINFO_UNAVAIL) { + switch(pd->cmd) { + case SSS_PAM_AUTHENTICATE: + if ((preq->domain != NULL) && + (preq->domain->cache_credentials == true) && + (pd->offline_auth == false)) { - if (pd->pam_status == PAM_AUTHINFO_UNAVAIL) { - /* do auth with offline credentials */ - pd->offline_auth = true; + /* do auth with offline credentials */ + pd->offline_auth = true; - ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list, - preq->domain, &sysdb); - if (ret != EOK) { - DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); - goto done; - } - - pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx); - - req = sysdb_cache_auth_send(preq, preq->cctx->ev, sysdb, - preq->domain, pd->user, pd->authtok, - pd->authtok_size, pctx->rctx->cdb); - if (req == NULL) { - DEBUG(1, ("Failed to setup offline auth")); - /* this error is not fatal, continue */ - } else { - tevent_req_set_callback(req, pam_cache_auth_done, preq); - return; - } - } - } + ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list, + preq->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for " + "domain [%s]!\n", preq->domain->name)); + goto done; + } + pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx, + struct pam_ctx); + + req = sysdb_cache_auth_send(preq, preq->cctx->ev, sysdb, + preq->domain, pd->user, + pd->authtok, pd->authtok_size, + pctx->rctx->cdb); + if (req == NULL) { + DEBUG(1, ("Failed to setup offline auth.\n")); + /* this error is not fatal, continue */ + } else { + tevent_req_set_callback(req, pam_cache_auth_done, preq); + return; + } + } + break; + case SSS_PAM_CHAUTHTOK_PRELIM: + case SSS_PAM_CHAUTHTOK: + DEBUG(5, ("Password change not possible while offline.\n")); + pd->pam_status = PAM_AUTHTOK_ERR; + user_info_type = SSS_PAM_USER_INFO_OFFLINE_CHPASS; + pam_add_response(pd, SSS_PAM_USER_INFO, sizeof(uint32_t), + (const uint8_t *) &user_info_type); + break; /* TODO: we need the pam session cookie here to make sure that cached * authentication was successful */ - if ((pd->cmd == SSS_PAM_SETCRED || pd->cmd == SSS_PAM_ACCT_MGMT || - pd->cmd == SSS_PAM_OPEN_SESSION || pd->cmd == SSS_PAM_CLOSE_SESSION) && - pd->pam_status == PAM_AUTHINFO_UNAVAIL) { - DEBUG(2, ("Assuming offline authentication " - "setting status for pam call %d to PAM_SUCCESS.\n", pd->cmd)); - pd->pam_status = PAM_SUCCESS; + case SSS_PAM_SETCRED: + case SSS_PAM_ACCT_MGMT: + case SSS_PAM_OPEN_SESSION: + case SSS_PAM_CLOSE_SESSION: + DEBUG(2, ("Assuming offline authentication setting status for " + "pam call %d to PAM_SUCCESS.\n", pd->cmd)); + pd->pam_status = PAM_SUCCESS; + break; + default: + DEBUG(1, ("Unknown PAM call [%d].\n", pd->cmd)); + pd->pam_status = PAM_MODULE_UNKNOWN; + } } cctx = preq->cctx; diff --git a/sss_client/pam_sss.c b/sss_client/pam_sss.c index 6e238ec..8c970e4 100644 --- a/sss_client/pam_sss.c +++ b/sss_client/pam_sss.c @@ -475,6 +475,27 @@ static int user_info_offline_auth_delayed(pam_handle_t *pamh, size_t buflen, return PAM_SUCCESS; } +static int user_info_offline_chpass(pam_handle_t *pamh, size_t buflen, + uint8_t *buf) +{ + int ret; + + if (buflen != sizeof(uint32_t)) { + D(("User info response data has the wrong size")); + return PAM_BUF_ERR; + } + + ret = do_pam_conversation(pamh, PAM_TEXT_INFO, + _("System is offline, password change not possible"), + NULL, NULL); + if (ret != PAM_SUCCESS) { + D(("do_pam_conversation failed.")); + return PAM_SYSTEM_ERR; + } + + return PAM_SUCCESS; +} + static int eval_user_info_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf) { @@ -495,6 +516,9 @@ static int eval_user_info_response(pam_handle_t *pamh, size_t buflen, case SSS_PAM_USER_INFO_OFFLINE_AUTH_DELAYED: ret = user_info_offline_auth_delayed(pamh, buflen, buf); break; + case SSS_PAM_USER_INFO_OFFLINE_CHPASS: + ret = user_info_offline_chpass(pamh, buflen, buf); + break; default: D(("Unknown user info type [%d]", type)); ret = PAM_SYSTEM_ERR; diff --git a/sss_client/sss_cli.h b/sss_client/sss_cli.h index 9546961..55d5a28 100644 --- a/sss_client/sss_cli.h +++ b/sss_client/sss_cli.h @@ -179,7 +179,8 @@ enum response_type { enum user_info_type { SSS_PAM_USER_INFO_OFFLINE_AUTH = 0x01, - SSS_PAM_USER_INFO_OFFLINE_AUTH_DELAYED + SSS_PAM_USER_INFO_OFFLINE_AUTH_DELAYED, + SSS_PAM_USER_INFO_OFFLINE_CHPASS }; enum nss_status sss_nss_make_request(enum sss_cli_command cmd, -- 1.6.6