>From f596aed00775985cc3c115d6b21b2dea4b46c4ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20=C5=A0ruba=C5=99?= <xsruba03@stud.fit.vutbr.cz>
Date: Thu, 18 Sep 2014 19:29:38 +0200
Subject: [PATCH 1/7] [1/9] SUDO: Support the IPA schema

https://fedorahosted.org/sssd/ticket/1108

IPA SUDO Provider uses LDAP sudo plugin for downloading sudo rules from IPA.
It also uses its purge/store sysdb functions.
---
 src/providers/ldap/sdap_async_sudo.c | 171 ++++++++++++++++++++++-------------
 src/providers/ldap/sdap_sudo.c       |  10 +-
 src/providers/ldap/sdap_sudo.h       |  52 ++++++++++-
 3 files changed, 162 insertions(+), 71 deletions(-)

diff --git a/src/providers/ldap/sdap_async_sudo.c b/src/providers/ldap/sdap_async_sudo.c
index b4899cbaa4c5821a79f1b228a88a4d6055c1558c..8dc60bff556b8504639e568104dceff85130999c 100644
--- a/src/providers/ldap/sdap_async_sudo.c
+++ b/src/providers/ldap/sdap_async_sudo.c
@@ -5,6 +5,7 @@
 
     Authors:
         Pavel Březina <pbrezina@redhat.com>
+        MIchal Šrubař <xsruba03@stud.fit.vutbr.cz>
 
     Copyright (C) 2012 Red Hat
 
@@ -34,23 +35,6 @@
 #include "providers/ldap/sdap_sudo_cache.h"
 #include "db/sysdb_sudo.h"
 
-struct sdap_sudo_refresh_state {
-    struct be_ctx *be_ctx;
-    struct sdap_options *opts;
-    struct sdap_id_op *sdap_op;
-    struct sdap_id_conn_cache *sdap_conn_cache;
-    struct sysdb_ctx *sysdb;
-    struct sss_domain_info *domain;
-
-    const char *ldap_filter;    /* search */
-    const char *sysdb_filter;   /* delete */
-
-    int dp_error;
-    int error;
-    char *highest_usn;
-    size_t num_rules;
-};
-
 struct sdap_sudo_load_sudoers_state {
     struct tevent_context *ev;
     struct sdap_options *opts;
@@ -79,27 +63,9 @@ static errno_t sdap_sudo_load_sudoers_next_base(struct tevent_req *req);
 
 static void sdap_sudo_load_sudoers_process(struct tevent_req *subreq);
 
-static int sdap_sudo_load_sudoers_recv(struct tevent_req *req,
-                                       TALLOC_CTX *mem_ctx,
-                                       size_t *rules_count,
-                                       struct sysdb_attrs ***rules);
-
-static void sdap_sudo_refresh_load_done(struct tevent_req *subreq);
-
-static int sdap_sudo_purge_sudoers(struct sss_domain_info *dom,
-                                   const char *filter,
-                                   struct sdap_attr_map *map,
-                                   size_t rules_count,
-                                   struct sysdb_attrs **rules);
-
-static int sdap_sudo_store_sudoers(TALLOC_CTX *mem_ctx,
-                                   struct sss_domain_info *domain,
-                                   struct sdap_options *opts,
-                                   size_t rules_count,
-                                   struct sysdb_attrs **rules,
-                                   int cache_timeout,
-                                   time_t now,
-                                   char **_usn);
+static void sdap_sudo_refresh_load_done_ex(struct tevent_req *subreq);
+static void sdap_sudo_refresh_load_done_ldap(struct tevent_req *subreq);
+static void sdap_sudo_refresh_load_done_ipa(struct tevent_req *subreq);
 
 struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx,
                                           struct be_ctx *be_ctx,
@@ -167,7 +133,8 @@ int sdap_sudo_refresh_recv(TALLOC_CTX *mem_ctx,
                            int *dp_error,
                            int *error,
                            char **usn,
-                           size_t *num_rules)
+                           size_t *num_rules,
+                           struct sysdb_attrs ***rules)
 {
     struct sdap_sudo_refresh_state *state;
 
@@ -186,6 +153,10 @@ int sdap_sudo_refresh_recv(TALLOC_CTX *mem_ctx,
         *num_rules = state->num_rules;
     }
 
+    if (rules != NULL) {
+        *rules = talloc_steal(mem_ctx, state->ldap_rules);
+    }
+
     return EOK;
 }
 
@@ -264,7 +235,7 @@ static void sdap_sudo_refresh_connect_done(struct tevent_req *subreq)
         goto fail;
     }
 
-    tevent_req_set_callback(subreq, sdap_sudo_refresh_load_done, req);
+    tevent_req_set_callback(subreq, sdap_sudo_refresh_load_done_ex, req);
 
     return;
 
@@ -279,9 +250,6 @@ static struct tevent_req * sdap_sudo_load_sudoers_send(TALLOC_CTX *mem_ctx,
                                                        struct sdap_options *opts,
                                                        struct sdap_handle *sh,
                                                        const char *ldap_filter)
-
-
-
 {
     struct tevent_req *req;
     struct sdap_sudo_load_sudoers_state *state;
@@ -310,8 +278,16 @@ static struct tevent_req * sdap_sudo_load_sudoers_send(TALLOC_CTX *mem_ctx,
     }
 
     /* create attrs from map */
-    ret = build_attrs_from_map(state, opts->sudorule_map, SDAP_OPTS_SUDO,
+    if (state->opts->schema_type == SDAP_SCHEMA_IPA_V1) {
+        /* req from ipa_sudo_refresh_send() */
+        ret = build_attrs_from_map(state, opts->ipa_sudorule_map,
+                                   SDAP_OPTS_IPA_SUDO, NULL, &state->attrs, NULL);
+    } else {
+        /* req from sdap_sudo_refresh_send() */
+        ret = build_attrs_from_map(state, opts->sudorule_map, SDAP_OPTS_SUDO,
                                NULL, &state->attrs, NULL);
+    }
+
     if (ret != EOK) {
         goto fail;
     }
@@ -337,6 +313,8 @@ static errno_t sdap_sudo_load_sudoers_next_base(struct tevent_req *req)
     struct sdap_sudo_load_sudoers_state *state;
     struct sdap_search_base *search_base;
     struct tevent_req *subreq;
+    struct sdap_attr_map *map;
+    int attr_count;
     char *filter;
 
     state = tevent_req_data(req, struct sdap_sudo_load_sudoers_state);
@@ -359,6 +337,17 @@ static errno_t sdap_sudo_load_sudoers_next_base(struct tevent_req *req)
           "Searching for sudo rules with base [%s]\n",
            search_base->basedn);
 
+    if (state->opts->schema_type == SDAP_SCHEMA_IPA_V1) {
+        /* req from ipa_sudo_refresh_send() */
+        attr_count = SDAP_OPTS_IPA_SUDO;
+        map = state->opts->ipa_sudorule_map;
+    }
+    else {
+        /* req from sdap_sudo_refresh_send() */
+        attr_count = SDAP_OPTS_SUDO;
+        map = state->opts->sudorule_map;
+    }
+
     subreq = sdap_get_generic_send(state,
                                    state->ev,
                                    state->opts,
@@ -367,8 +356,8 @@ static errno_t sdap_sudo_load_sudoers_next_base(struct tevent_req *req)
                                    search_base->scope,
                                    filter,
                                    state->attrs,
-                                   state->opts->sudorule_map,
-                                   SDAP_OPTS_SUDO,
+                                   map,
+                                   attr_count,
                                    state->timeout,
                                    true);
     if (subreq == NULL) {
@@ -390,6 +379,7 @@ static void sdap_sudo_load_sudoers_process(struct tevent_req *subreq)
     int ret;
     int i;
 
+    /* req from sdap_sudo_load_sudoers_send */
     req = tevent_req_callback_data(subreq, struct tevent_req);
     state = tevent_req_data(req, struct sdap_sudo_load_sudoers_state);
     search_base = state->search_bases[state->base_iter];
@@ -438,10 +428,10 @@ static void sdap_sudo_load_sudoers_process(struct tevent_req *subreq)
     tevent_req_done(req);
 }
 
-static int sdap_sudo_load_sudoers_recv(struct tevent_req *req,
-                                       TALLOC_CTX *mem_ctx,
-                                       size_t *rules_count,
-                                       struct sysdb_attrs ***rules)
+int sdap_sudo_load_sudoers_recv(struct tevent_req *req,
+                                TALLOC_CTX *mem_ctx,
+                                size_t *rules_count,
+                                struct sysdb_attrs ***rules)
 {
     struct sdap_sudo_load_sudoers_state *state;
 
@@ -455,7 +445,59 @@ static int sdap_sudo_load_sudoers_recv(struct tevent_req *req,
     return EOK;
 }
 
-static void sdap_sudo_refresh_load_done(struct tevent_req *subreq)
+static void sdap_sudo_refresh_load_done_ex(struct tevent_req *subreq)
+{
+    struct tevent_req *req;
+    struct sdap_sudo_refresh_state *state;
+
+    /* req from sdap_sudo_refresh_send() */
+    req = tevent_req_callback_data(subreq, struct tevent_req);
+    state = tevent_req_data(req, struct sdap_sudo_refresh_state);
+
+    if (state->opts->schema_type == SDAP_SCHEMA_IPA_V1) {
+        /* req from ipa_sudo_refresh_send() */
+        sdap_sudo_refresh_load_done_ipa(subreq);
+    }
+    else {
+        /* req from sdap_sudo_refresh_send() */
+        sdap_sudo_refresh_load_done_ldap(subreq);
+    }
+}
+
+static void sdap_sudo_refresh_load_done_ipa(struct tevent_req *subreq)
+{
+    struct sdap_sudo_refresh_state *state;
+    struct tevent_req *req;
+    int ret;
+
+    req = tevent_req_callback_data(subreq, struct tevent_req);
+    state = tevent_req_data(req, struct sdap_sudo_refresh_state);
+
+    ret = sdap_sudo_load_sudoers_recv(subreq, state, &state->ldap_rules_count,
+                                      &state->ldap_rules);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC, "Received %zu rules\n", state->ldap_rules_count);
+    DEBUG(SSSDBG_TRACE_FUNC, "Giving control back to IPA SUDO provider\n");
+
+    state->num_rules = state->ldap_rules_count;
+
+done:
+    /* req from ipa_sudo_refresh_send continue in ipa_sudo_sudoers_process */
+    state->error = ret;
+    if (ret == EOK) {
+        state->dp_error = DP_ERR_OK;
+        tevent_req_done(req);
+    } else {
+        state->dp_error = DP_ERR_FATAL;
+        tevent_req_error(req, ret);
+    }
+}
+
+static void sdap_sudo_refresh_load_done_ldap(struct tevent_req *subreq)
 {
     struct tevent_req *req; /* req from sdap_sudo_refresh_send() */
     struct sdap_sudo_refresh_state *state;
@@ -523,6 +565,7 @@ done:
         }
     }
 
+    /* finish sdap_sudo_refresh_send() */
     state->error = ret;
     if (ret == EOK) {
         state->dp_error = DP_ERR_OK;
@@ -533,11 +576,11 @@ done:
     }
 }
 
-static int sdap_sudo_purge_sudoers(struct sss_domain_info *dom,
-                                   const char *filter,
-                                   struct sdap_attr_map *map,
-                                   size_t rules_count,
-                                   struct sysdb_attrs **rules)
+int sdap_sudo_purge_sudoers(struct sss_domain_info *dom,
+                            const char *filter,
+                            struct sdap_attr_map *map,
+                            size_t rules_count,
+                            struct sysdb_attrs **rules)
 {
     const char *name;
     int i;
@@ -586,14 +629,14 @@ done:
     return ret;
 }
 
-static int sdap_sudo_store_sudoers(TALLOC_CTX *mem_ctx,
-                                   struct sss_domain_info *domain,
-                                   struct sdap_options *opts,
-                                   size_t rules_count,
-                                   struct sysdb_attrs **rules,
-                                   int cache_timeout,
-                                   time_t now,
-                                   char **_usn)
+int sdap_sudo_store_sudoers(TALLOC_CTX *mem_ctx,
+                            struct sss_domain_info *domain,
+                            struct sdap_options *opts,
+                            size_t rules_count,
+                            struct sysdb_attrs **rules,
+                            int cache_timeout,
+                            time_t now,
+                            char **_usn)
 {
     errno_t ret;
 
diff --git a/src/providers/ldap/sdap_sudo.c b/src/providers/ldap/sdap_sudo.c
index edef44208b69af454da0fc906e608b91d5634e90..1e3bf5fa216789962f135d8dacdef17a9b6cdbd5 100644
--- a/src/providers/ldap/sdap_sudo.c
+++ b/src/providers/ldap/sdap_sudo.c
@@ -288,7 +288,7 @@ static int sdap_sudo_setup_periodical_refresh(struct sdap_sudo_ctx *sudo_ctx)
     return EOK;
 }
 
-static void sdap_sudo_set_usn(struct sdap_server_opts *srv_opts, char *usn)
+void sdap_sudo_set_usn(struct sdap_server_opts *srv_opts, char *usn)
 {
     unsigned int usn_number;
     char *endptr = NULL;
@@ -621,7 +621,7 @@ static void sdap_sudo_full_refresh_done(struct tevent_req *subreq)
     state = tevent_req_data(req, struct sdap_sudo_full_refresh_state);
 
     ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error,
-                                 &state->error, &highest_usn, NULL);
+                                 &state->error, &highest_usn, NULL, NULL);
     talloc_zfree(subreq);
     if (ret != EOK || state->dp_error != DP_ERR_OK || state->error != EOK) {
         goto done;
@@ -795,7 +795,7 @@ static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq)
     state = tevent_req_data(req, struct sdap_sudo_rules_refresh_state);
 
     ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, &state->error,
-                                 &highest_usn, &downloaded_rules_num);
+                                 &highest_usn, &downloaded_rules_num, NULL);
     talloc_zfree(subreq);
     if (ret != EOK || state->dp_error != DP_ERR_OK || state->error != EOK) {
         goto done;
@@ -938,7 +938,7 @@ static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq)
     state = tevent_req_data(req, struct sdap_sudo_smart_refresh_state);
 
     ret = sdap_sudo_refresh_recv(state, subreq, &dp_error, &error,
-                                 &highest_usn, NULL);
+                                 &highest_usn, NULL, NULL);
     if (ret != EOK || dp_error != DP_ERR_OK || error != EOK) {
         goto done;
     }
@@ -969,7 +969,7 @@ static int sdap_sudo_smart_refresh_recv(struct tevent_req *req,
     TEVENT_REQ_RETURN_ON_ERROR(req);
 
     return sdap_sudo_refresh_recv(state, state->subreq, dp_error, error,
-                                  NULL, NULL);
+                                  NULL, NULL, NULL);
 }
 
 static void sdap_sudo_full_refresh_online_cb(void *pvt)
diff --git a/src/providers/ldap/sdap_sudo.h b/src/providers/ldap/sdap_sudo.h
index e2764b90c91470ed64e4c07a792206fa034646a6..1370fecf172f94ed9e5390d4e0d2014c42d6d10f 100644
--- a/src/providers/ldap/sdap_sudo.h
+++ b/src/providers/ldap/sdap_sudo.h
@@ -21,11 +21,17 @@
 #ifndef _SDAP_SUDO_H_
 #define _SDAP_SUDO_H_
 
+/* these two structures are used by both LDAP and IPA SUDO Providers */
 struct sdap_sudo_ctx {
+    struct be_ctx *be_ctx;
     struct sdap_id_ctx *id_ctx;
 
     char **hostnames;
     char **ip_addr;
+
+    char *ipa_hostname;
+    char **ipa_hostgroups;
+
     bool include_netgroups;
     bool include_regexp;
     bool use_host_filter;
@@ -37,6 +43,26 @@ struct sdap_sudo_ctx {
     struct tevent_req *first_refresh_timer;
 };
 
+struct sdap_sudo_refresh_state {
+    struct be_ctx *be_ctx;
+    struct sdap_options *opts;
+    struct sdap_id_op *sdap_op;
+    struct sdap_id_conn_cache *sdap_conn_cache;
+    struct sysdb_ctx *sysdb;
+    struct sss_domain_info *domain;
+
+    const char *ldap_filter;    /* search */
+    const char *sysdb_filter;   /* delete */
+
+    struct sysdb_attrs **ldap_rules; /* search result will be stored here */
+    size_t ldap_rules_count;
+
+    int dp_error;
+    int error;
+    char *highest_usn;
+    size_t num_rules;
+};
+
 enum sdap_sudo_refresh_type {
     SDAP_SUDO_REFRESH_FULL,
     SDAP_SUDO_REFRESH_SMART,
@@ -49,6 +75,7 @@ int sdap_sudo_init(struct be_ctx *be_ctx,
                    struct sdap_id_ctx *id_ctx,
                    struct bet_ops **ops,
                    void **pvt_data);
+void sdap_sudo_set_usn(struct sdap_server_opts *srv_opts, char *usn);
 
 /* sdap async interface */
 struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx,
@@ -58,14 +85,35 @@ struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx,
                                           const char *ldap_filter,
                                           const char *sysdb_filter);
 
+int sdap_sudo_load_sudoers_recv(struct tevent_req *req,
+                                       TALLOC_CTX *mem_ctx,
+                                       size_t *rules_count,
+                                       struct sysdb_attrs ***rules);
+
 int sdap_sudo_refresh_recv(TALLOC_CTX *mem_ctx,
                            struct tevent_req *req,
                            int *dp_error,
                            int *error,
                            char **usn,
-                           size_t *num_rules);
+                           size_t *num_rules,
+                           struct sysdb_attrs ***rules);
 
-/* timer */
+
+/* sysdb */
+int sdap_sudo_purge_sudoers(struct sss_domain_info *dom,
+                            const char *filter,
+                            struct sdap_attr_map *map,
+                            size_t rules_count,
+                            struct sysdb_attrs **rules);
+
+int sdap_sudo_store_sudoers(TALLOC_CTX *mem_ctx,
+                            struct sss_domain_info *domain,
+                            struct sdap_options *opts,
+                            size_t rules_count,
+                            struct sysdb_attrs **rules,
+                            int cache_timeout,
+                            time_t now,
+                            char **_usn);
 
 typedef struct tevent_req * (*sdap_sudo_timer_fn_t)(TALLOC_CTX *mem_ctx,
                                                     struct sdap_sudo_ctx *sudo_ctx);
-- 
1.9.3

