+ 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)
+{