X-Git-Url: https://git.sesse.net/?p=itkacl;a=blobdiff_plain;f=itkacl-2.1%2Fitkacl.c;h=2795cf4d6885899058ab740cb436997a9276db5d;hp=1ebd3a096fec2c24299b3b2f97a24d114ac4b287;hb=b53d275766bb14e5d2e6d06ff306878b311c8123;hpb=66f114e2e5b127115cc127ea23865371f1bea90d diff --git a/itkacl-2.1/itkacl.c b/itkacl-2.1/itkacl.c index 1ebd3a0..2795cf4 100644 --- a/itkacl-2.1/itkacl.c +++ b/itkacl-2.1/itkacl.c @@ -1,7 +1,7 @@ /* - * itkacl control library, version 0.1 + * ITKACL control library. * - * (C) 2004-2009 Steinar H. Gunderson + * (C) 2004-2013 Steinar H. Gunderson * GPL, v2. */ #include @@ -11,10 +11,12 @@ #include #include #include -#include +#include struct itkacl_config { char nszone[256]; + int require_dnssec; + char dnssec_public_key[256]; }; #define CONFIG_FILENAME "/etc/itkacl.conf" @@ -26,7 +28,10 @@ static int itkacl_read_config(const char * const filename, FILE *fp; int lineno = 0; + /* Defaults. */ strcpy(config->nszone, ""); + config->require_dnssec = 0; + strcpy(config->dnssec_public_key, ""); fp = fopen(CONFIG_FILENAME, "r"); if (fp == NULL) { @@ -70,6 +75,14 @@ static int itkacl_read_config(const char * const filename, strcpy(config->nszone, arg); continue; } + if (strcmp(line, "require-dnssec") == 0) { + config->require_dnssec = 1; + continue; + } + if (sscanf(line, "dnssec-public-key %255s", arg) == 1) { + strcpy(config->dnssec_public_key, arg); + continue; + } if (errmsg) snprintf(errmsg, errmsg_size, "%s: Could not parse line %d", @@ -94,11 +107,12 @@ int itkacl_check(const char * const realm, const char * const user, char *errmsg, size_t errmsg_size) { struct itkacl_config config; - struct hostent he, *he_ptr; - int ret, host_errno; + int ret, nxdomain; const char *ptr; char nszone[256]; - char temp[256], ns_temp[1024]; + char temp[256]; + struct ub_ctx* ctx; + struct ub_result* result; if (itkacl_read_config(CONFIG_FILENAME, &config, errmsg, errmsg_size) != 0) { return -1; @@ -173,34 +187,85 @@ int itkacl_check(const char * const realm, const char * const user, strcpy(temp, nszone); sprintf(nszone, "%s.%s", user, temp); - ret = gethostbyname_r(nszone, &he, ns_temp, 1024, &he_ptr, &host_errno); + /* 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; + } - /* - * The man page for gethostbyname_r() specifies ret != 0 on failure, but - * that seemingly does not include HOST_NOT_FOUND failure. - */ - if (he_ptr == NULL) { - // Not found => no access, but no error either. - if (host_errno == HOST_NOT_FOUND) { - return 1; - } + ret = ub_ctx_resolvconf(ctx, "/etc/resolv.conf"); + if (ret != 0) { + if (errmsg) + snprintf(errmsg, errmsg_size, + "Host name lookup failure: Could not read /etc/resolv.conf " + "(resolver error: %s) (system error: %s)", + ub_strerror(ret), strerror(errno)); + ub_ctx_delete(ctx); + return -1; + } - switch (host_errno) { - case TRY_AGAIN: - snprintf(errmsg, errmsg_size, "Host name lookup failure"); - break; - case NO_RECOVERY: - snprintf(errmsg, errmsg_size, "Unknown server error"); - break; - case NO_ADDRESS: - snprintf(errmsg, errmsg_size, "No address associated with name"); - break; - default: - snprintf(errmsg, errmsg_size, "Unknown DNS error %d", host_errno); + ret = ub_ctx_hosts(ctx, "/etc/hosts"); + if (ret != 0) { + if (errmsg) + snprintf(errmsg, errmsg_size, + "Host name lookup failure: Could not read /etc/hosts " + "(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); + if (ret != 0) { + if (errmsg) + snprintf(errmsg, errmsg_size, "Host name lookup failure: %s", + ub_strerror(ret)); + ub_ctx_delete(ctx); return -1; } - // The lookup succeeded, so we're good. - return 0; + /* Verify DNSSEC. */ + if (result->bogus) { + if (errmsg) + 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 (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; + else + return 0; }