223 lines
7.8 KiB
Diff
223 lines
7.8 KiB
Diff
|
From 325a3a1015a8ce239efa07b2371f2f8db8bf395e Mon Sep 17 00:00:00 2001
|
||
|
From: Pavel Reichl <preichl@redhat.com>
|
||
|
Date: Wed, 11 Feb 2015 19:38:16 -0500
|
||
|
Subject: [PATCH 01/99] PAM: do not reject abruptly
|
||
|
|
||
|
If account has expired then pass message.
|
||
|
|
||
|
Resolves:
|
||
|
https://fedorahosted.org/sssd/ticket/2050
|
||
|
|
||
|
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
||
|
(cherry picked from commit a61d6d01a4e89ec14175af135e84f1cac55af748)
|
||
|
---
|
||
|
src/responder/pam/pamsrv_cmd.c | 53 ++++++++++++++++++++++++++++++++++
|
||
|
src/sss_client/pam_sss.c | 64 +++++++++++++++++++++++++++++++++++++++++-
|
||
|
src/sss_client/sss_cli.h | 18 +++++++++---
|
||
|
3 files changed, 130 insertions(+), 5 deletions(-)
|
||
|
|
||
|
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
|
||
|
index 90cdbec519587a0d5dd680bfe3a991d896d6c008..c874cae61960ffa17dbe8aab7b96b792d65ac618 100644
|
||
|
--- a/src/responder/pam/pamsrv_cmd.c
|
||
|
+++ b/src/responder/pam/pamsrv_cmd.c
|
||
|
@@ -44,6 +44,54 @@ enum pam_verbosity {
|
||
|
|
||
|
static void pam_reply(struct pam_auth_req *preq);
|
||
|
|
||
|
+static errno_t pack_user_info_account_expired(TALLOC_CTX *mem_ctx,
|
||
|
+ const char *user_error_message,
|
||
|
+ size_t *resp_len,
|
||
|
+ uint8_t **_resp)
|
||
|
+{
|
||
|
+ uint32_t resp_type = SSS_PAM_USER_INFO_ACCOUNT_EXPIRED;
|
||
|
+ size_t err_len;
|
||
|
+ uint8_t *resp;
|
||
|
+ size_t p;
|
||
|
+
|
||
|
+ err_len = strlen(user_error_message);
|
||
|
+ *resp_len = 2 * sizeof(uint32_t) + err_len;
|
||
|
+ resp = talloc_size(mem_ctx, *resp_len);
|
||
|
+ if (resp == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n");
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ p = 0;
|
||
|
+ SAFEALIGN_SET_UINT32(&resp[p], resp_type, &p);
|
||
|
+ SAFEALIGN_SET_UINT32(&resp[p], err_len, &p);
|
||
|
+ safealign_memcpy(&resp[p], user_error_message, err_len, &p);
|
||
|
+ if (p != *resp_len) {
|
||
|
+ DEBUG(SSSDBG_FATAL_FAILURE, "Size mismatch\n");
|
||
|
+ }
|
||
|
+
|
||
|
+ *_resp = resp;
|
||
|
+ return EOK;
|
||
|
+}
|
||
|
+
|
||
|
+static void inform_account_expired(struct pam_data* pd)
|
||
|
+{
|
||
|
+ size_t msg_len;
|
||
|
+ uint8_t *msg;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ ret = pack_user_info_account_expired(pd, "", &msg_len, &msg);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "pack_user_info_account_expired failed.\n");
|
||
|
+ } else {
|
||
|
+ ret = pam_add_response(pd, SSS_PAM_USER_INFO, msg_len, msg);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
static bool is_domain_requested(struct pam_data *pd, const char *domain_name)
|
||
|
{
|
||
|
int i;
|
||
|
@@ -609,6 +657,11 @@ static void pam_reply(struct pam_auth_req *preq)
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
+ if (pd->pam_status == PAM_ACCT_EXPIRED && pd->service != NULL &&
|
||
|
+ strcasecmp(pd->service, "sshd") == 0) {
|
||
|
+ inform_account_expired(pd);
|
||
|
+ }
|
||
|
+
|
||
|
ret = filter_responses(pctx->rctx->cdb, pd->resp_list);
|
||
|
if (ret != EOK) {
|
||
|
DEBUG(SSSDBG_CRIT_FAILURE, "filter_responses failed, not fatal.\n");
|
||
|
diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
|
||
|
index fdf6c9e6da75c9f7eaa7c00d9a5792fbdd97eabc..59529796c682416d49c7f92f5feea3b0ace8d2d4 100644
|
||
|
--- a/src/sss_client/pam_sss.c
|
||
|
+++ b/src/sss_client/pam_sss.c
|
||
|
@@ -60,6 +60,9 @@
|
||
|
#define OPT_RETRY_KEY "retry="
|
||
|
#define OPT_DOMAINS_KEY "domains="
|
||
|
|
||
|
+#define EXP_ACC_MSG _("Your account has expired. ")
|
||
|
+#define SRV_MSG _("Server message: ")
|
||
|
+
|
||
|
struct pam_items {
|
||
|
const char* pam_service;
|
||
|
const char* pam_user;
|
||
|
@@ -797,6 +800,63 @@ static int user_info_otp_chpass(pam_handle_t *pamh)
|
||
|
return PAM_SUCCESS;
|
||
|
}
|
||
|
|
||
|
+static int user_info_account_expired(pam_handle_t *pamh, size_t buflen,
|
||
|
+ uint8_t *buf)
|
||
|
+{
|
||
|
+ int ret;
|
||
|
+ uint32_t msg_len;
|
||
|
+ char *user_msg;
|
||
|
+ size_t bufsize = 0;
|
||
|
+
|
||
|
+ /* resp_type and length of message are expected to be in buf */
|
||
|
+ if (buflen < 2* sizeof(uint32_t)) {
|
||
|
+ D(("User info response data is too short"));
|
||
|
+ return PAM_BUF_ERR;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* msg_len = legth of message */
|
||
|
+ memcpy(&msg_len, buf + sizeof(uint32_t), sizeof(uint32_t));
|
||
|
+
|
||
|
+ if (buflen != 2* sizeof(uint32_t) + msg_len) {
|
||
|
+ D(("User info response data has the wrong size"));
|
||
|
+ return PAM_BUF_ERR;
|
||
|
+ }
|
||
|
+
|
||
|
+ bufsize = strlen(EXP_ACC_MSG) + 1;
|
||
|
+
|
||
|
+ if (msg_len > 0) {
|
||
|
+ bufsize += strlen(SRV_MSG) + msg_len;
|
||
|
+ }
|
||
|
+
|
||
|
+ user_msg = (char *)malloc(sizeof(char) * bufsize);
|
||
|
+ if (!user_msg) {
|
||
|
+ D(("Out of memory."));
|
||
|
+ return PAM_SYSTEM_ERR;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = snprintf(user_msg, bufsize, "%s%s%.*s",
|
||
|
+ EXP_ACC_MSG,
|
||
|
+ msg_len > 0 ? SRV_MSG : "",
|
||
|
+ msg_len,
|
||
|
+ msg_len > 0 ? (char *)(buf + 2 * sizeof(uint32_t)) : "" );
|
||
|
+ if (ret < 0 || ret > bufsize) {
|
||
|
+ D(("snprintf failed."));
|
||
|
+
|
||
|
+ free(user_msg);
|
||
|
+ return PAM_SYSTEM_ERR;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = do_pam_conversation(pamh, PAM_TEXT_INFO, user_msg, NULL, NULL);
|
||
|
+ free(user_msg);
|
||
|
+ if (ret != PAM_SUCCESS) {
|
||
|
+ D(("do_pam_conversation failed."));
|
||
|
+
|
||
|
+ return PAM_SYSTEM_ERR;
|
||
|
+ }
|
||
|
+
|
||
|
+ return PAM_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
static int user_info_chpass_error(pam_handle_t *pamh, size_t buflen,
|
||
|
uint8_t *buf)
|
||
|
{
|
||
|
@@ -852,7 +912,6 @@ static int user_info_chpass_error(pam_handle_t *pamh, size_t buflen,
|
||
|
return PAM_SUCCESS;
|
||
|
}
|
||
|
|
||
|
-
|
||
|
static int eval_user_info_response(pam_handle_t *pamh, size_t buflen,
|
||
|
uint8_t *buf)
|
||
|
{
|
||
|
@@ -888,6 +947,9 @@ static int eval_user_info_response(pam_handle_t *pamh, size_t buflen,
|
||
|
case SSS_PAM_USER_INFO_CHPASS_ERROR:
|
||
|
ret = user_info_chpass_error(pamh, buflen, buf);
|
||
|
break;
|
||
|
+ case SSS_PAM_USER_INFO_ACCOUNT_EXPIRED:
|
||
|
+ ret = user_info_account_expired(pamh, buflen, buf);
|
||
|
+ break;
|
||
|
default:
|
||
|
D(("Unknown user info type [%d]", type));
|
||
|
ret = PAM_SYSTEM_ERR;
|
||
|
diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
|
||
|
index 6286077fcf25aead1dfcba5c6483e4ff8ae63b9f..d508a0671cd1b3ee087e0967f7015628ceabe20f 100644
|
||
|
--- a/src/sss_client/sss_cli.h
|
||
|
+++ b/src/sss_client/sss_cli.h
|
||
|
@@ -461,15 +461,25 @@ enum user_info_type {
|
||
|
* indicates that no message is following.
|
||
|
* @param String with the specified
|
||
|
* length. */
|
||
|
+
|
||
|
SSS_PAM_USER_INFO_GRACE_LOGIN, /**< Warn the user that the password is
|
||
|
* expired and inform about the remaining
|
||
|
* number of grace logins.
|
||
|
* @param The number of remaining grace
|
||
|
* logins as uint32_t */
|
||
|
- SSS_PAM_USER_INFO_EXPIRE_WARN /**< Warn the user that the password will
|
||
|
- * expire soon.
|
||
|
- * @param Number of seconds before the user's
|
||
|
- * password will expire. */
|
||
|
+ SSS_PAM_USER_INFO_EXPIRE_WARN, /**< Warn the user that the password will
|
||
|
+ * expire soon.
|
||
|
+ * @param Number of seconds before the
|
||
|
+ * user's password will expire. */
|
||
|
+
|
||
|
+ SSS_PAM_USER_INFO_ACCOUNT_EXPIRED, /**< Tell the user that the account
|
||
|
+ * has expired and optionally give
|
||
|
+ * a reason.
|
||
|
+ * @param Size of the message as
|
||
|
+ * unsigned 32-bit integer value. A
|
||
|
+ * value of 0 indicates that no message
|
||
|
+ * is following. @param String with the
|
||
|
+ * specified length. */
|
||
|
};
|
||
|
/**
|
||
|
* @}
|
||
|
--
|
||
|
2.4.0
|
||
|
|