Пример #1
0
/*
 * initialize a ub_ct for blocking dns calls. Do not call from pluto.
 * Call this function once directly, such as addconn.
 * dns_ctx is static in this file. call unbound_ctx_free() to free it.
 */
void unbound_sync_init(bool do_dnssec, const char *rootfile,
			const char *trusted)
{
	if (!do_dnssec)
		return;

	passert(dns_ctx == NULL); /* block re-entry to the function */
	dns_ctx = ub_ctx_create();
	passert(dns_ctx != NULL);
	unbound_ctx_config(do_dnssec, rootfile, trusted);
}
Пример #2
0
nss_ubdns_init(void) {
	ctx = ub_ctx_create();
	if (ctx != NULL) {
		/* disable logging to stderr */
		/* the stub resolver must not generate any output to stdio */
		ub_ctx_debugout(ctx, NULL);

		nss_ubdns_load_resolvconf();
		nss_ubdns_load_keys();
		nss_ubdns_load_cfg();
	}
}
Пример #3
0
int unbound_init(struct ub_ctx *dnsctx)
{
	int ugh;
	/* create unbound resolver context */
	dnsctx = ub_ctx_create();
        if(!dnsctx) {
                libreswan_log("error: could not create unbound context\n");
                return 0;
        }
		DBG(DBG_DNS, 
			ub_ctx_debuglevel(dnsctx,5);
			DBG_log("unbound context created - setting debug level to 5\n"));

	/* lookup from /etc/hosts before DNS lookups as people expect that */
	if( (ugh=ub_ctx_hosts(dnsctx, "/etc/hosts")) != 0) {
		libreswan_log("error reading hosts: %s: %s\n",
			ub_strerror(ugh), strerror(errno));
		return 0;
	}
	DBG(DBG_DNS, DBG_log("/etc/hosts lookups activated\n"));

	/*
	 * Use /etc/resolv.conf as forwarding cache - we expect people to reconfigure this
	 * file if they need to work around DHCP DNS obtained servers
	 */
	if( (ugh=ub_ctx_resolvconf(dnsctx, "/etc/resolv.conf")) != 0) {
		libreswan_log("error reading resolv.conf: %s: %s\n",
			ub_strerror(ugh), strerror(errno));
		return 0;
	}
	DBG(DBG_DNS, DBG_log("/etc/resolv.conf usage activated\n"));

        /* add trust anchors to libunbound context - make this configurable later */
	DBG(DBG_DNS, DBG_log("Loading root key:%s\n",rootanchor));
        ugh = ub_ctx_add_ta(dnsctx, rootanchor);
        if(ugh != 0) {
                libreswan_log("error adding the DNSSEC root key: %s: %s\n", ub_strerror(ugh), strerror(errno));
		return 0;
	}

        /* Enable DLV */
	DBG(DBG_DNS, DBG_log("Loading dlv key:%s\n",dlvanchor));
        ugh = ub_ctx_set_option(dnsctx, "dlv-anchor:",dlvanchor);
        if(ugh != 0) {
                libreswan_log("error adding the DLV key: %s: %s\n", ub_strerror(ugh), strerror(errno));
		return 0;
	}

	return 1;
}
Пример #4
0
bool unbound_init(struct ub_ctx *dnsctx)
{
	int ugh;

	/* create unbound resolver context */
	dnsctx = ub_ctx_create();
	if (!dnsctx) {
		libreswan_log("error: could not create unbound context");
		return FALSE;
	}
	DBG(DBG_DNS,
		ub_ctx_debuglevel(dnsctx, 5);
		DBG_log("unbound context created - setting debug level to 5");
		);
Пример #5
0
DNSResolver::DNSResolver() : m_data(new DNSResolverData())
{
  int use_dns_public = 0;
  const char* dns_public_addr = "8.8.4.4";
  if (auto res = getenv("DNS_PUBLIC"))
  {
    std::string dns_public(res);
    // TODO: could allow parsing of IP and protocol: e.g. DNS_PUBLIC=tcp:8.8.8.8
    if (dns_public == "tcp")
    {
      LOG_PRINT_L0("Using public DNS server: " << dns_public_addr << " (TCP)");
      use_dns_public = 1;
    }
  }

  // init libunbound context
  m_data->m_ub_context = ub_ctx_create();

  if (use_dns_public)
  {
    ub_ctx_set_fwd(m_data->m_ub_context, dns_public_addr);
    ub_ctx_set_option(m_data->m_ub_context, "do-udp:", "no");
    ub_ctx_set_option(m_data->m_ub_context, "do-tcp:", "yes");
  }
  else {
    // look for "/etc/resolv.conf" and "/etc/hosts" or platform equivalent
    ub_ctx_resolvconf(m_data->m_ub_context, NULL);
    ub_ctx_hosts(m_data->m_ub_context, NULL);
  }

  #ifdef DEVELOPER_LIBUNBOUND_OLD
    #pragma message "Using the work around for old libunbound"
    { // work around for bug https://www.nlnetlabs.nl/bugs-script/show_bug.cgi?id=515 needed for it to compile on e.g. Debian 7
      char * ds_copy = NULL; // this will be the writable copy of string that bugged version of libunbound requires
      try {
        char * ds_copy = strdup( ::get_builtin_ds() );
        ub_ctx_add_ta(m_data->m_ub_context, ds_copy);
      } catch(...) { // probably not needed but to work correctly in every case...
        if (ds_copy) { free(ds_copy); ds_copy=NULL; } // for the strdup
        throw ;
      }
      if (ds_copy) { free(ds_copy); ds_copy=NULL; } // for the strdup
    }
  #else
    // normal version for fixed libunbound
    ub_ctx_add_ta(m_data->m_ub_context, ::get_builtin_ds() );
  #endif

}
Пример #6
0
DNSResolver::DNSResolver() : m_data(new DNSResolverData())
{
  int use_dns_public = 0;
  std::vector<std::string> dns_public_addr;
  if (auto res = getenv("DNS_PUBLIC"))
  {
    dns_public_addr = tools::dns_utils::parse_dns_public(res);
    if (!dns_public_addr.empty())
    {
      MGINFO("Using public DNS server(s): " << boost::join(dns_public_addr, ", ") << " (TCP)");
      use_dns_public = 1;
    }
    else
    {
      MERROR("Failed to parse DNS_PUBLIC");
    }
  }

  // init libunbound context
  m_data->m_ub_context = ub_ctx_create();

  if (use_dns_public)
  {
    for (const auto &ip: dns_public_addr)
      ub_ctx_set_fwd(m_data->m_ub_context, string_copy(ip.c_str()));
    ub_ctx_set_option(m_data->m_ub_context, string_copy("do-udp:"), string_copy("no"));
    ub_ctx_set_option(m_data->m_ub_context, string_copy("do-tcp:"), string_copy("yes"));
  }
  else {
    // look for "/etc/resolv.conf" and "/etc/hosts" or platform equivalent
    ub_ctx_resolvconf(m_data->m_ub_context, NULL);
    ub_ctx_hosts(m_data->m_ub_context, NULL);
  }

  const char * const *ds = ::get_builtin_ds();
  while (*ds)
  {
    MINFO("adding trust anchor: " << *ds);
    ub_ctx_add_ta(m_data->m_ub_context, string_copy(*ds++));
  }
}
Пример #7
0
struct ub_result * unbify_resolve(const char *hostname) {
    /*@only@*/ static struct ub_ctx * u = NULL;
    struct ub_result * r = NULL;
    int ub_err;

    assert(hostname != NULL);

    if ( u == NULL ) {
        if ( (u = ub_ctx_create()) == NULL ) {
            unbify_log_error("ub_ctx_create() error");
            return NULL;
        }

        if ( (ub_err = ub_ctx_config(u, UNBOUND_CONFIG_FILE)) != 0 ) {
            /*@-mustfreefresh@*/
            unbify_log_error(ub_strerror(ub_err));
            /*@=mustfreefresh@*/
            ub_ctx_delete(u);
            u = NULL;
            return NULL;
        }
    }

    /*@-unrecog@*/
    if ( (ub_err = ub_resolve(u, (char*)hostname, LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, &r)) != 0 ) {
        /*@=unrecog -mustfreefresh@*/
        unbify_log_error(ub_strerror(ub_err));
        /*@=mustfreefresh@*/
        if (r) {
            ub_resolve_free(r);
            return NULL;
        }
    }

    return r;
}
Пример #8
0
/** update domain to file */
static int
do_update(char* domain, char* file)
{
	struct ub_ctx* ctx;
	struct ub_result* result;
	int r;
	printf("updating %s to %s\n", domain, file);
	ctx = ub_ctx_create();
	if(!ctx) fatal("ub_ctx_create failed");

	if((r=ub_ctx_add_ta_file(ctx, file))) {
		printf("%s\n", ub_strerror(r));
		fatal("ub_ctx_add_ta_file failed");
	}

	if(!(result=do_lookup(ctx, domain))) {
		ub_ctx_delete(ctx);
		return 1;
	}
	ub_ctx_delete(ctx);
	do_print(result, file);
	ub_resolve_free(result);
	return 0;
}
Пример #9
0
int main(void)
{
	struct ub_ctx* ctx;
	volatile int qlen = 0;
	int retval;
	char qname[QNAME_MAX];
	char *moredata, *nl;

	/* basic checks */
	if(QUEUE_MAX < 1) {
		printf("error: queue length must be >0\n");
		return 1;
	}

	/* create context */
	ctx = ub_ctx_create();
	if(!ctx) {
		printf("error: could not create unbound context\n");
		return 1;
	}

	fprintf(stderr, "HOST;ERR;RCODE;DATA;NXDOMAIN\n");

	/* we keep running, lets do something while waiting */
	moredata = (char*)-1;
	do {
		/* queue has room && more data on stdin? */
		if(qlen < QUEUE_MAX && moredata) {
			/* read and prepare qname from stdin */
			moredata = fgets(qname, QNAME_MAX, stdin);
			if(moredata != NULL) {
				nl = strrchr(qname, '\n');
				if(nl) *nl = '\0';
				if((int)nl == (int)&qname)
				{
					printf("empty input\n");
					continue;
				}

				/* add async query to queue */
				retval = ub_resolve_async(ctx, qname,
						1,
						1,
						(void*)&qlen, mycallback, NULL);
				if(retval != 0) {
					printf("resolve error for %s: %s\n", qname, ub_strerror(retval));
					continue;
				}
				qlen++;
			}
			usleep(50000); /* wait 1/50 of a second */
		} else {
			/* queue is full || eof stdin reached */
			usleep(100000); /* wait 1/10 of a second */
			retval = ub_process(ctx);
			if(retval != 0) {
				printf("resolve error: %s\n", ub_strerror(retval));
				return 1;
			}
		}
	} while(qlen || moredata);

	ub_ctx_delete(ctx);
	return 0;
}
Пример #10
0
struct starter_config *confread_load(const char *file,
				     err_t *perr,
				     bool resolvip,
				     const char *ctlbase,
				     bool setuponly)
{
	struct starter_config *cfg = NULL;
	struct config_parsed *cfgp;
	struct section_list *sconn;
	bool err = FALSE;
	bool connerr;

#ifdef DNSSEC
	struct ub_ctx *dnsctx =  ub_ctx_create();
	unbound_init(dnsctx);
#else
	struct ub_ctx *dnsctx = NULL;
#endif
	/**
	 * Load file
	 */
	cfgp = parser_load_conf(file, perr);
	if (!cfgp)
		return NULL;

	cfg = (struct starter_config *)alloc_bytes(sizeof(struct starter_config),"starter_config cfg");

	/**
	 * Set default values
	 */
	ipsecconf_default_values(cfg);

	if (ctlbase) {
		pfree(cfg->ctlbase);
		cfg->ctlbase = clone_str(ctlbase, "control socket");
	}

	/**
	 * Load setup
	 */
	err |= load_setup(cfg, cfgp);

	if (err) {
		parser_free_conf(cfgp);
		confread_free(cfg);
		return NULL;
	}

	if (!setuponly) {
		/**
		 * Find %default and %oedefault conn
		 *
		 */
		for (sconn = cfgp->sections.tqh_first; (!err) && sconn != NULL;
		     sconn = sconn->link.tqe_next) {
			if (streq(sconn->name, "%default")) {
				starter_log(LOG_LEVEL_DEBUG,
					    "Loading default conn");
				err |= load_conn(dnsctx,
						 &cfg->conn_default,
						 cfgp, sconn, FALSE,
						/*default conn*/ TRUE,
						 resolvip, perr);
			}

			if (streq(sconn->name, "%oedefault")) {
				starter_log(LOG_LEVEL_DEBUG,
					    "Loading oedefault conn");
				err |= load_conn(dnsctx,
						 &cfg->conn_oedefault,
						 cfgp, sconn, FALSE,
						/*default conn*/ TRUE,
						 resolvip, perr);
				if (!err)
					cfg->got_oedefault = TRUE;
			}
		}

		/**
		 * Load other conns
		 */
		for (sconn = cfgp->sections.tqh_first; sconn != NULL;
		     sconn = sconn->link.tqe_next) {
			if (streq(sconn->name, "%default"))
				continue;
			if (streq(sconn->name, "%oedefault"))
				continue;

			connerr = init_load_conn(dnsctx, cfg, cfgp, sconn,
						 FALSE,
						 resolvip, perr);

#if 0	/* ??? the following condition can never be true */
			if (connerr == -1) {
				parser_free_conf(cfgp);
				confread_free(cfg);
				return NULL;
			}
#endif
			err |= connerr;
		}

		/* if we have OE on, then create any missing OE conns! */
		if (cfg->setup.options[KBF_OPPOENCRYPT]) {
			starter_log(LOG_LEVEL_DEBUG, "Enabling OE conns");
			add_any_oeconns(cfg, cfgp);
		}
	}

	parser_free_conf(cfgp);

	return cfg;
}
Пример #11
0
/** Main routine for checkconf */
int main(int argc, char* argv[])
{
	int c;
	char* qclass = NULL;
	char* qtype = NULL;
	struct ub_ctx* ctx = NULL;
	int debuglevel = 0;
	
	ctx = ub_ctx_create();
	if(!ctx) {
		fprintf(stderr, "error: out of memory\n");
		exit(1);
	}

	/* parse the options */
	while( (c=getopt(argc, argv, "46F:c:df:hrt:vy:C:")) != -1) {
		switch(c) {
		case '4':
			check_ub_res(ub_ctx_set_option(ctx, "do-ip6:", "no"));
			break;
		case '6':
			check_ub_res(ub_ctx_set_option(ctx, "do-ip4:", "no"));
			break;
		case 'c':
			qclass = optarg;
			break;
		case 'C':
			check_ub_res(ub_ctx_config(ctx, optarg));
			break;
		case 'd':
			debuglevel++;
			if(debuglevel < 2) 
				debuglevel = 2; /* at least VERB_DETAIL */
			break;
		case 'r':
			check_ub_res(ub_ctx_resolvconf(ctx, "/etc/resolv.conf"));
			break;
		case 't':
			qtype = optarg;
			break;
		case 'v':
			verb++;
			break;
		case 'y':
			check_ub_res(ub_ctx_add_ta(ctx, optarg));
			break;
		case 'f':
			check_ub_res(ub_ctx_add_ta_file(ctx, optarg));
			break;
		case 'F':
			check_ub_res(ub_ctx_trustedkeys(ctx, optarg));
			break;
		case '?':
		case 'h':
		default:
			usage();
		}
	}
	if(debuglevel != 0) /* set after possible -C options */
		check_ub_res(ub_ctx_debuglevel(ctx, debuglevel));
	if(ub_ctx_get_option(ctx, "use-syslog", &optarg) == 0) {
		if(strcmp(optarg, "yes") == 0) /* disable use-syslog */
			check_ub_res(ub_ctx_set_option(ctx, 
				"use-syslog:", "no"));
		free(optarg);
	}
	argc -= optind;
	argv += optind;
	if(argc != 1)
		usage();

#ifdef HAVE_NSS
        if(NSS_NoDB_Init(".") != SECSuccess) {
		fprintf(stderr, "could not init NSS\n");
		return 1;
	}
#endif
	lookup(ctx, argv[0], qtype, qclass);
	return 0;
}
Пример #12
0
/** main program for asynclook */
int main(int argc, char** argv) 
{
	int c;
	struct ub_ctx* ctx;
	struct lookinfo* lookups;
	int i, r, cancel=0, blocking=0, ext=0;

	/* init log now because solaris thr_key_create() is not threadsafe */
	log_init(0,0,0);
	/* lock debug start (if any) */
	checklock_start();

	/* create context */
	ctx = ub_ctx_create();
	if(!ctx) {
		printf("could not create context, %s\n", strerror(errno));
		return 1;
	}

	/* command line options */
	if(argc == 1) {
		usage(argv);
	}
	while( (c=getopt(argc, argv, "bcdf:hH:r:tx")) != -1) {
		switch(c) {
			case 'd':
				r = ub_ctx_debuglevel(ctx, 3);
				checkerr("ub_ctx_debuglevel", r);
				break;
			case 't':
				r = ub_ctx_async(ctx, 1);
				checkerr("ub_ctx_async", r);
				break;
			case 'c':
				cancel = 1;
				break;
			case 'b':
				blocking = 1;
				break;
			case 'r':
				r = ub_ctx_resolvconf(ctx, optarg);
				if(r != 0) {
					printf("ub_ctx_resolvconf "
						"error: %s : %s\n",
						ub_strerror(r), 
						strerror(errno));
					return 1;
				}
				break;
			case 'H':
				r = ub_ctx_hosts(ctx, optarg);
				if(r != 0) {
					printf("ub_ctx_hosts "
						"error: %s : %s\n",
						ub_strerror(r), 
						strerror(errno));
					return 1;
				}
				break;
			case 'f':
				r = ub_ctx_set_fwd(ctx, optarg);
				checkerr("ub_ctx_set_fwd", r);
				break;
			case 'x':
				ext = 1;
				break;
			case 'h':
			case '?':
			default:
				usage(argv);
		}
	}
	argc -= optind;
	argv += optind;

	if(ext)
		return ext_test(ctx, argc, argv);

	/* allocate array for results. */
	lookups = (struct lookinfo*)calloc((size_t)argc, 
		sizeof(struct lookinfo));
	if(!lookups) {
		printf("out of memory\n");
		return 1;
	}

	/* perform asynchronous calls */
	num_wait = argc;
	for(i=0; i<argc; i++) {
		lookups[i].name = argv[i];
		if(blocking) {
			fprintf(stderr, "lookup %s\n", argv[i]);
			r = ub_resolve(ctx, argv[i], LDNS_RR_TYPE_A,
				LDNS_RR_CLASS_IN, &lookups[i].result);
			checkerr("ub_resolve", r);
		} else {
			fprintf(stderr, "start async lookup %s\n", argv[i]);
			r = ub_resolve_async(ctx, argv[i], LDNS_RR_TYPE_A,
				LDNS_RR_CLASS_IN, &lookups[i], &lookup_is_done, 
				&lookups[i].async_id);
			checkerr("ub_resolve_async", r);
		}
	}
	if(blocking)
		num_wait = 0;
	else if(cancel) {
		for(i=0; i<argc; i++) {
			fprintf(stderr, "cancel %s\n", argv[i]);
			r = ub_cancel(ctx, lookups[i].async_id);
			if(r != UB_NOID) 
				checkerr("ub_cancel", r);
		}
		num_wait = 0;
	}

	/* wait while the hostnames are looked up. Do something useful here */
	if(num_wait > 0)
	    for(i=0; i<1000; i++) {
		usleep(100000);
		fprintf(stderr, "%g seconds passed\n", 0.1*(double)i);
		r = ub_process(ctx);
		checkerr("ub_process", r);
		if(num_wait == 0)
			break;
	}
	if(i>=999) {
		printf("timed out\n");
		return 0;
	}
	printf("lookup complete\n");

	/* print lookup results */
	for(i=0; i<argc; i++) {
		print_result(&lookups[i]);
		ub_resolve_free(lookups[i].result);
	}

	ub_ctx_delete(ctx);
	free(lookups);
	checklock_stop();
	return 0;
}
Пример #13
0
int ifconf_acquire_addresses(const char *name, 
        struct address **_list, unsigned *_n_list) {

        struct {
                struct nlmsghdr hdr;
                struct rtgenmsg gen;
        } req;
        struct rtgenmsg *gen;
        int fd, r, on = 1;
        uint32_t seq = 4711;
        struct address *list = NULL;
        unsigned n_list = 0;
        struct ub_ctx* ctx;
        struct ub_result* result;
        int retval, i;

        char *server = "127.0.0.1:8080";
        char url[3000];

        fprintf(stderr, "ifconf_acquire_addresses \n");

        URL *curl;
        CURLcode res;
    
        curl = curl_easy_init();
        if(curl) {
            sprintf(url, "http://%s/address/%s", server, name);
            curl_easy_setopt(curl, CURLOPT_URL,url);
            /*  send all data to this function  */ 
            //curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
            fprintf(stderr, "Sending http request\n");
            res = curl_easy_perform(curl);
                    
            //printf("read:%s\n", reply);

            /*  always cleanup */ 
            curl_easy_cleanup(curl);
        }
        ctx = ub_ctx_create();
        if(!ctx) {
            printf("error: could not create unbound context\n");
            retval = -1;
            goto finish;
        }

        //ub_ctx_debuglevel(ctx, 10);

        //requesting ip address from signpost


        /*  read /etc/resolv.conf for DNS proxy settings (from DHCP) */
        if( (retval=ub_ctx_resolvconf(ctx, "/etc/resolv.conf")) != 0) {
            fprintf(stderr, "error reading resolv.conf: %s. errno says: %s\n", 
                    ub_strerror(retval), strerror(errno));
            //retval = errno;
            //goto finish;
        }

        /*  read /etc/hosts for locally supplied host addresses */
        if( (retval=ub_ctx_hosts(ctx, "/etc/hosts")) != 0) {
            fprintf(stderr, "error reading hosts: %s. errno says: %s\n", 
                    ub_strerror(retval), strerror(errno));
            //retval = errno;
            //goto finish;
        }
        /*  query for webserver */
        retval = ub_resolve(ctx, name, 
                1 /*  TYPE A (IPv4 address) */, 
                1 /*  CLASS IN (internet) */, &result);
        if(retval != 0) {
            fprintf(stderr, "error resolving: %s. errno says: %s\n", 
                    ub_strerror(retval), strerror(errno));
            retval = -ENOENT;
            goto finish;
        }

        if(!result->havedata) {
           //fprintf(stderr, "no response found\n"); 
            retval = -ENOENT;
            goto finish;
        }


        while(result->data[n_list]) {
            list = realloc(list, (n_list+1) * sizeof(struct address));
            if (!list) {
                retval = -ENOMEM;
                goto finish;
            }
                 struct in_addr in;
            in.s_addr = *(uint32_t *)result->data[n_list];
            fprintf(stderr, "found ip %s\n", inet_ntoa(in));
            list[n_list].family = AF_INET;
            list[n_list].scope = 1; //ifaddrmsg->ifa_scope;
            memcpy(list[n_list].address, result->data[n_list], 4);
            list[n_list].ifindex = 1; //ifaddrmsg->ifa_index;

            n_list++;
        }
        r= n_list;
        goto finish;
finish:
        close(fd);

        ub_resolve_free(result);
        ub_ctx_delete(ctx);

        if (r < 0)
            free(list);
        else {
            qsort(list, n_list, sizeof(struct address), address_compare);

            *_list = list;
            *_n_list = n_list;
        }
        //fprintf(stderr, "returned %d addr\n", n_list);

        return r;
}
Пример #14
0
static int mod_instantiate(void *instance, CONF_SECTION *conf)
{
	rlm_unbound_t *inst = instance;
	int res;
	char *optval;

	fr_log_dst_t log_dst;
	int log_level;
	int log_fd = -1;

	char k[64]; /* To silence const warns until newer unbound in distros */

	/*
	 *	@todo - move this to the thread-instantiate function
	 */
	inst->el = fr_global_event_list();
	inst->log_pipe_stream[0] = NULL;
	inst->log_pipe_stream[1] = NULL;
	inst->log_fd = -1;
	inst->log_pipe_in_use = false;

	inst->ub = ub_ctx_create();
	if (!inst->ub) {
		cf_log_err(conf, "ub_ctx_create failed");
		return -1;
	}

	/*
	 *	Note unbound threads WILL happen with -s option, if it matters.
	 *	We cannot tell from here whether that option is in effect.
	 */
	res = ub_ctx_async(inst->ub, 1);

	if (res) goto error;

	/*	Glean some default settings to match the main server.	*/
	/*	TODO: debug_level can be changed at runtime. */
	/*	TODO: log until fork when stdout or stderr and !rad_debug_lvl. */
	log_level = 0;

	if (rad_debug_lvl > 0) {
		log_level = rad_debug_lvl;

	} else if (main_config->debug_level > 0) {
		log_level = main_config->debug_level;
	}

	switch (log_level) {
	/* TODO: This will need some tweaking */
	case 0:
	case 1:
		break;

	case 2:
		log_level = 1;
		break;

	case 3:
	case 4:
		log_level = 2; /* mid-to-heavy levels of output */
		break;

	case 5:
	case 6:
	case 7:
	case 8:
		log_level = 3; /* Pretty crazy amounts of output */
		break;

	default:
		log_level = 4; /* Insane amounts of output including crypts */
		break;
	}

	res = ub_ctx_debuglevel(inst->ub, log_level);
	if (res) goto error;

	switch (default_log.dst) {
	case L_DST_STDOUT:
		if (!rad_debug_lvl) {
			log_dst = L_DST_NULL;
			break;
		}
		log_dst = L_DST_STDOUT;
		log_fd = dup(STDOUT_FILENO);
		break;

	case L_DST_STDERR:
		if (!rad_debug_lvl) {
			log_dst = L_DST_NULL;
			break;
		}
		log_dst = L_DST_STDOUT;
		log_fd = dup(STDERR_FILENO);
		break;

	case L_DST_FILES:
		if (main_config->log_file) {
			char *log_file;

			strcpy(k, "logfile:");
			/* 3rd argument isn't const'd in libunbounds API */
			memcpy(&log_file, &main_config->log_file, sizeof(log_file));
			res = ub_ctx_set_option(inst->ub, k, log_file);
			if (res) {
				goto error;
			}
			log_dst = L_DST_FILES;
			break;
		}
		/* FALL-THROUGH */

	case L_DST_NULL:
		log_dst = L_DST_NULL;
		break;

	default:
		log_dst = L_DST_SYSLOG;
		break;
	}

	/* Now load the config file, which can override gleaned settings. */
	{
		char *file;

		memcpy(&file, &inst->filename, sizeof(file));
		res = ub_ctx_config(inst->ub, file);
		if (res) goto error;
	}

	/*
	 *	Check if the config file tried to use syslog.  Unbound
	 *	does not share syslog gracefully.
	 */
	strcpy(k, "use-syslog");
	res = ub_ctx_get_option(inst->ub, k, &optval);
	if (res || !optval) goto error;

	if (!strcmp(optval, "yes")) {
		char v[3];

		free(optval);

		WARN("Overriding syslog settings");
		strcpy(k, "use-syslog:");
		strcpy(v, "no");
		res = ub_ctx_set_option(inst->ub, k, v);
		if (res) goto error;

		if (log_dst == L_DST_FILES) {
			char *log_file;

			/* Reinstate the log file name JIC */
			strcpy(k, "logfile:");
			/* 3rd argument isn't const'd in libunbounds API */
			memcpy(&log_file, &main_config->log_file, sizeof(log_file));
			res = ub_ctx_set_option(inst->ub, k, log_file);
			if (res) goto error;
		}

	} else {
		if (optval) free(optval);
		strcpy(k, "logfile");

		res = ub_ctx_get_option(inst->ub, k, &optval);
		if (res) goto error;

		if (optval && strlen(optval)) {
			log_dst = L_DST_FILES;

			/*
			 *	We open log_fd early in the process,
			 *	so that libunbound doesn't close
			 *	stdout / stderr on us (grrr, stupid
			 *	software).  But if the config say to
			 *	use files, we now have to close the
			 *	dup'd FD.
			 */
			if (log_fd >= 0) {
				close(log_fd);
				log_fd = -1;
			}

		} else if (!rad_debug_lvl) {
			log_dst = L_DST_NULL;
		}

		if (optval) free(optval);
	}

	switch (log_dst) {
	case L_DST_STDOUT:
		/*
		 * We have an fd to log to.  And we've already attempted to
		 * dup it so libunbound doesn't close it on us.
		 */
		if (log_fd == -1) {
			cf_log_err(conf, "Could not dup fd");
			goto error_nores;
		}

		inst->log_stream = fdopen(log_fd, "w");
		if (!inst->log_stream) {
			cf_log_err(conf, "error setting up log stream");
			goto error_nores;
		}

		res = ub_ctx_debugout(inst->ub, inst->log_stream);
		if (res) goto error;
		break;

	case L_DST_FILES:
		/* We gave libunbound a filename.  It is on its own now. */
		break;

	case L_DST_NULL:
		/* We tell libunbound not to log at all. */
		res = ub_ctx_debugout(inst->ub, NULL);
		if (res) goto error;
		break;

	case L_DST_SYSLOG:
		/*
		 *  Currently this wreaks havoc when running threaded, so just
		 *  turn logging off until that gets figured out.
		 */
		res = ub_ctx_debugout(inst->ub, NULL);
		if (res) goto error;
		break;

	default:
		break;
	}

	/*
	 *  Now we need to finalize the context.
	 *
	 *  There's no clean API to just finalize the context made public
	 *  in libunbound.  But we can trick it by trying to delete data
	 *  which as it happens fails quickly and quietly even though the
	 *  data did not exist.
	 */
	strcpy(k, "notar33lsite.foo123.nottld A 127.0.0.1");
	ub_ctx_data_remove(inst->ub, k);

	inst->log_fd = ub_fd(inst->ub);
	if (inst->log_fd >= 0) {
		if (fr_event_fd_insert(inst, inst->el, inst->log_fd,
				       ub_fd_handler,
				       NULL,
				       NULL,
				       inst) < 0) {
			cf_log_err(conf, "could not insert async fd");
			inst->log_fd = -1;
			goto error_nores;
		}

	}

	return 0;

 error:
	cf_log_err(conf, "%s", ub_strerror(res));

 error_nores:
	if (log_fd > -1) close(log_fd);

	return -1;
}
Пример #15
0
int main(int argc, char **argv)
{
	struct ub_ctx* ctx;
	struct ub_result* result;
	int retval;
        int i;
        struct timeval starttime, endtime;

        int number = 100000;
        if (argc > 1) {
            number = atoi(argv[1]);
        }

	/* create context */
	ctx = ub_ctx_create();
	if(!ctx) {
		printf("error: could not create unbound context\n");
		return 1;
	}

	/* read /etc/resolv.conf for DNS proxy settings (from DHCP) */
	if( (retval=ub_ctx_resolvconf(ctx, "resolv.conf")) != 0) {
		printf("error reading resolv.conf: %s. errno says: %s\n", 
			ub_strerror(retval), strerror(errno));
		return 1;
	}

	/* read /etc/hosts for locally supplied host addresses */
	if( (retval=ub_ctx_hosts(ctx, "hosts")) != 0) {
		printf("error reading hosts: %s. errno says: %s\n", 
			ub_strerror(retval), strerror(errno));
		return 1;
	}

	/* read public keys for DNSSEC verification */
	if( (retval=ub_ctx_add_ta_file(ctx, "keys")) != 0) {
		printf("error adding keys: %s\n", ub_strerror(retval));
		return 1;
	}

	/* query for webserver */
	retval = ub_resolve(ctx, LOOKUP_NAME, 1, 1, &result);
	if(retval != 0) {
		printf("resolve error: %s\n", ub_strerror(retval));
		return 1;
	}

	/* show first result */
	if(result->havedata)
		printf("The address is %s\n", 
			inet_ntoa(*(struct in_addr*)result->data[0]));
	/* show security status */
	if(!result->secure) {
            fprintf(stderr, "something very wrong; not validated response returned\n");
            exit(1);
        }
        fprintf(stderr, "validated response returned\n");

        // Note: this is without proper memory freeing
        fprintf(stderr, "starting %d queries without context....\n", number);
        gettimeofday(&starttime, NULL);
        for (i = 0; i < number; i++) {
            retval = ub_resolve(ctx, LOOKUP_NAME, 1, 1, &result);
        }
        gettimeofday(&endtime, NULL);
        fprintf(stderr, "time elapsed (ms) for %d queries: %d\n", number, timeofday_diff(&starttime, &endtime));

	ub_resolve_free(result);
	ub_ctx_delete(ctx);

	return 0;
}
Пример #16
0
int dane_verify_cb(int ok, X509_STORE_CTX *store) {
	struct ub_result *dns_result;
	struct ub_ctx* ctx;
	char dns_name[256];
	X509 *cert;
	SSL *con;
	typedef struct {
		int verbose_mode;
		int verify_depth;
		int always_continue;
	} mydata_t;
	int mydata_index;
	mydata_t *mydata;
	int retval, err, depth;
	
	if (b_err == NULL)
		b_err=BIO_new_fp(stderr,BIO_NOCLOSE);
	
	cert = X509_STORE_CTX_get_current_cert(store);
	err = X509_STORE_CTX_get_error(store);
	depth = X509_STORE_CTX_get_error_depth(ctx);
	
	int ssl_idx = SSL_get_ex_data_X509_STORE_CTX_idx();
	if (ssl_idx < 0) {
		BIO_printf(b_err, "DANE failed to find SSL index: %d\n", ssl_idx);
		return -1;
	}
	con = X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx());
	mydata = SSL_get_ex_data(con, mydata_index);
	
	int peerfd;
	peerfd = SSL_get_fd(con);
	socklen_t len;
	struct sockaddr_storage addr;
	char ipstr[INET6_ADDRSTRLEN];
	char node[NI_MAXHOST];
	int port;

	len = sizeof addr;
	getpeername(peerfd, (struct sockaddr*)&addr, &len);

	// deal with both IPv4 and IPv6:
	if (addr.ss_family == AF_INET) {
	    struct sockaddr_in *s = (struct sockaddr_in *)&addr;
	    port = ntohs(s->sin_port);
	    inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
		struct sockaddr_in sa;
		sa.sin_family = AF_INET;
		inet_pton(AF_INET, ipstr, &sa.sin_addr);
		int res = getnameinfo((struct sockaddr*)&sa, sizeof(sa), node, sizeof(node), NULL, 0, 0);
	} else { // AF_INET6
		struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
	    port = ntohs(s->sin6_port);
	    inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
	}

	BIO_printf(b_err, "Peer IP address: %s\n", ipstr);
	BIO_printf(b_err, "Peer port      : %d\n", port);
	BIO_printf(b_err, "Peer hostname  : %s\n", node);
		
	ctx = ub_ctx_create();
	if(!ctx) {
		printf("error: could not create unbound context\n");
		return -1;
	}
	if( (retval=ub_ctx_resolvconf(ctx, "/etc/resolv.conf")) != 0) {
		printf("error reading resolv.conf: %s. errno says: %s\n", 
			ub_strerror(retval), strerror(errno));
		return -1;
	}
	if( (retval=ub_ctx_hosts(ctx, "/etc/hosts")) != 0) {
		printf("error reading hosts: %s. errno says: %s\n", 
			ub_strerror(retval), strerror(errno));
		return -1;
	}
	
	retval = sprintf(dns_name, "_%d._tcp.%s", port, node);
	if(retval < 0) {
		printf("failure to create dns name\n");
		return -1;
	}
	BIO_printf(b_err,"DANE dane_verify_cb() dns name: %s\n", dns_name);
	retval = ub_resolve(ctx, dns_name, 65534, 1, &dns_result);
	if(retval != 0) {
		BIO_printf(b_err, "resolve error: %s\n", ub_strerror(retval));
		return -1;
	}
	
	if(dns_result->havedata) {
		int i;
		for (i = 0; dns_result->data[i] != NULL; i++) {
			unsigned char usage, selector, matching_type;
			unsigned char *tlsa_bytes;
			
			if (dns_result->len[i] < 35) {
				// must have at least 1+1+1+32 bytes for the SHA-256 case
				BIO_printf(b_err, "DANE: Not enough data: %d available\n",
					dns_result->len[i]);
				return -1;
			}
			unsigned char *rdata = (unsigned char *)dns_result->data[i];
			usage = (char) *rdata++;
			selector = (char) *rdata++;
			matching_type = (char) *rdata++;
			tlsa_bytes = (unsigned char *) rdata;
			X509 *tlsa_cert;
			tlsa_cert = d2i_X509(NULL, &tlsa_bytes, dns_result->len[i]-3);
			
			BIO_printf(b_err, "DANE: Usage %d Selector %d Matching Type %d\n",
				usage, selector, matching_type);
			
			if (selector != 0)
				continue;
			if (matching_type != 0)
				continue;
			
			if (usage == 0 || usage == 2) {
				int retval;
				retval = ca_constraint(con, tlsa_cert, usage);
				if (retval == 0)
					BIO_printf(b_err, "DANE dane_verify_cb() Passed validation for usage %d\n", usage);
				else
					BIO_printf(b_err, "DANE dane_verify_cb() Failed validation for usage %d\n", usage);
				return retval;
			}
			if (usage == 1) {
				int retval;
				retval = service_cert_constraint(cert, tlsa_cert);
				if (retval == 0)
					BIO_printf(b_err, "DANE dane_verify_cb() Passed validation for usage %d\n", usage);
				else
					BIO_printf(b_err, "DANE dane_verify_cb() Failed validation for usage %d\n", usage);
				return retval;
			}
		}
	}
	return ok;
}