/*
* 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,
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 /)",
/* 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 */
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;
}
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;