>From add61e4819be0c013da2c452cc86d0d98d803440 Mon Sep 17 00:00:00 2001
From: Pavel Reichl <preichl@redhat.com>
Date: Wed, 18 Feb 2015 01:03:40 -0500
Subject: [PATCH 2/2] SDAP: enable change phase of pw expire policy check

Implement new option which does checking password expiration policy
in accounting phase.

This allows SSSD to issue shadow expiration warning even if alternate
authentication method is used.

Resolves:
https://fedorahosted.org/sssd/ticket/2167
---
 Makefile.am                      |  1 +
 src/man/sssd-ldap.5.xml          | 12 +++++++++++
 src/providers/ldap/ldap_auth.c   |  1 +
 src/providers/ldap/ldap_init.c   |  3 +++
 src/providers/ldap/sdap_access.c | 43 +++++++++++++++++++++++++++++++++++++++-
 src/providers/ldap/sdap_access.h |  2 ++
 6 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/Makefile.am b/Makefile.am
index 70278550fd22b820528f9613d30e11a723ea6c5c..35e3b39027f1163078a61a0528df2306367d6187 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -562,6 +562,7 @@ dist_noinst_HEADERS = \
     src/providers/ldap/sdap_autofs.h \
     src/providers/ldap/sdap_id_op.h \
     src/providers/ldap/ldap_opts.h \
+    src/providers/ldap/ldap_auth.h \
     src/providers/ldap/sdap_range.h \
     src/providers/ldap/sdap_users.h \
     src/providers/ldap/sdap_dyndns.h \
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index 9f2e9ac34add13e40d316374094024afdcc4ae31..4e3f3510250b19b5f397125fa3e3a376e0d3701f 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -1959,6 +1959,18 @@ ldap_access_filter = (employeeType=admin)
                             ldap_account_expire_policy
                         </para>
                         <para>
+                            <emphasis>pwd_expire_policy</emphasis>:
+                            This option is useful if users are interested in
+                            seeing password expiration warning when authenticating
+                            using different method then passwords - for example
+                            SSH keys.
+                        </para>
+                        <para>
+                            Please note that 'access_provider = ldap' must
+                            be set for this feature to work. Also 'ldap_pwd_policy'
+                            must be set to appropriate password policy.
+                        </para>
+                        <para>
                             <emphasis>authorized_service</emphasis>: use
                             the authorizedService attribute to determine
                             access
diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
index 1f1add53713201c83a13928ebb66f6bd130d7bac..1b610cfee75b167c14fcaf5a6b65b62b87aac99a 100644
--- a/src/providers/ldap/ldap_auth.c
+++ b/src/providers/ldap/ldap_auth.c
@@ -47,6 +47,7 @@
 #include "providers/ldap/sdap_async.h"
 #include "providers/ldap/sdap_async_private.h"
 #include "providers/ldap/ldap_auth.h"
+#include "providers/ldap/sdap_access.h"
 
 #define LDAP_PWEXPIRE_WARNING_TIME 0
 
diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c
index 44333a9a3a45de16aaaf83fecaea4817cebc90d4..3b8db83300c43e5e5397cdf0c880a1d82effb4c2 100644
--- a/src/providers/ldap/ldap_init.c
+++ b/src/providers/ldap/ldap_init.c
@@ -423,6 +423,9 @@ int sssm_ldap_access_init(struct be_ctx *bectx,
             access_ctx->access_rule[c] = LDAP_ACCESS_HOST;
         } else if (strcasecmp(order_list[c], LDAP_ACCESS_LOCK_NAME) == 0) {
             access_ctx->access_rule[c] = LDAP_ACCESS_LOCKOUT;
+        } else if (strcasecmp(order_list[c],
+                              LDAP_ACCESS_EXPIRE_POLICY_NAME) == 0) {
+            access_ctx->access_rule[c] = LDAP_ACCESS_EXPIRE_POLICY;
         } else {
             DEBUG(SSSDBG_CRIT_FAILURE,
                   "Unexpected access rule name [%s].\n", order_list[c]);
diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c
index a6c882cae634f080b200fe75f51867e39192bcd9..84ed05a516b9a4996d5693f0991f73f4410057ab 100644
--- a/src/providers/ldap/sdap_access.c
+++ b/src/providers/ldap/sdap_access.c
@@ -39,10 +39,16 @@
 #include "providers/ldap/sdap_async.h"
 #include "providers/data_provider.h"
 #include "providers/dp_backend.h"
+#include "providers/ldap/ldap_auth.h"
 
 #define PERMANENTLY_LOCKED_ACCOUNT "000001010000Z"
 #define MALFORMED_FILTER "Malformed access control filter [%s]\n"
 
+static errno_t perform_pwexpire_policy(TALLOC_CTX *mem_ctx,
+                                       struct sss_domain_info *domain,
+                                       struct pam_data *pd,
+                                       struct sdap_options *opts);
+
 static errno_t sdap_save_user_cache_bool(struct sss_domain_info *domain,
                                          const char *username,
                                          const char *attr_name,
@@ -237,6 +243,11 @@ static errno_t sdap_access_check_next_rule(struct sdap_access_req_ctx *state,
                                        state->pd, state->user_entry);
             break;
 
+        case LDAP_ACCESS_EXPIRE_POLICY:
+            ret = perform_pwexpire_policy(state, state->domain, state->pd,
+                                          state->access_ctx->id_ctx->opts);
+            break;
+
         case LDAP_ACCESS_SERVICE:
             ret = sdap_access_service( state->pd, state->user_entry);
             break;
@@ -651,7 +662,6 @@ static errno_t sdap_account_expired_nds(struct pam_data *pd,
     return EOK;
 }
 
-
 static errno_t sdap_account_expired(struct sdap_access_ctx *access_ctx,
                                     struct pam_data *pd,
                                     struct ldb_message *user_entry)
@@ -702,6 +712,37 @@ static errno_t sdap_account_expired(struct sdap_access_ctx *access_ctx,
     return ret;
 }
 
+static errno_t perform_pwexpire_policy(TALLOC_CTX *mem_ctx,
+                                       struct sss_domain_info *domain,
+                                       struct pam_data *pd,
+                                       struct sdap_options *opts)
+{
+    enum pwexpire pw_expire_type;
+    void *pw_expire_data;
+    errno_t ret;
+    char *dn;
+
+    ret = get_user_dn(mem_ctx, domain, opts, pd->user, &dn, &pw_expire_type,
+                      &pw_expire_data);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_MINOR_FAILURE, "get_user_dn returned %d:[%s]\n.",
+              ret, sss_strerror(ret));
+        goto done;
+    }
+
+    ret = check_pwexpire_policy(pw_expire_type, pw_expire_data, pd,
+                                domain->pwd_expiration_warning);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_MINOR_FAILURE,
+              "check_pwexpire_policy returned %d:[%s]\n.",
+              ret, sss_strerror(ret));
+        goto done;
+    }
+
+done:
+    return ret;
+}
+
 struct sdap_access_filter_req_ctx {
     const char *username;
     const char *filter;
diff --git a/src/providers/ldap/sdap_access.h b/src/providers/ldap/sdap_access.h
index f085e619961198b887d65ed5ee0bc5cdd90d1b20..825fcffbc5fcd9413c9aa0dd79a8b87bd57d4dbc 100644
--- a/src/providers/ldap/sdap_access.h
+++ b/src/providers/ldap/sdap_access.h
@@ -39,6 +39,7 @@
 
 #define LDAP_ACCESS_FILTER_NAME "filter"
 #define LDAP_ACCESS_EXPIRE_NAME "expire"
+#define LDAP_ACCESS_EXPIRE_POLICY_NAME "pwd_expire_policy"
 #define LDAP_ACCESS_SERVICE_NAME "authorized_service"
 #define LDAP_ACCESS_HOST_NAME "host"
 #define LDAP_ACCESS_LOCK_NAME "lockout"
@@ -57,6 +58,7 @@ enum ldap_access_rule {
     LDAP_ACCESS_SERVICE,
     LDAP_ACCESS_HOST,
     LDAP_ACCESS_LOCKOUT,
+    LDAP_ACCESS_EXPIRE_POLICY,
     LDAP_ACCESS_LAST
 };
 
-- 
2.1.0

