]> git.sesse.net Git - itkacl/blobdiff - itkacl-2.2/itkacl.c
Add an API for keeping a permanent library context, for performance reasons
[itkacl] / itkacl-2.2 / itkacl.c
similarity index 76%
rename from itkacl-2.1/itkacl.c
rename to itkacl-2.2/itkacl.c
index eda3ebb70dbe00694a87d3d23f0d1abe9b5717e8..d7bdfa016c06bc37225628cda3b098f2c62d317a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ITKACL control library.
  *
- * (C) 2004-2013 Steinar H. Gunderson
+ * (C) 2004-2022 Steinar H. Gunderson
  * GPL, v2.
  */
 #include <stdio.h>
 #include <ctype.h>
 #include <unbound.h>
 
+#include "itkacl.h"
+
 struct itkacl_config {
        char nszone[256];
        int require_dnssec;
        char dnssec_public_key[256];
 };
 
+struct itkacl_ctx {
+       struct itkacl_config config;
+       struct ub_ctx *ubctx;
+};
+
 #define CONFIG_FILENAME "/etc/itkacl.conf"
 
 static int itkacl_read_config(const char * const filename,
@@ -106,18 +113,105 @@ static int itkacl_read_config(const char * const filename,
 int itkacl_check(const char * const realm, const char * const user,
                 char *errmsg, size_t errmsg_size)
 {
-       struct itkacl_config config;
+       struct itkacl_ctx *ctx;
+       int err;
+
+       ctx = itkacl_create_ctx(errmsg, errmsg_size);
+       if (ctx == NULL) {
+               return -1;
+       }
+
+       err = itkacl_check_with_ctx(ctx, realm, user, errmsg, errmsg_size);
+
+       itkacl_free_ctx(ctx);
+
+       return err;
+}
+
+struct itkacl_ctx *itkacl_create_ctx(char *errmsg, size_t errmsg_size)
+{
+       struct itkacl_ctx *ctx;
+       int ret;
+
+       ctx = (struct itkacl_ctx *)malloc(sizeof(struct itkacl_ctx));
+       if (ctx == NULL) {
+               if (errmsg)
+                       snprintf(errmsg, errmsg_size, "Memory allocation failed");
+               return NULL;
+       }
+
+       if (itkacl_read_config(CONFIG_FILENAME, &ctx->config, errmsg, errmsg_size) != 0) {
+               free(ctx);
+               return NULL;
+       }
+
+       /* Create the DNS resolver context. */
+       ctx->ubctx = ub_ctx_create();
+       if (ctx->ubctx == NULL) {
+               if (errmsg)
+                       snprintf(errmsg, errmsg_size, "Host name lookup failure: Could not create DNS context");
+               free(ctx);
+               return NULL;
+       }
+
+       ret = ub_ctx_resolvconf(ctx->ubctx, NULL);
+       if (ret != 0) {
+               if (errmsg)
+                       snprintf(errmsg, errmsg_size,
+                                "Host name lookup failure: Could not read resolv.conf "
+                                "(resolver error: %s) (system error: %s)",
+                                ub_strerror(ret), strerror(errno));
+               ub_ctx_delete(ctx->ubctx);
+               free(ctx);
+               return NULL;
+       }
+
+       ret = ub_ctx_hosts(ctx->ubctx, NULL);
+       if (ret != 0) {
+               if (errmsg)
+                       snprintf(errmsg, errmsg_size,
+                                "Host name lookup failure: Could not read hosts file "
+                                "(resolver error: %s) (system error: %s)",
+                                ub_strerror(ret), strerror(errno));
+               ub_ctx_delete(ctx->ubctx);
+               free(ctx);
+               return NULL;
+       }
+
+       if (strlen(ctx->config.dnssec_public_key) != 0) {
+               ret = ub_ctx_add_ta_file(ctx->ubctx, ctx->config.dnssec_public_key);
+               if (ret != 0) {
+                       if (errmsg)
+                               snprintf(errmsg, errmsg_size,
+                                        "Host name lookup failure: Error adding keys from %s "
+                                        "(resolver error: %s) (system error: %s)",
+                                        ctx->config.dnssec_public_key,
+                                        ub_strerror(ret), strerror(errno));
+                       ub_ctx_delete(ctx->ubctx);
+                       free(ctx);
+                       return NULL;
+               }
+       }
+
+       return ctx;
+}
+
+void itkacl_free_ctx(struct itkacl_ctx *ctx)
+{
+       ub_ctx_delete(ctx->ubctx);
+       free(ctx);
+}
+
+int itkacl_check_with_ctx(struct itkacl_ctx *ctx,
+                          const char * const realm, const char * const user,
+                         char *errmsg, size_t errmsg_size)
+{
        int ret, nxdomain;
        const char *ptr;
        char nszone[256];
        char temp[256];
-       struct ub_ctx* ctx;
        struct ub_result* result;
 
-       if (itkacl_read_config(CONFIG_FILENAME, &config, errmsg, errmsg_size) != 0) {
-               return -1;
-       }
-
        if (realm[0] != '/') {
                if (errmsg)
                        snprintf(errmsg, errmsg_size, "Invalid realm '%s' (missing leading /)",
@@ -155,7 +249,7 @@ int itkacl_check(const char * const realm, const char * const user,
 
        /* traverse the realm entry by entry from the root,
         * creating a DNS zone name as we go */
-       strcpy(nszone, config.nszone);
+       strcpy(nszone, ctx->config.nszone);
        ptr = realm;
        while (*ptr) {
                /* copy all characters to next / or end of string */
@@ -187,57 +281,12 @@ int itkacl_check(const char * const realm, const char * const user,
        strcpy(temp, nszone);
        sprintf(nszone, "%s.%s", user, temp);
 
-       /* Create the DNS resolver context. */
-       ctx = ub_ctx_create();
-       if (ctx == NULL) {
-               if (errmsg)
-                       snprintf(errmsg, errmsg_size, "Host name lookup failure: Could not create DNS context");
-               return -1;
-       }
-
-       ret = ub_ctx_resolvconf(ctx, NULL);
-       if (ret != 0) {
-               if (errmsg)
-                       snprintf(errmsg, errmsg_size,
-                                "Host name lookup failure: Could not read resolv.conf "
-                                "(resolver error: %s) (system error: %s)",
-                                ub_strerror(ret), strerror(errno));
-               ub_ctx_delete(ctx);
-               return -1;
-       }
-
-       ret = ub_ctx_hosts(ctx, NULL);
-       if (ret != 0) {
-               if (errmsg)
-                       snprintf(errmsg, errmsg_size,
-                                "Host name lookup failure: Could not read hosts file "
-                                "(resolver error: %s) (system error: %s)",
-                                ub_strerror(ret), strerror(errno));
-               ub_ctx_delete(ctx);
-               return -1;
-       }
-
-       if (strlen(config.dnssec_public_key) != 0) {
-               ret = ub_ctx_add_ta_file(ctx, config.dnssec_public_key);
-               if (ret != 0) {
-                       if (errmsg)
-                               snprintf(errmsg, errmsg_size,
-                                        "Host name lookup failure: Error adding keys from %s "
-                                        "(resolver error: %s) (system error: %s)",
-                                        config.dnssec_public_key,
-                                        ub_strerror(ret), strerror(errno));
-                       ub_ctx_delete(ctx);
-                       return -1;
-               }
-       }
-
        /* Do the actual DNS lookup (TYPE A, CLASS IN). */
-       ret = ub_resolve(ctx, nszone, 1, 1, &result);
+       ret = ub_resolve(ctx->ubctx, nszone, 1, 1, &result);
        if (ret != 0) {
                if (errmsg)
                        snprintf(errmsg, errmsg_size, "Host name lookup failure: %s",
                                 ub_strerror(ret));
-               ub_ctx_delete(ctx);
                return -1;
        }
 
@@ -247,22 +296,19 @@ int itkacl_check(const char * const realm, const char * const user,
                        snprintf(errmsg, errmsg_size,
                                 "Host name lookup failure: Bogus DNSSEC result (security failure)");
                ub_resolve_free(result);
-               ub_ctx_delete(ctx);
                return -1;
        }
-       if (config.require_dnssec && !result->secure) {
+       if (ctx->config.require_dnssec && !result->secure) {
                if (errmsg)
                        snprintf(errmsg, errmsg_size,
                                 "Host name lookup failure: Result was not secured with DNSSEC");
                ub_resolve_free(result);
-               ub_ctx_delete(ctx);
                return -1;
        }
 
        nxdomain = result->nxdomain;
 
        ub_resolve_free(result);
-       ub_ctx_delete(ctx);
 
        if (nxdomain)
                return 1;