URL: https://github.com/freeipa/freeipa/pull/353
Author: simo5
 Title: #353: [RFE] Pwdpolicy
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/353/head:pr353
git checkout pr353
From a7213592a0b643a63dbdc8bff5bae08f30448b7b Mon Sep 17 00:00:00 2001
From: Simo Sorce <s...@redhat.com>
Date: Fri, 16 Dec 2016 07:12:45 -0500
Subject: [PATCH 1/2] Add code to retrieve results from multiple bases

Internally performs multiple seraches as needed based on the basedn
strings passed in and whether the caller indicated that any result is ok
or all results are needed.

Signed-off-by: Simo Sorce <s...@redhat.com>
---
 daemons/ipa-kdb/ipa_kdb.h        |  10 ++++
 daemons/ipa-kdb/ipa_kdb_common.c | 103 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 113 insertions(+)

diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h
index 1fdb409..e1f46c6 100644
--- a/daemons/ipa-kdb/ipa_kdb.h
+++ b/daemons/ipa-kdb/ipa_kdb.h
@@ -174,6 +174,16 @@ int ipadb_ldap_attr_has_value(LDAP *lcontext, LDAPMessage *le,
 int ipadb_ldap_deref_results(LDAP *lcontext, LDAPMessage *le,
                              LDAPDerefRes **results);
 
+struct ipadb_multires;
+krb5_error_code ipadb_multires_init(LDAP *lcontext, struct ipadb_multires **r);
+void ipadb_multires_free(struct ipadb_multires *r);
+LDAPMessage *ipadb_multires_next_entry(struct ipadb_multires *r);
+krb5_error_code ipadb_multibase_search(struct ipadb_context *ipactx,
+                                       char **basedns, int scope,
+                                       char *filter, char **attrs,
+                                       struct ipadb_multires **res,
+                                       bool any);
+
 /* PRINCIPALS FUNCTIONS */
 krb5_error_code ipadb_get_principal(krb5_context kcontext,
                                     krb5_const_principal search_for,
diff --git a/daemons/ipa-kdb/ipa_kdb_common.c b/daemons/ipa-kdb/ipa_kdb_common.c
index 7438f35..5995efe 100644
--- a/daemons/ipa-kdb/ipa_kdb_common.c
+++ b/daemons/ipa-kdb/ipa_kdb_common.c
@@ -610,3 +610,106 @@ int ipadb_ldap_deref_results(LDAP *lcontext, LDAPMessage *le,
     ldap_controls_free(ctrls);
     return ret;
 }
+
+struct ipadb_multires {
+    LDAP *lcontext;
+    LDAPMessage **res;
+    LDAPMessage *next;
+    ssize_t cursor;
+    ssize_t count;
+};
+
+krb5_error_code ipadb_multires_init(LDAP *lcontext, struct ipadb_multires **r)
+{
+    *r = malloc(sizeof(struct ipadb_multires));
+    if (!*r) return ENOMEM;
+    (*r)->lcontext = lcontext;
+    (*r)->res = NULL;
+    (*r)->next = NULL;
+    (*r)->cursor = -1;
+    (*r)->count = 0;
+
+    return 0;
+}
+
+void ipadb_multires_free(struct ipadb_multires *r)
+{
+    for (int i = 0; i < r->count; i++) {
+        ldap_msgfree(r->res[i]);
+    }
+    free(r);
+}
+
+LDAPMessage *ipadb_multires_next_entry(struct ipadb_multires *r)
+{
+    if (r->count == 0) return NULL;
+
+    if (r->next) {
+        r->next = ldap_next_entry(r->lcontext, r->next);
+    }
+    if (r->next == NULL) {
+        if (r->cursor >= r->count - 1) {
+            return NULL;
+        }
+        r->cursor++;
+        r->next = ldap_first_entry(r->lcontext, r->res[r->cursor]);
+    }
+
+    return r->next;
+}
+
+krb5_error_code ipadb_multibase_search(struct ipadb_context *ipactx,
+                                       char **basedns, int scope,
+                                       char *filter, char **attrs,
+                                       struct ipadb_multires **res,
+                                       bool any)
+{
+    int ret;
+
+    ret = ipadb_multires_init(ipactx->lcontext, res);
+    if (ret != 0) return ret;
+
+    ret = ipadb_check_connection(ipactx);
+    if (ret != 0)
+        return ipadb_simple_ldap_to_kerr(ret);
+
+    for (int b = 0; basedns[b]; b++) {
+        LDAPMessage *r;
+        ret = ldap_search_ext_s(ipactx->lcontext, basedns[b], scope,
+                                filter, attrs, 0, NULL, NULL,
+                                &std_timeout, LDAP_NO_LIMIT, &r);
+
+        /* first test if we need to retry to connect */
+        if (ret != 0 &&
+            ipadb_need_retry(ipactx, ret)) {
+            ldap_msgfree(r);
+            ret = ldap_search_ext_s(ipactx->lcontext, basedns[b], scope,
+                                    filter, attrs, 0, NULL, NULL,
+                                    &std_timeout, LDAP_NO_LIMIT, &r);
+        }
+
+        if (ret != 0) break;
+
+        if (ldap_count_entries(ipactx->lcontext, r) > 0) {
+            void *tmp = realloc((*res)->res, (((*res)->count + 1) *
+                                                sizeof(LDAPMessage *)));
+            if (tmp == NULL) {
+                ret = ENOMEM;
+                break;
+            }
+            (*res)->res = tmp;
+            (*res)->res[(*res)->count] = r;
+            (*res)->count++;
+
+            if (any) break;
+        }
+    }
+
+    if (ret != 0) {
+        ipadb_multires_free(*res);
+        *res = NULL;
+    }
+
+    return ipadb_simple_ldap_to_kerr(ret);
+}
+

From ace018d4cacee51b8b5c2e207cc1b3843cd92582 Mon Sep 17 00:00:00 2001
From: Simo Sorce <s...@redhat.com>
Date: Fri, 16 Dec 2016 07:13:58 -0500
Subject: [PATCH 2/2] Add support for searching policies in cn=accounts

Use the new multibase search to collect policies from multiple subtrees.
The 'any' parameter is set to 'true' so the search stop when the first result
is found in any of the bases.

https://fedorahosted.org/freeipa/ticket/6568

Signed-off-by: Simo Sorce <s...@redhat.com>
---
 daemons/ipa-kdb/ipa_kdb.c           |  7 +++++++
 daemons/ipa-kdb/ipa_kdb.h           |  1 +
 daemons/ipa-kdb/ipa_kdb_pwdpolicy.c | 15 +++++++++------
 3 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c
index e96353f..b0cc498 100644
--- a/daemons/ipa-kdb/ipa_kdb.c
+++ b/daemons/ipa-kdb/ipa_kdb.c
@@ -50,6 +50,7 @@ static void ipadb_context_free(krb5_context kcontext,
         free((*ctx)->uri);
         free((*ctx)->base);
         free((*ctx)->realm_base);
+        free((*ctx)->accounts_base);
         free((*ctx)->kdc_hostname);
         /* ldap free lcontext */
         if ((*ctx)->lcontext) {
@@ -554,6 +555,12 @@ static krb5_error_code ipadb_init_module(krb5_context kcontext,
         goto fail;
     }
 
+    ret = asprintf(&ipactx->accounts_base, "cn=accounts,%s", ipactx->base);
+    if (ret == -1) {
+        ret = ENOMEM;
+        goto fail;
+    }
+
     ret = uname(&uname_data);
     if (ret) {
         ret = EINVAL;
diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h
index e1f46c6..10aaee4 100644
--- a/daemons/ipa-kdb/ipa_kdb.h
+++ b/daemons/ipa-kdb/ipa_kdb.h
@@ -101,6 +101,7 @@ struct ipadb_context {
     char *base;
     char *realm;
     char *realm_base;
+    char *accounts_base;
     char *kdc_hostname;
     LDAP *lcontext;
     krb5_context kcontext;
diff --git a/daemons/ipa-kdb/ipa_kdb_pwdpolicy.c b/daemons/ipa-kdb/ipa_kdb_pwdpolicy.c
index 0c810af..1ec5846 100644
--- a/daemons/ipa-kdb/ipa_kdb_pwdpolicy.c
+++ b/daemons/ipa-kdb/ipa_kdb_pwdpolicy.c
@@ -137,10 +137,11 @@ krb5_error_code ipadb_get_pwd_policy(krb5_context kcontext, char *name,
                                      osa_policy_ent_t *policy)
 {
     struct ipadb_context *ipactx;
+    char *bases[3] = { NULL };
     char *esc_name = NULL;
     char *src_filter = NULL;
     krb5_error_code kerr;
-    LDAPMessage *res = NULL;
+    struct ipadb_multires *res;
     LDAPMessage *lentry;
     osa_policy_ent_t pentry = NULL;
     uint32_t result;
@@ -150,6 +151,8 @@ krb5_error_code ipadb_get_pwd_policy(krb5_context kcontext, char *name,
     if (!ipactx) {
         return KRB5_KDB_DBNOTINITED;
     }
+    bases[0] = ipactx->realm_base;
+    bases[1] = ipactx->accounts_base;
 
     esc_name = ipadb_filter_escape(name, true);
     if (!esc_name) {
@@ -162,14 +165,14 @@ krb5_error_code ipadb_get_pwd_policy(krb5_context kcontext, char *name,
         goto done;
     }
 
-    kerr = ipadb_simple_search(ipactx,
-                               ipactx->base, LDAP_SCOPE_SUBTREE,
-                               src_filter, std_pwdpolicy_attrs, &res);
+    kerr = ipadb_multibase_search(ipactx, bases, LDAP_SCOPE_SUBTREE,
+                                  src_filter, std_pwdpolicy_attrs, &res,
+                                  true);
     if (kerr) {
         goto done;
     }
 
-    lentry = ldap_first_entry(ipactx->lcontext, res);
+    lentry = ipadb_multires_next_entry(res);
     if (!lentry) {
         kerr = KRB5_KDB_INTERNAL_ERROR;
         goto done;
@@ -252,7 +255,7 @@ krb5_error_code ipadb_get_pwd_policy(krb5_context kcontext, char *name,
     }
     free(esc_name);
     free(src_filter);
-    ldap_msgfree(res);
+    ipadb_multires_free(res);
 
     return kerr;
 }
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to