ac7d03
From 3a946e38a911fdfb1575135c41128f41ab44324c Mon Sep 17 00:00:00 2001
ac7d03
From: Sumit Bose <sbose@redhat.com>
ac7d03
Date: Fri, 26 May 2017 18:19:48 +0200
ac7d03
Subject: [PATCH] ipa-kdb: reload certificate mapping rules periodically
ac7d03
ac7d03
With this patch the certificate mapping rules are reloaded every 5
ac7d03
minutes.
ac7d03
ac7d03
Resolves https://pagure.io/freeipa/issue/6963
ac7d03
ac7d03
Reviewed-By: David Kupka <dkupka@redhat.com>
ac7d03
---
ac7d03
 daemons/ipa-kdb/ipa_kdb_certauth.c | 153 ++++++++++++++++++++-----------------
ac7d03
 1 file changed, 81 insertions(+), 72 deletions(-)
ac7d03
ac7d03
diff --git a/daemons/ipa-kdb/ipa_kdb_certauth.c b/daemons/ipa-kdb/ipa_kdb_certauth.c
ac7d03
index a53a2ce4e7ceb06ec8de117cdbca2666fdb5a97a..dbe7a0443700784d2b8dbb1fb9196d6249e5522a 100644
ac7d03
--- a/daemons/ipa-kdb/ipa_kdb_certauth.c
ac7d03
+++ b/daemons/ipa-kdb/ipa_kdb_certauth.c
ac7d03
@@ -58,6 +58,8 @@
ac7d03
 #define CERTMAP_FILTER "(&("OBJECTCLASS"="IPA_OC_CERTMAP_RULE")" \
ac7d03
                               "("IPA_ENABLED_FLAG"="IPA_TRUE_VALUE"))"
ac7d03
 
ac7d03
+#define DEFAULT_CERTMAP_LIFETIME 300
ac7d03
+
ac7d03
 #ifndef discard_const
ac7d03
 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
ac7d03
 #endif
ac7d03
@@ -67,6 +69,7 @@ struct krb5_certauth_moddata_st {
ac7d03
     char *local_domain;
ac7d03
     struct sss_certmap_ctx *sss_certmap_ctx;
ac7d03
     struct ipadb_context *ipactx;
ac7d03
+    time_t valid_until;
ac7d03
 };
ac7d03
 
ac7d03
 void ipa_certmap_debug(void *private,
ac7d03
@@ -133,95 +136,101 @@ static krb5_error_code ipa_get_init_data(krb5_context kcontext,
ac7d03
     }
ac7d03
 
ac7d03
     if (ipactx->certauth_moddata == NULL) {
ac7d03
-        ret = asprintf(&basedn, "cn=certmap,%s", ipactx->base);
ac7d03
-        if (ret == -1) {
ac7d03
-            return ENOMEM;
ac7d03
-        }
ac7d03
+        ipactx->certauth_moddata = moddata_out;
ac7d03
 
ac7d03
-        kerr = ipadb_simple_search(ipactx,basedn, LDAP_SCOPE_SUBTREE,
ac7d03
-                                   CERTMAP_FILTER, discard_const(certmap_attrs),
ac7d03
-                                   &result);
ac7d03
-        if (kerr != 0 && kerr != KRB5_KDB_NOENTRY) {
ac7d03
-            goto done;
ac7d03
+        if (ipactx->realm != NULL) {
ac7d03
+            ipactx->certauth_moddata->local_domain = strdup(ipactx->realm);
ac7d03
+            if (ipactx->certauth_moddata->local_domain == NULL) {
ac7d03
+                free(ipactx->certauth_moddata);
ac7d03
+                ipactx->certauth_moddata = NULL;
ac7d03
+                ret = ENOMEM;
ac7d03
+                goto done;
ac7d03
+            }
ac7d03
         }
ac7d03
 
ac7d03
-        ret = sss_certmap_init(NULL, ipa_certmap_debug, NULL, &ctx;;
ac7d03
+        ipactx->certauth_moddata->ipactx = ipactx;
ac7d03
+
ac7d03
+    }
ac7d03
+
ac7d03
+    ret = asprintf(&basedn, "cn=certmap,%s", ipactx->base);
ac7d03
+    if (ret == -1) {
ac7d03
+        return ENOMEM;
ac7d03
+    }
ac7d03
+
ac7d03
+    kerr = ipadb_simple_search(ipactx,basedn, LDAP_SCOPE_SUBTREE,
ac7d03
+                               CERTMAP_FILTER, discard_const(certmap_attrs),
ac7d03
+                               &result);
ac7d03
+    if (kerr != 0 && kerr != KRB5_KDB_NOENTRY) {
ac7d03
+        goto done;
ac7d03
+    }
ac7d03
+
ac7d03
+    ret = sss_certmap_init(NULL, ipa_certmap_debug, NULL, &ctx;;
ac7d03
+    if (ret != 0) {
ac7d03
+        return ret;
ac7d03
+    }
ac7d03
+
ac7d03
+    if (kerr == KRB5_KDB_NOENTRY) {
ac7d03
+        ret = sss_certmap_add_rule(ctx, SSS_CERTMAP_MIN_PRIO,
ac7d03
+                                   NULL, NULL, NULL);
ac7d03
         if (ret != 0) {
ac7d03
-            return ret;
ac7d03
+            goto done;
ac7d03
         }
ac7d03
-
ac7d03
-        if (kerr == KRB5_KDB_NOENTRY) {
ac7d03
-            ret = sss_certmap_add_rule(ctx, SSS_CERTMAP_MIN_PRIO,
ac7d03
-                                       NULL, NULL, NULL);
ac7d03
-            if (ret != 0) {
ac7d03
+    } else {
ac7d03
+        lc = ipactx->lcontext;
ac7d03
+
ac7d03
+        for (le = ldap_first_entry(lc, result); le;
ac7d03
+                                             le = ldap_next_entry(lc, le)) {
ac7d03
+            prio = SSS_CERTMAP_MIN_PRIO;
ac7d03
+            ret = ipadb_ldap_attr_to_uint32(lc, le, IPA_CERTMAP_PRIORITY,
ac7d03
+                                            &prio;;
ac7d03
+            if (ret != 0 && ret != ENOENT) {
ac7d03
                 goto done;
ac7d03
             }
ac7d03
-        } else {
ac7d03
-            lc = ipactx->lcontext;
ac7d03
-
ac7d03
-            for (le = ldap_first_entry(lc, result); le;
ac7d03
-                                                 le = ldap_next_entry(lc, le)) {
ac7d03
-                prio = SSS_CERTMAP_MIN_PRIO;
ac7d03
-                ret = ipadb_ldap_attr_to_uint32(lc, le, IPA_CERTMAP_PRIORITY,
ac7d03
-                                                &prio;;
ac7d03
-                if (ret != 0 && ret != ENOENT) {
ac7d03
-                    goto done;
ac7d03
-                }
ac7d03
-
ac7d03
-                free(map_rule);
ac7d03
-                map_rule = NULL;
ac7d03
-                ret = ipadb_ldap_attr_to_str(lc, le, IPA_CERTMAP_MAPRULE,
ac7d03
-                                             &map_rule);
ac7d03
-                if (ret != 0 && ret != ENOENT) {
ac7d03
-                    goto done;
ac7d03
-                }
ac7d03
 
ac7d03
-                free(match_rule);
ac7d03
-                match_rule = NULL;
ac7d03
-                ret = ipadb_ldap_attr_to_str(lc, le, IPA_CERTMAP_MATCHRULE,
ac7d03
-                                             &match_rule);
ac7d03
-                if (ret != 0 && ret != ENOENT) {
ac7d03
-                    goto done;
ac7d03
-                }
ac7d03
+            free(map_rule);
ac7d03
+            map_rule = NULL;
ac7d03
+            ret = ipadb_ldap_attr_to_str(lc, le, IPA_CERTMAP_MAPRULE,
ac7d03
+                                         &map_rule);
ac7d03
+            if (ret != 0 && ret != ENOENT) {
ac7d03
+                goto done;
ac7d03
+            }
ac7d03
 
ac7d03
-                if (domains != NULL) {
ac7d03
-                    for (c = 0; domains[c] != NULL; c++) {
ac7d03
-                        free(domains[c]);
ac7d03
-                    }
ac7d03
-                    free(domains);
ac7d03
-                    domains = NULL;
ac7d03
-                }
ac7d03
-                ret = ipadb_ldap_attr_to_strlist(lc, le, IPA_ASSOCIATED_DOMAIN,
ac7d03
-                                                 &domains);
ac7d03
-                if (ret != 0 && ret != ENOENT) {
ac7d03
-                    goto done;
ac7d03
-                }
ac7d03
+            free(match_rule);
ac7d03
+            match_rule = NULL;
ac7d03
+            ret = ipadb_ldap_attr_to_str(lc, le, IPA_CERTMAP_MATCHRULE,
ac7d03
+                                         &match_rule);
ac7d03
+            if (ret != 0 && ret != ENOENT) {
ac7d03
+                goto done;
ac7d03
+            }
ac7d03
 
ac7d03
-                ret = sss_certmap_add_rule(ctx, prio, match_rule, map_rule,
ac7d03
-                                           (const char **) domains);
ac7d03
-                if (ret != 0) {
ac7d03
-                    goto done;
ac7d03
+            if (domains != NULL) {
ac7d03
+                for (c = 0; domains[c] != NULL; c++) {
ac7d03
+                    free(domains[c]);
ac7d03
                 }
ac7d03
+                free(domains);
ac7d03
+                domains = NULL;
ac7d03
+            }
ac7d03
+            ret = ipadb_ldap_attr_to_strlist(lc, le, IPA_ASSOCIATED_DOMAIN,
ac7d03
+                                             &domains);
ac7d03
+            if (ret != 0 && ret != ENOENT) {
ac7d03
+                goto done;
ac7d03
             }
ac7d03
-        }
ac7d03
-
ac7d03
-        ipactx->certauth_moddata = moddata_out;
ac7d03
 
ac7d03
-        if (ipactx->realm != NULL) {
ac7d03
-            ipactx->certauth_moddata->local_domain = strdup(ipactx->realm);
ac7d03
-            if (ipactx->certauth_moddata->local_domain == NULL) {
ac7d03
-                free(ipactx->certauth_moddata);
ac7d03
-                ipactx->certauth_moddata = NULL;
ac7d03
-                ret = ENOMEM;
ac7d03
+            ret = sss_certmap_add_rule(ctx, prio, match_rule, map_rule,
ac7d03
+                                       (const char **) domains);
ac7d03
+            if (ret != 0) {
ac7d03
                 goto done;
ac7d03
             }
ac7d03
         }
ac7d03
-
ac7d03
-        ipactx->certauth_moddata->sss_certmap_ctx = ctx;
ac7d03
-        ipactx->certauth_moddata->ipactx = ipactx;
ac7d03
-
ac7d03
     }
ac7d03
 
ac7d03
+    sss_certmap_free_ctx(ipactx->certauth_moddata->sss_certmap_ctx);
ac7d03
+    ipactx->certauth_moddata->sss_certmap_ctx = ctx;
ac7d03
+    ipactx->certauth_moddata->valid_until = time(NULL)
ac7d03
+                                                 + DEFAULT_CERTMAP_LIFETIME;
ac7d03
+    krb5_klog_syslog(LOG_DEBUG,
ac7d03
+                     "Successfully updates certificate mapping rules.");
ac7d03
+
ac7d03
     ret = 0;
ac7d03
 
ac7d03
 done:
ac7d03
@@ -266,7 +275,7 @@ static krb5_error_code ipa_certauth_authorize(krb5_context context,
ac7d03
         return KRB5_PLUGIN_NO_HANDLE;
ac7d03
     }
ac7d03
 
ac7d03
-    if (moddata->sss_certmap_ctx == NULL) {
ac7d03
+    if (moddata->sss_certmap_ctx == NULL || time(NULL) > moddata->valid_until) {
ac7d03
         kerr = ipa_get_init_data(context, moddata);
ac7d03
         if (kerr != 0) {
ac7d03
             krb5_klog_syslog(LOG_ERR, "Failed to init certmapping data");
ac7d03
-- 
ac7d03
2.9.4
ac7d03