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