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