>From 74f70391d78062fdbadb34f59d77b65ae6167ccb Mon Sep 17 00:00:00 2001
From: Pavel Reichl <preichl@redhat.com>
Date: Thu, 2 Jul 2015 07:28:05 -0400
Subject: [PATCH 1/3] sysdb: new attribute lastOnlineAuthWithCurrentToken

Introduce new user attribute lastOnlineAuthWithCurrentToken.
This attribute behaves similarly to lastOnlineAuth but is set to NULL
after password is changed.

This attribute is needed for use-case when cached authentication is used, to
request online authentication after password is locally changed.

Resolves:
https://fedorahosted.org/sssd/ticket/1807
---
 src/db/sysdb.h                 |  1 +
 src/responder/pam/pamsrv_cmd.c | 66 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 67 insertions(+)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index fbc01851e66323e742bcbdfd2fa5c3b32695ad15..48dd26dd294333b265b69b28cd3b5d37f1293b43 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -87,6 +87,7 @@
 #define SYSDB_LAST_ONLINE_AUTH "lastOnlineAuth"
 #define SYSDB_LAST_FAILED_LOGIN "lastFailedLogin"
 #define SYSDB_FAILED_LOGIN_ATTEMPTS "failedLoginAttempts"
+#define SYSDB_LAST_ONLINE_AUTH_WITH_CURR_TOKEN "lastOnlineAuthWithCurrentToken"
 
 #define SYSDB_LAST_UPDATE "lastUpdate"
 #define SYSDB_CACHE_EXPIRE "dataExpireTimestamp"
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index 1ca87a6513b83f601e16300c01041076a7a48cb5..3bd67639585e83bb0945e7e4750553370c6566e0 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -42,6 +42,9 @@ enum pam_verbosity {
 
 #define DEFAULT_PAM_VERBOSITY PAM_VERBOSITY_IMPORTANT
 
+static errno_t
+pam_null_last_online_auth_with_curr_token(struct sss_domain_info *domain,
+                                          const char *username);
 static void pam_reply(struct pam_auth_req *preq);
 
 static errno_t pack_user_info_account_expired(TALLOC_CTX *mem_ctx,
@@ -426,6 +429,13 @@ static errno_t set_last_login(struct pam_auth_req *preq)
         goto fail;
     }
 
+    ret = sysdb_attrs_add_time_t(attrs,
+                                 SYSDB_LAST_ONLINE_AUTH_WITH_CURR_TOKEN,
+                                 time(NULL));
+    if (ret != EOK) {
+        goto fail;
+    }
+
     ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_LOGIN, time(NULL));
     if (ret != EOK) {
         goto fail;
@@ -661,6 +671,17 @@ static void pam_reply(struct pam_auth_req *preq)
         }
     }
 
+    if (pd->pam_status == PAM_SUCCESS && pd->cmd == SSS_PAM_CHAUTHTOK) {
+        ret = pam_null_last_online_auth_with_curr_token(preq->domain,
+                                                        pd->user);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "sysdb_null_last_online_auth_with_curr_token failed: "
+                  "%s [%d].\n", sss_strerror(ret), ret);
+            goto done;
+        }
+    }
+
     if (pd->response_delay > 0) {
         ret = gettimeofday(&tv, NULL);
         if (ret != EOK) {
@@ -1519,3 +1540,48 @@ struct sss_cmd_table *get_pam_cmds(void)
 
     return sss_cmds;
 }
+
+static errno_t
+pam_set_last_online_auth_with_curr_token(struct sss_domain_info *domain,
+                                         const char *username,
+                                         uint64_t value)
+{
+    TALLOC_CTX *tmp_ctx;
+    struct sysdb_attrs *attrs;
+    int ret;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    attrs = sysdb_new_attrs(tmp_ctx);
+    if (attrs == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = sysdb_attrs_add_time_t(attrs,
+                                 SYSDB_LAST_ONLINE_AUTH_WITH_CURR_TOKEN,
+                                 value);
+    if (ret != EOK) { goto done; }
+
+    ret = sysdb_set_user_attr(domain, username, attrs, SYSDB_MOD_REP);
+    if (ret != EOK) { goto done; }
+
+done:
+    if (ret != EOK) {
+        DEBUG(SSSDBG_TRACE_FUNC, "Error: %d (%s)\n", ret, sss_strerror(ret));
+    }
+
+    talloc_zfree(tmp_ctx);
+    return ret;
+}
+
+static errno_t
+pam_null_last_online_auth_with_curr_token(struct sss_domain_info *domain,
+                                          const char *username)
+{
+    return pam_set_last_online_auth_with_curr_token(domain, username, 0);
+}
-- 
2.1.0

