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; }
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++)); } }
static void unbound_ctx_config(bool do_dnssec, const char *rootfile, const char *trusted) { int ugh; if (DBGP(DBG_DNS)) { ub_ctx_debuglevel(dns_ctx, 5); DBG_log("unbound context created - setting debug level to 5"); }; /* lookup from /etc/hosts before DNS lookups as people expect that */ ugh = ub_ctx_hosts(dns_ctx, "/etc/hosts"); if (ugh != 0) { loglog(RC_LOG_SERIOUS, "error reading hosts: %s: %s", ub_strerror(ugh), strerror(errno)); } else { DBG(DBG_DNS, DBG_log("/etc/hosts lookups activated")); } /* * Use /etc/resolv.conf as forwarding cache - we expect people * to reconfigure this file if they need to work around DHCP DNS * obtained servers. */ /* * ??? ub_ctx_resolvconf is not currently documented to set errno. * Private communications with W.C.A. Wijngaards 2017 October: * "Is errno is meaningful after a failed call to libunbound?" * "Yes it is. Specifically for the error-to-read-file case. * Not other cases (eg. socket errors happen too far away in the code)." */ errno = 0; ugh = ub_ctx_resolvconf(dns_ctx, "/etc/resolv.conf"); if (ugh != 0) { int e = errno; /* protect value from ub_strerror */ loglog(RC_LOG_SERIOUS, "error reading /etc/resolv.conf: %s: [errno: %s]", ub_strerror(ugh), strerror(e)); } else { DBG(DBG_DNS, DBG_log("/etc/resolv.conf usage activated")); } if (!do_dnssec) { /* No DNSSEC - nothing more to configure */ DBG(DBG_DNS, DBG_log("dnssec validation disabled by configuration")); } if (rootfile == NULL) { if (trusted != NULL) { loglog(RC_LOG_SERIOUS, "dnssec-enable=yes but no dnssec-rootkey-file or trust anchors specified."); loglog(RC_LOG_SERIOUS, "WARNING: DNSSEC validation disabled"); } } else { DBG(DBG_DNS, DBG_log("Loading dnssec root key from:%s", rootfile)); /* the cast is there for unbound < 1.4.12 */ /* ??? ub_ctx_add_ta_autr is not documented to set errno */ errno = 0; ugh = ub_ctx_add_ta_autr(dns_ctx, (char *) rootfile); if (ugh != 0) { int e = errno; /* protect value from ub_strerror */ loglog(RC_LOG_SERIOUS, "error adding dnssec root key: %s [errno: %s]", ub_strerror(ugh), strerror(e)); loglog(RC_LOG_SERIOUS, "WARNING: DNSSEC validation likely broken!"); } } if (trusted == NULL) { DBG(DBG_DNS,DBG_log("No additional dnssec trust anchors defined via dnssec-trusted= option")); } else { glob_t globbuf; char **fnp; int r = glob(trusted, GLOB_ERR, globugh_ta, &globbuf); switch (r) { case 0: /* success */ for (fnp = globbuf.gl_pathv; fnp != NULL && *fnp != NULL; fnp++) { ugh = ub_ctx_add_ta_file(dns_ctx, *fnp); if (ugh != 0) { loglog(RC_LOG_SERIOUS, "Ignored trusted key file %s: %s", *fnp, ub_strerror(ugh)); } else { DBG(DBG_DNS, DBG_log("Added contents of trusted key file %s to unbound resolver context", *fnp)); } } break; case GLOB_NOSPACE: loglog(RC_LOG_SERIOUS, "out of space processing dnssec-trusted= argument: %s", trusted); break; case GLOB_ABORTED: /* already logged by globugh_ta */ break; case GLOB_NOMATCH: loglog(RC_LOG_SERIOUS, "no trust anchor files matched '%s'", trusted); break; default: loglog(RC_LOG_SERIOUS, "trusted key file '%s': unknown glob error %d", trusted, r); break; } globfree(&globbuf); } }
int ub_ctx_hosts(struct ub_ctx* ctx, char* fname) { FILE* in; char buf[1024], ldata[1024]; char* parse, *addr, *name, *ins; lock_basic_lock(&ctx->cfglock); if(ctx->finalized) { lock_basic_unlock(&ctx->cfglock); errno=EINVAL; return UB_AFTERFINAL; } lock_basic_unlock(&ctx->cfglock); if(fname == NULL) { #if defined(UB_ON_WINDOWS) && defined(HAVE_WINDOWS_H) /* * If this is Windows NT/XP/2K it's in * %WINDIR%\system32\drivers\etc\hosts. * If this is Windows 95/98/Me it's in %WINDIR%\hosts. */ name = getenv("WINDIR"); if (name != NULL) { int retval=0; snprintf(buf, sizeof(buf), "%s%s", name, "\\system32\\drivers\\etc\\hosts"); if((retval=ub_ctx_hosts(ctx, buf)) !=0 ) { snprintf(buf, sizeof(buf), "%s%s", name, "\\hosts"); retval=ub_ctx_hosts(ctx, buf); } free(name); return retval; } return UB_READFILE; #else fname = "/etc/hosts"; #endif /* WIN32 */ } in = fopen(fname, "r"); if(!in) { /* error in errno! perror(fname) */ return UB_READFILE; } while(fgets(buf, (int)sizeof(buf), in)) { buf[sizeof(buf)-1] = 0; parse=buf; while(*parse == ' ' || *parse == '\t') parse++; if(*parse == '#') continue; /* skip comment */ /* format: <addr> spaces <name> spaces <name> ... */ addr = parse; /* skip addr */ while(isxdigit(*parse) || *parse == '.' || *parse == ':') parse++; if(*parse == '\n' || *parse == 0) continue; if(*parse == '%') continue; /* ignore macOSX fe80::1%lo0 localhost */ if(*parse != ' ' && *parse != '\t') { /* must have whitespace after address */ fclose(in); errno=EINVAL; return UB_SYNTAX; } *parse++ = 0; /* end delimiter for addr ... */ /* go to names and add them */ while(*parse) { while(*parse == ' ' || *parse == '\t' || *parse=='\n') parse++; if(*parse == 0 || *parse == '#') break; /* skip name, allows (too) many printable characters */ name = parse; while('!' <= *parse && *parse <= '~') parse++; if(*parse) *parse++ = 0; /* end delimiter for name */ snprintf(ldata, sizeof(ldata), "%s %s %s", name, str_is_ip6(addr)?"AAAA":"A", addr); ins = strdup(ldata); if(!ins) { /* out of memory */ fclose(in); errno=ENOMEM; return UB_NOMEM; } lock_basic_lock(&ctx->cfglock); if(!cfg_strlist_insert(&ctx->env->cfg->local_data, ins)) { lock_basic_unlock(&ctx->cfglock); fclose(in); free(ins); errno=ENOMEM; return UB_NOMEM; } lock_basic_unlock(&ctx->cfglock); } } fclose(in); return UB_NOERROR; }
/** 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; }
{ 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"); ); /* lookup from /etc/hosts before DNS lookups as people expect that */ ugh = ub_ctx_hosts(dnsctx, "/etc/hosts"); if (ugh != 0) { libreswan_log("error reading hosts: %s: %s", ub_strerror(ugh), strerror(errno)); return FALSE; } DBG(DBG_DNS, DBG_log("/etc/hosts lookups activated"); ); /* * Use /etc/resolv.conf as forwarding cache - we expect people to * reconfigure this file if they need to work around DHCP DNS obtained * servers */ ugh = ub_ctx_resolvconf(dnsctx, "/etc/resolv.conf");
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; }