On 02/11/2015 05:50 PM, Sumit Bose wrote:
On Wed, Feb 11, 2015 at 04:56:48PM +0100, Pavel Reichl wrote:
Hello,
please see attached patch. I'm not sure whether using pam_strerror() is the
right thing to do. It might be better to use our own string?
I'm also not sure about using _(STRING) macro on the output of
pam_strerror().
The _() macro will not work here. You can use it only to enclose literal
strings. The strings will then be extracted into the *.pot file and
translators can pick them for translation. In the pam_strerror() case
libpam has to take care of the translations.
I attached output of sequence of commands to show differences.
1) This is output without patch being applied.
$ su john
Password:
su: User account has expired
ssh -l john `hostname`
Connection closed by 192.168.122.166
#not matching key
$ ssh -l john `hostname` -i /tmp/local
j...@dev.local.test's password:
Connection closed by 192.168.122.166
2) This is output when patch is applied. Please note the duplicity when
using su.
The service name is available, so you can add this only if ssh is used.
$ su john
Password:
User account has expired
su: User account has expired
$ ssh -l john `hostname`
User account has expired
Connection closed by 192.168.122.166
#not matching key
$ ssh -l john `hostname` -i /tmp/local
j...@dev.local.test's password:
User account has expired
Connection closed by 192.168.122.166
Thanks for comments.
From 953f1721996e6c2bf8ee53ea232de2240f168d94 Mon Sep 17 00:00:00 2001
From: Pavel Reichl <prei...@redhat.com>
Date: Wed, 11 Feb 2015 19:38:16 -0500
Subject: [PATCH] PAM: do not reject abruptly
If account has expired use pam_conversation to pass message.
Resolves:
https://fedorahosted.org/sssd/ticket/2050
---
src/sss_client/pam_sss.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
index
fdf6c9e6da75c9f7eaa7c00d9a5792fbdd97eabc..767b2a839e9f001be52c5ff4c7651b0f06ba4221
100644
--- a/src/sss_client/pam_sss.c
+++ b/src/sss_client/pam_sss.c
@@ -1585,6 +1585,13 @@ static int pam_sss(enum sss_cli_command task,
pam_handle_t *pamh,
D(("do_pam_conversation failed."));
}
pam_status = PAM_NEW_AUTHTOK_REQD;
+ } else if (pam_status == PAM_ACCT_EXPIRED) {
+ ret = do_pam_conversation(pamh, PAM_TEXT_INFO,
+ _(pam_strerror(pamh, pam_status)),
+ NULL, NULL);
+ if (ret != PAM_SUCCESS) {
+ D(("do_pam_conversation failed."));
+ }
I would recommend to not do this in pam_sss directly but send a
SSS_PAM_USER_INFO response back to pam_sss. This response can e.g. be
generated in the pam responder if pam_status == PAM_ACCT_EXPIRED and the
service is sshd. Doing it in the pam responder has the advantage that
you do not have to duplicate code in the backends. Additionally it is
more easy configure the behavior. E.g. you can check pam_verbosity and
only add this message is the level is 2 (1?) or higher.
bye,
Sumit
}
break;
case SSS_PAM_CHAUTHTOK:
--
2.1.0
_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel
_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel
Thanks for comments. Please see updated patch.
>From 7e7a0834c4af8c277d53790966cfc9ab6f0cfd75 Mon Sep 17 00:00:00 2001
From: Pavel Reichl <prei...@redhat.com>
Date: Wed, 11 Feb 2015 19:38:16 -0500
Subject: [PATCH] PAM: do not reject abruptly
If account has expired then pass message.
Resolves:
https://fedorahosted.org/sssd/ticket/2050
---
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 7cab7b2b4be99833d1446a25e1411898a9e5e67b..5a0f1a34ae04e0a11c253786c80d828ba38c4cc4 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..9b8fe0dcb09ca30b5bc1ff4c9b68b329e1839852 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.1.0
_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel