Blob Blame History Raw
From a8212a7884175fe32dccc29f3fed3688f81c76fe Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Tue, 25 Jun 2019 14:16:31 +0200
Subject: [PATCH 59/64] BE/IPA/AD/LDAP: Add inigroups refresh support

Related: https://pagure.io/SSSD/sssd/issue/4012

In addition to refreshing users, groups and netgroups, this patch adds
the ability to also refresh initgroups. The refresh is ran for any users
that have the initgrExpireTimestamp attribute close to expiration.

This request is ran as the first one, because the initgroups operation
refreshes the user entry and can touch groups as well.

Reviewed-by: Sumit Bose <sbose@redhat.com>
(cherry picked from commit 1d0e75e9c5db0acf946f82705a4640063ea5aea9)

Reviewed-by: Sumit Bose <sbose@redhat.com>
---
 src/providers/ad/ad_refresh.c     | 28 +++++++++++++++++++++++
 src/providers/be_refresh.c        | 37 +++++++++++++++++++++++--------
 src/providers/be_refresh.h        |  1 +
 src/providers/ipa/ipa_refresh.c   | 27 ++++++++++++++++++++++
 src/providers/ldap/sdap_refresh.c | 17 ++++++++++++++
 5 files changed, 101 insertions(+), 9 deletions(-)

diff --git a/src/providers/ad/ad_refresh.c b/src/providers/ad/ad_refresh.c
index ee541056f..f0130cbaf 100644
--- a/src/providers/ad/ad_refresh.c
+++ b/src/providers/ad/ad_refresh.c
@@ -65,6 +65,7 @@ static struct tevent_req *ad_refresh_send(TALLOC_CTX *mem_ctx,
     state->index = 0;
 
     switch (entry_type) {
+    case BE_REQ_INITGROUPS:
     case BE_REQ_NETGROUP:
         filter_type = BE_FILTER_NAME;
         break;
@@ -187,6 +188,23 @@ static errno_t ad_refresh_recv(struct tevent_req *req)
     return EOK;
 }
 
+static struct tevent_req *
+ad_refresh_initgroups_send(TALLOC_CTX *mem_ctx,
+                           struct tevent_context *ev,
+                           struct be_ctx *be_ctx,
+                           struct sss_domain_info *domain,
+                           char **names,
+                           void *pvt)
+{
+    return ad_refresh_send(mem_ctx, ev, be_ctx, domain,
+                           BE_REQ_INITGROUPS, names, pvt);
+}
+
+static errno_t ad_refresh_initgroups_recv(struct tevent_req *req)
+{
+    return ad_refresh_recv(req);
+}
+
 static struct tevent_req *
 ad_refresh_users_send(TALLOC_CTX *mem_ctx,
                       struct tevent_context *ev,
@@ -249,6 +267,16 @@ errno_t ad_refresh_init(struct be_ctx *be_ctx,
         return ret;
     }
 
+    ret = be_refresh_add_cb(be_ctx->refresh_ctx,
+                            BE_REFRESH_TYPE_INITGROUPS,
+                            ad_refresh_initgroups_send,
+                            ad_refresh_initgroups_recv,
+                            id_ctx);
+    if (ret != EOK && ret != EEXIST) {
+        DEBUG(SSSDBG_MINOR_FAILURE, "Periodical refresh of users "
+              "will not work [%d]: %s\n", ret, strerror(ret));
+    }
+
     ret = be_refresh_add_cb(be_ctx->refresh_ctx,
                             BE_REFRESH_TYPE_USERS,
                             ad_refresh_users_send,
diff --git a/src/providers/be_refresh.c b/src/providers/be_refresh.c
index a9d4295ec..6945ca9e3 100644
--- a/src/providers/be_refresh.c
+++ b/src/providers/be_refresh.c
@@ -33,11 +33,12 @@ static errno_t be_refresh_get_values_ex(TALLOC_CTX *mem_ctx,
                                         struct sss_domain_info *domain,
                                         time_t period,
                                         struct ldb_dn *base_dn,
-                                        const char *attr,
+                                        const char *key_attr,
+                                        const char *value_attr,
                                         char ***_values)
 {
     TALLOC_CTX *tmp_ctx = NULL;
-    const char *attrs[] = {attr, NULL};
+    const char *attrs[] = {value_attr, NULL};
     const char *filter = NULL;
     char **values = NULL;
     struct sysdb_attrs **records = NULL;
@@ -45,13 +46,17 @@ static errno_t be_refresh_get_values_ex(TALLOC_CTX *mem_ctx,
     time_t now = time(NULL);
     errno_t ret;
 
+    if (key_attr == NULL || domain == NULL || base_dn == NULL) {
+        return EINVAL;
+    }
+
     tmp_ctx = talloc_new(NULL);
     if (tmp_ctx == NULL) {
         return ENOMEM;
     }
 
     filter = talloc_asprintf(tmp_ctx, "(&(%s<=%lld))",
-                             SYSDB_CACHE_EXPIRE, (long long) now + period);
+                             key_attr, (long long) now + period);
     if (filter == NULL) {
         ret = ENOMEM;
         goto done;
@@ -73,7 +78,7 @@ static errno_t be_refresh_get_values_ex(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
-    ret = sysdb_attrs_to_list(tmp_ctx, records, res->count, attr, &values);
+    ret = sysdb_attrs_to_list(tmp_ctx, records, res->count, value_attr, &values);
     if (ret != EOK) {
         goto done;
     }
@@ -96,18 +101,27 @@ static errno_t be_refresh_get_values(TALLOC_CTX *mem_ctx,
 {
     struct ldb_dn *base_dn = NULL;
     errno_t ret;
+    const char *key_attr;
 
     switch (type) {
+    case BE_REFRESH_TYPE_INITGROUPS:
+        key_attr = SYSDB_INITGR_EXPIRE;
+        base_dn = sysdb_user_base_dn(mem_ctx, domain);
+        break;
     case BE_REFRESH_TYPE_USERS:
+        key_attr = SYSDB_CACHE_EXPIRE;
         base_dn = sysdb_user_base_dn(mem_ctx, domain);
         break;
     case BE_REFRESH_TYPE_GROUPS:
+        key_attr = SYSDB_CACHE_EXPIRE;
         base_dn = sysdb_group_base_dn(mem_ctx, domain);
         break;
     case BE_REFRESH_TYPE_NETGROUPS:
+        key_attr = SYSDB_CACHE_EXPIRE;
         base_dn = sysdb_netgroup_base_dn(mem_ctx, domain);
         break;
-    case BE_REFRESH_TYPE_SENTINEL:
+    default:
+        DEBUG(SSSDBG_CRIT_FAILURE, "Uknown or unsupported refresh type\n");
         return ERR_INTERNAL;
         break;
     }
@@ -117,7 +131,8 @@ static errno_t be_refresh_get_values(TALLOC_CTX *mem_ctx,
     }
 
     ret = be_refresh_get_values_ex(mem_ctx, domain, period,
-                                   base_dn, attr_name, _values);
+                                   base_dn, key_attr,
+                                   attr_name, _values);
 
     talloc_free(base_dn);
     return ret;
@@ -125,6 +140,7 @@ static errno_t be_refresh_get_values(TALLOC_CTX *mem_ctx,
 
 struct be_refresh_cb {
     const char *name;
+    const char *attr_name;
     bool enabled;
     be_refresh_send_t send_fn;
     be_refresh_recv_t recv_fn;
@@ -132,7 +148,6 @@ struct be_refresh_cb {
 };
 
 struct be_refresh_ctx {
-    const char *attr_name;
     struct be_refresh_cb callbacks[BE_REFRESH_TYPE_SENTINEL];
 };
 
@@ -148,10 +163,14 @@ errno_t be_refresh_ctx_init(struct be_ctx *be_ctx,
         return ENOMEM;
     }
 
-    ctx->attr_name = attr_name;
+    ctx->callbacks[BE_REFRESH_TYPE_INITGROUPS].name = "initgroups";
+    ctx->callbacks[BE_REFRESH_TYPE_INITGROUPS].attr_name = SYSDB_NAME;
     ctx->callbacks[BE_REFRESH_TYPE_USERS].name = "users";
+    ctx->callbacks[BE_REFRESH_TYPE_USERS].attr_name = attr_name;
     ctx->callbacks[BE_REFRESH_TYPE_GROUPS].name = "groups";
+    ctx->callbacks[BE_REFRESH_TYPE_GROUPS].attr_name = attr_name;
     ctx->callbacks[BE_REFRESH_TYPE_NETGROUPS].name = "netgroups";
+    ctx->callbacks[BE_REFRESH_TYPE_NETGROUPS].attr_name = SYSDB_NAME;
 
     refresh_interval = be_ctx->domain->refresh_expired_interval;
     if (refresh_interval > 0) {
@@ -310,7 +329,7 @@ static errno_t be_refresh_step(struct tevent_req *req)
         }
 
         talloc_zfree(state->refresh_values);
-        ret = be_refresh_get_values(state, state->index, state->ctx->attr_name,
+        ret = be_refresh_get_values(state, state->index, state->cb->attr_name,
                                     state->domain, state->period,
                                     &state->refresh_values);
         if (ret != EOK) {
diff --git a/src/providers/be_refresh.h b/src/providers/be_refresh.h
index c7b4872df..4ac5b70c2 100644
--- a/src/providers/be_refresh.h
+++ b/src/providers/be_refresh.h
@@ -44,6 +44,7 @@ typedef errno_t
 (*be_refresh_recv_t)(struct tevent_req *req);
 
 enum be_refresh_type {
+    BE_REFRESH_TYPE_INITGROUPS,
     BE_REFRESH_TYPE_USERS,
     BE_REFRESH_TYPE_GROUPS,
     BE_REFRESH_TYPE_NETGROUPS,
diff --git a/src/providers/ipa/ipa_refresh.c b/src/providers/ipa/ipa_refresh.c
index 72051cfdd..bb47b0edf 100644
--- a/src/providers/ipa/ipa_refresh.c
+++ b/src/providers/ipa/ipa_refresh.c
@@ -168,6 +168,23 @@ static errno_t ipa_refresh_recv(struct tevent_req *req)
     return EOK;
 }
 
+static struct tevent_req *
+ipa_refresh_initgroups_send(TALLOC_CTX *mem_ctx,
+                            struct tevent_context *ev,
+                            struct be_ctx *be_ctx,
+                            struct sss_domain_info *domain,
+                            char **names,
+                            void *pvt)
+{
+    return ipa_refresh_send(mem_ctx, ev, be_ctx, domain,
+                           BE_REQ_INITGROUPS, names, pvt);
+}
+
+static errno_t ipa_refresh_initgroups_recv(struct tevent_req *req)
+{
+    return ipa_refresh_recv(req);
+}
+
 static struct tevent_req *
 ipa_refresh_users_send(TALLOC_CTX *mem_ctx,
                         struct tevent_context *ev,
@@ -230,6 +247,16 @@ errno_t ipa_refresh_init(struct be_ctx *be_ctx,
         return ENOMEM;
     }
 
+    ret = be_refresh_add_cb(be_ctx->refresh_ctx,
+                            BE_REFRESH_TYPE_USERS,
+                            ipa_refresh_initgroups_send,
+                            ipa_refresh_initgroups_recv,
+                            id_ctx);
+    if (ret != EOK && ret != EEXIST) {
+        DEBUG(SSSDBG_MINOR_FAILURE, "Periodical refresh of initgroups "
+              "will not work [%d]: %s\n", ret, strerror(ret));
+    }
+
     ret = be_refresh_add_cb(be_ctx->refresh_ctx,
                             BE_REFRESH_TYPE_USERS,
                             ipa_refresh_users_send,
diff --git a/src/providers/ldap/sdap_refresh.c b/src/providers/ldap/sdap_refresh.c
index 2206d6670..3ceddb61e 100644
--- a/src/providers/ldap/sdap_refresh.c
+++ b/src/providers/ldap/sdap_refresh.c
@@ -186,6 +186,23 @@ static errno_t sdap_refresh_recv(struct tevent_req *req)
     return EOK;
 }
 
+static struct tevent_req *
+sdap_refresh_initgroups_send(TALLOC_CTX *mem_ctx,
+                        struct tevent_context *ev,
+                        struct be_ctx *be_ctx,
+                        struct sss_domain_info *domain,
+                        char **names,
+                        void *pvt)
+{
+    return sdap_refresh_send(mem_ctx, ev, be_ctx, domain,
+                             BE_REQ_INITGROUPS, names, pvt);
+}
+
+static errno_t sdap_refresh_initgroups_recv(struct tevent_req *req)
+{
+    return sdap_refresh_recv(req);
+}
+
 static struct tevent_req *
 sdap_refresh_users_send(TALLOC_CTX *mem_ctx,
                         struct tevent_context *ev,
-- 
2.20.1