ldns_status ldns_resolver_new_default(ldns_resolver **res) { ldns_resolver *r; ldns_rdf *tmp; HKEY hKey; DWORD data_sz; char* buf; char* addr; RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 0, KEY_QUERY_VALUE, &hKey); RegQueryValueEx(hKey, "DhcpNameServer", NULL, NULL, NULL, &data_sz); buf = (char*)malloc(data_sz + 1); RegQueryValueEx(hKey, "DhcpNameServer", NULL, NULL, (LPBYTE)buf, &data_sz); RegCloseKey(hKey); if(buf[data_sz - 1] != 0) { buf[data_sz] = 0; } r = ldns_resolver_new(); if(!r) { free(buf); return LDNS_STATUS_MEM_ERR; } addr = strtok(buf, " "); while(addr != NULL) { tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, addr); if (!tmp) { // try ip4 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, addr); } // could not parse it, exit if (!tmp) { ldns_resolver_deep_free(r); free(buf); return LDNS_STATUS_SYNTAX_ERR; } (void)ldns_resolver_push_nameserver(r, tmp); ldns_rdf_deep_free(tmp); addr = strtok(NULL, " "); } free(buf); if(res) { *res = r; return LDNS_STATUS_OK; } else { return LDNS_STATUS_NULL; } }
ldns_resolver* createResolver(const char *dnsserver) { ldns_resolver *res = NULL; ldns_status status; ldns_rdf *ns_rdf; if (dnsserver) { // Use the given DNS server res = ldns_resolver_new(); if (!res) return NULL; // Create rdf from dnsserver ns_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, dnsserver); #ifdef USE_IPV6 if (!ns_rdf) ns_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, dnsserver); #endif if (!ns_rdf) { ldns_resolver_deep_free(res); return NULL; } else { status = ldns_resolver_push_nameserver(res, ns_rdf); ldns_rdf_deep_free(ns_rdf); if (status != LDNS_STATUS_OK) { ldns_resolver_free(res); return NULL; } } } else { // Use a DNS server from resolv.conf status = ldns_resolver_new_frm_file(&res, NULL); if (status != LDNS_STATUS_OK) { ldns_resolver_free(res); return NULL; } } // Enable TCP if requested ldns_resolver_set_usevc(res, mp_ldns_usevc); return res; }
switch_status_t ldns_lookup(const char *number, const char *root, char *server_name[ENUM_MAXNAMESERVERS] , enum_record_t **results) { ldns_resolver *res = NULL; ldns_rdf *domain = NULL; ldns_pkt *p = NULL; ldns_rr_list *naptr = NULL; ldns_status s = LDNS_STATUS_ERR; ldns_rdf *serv_rdf; switch_status_t status = SWITCH_STATUS_FALSE; char *name = NULL; struct timeval to = { 0, 0}; int inameserver = 0; int added_server = 0; if (!(name = reverse_number(number, root))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Parse Error!\n"); goto end; } if (!(domain = ldns_dname_new_frm_str(name))) { goto end; } if (server_name) { res = ldns_resolver_new(); switch_assert(res); for(inameserver=0; inameserver<ENUM_MAXNAMESERVERS; inameserver++) { if ( server_name[inameserver] != NULL ) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding Nameserver [%s]\n", server_name[inameserver]); if ((serv_rdf = ldns_rdf_new_addr_frm_str( server_name[inameserver] ))) { s = ldns_resolver_push_nameserver(res, serv_rdf); ldns_rdf_deep_free(serv_rdf); added_server = 1; } } } } if (!added_server) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No Nameservers specified, using host default\n"); /* create a new resolver from /etc/resolv.conf */ s = ldns_resolver_new_frm_file(&res, NULL); } if (s != LDNS_STATUS_OK) { goto end; } to.tv_sec = globals.timeout / 1000; to.tv_usec = (globals.timeout % 1000) * 1000; ldns_resolver_set_timeout(res, to); ldns_resolver_set_retry(res, (uint8_t)globals.retries); ldns_resolver_set_random(res, globals.random); if ((p = ldns_resolver_query(res, domain, LDNS_RR_TYPE_NAPTR, LDNS_RR_CLASS_IN, LDNS_RD))) { /* retrieve the NAPTR records from the answer section of that * packet */ if ((naptr = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NAPTR, LDNS_SECTION_ANSWER))) { size_t i; ldns_rr_list_sort(naptr); for (i = 0; i < ldns_rr_list_rr_count(naptr); i++) { parse_naptr(ldns_rr_list_rr(naptr, i), number, results); } //ldns_rr_list_print(stdout, naptr); ldns_rr_list_deep_free(naptr); status = SWITCH_STATUS_SUCCESS; } } end: switch_safe_free(name); if (domain) { ldns_rdf_deep_free(domain); } if (p) { ldns_pkt_free(p); } if (res) { ldns_resolver_deep_free(res); } return status; }
int main(int argc, char *argv[]) { ldns_resolver *res; ldns_rdf *domain; ldns_pkt *p; ldns_rr_list *mx; ldns_status s; p = NULL; mx = NULL; domain = NULL; res = NULL; if (argc != 2) { usage(stdout, argv[0]); exit(EXIT_FAILURE); } else { /* create a rdf from the command line arg */ domain = ldns_dname_new_frm_str(argv[1]); if (!domain) { usage(stdout, argv[0]); exit(EXIT_FAILURE); } } /* create a new resolver from /etc/resolv.conf */ s = ldns_resolver_new_frm_file(&res, NULL); if (s != LDNS_STATUS_OK) { exit(EXIT_FAILURE); } /* use the resolver to send a query for the mx * records of the domain given on the command line */ std::clock_t start; start = std::clock(); p = ldns_resolver_query(res, domain, LDNS_RR_TYPE_MX, LDNS_RR_CLASS_IN, LDNS_RD); if(!p) std::cout << "no packet is generated" << std::endl; else{ std::clock_t current; current = std::clock(); double latency = (current-start)*1000.0/CLOCKS_PER_SEC; std::cout <<"Qurey sent to " << domain << ", latency is " << latency << " ms." <<std::endl; } ldns_rdf_deep_free(domain); //if (!p) { // exit(EXIT_FAILURE); //} else { // /* retrieve the MX records from the answer section of that // * packet // */ // mx = ldns_pkt_rr_list_by_type(p, // LDNS_RR_TYPE_MX, // LDNS_SECTION_ANSWER); // if (!mx) { // fprintf(stderr, // " *** invalid answer name %s after MX query for %s\n", // argv[1], argv[1]); // ldns_pkt_free(p); // ldns_resolver_deep_free(res); // exit(EXIT_FAILURE); // } else { // ldns_rr_list_sort(mx); // ldns_rr_list_print(stdout, mx); // ldns_rr_list_deep_free(mx); // } //} ldns_pkt_free(p); ldns_resolver_deep_free(res); return 0; }
ldns_status ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) { ldns_resolver *r; const char *keyword[LDNS_RESOLV_KEYWORDS]; char word[LDNS_MAX_LINELEN + 1]; int8_t expect; uint8_t i; ldns_rdf *tmp; #ifdef HAVE_SSL ldns_rr *tmp_rr; #endif ssize_t gtr; ldns_buffer *b; /* do this better * expect = * 0: keyword * 1: default domain dname * 2: NS aaaa or a record */ /* recognized keywords */ keyword[LDNS_RESOLV_NAMESERVER] = "nameserver"; keyword[LDNS_RESOLV_DEFDOMAIN] = "domain"; keyword[LDNS_RESOLV_SEARCH] = "search"; /* these two are read but not used atm TODO */ keyword[LDNS_RESOLV_SORTLIST] = "sortlist"; keyword[LDNS_RESOLV_OPTIONS] = "options"; keyword[LDNS_RESOLV_ANCHOR] = "anchor"; expect = LDNS_RESOLV_KEYWORD; r = ldns_resolver_new(); if (!r) { return LDNS_STATUS_MEM_ERR; } gtr = 1; word[0] = 0; while (gtr > 0) { /* check comments */ if (word[0] == '#') { /* read the rest of the line, should be 1 word */ gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); /* prepare the next string for further parsing */ gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); continue; } switch(expect) { case LDNS_RESOLV_KEYWORD: /* keyword */ gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); if (gtr != 0) { for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) { if (strcasecmp(keyword[i], word) == 0) { /* chosen the keyword and * expect values carefully */ expect = i; break; } } /* no keyword recognized */ if (expect == LDNS_RESOLV_KEYWORD) { /* skip line */ /* ldns_resolver_deep_free(r); return LDNS_STATUS_SYNTAX_KEYWORD_ERR; */ } } break; case LDNS_RESOLV_DEFDOMAIN: /* default domain dname */ gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); if (gtr == 0) { return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; } tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word); if (!tmp) { ldns_resolver_deep_free(r); return LDNS_STATUS_SYNTAX_DNAME_ERR; } /* DOn't free, because we copy the pointer */ ldns_resolver_set_domain(r, tmp); expect = LDNS_RESOLV_KEYWORD; break; case LDNS_RESOLV_NAMESERVER: /* NS aaaa or a record */ gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); if (gtr == 0) { return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; } tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word); if (!tmp) { /* try ip4 */ tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word); } /* could not parse it, exit */ if (!tmp) { ldns_resolver_deep_free(r); return LDNS_STATUS_SYNTAX_ERR; } (void)ldns_resolver_push_nameserver(r, tmp); ldns_rdf_deep_free(tmp); expect = LDNS_RESOLV_KEYWORD; break; case LDNS_RESOLV_SEARCH: /* search list domain dname */ gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); b = LDNS_MALLOC(ldns_buffer); ldns_buffer_new_frm_data(b, word, (size_t) gtr); gtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr); while (gtr > 0) { tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word); if (!tmp) { ldns_resolver_deep_free(r); return LDNS_STATUS_SYNTAX_DNAME_ERR; } ldns_resolver_push_searchlist(r, tmp); ldns_rdf_deep_free(tmp); gtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr); } ldns_buffer_free(b); gtr = 1; expect = LDNS_RESOLV_KEYWORD; break; case LDNS_RESOLV_SORTLIST: gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); /* sortlist not implemented atm */ expect = LDNS_RESOLV_KEYWORD; break; case LDNS_RESOLV_OPTIONS: gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); /* options not implemented atm */ expect = LDNS_RESOLV_KEYWORD; break; case LDNS_RESOLV_ANCHOR: /* a file containing a DNSSEC trust anchor */ gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); if (gtr == 0) { return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; } #ifdef HAVE_SSL tmp_rr = ldns_read_anchor_file(word); (void) ldns_resolver_push_dnssec_anchor(r, tmp_rr); ldns_rr_free(tmp_rr); #endif expect = LDNS_RESOLV_KEYWORD; break; } } if (res) { *res = r; return LDNS_STATUS_OK; } else { return LDNS_STATUS_NULL; } }
int main(int argc, char *argv[]) { ldns_resolver *res; ldns_rdf *name; ldns_rdf *version, *id; ldns_pkt *p; ldns_rr_list *addr; ldns_rr_list *info; ldns_status s; ldns_rdf *pop; size_t i; if (argc != 2) { usage(stdout, argv[0]); exit(EXIT_FAILURE); } else { /* create a rdf from the command line arg */ name = ldns_dname_new_frm_str(argv[1]); if (!name) { usage(stdout, argv[0]); exit(EXIT_FAILURE); } } /* create rdf for what we are going to ask */ version = ldns_dname_new_frm_str("version.bind"); id = ldns_dname_new_frm_str("hostname.bind"); /* create a new resolver from /etc/resolv.conf */ s = ldns_resolver_new_frm_file(&res, NULL); if (s != LDNS_STATUS_OK) { ldns_rdf_deep_free(name); exit(EXIT_FAILURE); } ldns_resolver_set_retry(res, 1); /* don't want to wait too long */ /* use the resolver to send it a query for the a/aaaa of name */ addr = ldns_get_rr_list_addr_by_name(res, name, LDNS_RR_CLASS_IN, LDNS_RD); if (!addr) { fprintf(stderr, " *** could not get an address for %s\n", argv[1]); ldns_rdf_deep_free(name); ldns_resolver_deep_free(res); exit(EXIT_FAILURE); } /* remove current list of nameservers from resolver */ while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); } /* can be multihomed */ for(i = 0; i < ldns_rr_list_rr_count(addr); i++) { if (i > 0) { fprintf(stdout, "\n"); } if (ldns_resolver_push_nameserver_rr(res, ldns_rr_list_rr(addr, i)) != LDNS_STATUS_OK) { printf("Error adding nameserver to resolver\n"); } ldns_rr_print(stdout, ldns_rr_list_rr(addr, i)); fprintf(stdout, "\n"); p = ldns_resolver_query(res, version, LDNS_RR_TYPE_TXT, LDNS_RR_CLASS_CH, LDNS_RD); if (p) { ldns_pkt_print(stdout, p); info = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_TXT, LDNS_SECTION_ANSWER); if (info) { ldns_rr_list_print(stdout, info); ldns_rr_list_deep_free(info); } else { printf(" *** version retrieval failed\n"); } ldns_pkt_free(p); } else { printf(" *** query failed\n"); } p = ldns_resolver_query(res, id, LDNS_RR_TYPE_TXT, LDNS_RR_CLASS_CH, LDNS_RD); if (p) { info = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_TXT, LDNS_SECTION_ANSWER); if (info) { ldns_rr_list_print(stdout, info); ldns_rr_list_deep_free(info); } else { printf(" *** id retrieval failed\n"); } ldns_pkt_free(p); } else { printf(" *** query failed for\n"); } ldns_rdf_deep_free(ldns_resolver_pop_nameserver(res)); } ldns_rdf_deep_free(name); ldns_resolver_deep_free(res); exit(EXIT_SUCCESS); }
/** * Main function of drill * parse the arguments and prepare a query */ int main(int argc, char *argv[]) { ldns_resolver *res = NULL; ldns_resolver *cmdline_res = NULL; /* only used to resolv @name names */ ldns_rr_list *cmdline_rr_list = NULL; ldns_rdf *cmdline_dname = NULL; ldns_rdf *qname, *qname_tmp; ldns_pkt *pkt; ldns_pkt *qpkt; char *serv; const char *name; char *name2; char *progname; char *query_file = NULL; char *answer_file = NULL; ldns_buffer *query_buffer = NULL; ldns_rdf *serv_rdf; ldns_rr_type type; ldns_rr_class clas; #if 0 ldns_pkt_opcode opcode = LDNS_PACKET_QUERY; #endif int i, c; int int_type; int int_clas; int PURPOSE; char *tsig_name = NULL; char *tsig_data = NULL; char *tsig_algorithm = NULL; size_t tsig_separator; size_t tsig_separator2; ldns_rr *axfr_rr; ldns_status status; char *type_str; /* list of keys used in dnssec operations */ ldns_rr_list *key_list = ldns_rr_list_new(); /* what key verify the current answer */ ldns_rr_list *key_verified; /* resolver options */ uint16_t qflags; uint16_t qbuf; uint16_t qport; uint8_t qfamily; bool qdnssec; bool qfallback; bool qds; bool qusevc; bool qrandom; char *resolv_conf_file = NULL; ldns_rdf *trace_start_name = NULL; int result = 0; #ifdef USE_WINSOCK int r; WSADATA wsa_data; #endif int_type = -1; serv = NULL; type = 0; int_clas = -1; name = NULL; clas = 0; qname = NULL; progname = strdup(argv[0]); #ifdef USE_WINSOCK r = WSAStartup(MAKEWORD(2,2), &wsa_data); if(r != 0) { printf("Failed WSAStartup: %d\n", r); result = EXIT_FAILURE; goto exit; } #endif /* USE_WINSOCK */ PURPOSE = DRILL_QUERY; qflags = LDNS_RD; qport = LDNS_PORT; verbosity = 2; qdnssec = false; qfamily = LDNS_RESOLV_INETANY; qfallback = false; qds = false; qbuf = 0; qusevc = false; qrandom = true; key_verified = NULL; ldns_init_random(NULL, 0); if (argc == 0) { usage(stdout, progname); result = EXIT_FAILURE; goto exit; } /* string from orig drill: "i:w:I46Sk:TNp:b:DsvhVcuaq:f:xr" */ /* global first, query opt next, option with parm's last * and sorted */ /* "46DITSVQf:i:w:q:achuvxzy:so:p:b:k:" */ while ((c = getopt(argc, argv, "46ab:c:d:Df:hi:Ik:o:p:q:Qr:sStTuvV:w:xy:z")) != -1) { switch(c) { /* global options */ case '4': qfamily = LDNS_RESOLV_INET; break; case '6': qfamily = LDNS_RESOLV_INET6; break; case 'D': qdnssec = true; break; case 'I': /* reserved for backward compatibility */ break; case 'T': if (PURPOSE == DRILL_CHASE) { fprintf(stderr, "-T and -S cannot be used at the same time.\n"); exit(EXIT_FAILURE); } PURPOSE = DRILL_TRACE; break; #ifdef HAVE_SSL case 'S': if (PURPOSE == DRILL_TRACE) { fprintf(stderr, "-T and -S cannot be used at the same time.\n"); exit(EXIT_FAILURE); } PURPOSE = DRILL_CHASE; break; #endif /* HAVE_SSL */ case 'V': if (strtok(optarg, "0123456789") != NULL) { fprintf(stderr, "-V expects an number as an argument.\n"); exit(EXIT_FAILURE); } verbosity = atoi(optarg); break; case 'Q': verbosity = -1; break; case 'f': query_file = optarg; break; case 'i': answer_file = optarg; PURPOSE = DRILL_AFROMFILE; break; case 'w': answer_file = optarg; break; case 'q': query_file = optarg; PURPOSE = DRILL_QTOFILE; break; case 'r': if (global_dns_root) { fprintf(stderr, "There was already a series of root servers set\n"); exit(EXIT_FAILURE); } global_dns_root = read_root_hints(optarg); if (!global_dns_root) { fprintf(stderr, "Unable to read root hints file %s, aborting\n", optarg); exit(EXIT_FAILURE); } break; /* query options */ case 'a': qfallback = true; break; case 'b': qbuf = (uint16_t)atoi(optarg); if (qbuf == 0) { error("%s", "<bufsize> could not be converted"); } break; case 'c': resolv_conf_file = optarg; break; case 't': qusevc = true; break; case 'k': status = read_key_file(optarg, key_list, false); if (status != LDNS_STATUS_OK) { error("Could not parse the key file %s: %s", optarg, ldns_get_errorstr_by_id(status)); } qdnssec = true; /* enable that too */ break; case 'o': /* only looks at the first hit: capital=ON, lowercase=OFF*/ if (strstr(optarg, "QR")) { DRILL_ON(qflags, LDNS_QR); } if (strstr(optarg, "qr")) { DRILL_OFF(qflags, LDNS_QR); } if (strstr(optarg, "AA")) { DRILL_ON(qflags, LDNS_AA); } if (strstr(optarg, "aa")) { DRILL_OFF(qflags, LDNS_AA); } if (strstr(optarg, "TC")) { DRILL_ON(qflags, LDNS_TC); } if (strstr(optarg, "tc")) { DRILL_OFF(qflags, LDNS_TC); } if (strstr(optarg, "RD")) { DRILL_ON(qflags, LDNS_RD); } if (strstr(optarg, "rd")) { DRILL_OFF(qflags, LDNS_RD); } if (strstr(optarg, "CD")) { DRILL_ON(qflags, LDNS_CD); } if (strstr(optarg, "cd")) { DRILL_OFF(qflags, LDNS_CD); } if (strstr(optarg, "RA")) { DRILL_ON(qflags, LDNS_RA); } if (strstr(optarg, "ra")) { DRILL_OFF(qflags, LDNS_RA); } if (strstr(optarg, "AD")) { DRILL_ON(qflags, LDNS_AD); } if (strstr(optarg, "ad")) { DRILL_OFF(qflags, LDNS_AD); } break; case 'p': qport = (uint16_t)atoi(optarg); if (qport == 0) { error("%s", "<port> could not be converted"); } break; case 's': qds = true; break; case 'u': qusevc = false; break; case 'v': version(stdout, progname); result = EXIT_SUCCESS; goto exit; case 'x': PURPOSE = DRILL_REVERSE; break; case 'y': #ifdef HAVE_SSL if (strchr(optarg, ':')) { tsig_separator = (size_t) (strchr(optarg, ':') - optarg); if (strchr(optarg + tsig_separator + 1, ':')) { tsig_separator2 = (size_t) (strchr(optarg + tsig_separator + 1, ':') - optarg); tsig_algorithm = xmalloc(strlen(optarg) - tsig_separator2); strncpy(tsig_algorithm, optarg + tsig_separator2 + 1, strlen(optarg) - tsig_separator2); tsig_algorithm[strlen(optarg) - tsig_separator2 - 1] = '\0'; } else { tsig_separator2 = strlen(optarg); tsig_algorithm = xmalloc(26); strncpy(tsig_algorithm, "hmac-md5.sig-alg.reg.int.", 25); tsig_algorithm[25] = '\0'; } tsig_name = xmalloc(tsig_separator + 1); tsig_data = xmalloc(tsig_separator2 - tsig_separator); strncpy(tsig_name, optarg, tsig_separator); strncpy(tsig_data, optarg + tsig_separator + 1, tsig_separator2 - tsig_separator - 1); /* strncpy does not append \0 if source is longer than n */ tsig_name[tsig_separator] = '\0'; tsig_data[ tsig_separator2 - tsig_separator - 1] = '\0'; } #else fprintf(stderr, "TSIG requested, but SSL is not supported\n"); result = EXIT_FAILURE; goto exit; #endif /* HAVE_SSL */ break; case 'z': qrandom = false; break; case 'd': trace_start_name = ldns_dname_new_frm_str(optarg); if (!trace_start_name) { fprintf(stderr, "Unable to parse argument for -%c\n", c); result = EXIT_FAILURE; goto exit; } break; case 'h': version(stdout, progname); usage(stdout, progname); result = EXIT_SUCCESS; goto exit; break; default: fprintf(stderr, "Unknown argument: -%c, use -h to see usage\n", c); result = EXIT_FAILURE; goto exit; } } argc -= optind; argv += optind; if ((PURPOSE == DRILL_CHASE || (PURPOSE == DRILL_TRACE && qdnssec)) && ldns_rr_list_rr_count(key_list) == 0) { (void) read_key_file(LDNS_TRUST_ANCHOR_FILE, key_list, true); } if (ldns_rr_list_rr_count(key_list) > 0) { printf(";; Number of trusted keys: %d\n", (int) ldns_rr_list_rr_count(key_list)); } /* do a secure trace when requested */ if (PURPOSE == DRILL_TRACE && qdnssec) { #ifdef HAVE_SSL if (ldns_rr_list_rr_count(key_list) == 0) { warning("%s", "No trusted keys were given. Will not be able to verify authenticity!"); } PURPOSE = DRILL_SECTRACE; #else fprintf(stderr, "ldns has not been compiled with OpenSSL support. Secure trace not available\n"); exit(1); #endif /* HAVE_SSL */ } /* parse the arguments, with multiple arguments, the last argument * found is used */ for(i = 0; i < argc; i++) { /* if ^@ then it's a server */ if (argv[i][0] == '@') { if (strlen(argv[i]) == 1) { warning("%s", "No nameserver given"); exit(EXIT_FAILURE); } serv = argv[i] + 1; continue; } /* if has a dot, it's a name */ if (strchr(argv[i], '.')) { name = argv[i]; continue; } /* if it matches a type, it's a type */ if (int_type == -1) { type = ldns_get_rr_type_by_name(argv[i]); if (type != 0) { int_type = 0; continue; } } /* if it matches a class, it's a class */ if (int_clas == -1) { clas = ldns_get_rr_class_by_name(argv[i]); if (clas != 0) { int_clas = 0; continue; } } /* it all fails assume it's a name */ name = argv[i]; } /* act like dig and use for . NS */ if (!name) { name = "."; int_type = 0; type = LDNS_RR_TYPE_NS; } /* defaults if not given */ if (int_clas == -1) { clas = LDNS_RR_CLASS_IN; } if (int_type == -1) { if (PURPOSE != DRILL_REVERSE) { type = LDNS_RR_TYPE_A; } else { type = LDNS_RR_TYPE_PTR; } } /* set the nameserver to use */ if (!serv) { /* no server given make a resolver from /etc/resolv.conf */ status = ldns_resolver_new_frm_file(&res, resolv_conf_file); if (status != LDNS_STATUS_OK) { warning("Could not create a resolver structure: %s (%s)\n" "Try drill @localhost if you have a resolver running on your machine.", ldns_get_errorstr_by_id(status), resolv_conf_file); result = EXIT_FAILURE; goto exit; } } else { res = ldns_resolver_new(); if (!res || strlen(serv) <= 0) { warning("Could not create a resolver structure"); result = EXIT_FAILURE; goto exit; } /* add the nameserver */ serv_rdf = ldns_rdf_new_addr_frm_str(serv); if (!serv_rdf) { /* try to resolv the name if possible */ status = ldns_resolver_new_frm_file(&cmdline_res, resolv_conf_file); if (status != LDNS_STATUS_OK) { error("%s", "@server ip could not be converted"); } ldns_resolver_set_dnssec(cmdline_res, qdnssec); ldns_resolver_set_ip6(cmdline_res, qfamily); ldns_resolver_set_fallback(cmdline_res, qfallback); ldns_resolver_set_usevc(cmdline_res, qusevc); cmdline_dname = ldns_dname_new_frm_str(serv); cmdline_rr_list = ldns_get_rr_list_addr_by_name( cmdline_res, cmdline_dname, LDNS_RR_CLASS_IN, qflags); ldns_rdf_deep_free(cmdline_dname); if (!cmdline_rr_list) { /* This error msg is not always accurate */ error("%s `%s\'", "could not find any address for the name:", serv); } else { if (ldns_resolver_push_nameserver_rr_list( res, cmdline_rr_list ) != LDNS_STATUS_OK) { error("%s", "pushing nameserver"); } } } else { if (ldns_resolver_push_nameserver(res, serv_rdf) != LDNS_STATUS_OK) { error("%s", "pushing nameserver"); } else { ldns_rdf_deep_free(serv_rdf); } } } /* set the resolver options */ ldns_resolver_set_port(res, qport); if (verbosity >= 5) { ldns_resolver_set_debug(res, true); } else { ldns_resolver_set_debug(res, false); } ldns_resolver_set_dnssec(res, qdnssec); /* ldns_resolver_set_dnssec_cd(res, qdnssec);*/ ldns_resolver_set_ip6(res, qfamily); ldns_resolver_set_fallback(res, qfallback); ldns_resolver_set_usevc(res, qusevc); ldns_resolver_set_random(res, qrandom); if (qbuf != 0) { ldns_resolver_set_edns_udp_size(res, qbuf); } if (!name && PURPOSE != DRILL_AFROMFILE && !query_file ) { usage(stdout, progname); result = EXIT_FAILURE; goto exit; } if (tsig_name && tsig_data) { ldns_resolver_set_tsig_keyname(res, tsig_name); ldns_resolver_set_tsig_keydata(res, tsig_data); ldns_resolver_set_tsig_algorithm(res, tsig_algorithm); } /* main switching part of drill */ switch(PURPOSE) { case DRILL_TRACE: /* do a trace from the root down */ if (!global_dns_root) { init_root(); } qname = ldns_dname_new_frm_str(name); if (!qname) { error("%s", "parsing query name"); } /* don't care about return packet */ (void)do_trace(res, qname, type, clas); clear_root(); break; case DRILL_SECTRACE: /* do a secure trace from the root down */ if (!global_dns_root) { init_root(); } qname = ldns_dname_new_frm_str(name); if (!qname) { error("%s", "making qname"); } /* don't care about return packet */ #ifdef HAVE_SSL result = do_secure_trace(res, qname, type, clas, key_list, trace_start_name); #endif /* HAVE_SSL */ clear_root(); break; case DRILL_CHASE: qname = ldns_dname_new_frm_str(name); if (!qname) { error("%s", "making qname"); } ldns_resolver_set_dnssec(res, true); ldns_resolver_set_dnssec_cd(res, true); /* set dnssec implies udp_size of 4096 */ ldns_resolver_set_edns_udp_size(res, 4096); pkt = ldns_resolver_query(res, qname, type, clas, qflags); if (!pkt) { error("%s", "error pkt sending"); result = EXIT_FAILURE; } else { if (verbosity >= 3) { ldns_pkt_print(stdout, pkt); } if (!ldns_pkt_answer(pkt)) { mesg("No answer in packet"); } else { #ifdef HAVE_SSL ldns_resolver_set_dnssec_anchors(res, ldns_rr_list_clone(key_list)); result = do_chase(res, qname, type, clas, key_list, pkt, qflags, NULL, verbosity); if (result == LDNS_STATUS_OK) { if (verbosity != -1) { mesg("Chase successful"); } result = 0; } else { if (verbosity != -1) { mesg("Chase failed."); } } #endif /* HAVE_SSL */ } ldns_pkt_free(pkt); } break; case DRILL_AFROMFILE: pkt = read_hex_pkt(answer_file); if (pkt) { if (verbosity != -1) { ldns_pkt_print(stdout, pkt); } ldns_pkt_free(pkt); } break; case DRILL_QTOFILE: qname = ldns_dname_new_frm_str(name); if (!qname) { error("%s", "making qname"); } status = ldns_resolver_prepare_query_pkt(&qpkt, res, qname, type, clas, qflags); if(status != LDNS_STATUS_OK) { error("%s", "making query: %s", ldns_get_errorstr_by_id(status)); } dump_hex(qpkt, query_file); ldns_pkt_free(qpkt); break; case DRILL_NSEC: break; case DRILL_REVERSE: /* ipv4 or ipv6 addr? */ if (strchr(name, ':')) { if (strchr(name, '.')) { error("Syntax error: both '.' and ':' seen in address\n"); } name2 = malloc(IP6_ARPA_MAX_LEN + 20); c = 0; for (i=0; i<(int)strlen(name); i++) { if (i >= IP6_ARPA_MAX_LEN) { error("%s", "reverse argument to long"); } if (name[i] == ':') { if (i < (int) strlen(name) && name[i + 1] == ':') { error("%s", ":: not supported (yet)"); } else { if (i + 2 == (int) strlen(name) || name[i + 2] == ':') { name2[c++] = '0'; name2[c++] = '.'; name2[c++] = '0'; name2[c++] = '.'; name2[c++] = '0'; name2[c++] = '.'; } else if (i + 3 == (int) strlen(name) || name[i + 3] == ':') { name2[c++] = '0'; name2[c++] = '.'; name2[c++] = '0'; name2[c++] = '.'; } else if (i + 4 == (int) strlen(name) || name[i + 4] == ':') { name2[c++] = '0'; name2[c++] = '.'; } } } else { name2[c++] = name[i]; name2[c++] = '.'; } } name2[c++] = '\0'; qname = ldns_dname_new_frm_str(name2); qname_tmp = ldns_dname_reverse(qname); ldns_rdf_deep_free(qname); qname = qname_tmp; qname_tmp = ldns_dname_new_frm_str("ip6.arpa."); status = ldns_dname_cat(qname, qname_tmp); if (status != LDNS_STATUS_OK) { error("%s", "could not create reverse address for ip6: %s\n", ldns_get_errorstr_by_id(status)); } ldns_rdf_deep_free(qname_tmp); free(name2); } else { qname = ldns_dname_new_frm_str(name); qname_tmp = ldns_dname_reverse(qname); ldns_rdf_deep_free(qname); qname = qname_tmp; qname_tmp = ldns_dname_new_frm_str("in-addr.arpa."); status = ldns_dname_cat(qname, qname_tmp); if (status != LDNS_STATUS_OK) { error("%s", "could not create reverse address for ip4: %s\n", ldns_get_errorstr_by_id(status)); } ldns_rdf_deep_free(qname_tmp); } if (!qname) { error("%s", "-x implies an ip address"); } /* create a packet and set the RD flag on it */ pkt = ldns_resolver_query(res, qname, type, clas, qflags); if (!pkt) { error("%s", "pkt sending"); result = EXIT_FAILURE; } else { if (verbosity != -1) { ldns_pkt_print(stdout, pkt); } ldns_pkt_free(pkt); } break; case DRILL_QUERY: default: if (query_file) { /* this old way, the query packet needed to be parseable, but we want to be able to send mangled packets, so we need to do it directly */ #if 0 qpkt = read_hex_pkt(query_file); if (qpkt) { status = ldns_resolver_send_pkt(&pkt, res, qpkt); if (status != LDNS_STATUS_OK) { printf("Error: %s\n", ldns_get_errorstr_by_id(status)); exit(1); } } else { /* qpkt was bogus, reset pkt */ pkt = NULL; } #endif query_buffer = read_hex_buffer(query_file); if (query_buffer) { status = ldns_send_buffer(&pkt, res, query_buffer, NULL); ldns_buffer_free(query_buffer); if (status != LDNS_STATUS_OK) { printf("Error: %s\n", ldns_get_errorstr_by_id(status)); exit(1); } } else { printf("NO BUFFER\n"); pkt = NULL; } } else { qname = ldns_dname_new_frm_str(name); if (!qname) { error("%s", "error in making qname"); } if (type == LDNS_RR_TYPE_AXFR) { status = ldns_axfr_start(res, qname, clas); if(status != LDNS_STATUS_OK) { error("Error starting axfr: %s", ldns_get_errorstr_by_id(status)); } axfr_rr = ldns_axfr_next(res); if(!axfr_rr) { fprintf(stderr, "AXFR failed.\n"); ldns_pkt_print(stdout, ldns_axfr_last_pkt(res)); goto exit; } while (axfr_rr) { if (verbosity != -1) { ldns_rr_print(stdout, axfr_rr); } ldns_rr_free(axfr_rr); axfr_rr = ldns_axfr_next(res); } goto exit; } else { /* create a packet and set the RD flag on it */ pkt = ldns_resolver_query(res, qname, type, clas, qflags); } } if (!pkt) { mesg("No packet received"); result = EXIT_FAILURE; } else { if (verbosity != -1) { ldns_pkt_print(stdout, pkt); if (ldns_pkt_tc(pkt)) { fprintf(stdout, "\n;; WARNING: The answer packet was truncated; you might want to\n"); fprintf(stdout, ";; query again with TCP (-t argument), or EDNS0 (-b for buffer size)\n"); } } if (qds) { if (verbosity != -1) { print_ds_of_keys(pkt); printf("\n"); } } if (ldns_rr_list_rr_count(key_list) > 0) { /* -k's were given on the cmd line */ ldns_rr_list *rrset_verified; uint16_t key_count; rrset_verified = ldns_pkt_rr_list_by_name_and_type( pkt, qname, type, LDNS_SECTION_ANY_NOQUESTION); if (type == LDNS_RR_TYPE_ANY) { /* don't verify this */ break; } if (verbosity != -1) { printf("; "); ldns_rr_list_print(stdout, rrset_verified); } /* verify */ #ifdef HAVE_SSL key_verified = ldns_rr_list_new(); result = ldns_pkt_verify(pkt, type, qname, key_list, NULL, key_verified); if (result == LDNS_STATUS_ERR) { /* is the existence denied then? */ result = ldns_verify_denial(pkt, qname, type, NULL, NULL); if (result == LDNS_STATUS_OK) { if (verbosity != -1) { printf("Existence denied for "); ldns_rdf_print(stdout, qname); type_str = ldns_rr_type2str(type); printf("\t%s\n", type_str); LDNS_FREE(type_str); } } else { if (verbosity != -1) { printf("Bad data; RR for name and " "type not found or failed to " "verify, and denial of " "existence failed.\n"); } } } else if (result == LDNS_STATUS_OK) { for(key_count = 0; key_count < ldns_rr_list_rr_count(key_verified); key_count++) { if (verbosity != -1) { printf("; VALIDATED by id = %u, owner = ", (unsigned int)ldns_calc_keytag( ldns_rr_list_rr(key_verified, key_count))); ldns_rdf_print(stdout, ldns_rr_owner( ldns_rr_list_rr(key_list, key_count))); printf("\n"); } } } else { for(key_count = 0; key_count < ldns_rr_list_rr_count(key_list); key_count++) { if (verbosity != -1) { printf("; %s for id = %u, owner = ", ldns_get_errorstr_by_id(result), (unsigned int)ldns_calc_keytag( ldns_rr_list_rr(key_list, key_count))); ldns_rdf_print(stdout, ldns_rr_owner( ldns_rr_list_rr(key_list, key_count))); printf("\n"); } } } ldns_rr_list_free(key_verified); #else (void) key_count; #endif /* HAVE_SSL */ } if (answer_file) { dump_hex(pkt, answer_file); } ldns_pkt_free(pkt); } break; } exit: ldns_rdf_deep_free(qname); ldns_resolver_deep_free(res); ldns_resolver_deep_free(cmdline_res); ldns_rr_list_deep_free(key_list); ldns_rr_list_deep_free(cmdline_rr_list); ldns_rdf_deep_free(trace_start_name); xfree(progname); xfree(tsig_name); xfree(tsig_data); xfree(tsig_algorithm); #ifdef HAVE_SSL ERR_remove_state(0); CRYPTO_cleanup_all_ex_data(); ERR_free_strings(); EVP_cleanup(); #endif #ifdef USE_WINSOCK WSACleanup(); #endif return result; }
ldns_status ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) { ldns_resolver *r; const char *keyword[LDNS_RESOLV_KEYWORDS]; char word[LDNS_MAX_LINELEN + 1]; int8_t expect; uint8_t i; ldns_rdf *tmp; #ifdef HAVE_SSL ldns_rr *tmp_rr; #endif ssize_t gtr, bgtr; ldns_buffer *b; int lnr = 0, oldline; if(!line_nr) line_nr = &lnr; /* do this better * expect = * 0: keyword * 1: default domain dname * 2: NS aaaa or a record */ /* recognized keywords */ keyword[LDNS_RESOLV_NAMESERVER] = "nameserver"; keyword[LDNS_RESOLV_DEFDOMAIN] = "domain"; keyword[LDNS_RESOLV_SEARCH] = "search"; /* these two are read but not used atm TODO */ keyword[LDNS_RESOLV_SORTLIST] = "sortlist"; keyword[LDNS_RESOLV_OPTIONS] = "options"; keyword[LDNS_RESOLV_ANCHOR] = "anchor"; expect = LDNS_RESOLV_KEYWORD; r = ldns_resolver_new(); if (!r) { return LDNS_STATUS_MEM_ERR; } gtr = 1; word[0] = 0; oldline = *line_nr; expect = LDNS_RESOLV_KEYWORD; while (gtr > 0) { /* check comments */ if (word[0] == '#') { word[0]='x'; if(oldline == *line_nr) { /* skip until end of line */ int c; do { c = fgetc(fp); } while(c != EOF && c != '\n'); if(c=='\n' && line_nr) (*line_nr)++; } /* and read next to prepare for further parsing */ oldline = *line_nr; continue; } oldline = *line_nr; switch(expect) { case LDNS_RESOLV_KEYWORD: /* keyword */ gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); if (gtr != 0) { if(word[0] == '#') continue; for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) { if (strcasecmp(keyword[i], word) == 0) { /* chosen the keyword and * expect values carefully */ expect = i; break; } } /* no keyword recognized */ if (expect == LDNS_RESOLV_KEYWORD) { /* skip line */ /* ldns_resolver_deep_free(r); return LDNS_STATUS_SYNTAX_KEYWORD_ERR; */ } } break; case LDNS_RESOLV_DEFDOMAIN: /* default domain dname */ gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); if (gtr == 0) { return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; } if(word[0] == '#') { expect = LDNS_RESOLV_KEYWORD; continue; } tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word); if (!tmp) { ldns_resolver_deep_free(r); return LDNS_STATUS_SYNTAX_DNAME_ERR; } /* DOn't free, because we copy the pointer */ ldns_resolver_set_domain(r, tmp); expect = LDNS_RESOLV_KEYWORD; break; case LDNS_RESOLV_NAMESERVER: /* NS aaaa or a record */ gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); if (gtr == 0) { return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; } if(word[0] == '#') { expect = LDNS_RESOLV_KEYWORD; continue; } if(strchr(word, '%')) { /* snip off interface labels, * fe80::222:19ff:fe31:4222%eth0 */ strchr(word, '%')[0]=0; } tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word); if (!tmp) { /* try ip4 */ tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word); } /* could not parse it, exit */ if (!tmp) { ldns_resolver_deep_free(r); return LDNS_STATUS_SYNTAX_ERR; } (void)ldns_resolver_push_nameserver(r, tmp); ldns_rdf_deep_free(tmp); expect = LDNS_RESOLV_KEYWORD; break; case LDNS_RESOLV_SEARCH: /* search list domain dname */ gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); b = LDNS_MALLOC(ldns_buffer); if(!b) { ldns_resolver_deep_free(r); return LDNS_STATUS_MEM_ERR; } ldns_buffer_new_frm_data(b, word, (size_t) gtr); if(ldns_buffer_status(b) != LDNS_STATUS_OK) { LDNS_FREE(b); ldns_resolver_deep_free(r); return LDNS_STATUS_MEM_ERR; } bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1); while (bgtr > 0) { gtr -= bgtr; if(word[0] == '#') { expect = LDNS_RESOLV_KEYWORD; ldns_buffer_free(b); continue; } tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word); if (!tmp) { ldns_resolver_deep_free(r); ldns_buffer_free(b); return LDNS_STATUS_SYNTAX_DNAME_ERR; } ldns_resolver_push_searchlist(r, tmp); ldns_rdf_deep_free(tmp); bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1); } ldns_buffer_free(b); gtr = 1; expect = LDNS_RESOLV_KEYWORD; break; case LDNS_RESOLV_SORTLIST: gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); /* sortlist not implemented atm */ expect = LDNS_RESOLV_KEYWORD; break; case LDNS_RESOLV_OPTIONS: gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); /* options not implemented atm */ expect = LDNS_RESOLV_KEYWORD; break; case LDNS_RESOLV_ANCHOR: /* a file containing a DNSSEC trust anchor */ gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); if (gtr == 0) { ldns_resolver_deep_free(r); return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; } if(word[0] == '#') { expect = LDNS_RESOLV_KEYWORD; continue; } #ifdef HAVE_SSL tmp_rr = ldns_read_anchor_file(word); (void) ldns_resolver_push_dnssec_anchor(r, tmp_rr); ldns_rr_free(tmp_rr); #endif expect = LDNS_RESOLV_KEYWORD; break; } } /* finally, add the root domain to the search list */ ldns_resolver_push_searchlist(r, ldns_dname_new_frm_str(".")); if (res) { *res = r; return LDNS_STATUS_OK; } else { ldns_resolver_deep_free(r); return LDNS_STATUS_NULL; } }
int main(int argc, char *argv[]) { ldns_resolver *res; ldns_rdf *ns; ldns_rdf *domain; ldns_rr_list *l = NULL; ldns_rr_list *dns_root = NULL; const char *root_file = "/etc/named.root"; ldns_status status; int i; char *domain_str; char *outputfile_str; ldns_buffer *outputfile_buffer; FILE *outputfile; ldns_rr *k; bool insecure = false; ldns_pkt *pkt; domain = NULL; res = NULL; if (argc < 2) { usage(stdout, argv[0]); exit(EXIT_FAILURE); } else { for (i = 1; i < argc; i++) { if (strncmp("-4", argv[i], 3) == 0) { if (address_family != 0) { fprintf(stderr, "Options -4 and -6 cannot be specified at the same time\n"); exit(EXIT_FAILURE); } address_family = 1; } else if (strncmp("-6", argv[i], 3) == 0) { if (address_family != 0) { fprintf(stderr, "Options -4 and -6 cannot be specified at the same time\n"); exit(EXIT_FAILURE); } address_family = 2; } else if (strncmp("-h", argv[i], 3) == 0) { usage(stdout, argv[0]); exit(EXIT_SUCCESS); } else if (strncmp("-i", argv[i], 2) == 0) { insecure = true; } else if (strncmp("-r", argv[i], 2) == 0) { if (strlen(argv[i]) > 2) { root_file = argv[i]+2; } else if (i+1 >= argc) { usage(stdout, argv[0]); exit(EXIT_FAILURE); } else { root_file = argv[i+1]; i++; } } else if (strncmp("-s", argv[i], 3) == 0) { store_in_file = true; } else if (strncmp("-v", argv[i], 2) == 0) { if (strlen(argv[i]) > 2) { verbosity = atoi(argv[i]+2); } else if (i+1 > argc) { usage(stdout, argv[0]); exit(EXIT_FAILURE); } else { verbosity = atoi(argv[i+1]); i++; } } else { /* create a rdf from the command line arg */ if (domain) { fprintf(stdout, "You can only specify one domain at a time\n"); exit(EXIT_FAILURE); } domain = ldns_dname_new_frm_str(argv[i]); } } if (!domain) { usage(stdout, argv[0]); exit(EXIT_FAILURE); } } dns_root = read_root_hints(root_file); if (!dns_root) { fprintf(stderr, "cannot read the root hints file\n"); exit(EXIT_FAILURE); } /* create a new resolver from /etc/resolv.conf */ status = ldns_resolver_new_frm_file(&res, NULL); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Warning: Unable to create stub resolver from /etc/resolv.conf:\n"); fprintf(stderr, "%s\n", ldns_get_errorstr_by_id(status)); fprintf(stderr, "defaulting to nameserver at 127.0.0.1 for separate nameserver name lookups\n"); res = ldns_resolver_new(); ns = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, "127.0.0.1"); status = ldns_resolver_push_nameserver(res, ns); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Unable to create stub resolver: %s\n", ldns_get_errorstr_by_id(status)); exit(EXIT_FAILURE); } ldns_rdf_deep_free(ns); } ldns_resolver_set_ip6(res, address_family); if (insecure) { pkt = ldns_resolver_query(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD); if (pkt) { l = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_DNSKEY, LDNS_SECTION_ANY_NOQUESTION); } } else { l = retrieve_dnskeys(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, dns_root); } /* separator for result data and verbosity data */ if (verbosity > 0) { fprintf(stdout, "; ---------------------------\n"); fprintf(stdout, "; Got the following keys:\n"); } if (l) { if (store_in_file) { /* create filename: * K<domain>.+<alg>.+<id>.key */ for (i = 0; (size_t) i < ldns_rr_list_rr_count(l); i++) { k = ldns_rr_list_rr(l, (size_t) i); outputfile_buffer = ldns_buffer_new(300); domain_str = ldns_rdf2str(ldns_rr_owner(k)); ldns_buffer_printf(outputfile_buffer, "K%s+%03u+%05u.key", domain_str, ldns_rdf2native_int8(ldns_rr_rdf(k, 2)), (unsigned int) ldns_calc_keytag(k)); outputfile_str = ldns_buffer_export(outputfile_buffer); if (verbosity >= 1) { fprintf(stdout, "Writing key to file %s\n", outputfile_str); } outputfile = fopen(outputfile_str, "w"); if (!outputfile) { fprintf(stderr, "Error writing key to file %s: %s\n", outputfile_str, strerror(errno)); } else { ldns_rr_print(outputfile, k); fclose(outputfile); } LDNS_FREE(domain_str); LDNS_FREE(outputfile_str); LDNS_FREE(outputfile_buffer); } } else { ldns_rr_list_print(stdout, l); } } else { fprintf(stderr, "no answer packet received, stub resolver config:\n"); ldns_resolver_print(stderr, res); } printf("\n"); ldns_rdf_deep_free(domain); ldns_resolver_deep_free(res); ldns_rr_list_deep_free(l); ldns_rr_list_deep_free(dns_root); return EXIT_SUCCESS; }
static ldns_rr_list * retrieve_dnskeys(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, ldns_rr_list *dns_root) { ldns_resolver *res; ldns_pkt *p; ldns_rr_list *new_nss_a; ldns_rr_list *new_nss_aaaa; ldns_rr_list *final_answer; ldns_rr_list *new_nss; ldns_rr_list *ns_addr; ldns_rr_list *ns_addr2; uint16_t loop_count; ldns_rdf *pop; ldns_status status; size_t i; size_t nss_i; ldns_rr_list *answer_list = NULL; ldns_rr_list *authority_list = NULL; size_t last_nameserver_count; ldns_rdf **last_nameservers; loop_count = 0; new_nss_a = NULL; new_nss_aaaa = NULL; new_nss = NULL; ns_addr = NULL; ns_addr2 = NULL; final_answer = NULL; p = ldns_pkt_new(); res = ldns_resolver_new(); if (!p || !res) { fprintf(stderr, "Memory allocation failed"); return NULL; } if (verbosity >= 2) { printf("Finding dnskey data for zone: "); ldns_rdf_print(stdout, name); printf("\n\n"); } /* transfer some properties of local_res to res, * because they were given on the commandline */ ldns_resolver_set_ip6(res, ldns_resolver_ip6(local_res)); ldns_resolver_set_port(res, ldns_resolver_port(local_res)); ldns_resolver_set_debug(res, ldns_resolver_debug(local_res)); ldns_resolver_set_dnssec(res, ldns_resolver_dnssec(local_res)); ldns_resolver_set_fail(res, ldns_resolver_fail(local_res)); ldns_resolver_set_usevc(res, ldns_resolver_usevc(local_res)); ldns_resolver_set_random(res, ldns_resolver_random(local_res)); ldns_resolver_set_recursive(res, false); /* setup the root nameserver in the new resolver */ status = ldns_resolver_push_nameserver_rr_list(res, dns_root); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error setting root nameservers in resolver: %s\n", ldns_get_errorstr_by_id(status)); return NULL; } ldns_pkt_free(p); status = ldns_resolver_send(&p, res, name, t, c, 0); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error querying root servers: %s\n", ldns_get_errorstr_by_id(status)); return NULL; } if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { printf("Error in packet:\n"); ldns_pkt_print(stdout, p); return NULL; } if (verbosity >= 4) { ldns_pkt_print(stdout, p); printf("\n\n"); } /* from now on, use TCP */ ldns_resolver_set_usevc(res, true); while(status == LDNS_STATUS_OK && ldns_pkt_reply_type(p) == LDNS_PACKET_REFERRAL) { if (verbosity >= 3) { printf("This is a delegation!\n\n"); } if (address_family == 0 || address_family == 1) { new_nss_a = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_A, LDNS_SECTION_ADDITIONAL); } else { new_nss_a = ldns_rr_list_new(); } if (address_family == 0 || address_family == 2) { new_nss_aaaa = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_AAAA, LDNS_SECTION_ADDITIONAL); } else { new_nss_aaaa = ldns_rr_list_new(); } new_nss = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS, LDNS_SECTION_AUTHORITY); /* remove the old nameserver from the resolver */ while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); } /* also check for new_nss emptyness */ if (!new_nss_aaaa && !new_nss_a) { /* * no nameserver found!!! * try to resolve the names we do got */ if (verbosity >= 3) { printf("Did not get address record for nameserver, doing seperate query.\n"); } ns_addr = ldns_rr_list_new(); for(i = 0; (size_t) i < ldns_rr_list_rr_count(new_nss); i++) { /* get the name of the nameserver */ pop = ldns_rr_rdf(ldns_rr_list_rr(new_nss, i), 0); if (!pop) { break; } /* retrieve it's addresses */ ns_addr2 = ldns_get_rr_list_addr_by_name(local_res, pop, c, 0); if (!ldns_rr_list_cat(ns_addr, ns_addr2)) { fprintf(stderr, "Internal error adding nameserver address.\n"); exit(EXIT_FAILURE); } ldns_rr_list_free(ns_addr2); } if (ns_addr) { if (ldns_resolver_push_nameserver_rr_list(res, ns_addr) != LDNS_STATUS_OK) { fprintf(stderr, "Error adding new nameservers"); ldns_pkt_free(p); return NULL; } ldns_rr_list_deep_free(ns_addr); } else { ldns_rr_list_print(stdout, ns_addr); fprintf(stderr, "Could not find the nameserver ip addr; abort"); ldns_pkt_free(p); return NULL; } } /* normally, the first working ns is used, but we need all now, so do it one by one * if the answer is null, take it from the next resolver * if the answer is not, compare it to that of the next resolver * error if different, continue if the same * if answer list null and no resolvers left die. */ ldns_rr_list_deep_free(answer_list); ldns_rr_list_deep_free(authority_list); answer_list = NULL; authority_list = NULL; for (nss_i = 0; nss_i < ldns_rr_list_rr_count(new_nss_aaaa); nss_i++) { while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); } status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0)); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status)); } if (verbosity >= 1) { fprintf(stdout, "Querying nameserver: "); ldns_rdf_print(stdout, ldns_rr_owner(ldns_rr_list_rr(new_nss_aaaa, nss_i))); fprintf(stdout, " ("); ldns_rdf_print(stdout, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0)); fprintf(stdout, ")\n"); } status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0)); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status)); } ldns_pkt_free(p); status = ldns_resolver_send(&p, res, name, t, c, 0); if (status == LDNS_STATUS_OK && p) { if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { printf("Error in packet:\n"); ldns_pkt_print(stdout, p); return NULL; } if (verbosity >= 4) { ldns_pkt_print(stdout, p); printf("\n\n"); } if (answer_list) { if (verbosity >= 2) { printf("Comparing answer list of answer to previous\n\n"); } ldns_rr_list_sort(ldns_pkt_answer(p)); ldns_rr_list_sort(answer_list); if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) { fprintf(stderr, "ERROR: different answer answer from nameserver\n"); fprintf(stderr, "\nI had (from previous servers):\n"); ldns_rr_list_print(stderr, answer_list); fprintf(stderr, "\nI received (from nameserver at "); ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]); fprintf(stderr, "):\n"); ldns_rr_list_print(stderr, ldns_pkt_answer(p)); exit(EXIT_FAILURE); } } else { answer_list = ldns_rr_list_clone(ldns_pkt_answer(p)); ldns_rr_list_sort(answer_list); if (verbosity >= 2) { printf("First answer list for this set, nothing to compare with\n\n"); } } if (authority_list) { if (verbosity >= 2) { printf("Comparing authority list of answer to previous\n\n"); } ldns_rr_list_sort(ldns_pkt_authority(p)); ldns_rr_list_sort(authority_list); if (ldns_rr_list_compare(authority_list, ldns_pkt_authority(p)) != 0) { fprintf(stderr, "ERROR: different authority answer from nameserver\n"); fprintf(stderr, "\nI had (from previous servers):\n"); ldns_rr_list_print(stderr, authority_list); fprintf(stderr, "\nI received (from nameserver at "); ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]); fprintf(stderr, "):\n"); ldns_rr_list_print(stderr, ldns_pkt_authority(p)); exit(EXIT_FAILURE); } } else { authority_list = ldns_rr_list_clone(ldns_pkt_authority(p)); ldns_rr_list_sort(authority_list); if (verbosity >= 2) { printf("First authority list for this set, nothing to compare with\n\n"); } if (verbosity >= 3) { printf("NS RRset:\n"); ldns_rr_list_print(stdout, authority_list); printf("\n"); } } } } ldns_rr_list_deep_free(answer_list); ldns_rr_list_deep_free(authority_list); answer_list = NULL; authority_list = NULL; for (nss_i = 0; nss_i < ldns_rr_list_rr_count(new_nss_a); nss_i++) { while((pop = ldns_resolver_pop_nameserver(res))) {ldns_rdf_deep_free(pop); } if (verbosity >= 1) { fprintf(stdout, "Querying nameserver: "); ldns_rdf_print(stdout, ldns_rr_owner(ldns_rr_list_rr(new_nss_a, nss_i))); fprintf(stdout, " ("); ldns_rdf_print(stdout, ldns_rr_rdf(ldns_rr_list_rr(new_nss_a, nss_i), 0)); fprintf(stdout, ")\n"); } status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_a, nss_i), 0)); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status)); } ldns_pkt_free(p); status = ldns_resolver_send(&p, res, name, t, c, 0); if (status == LDNS_STATUS_OK) { if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { printf("Error in packet:\n"); ldns_pkt_print(stdout, p); return NULL; } if (verbosity >= 4) { ldns_pkt_print(stdout, p); printf("\n\n"); } if (answer_list) { if (verbosity >= 2) { printf("Comparing answer list of answer to previous\n\n"); } ldns_rr_list_sort(ldns_pkt_answer(p)); ldns_rr_list_sort(answer_list); if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) { fprintf(stderr, "ERROR: different answer answer from nameserver\n"); fprintf(stderr, "\nI had (from previous servers):\n"); ldns_rr_list_print(stderr, answer_list); fprintf(stderr, "\nI received (from nameserver at "); ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]); fprintf(stderr, "):\n"); ldns_rr_list_print(stderr, ldns_pkt_answer(p)); exit(EXIT_FAILURE); } } else { if (verbosity >= 2) { printf("First answer list for this set, nothing to compare with\n\n"); } answer_list = ldns_rr_list_clone(ldns_pkt_answer(p)); ldns_rr_list_sort(answer_list); } if (authority_list) { if (verbosity >= 2) { printf("Comparing authority list of answer to previous\n\n"); } ldns_rr_list_sort(ldns_pkt_authority(p)); ldns_rr_list_sort(authority_list); if (ldns_rr_list_compare(authority_list, ldns_pkt_authority(p)) != 0) { fprintf(stderr, "ERROR: different authority answer from nameserver\n"); fprintf(stderr, "\nI had (from previous servers):\n"); ldns_rr_list_print(stderr, authority_list); fprintf(stderr, "\nI received (from nameserver at "); ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]); fprintf(stderr, "):\n"); ldns_rr_list_print(stderr, ldns_pkt_authority(p)); exit(EXIT_FAILURE); } } else { if (verbosity >= 2) { printf("First authority list for this set, nothing to compare with\n\n"); } authority_list = ldns_rr_list_clone(ldns_pkt_authority(p)); ldns_rr_list_sort(authority_list); if (verbosity >= 3) { printf("NS RRset:\n"); ldns_rr_list_print(stdout, authority_list); printf("\n"); } } } } ldns_rr_list_deep_free(authority_list); authority_list = NULL; if (loop_count++ > 20) { /* unlikely that we are doing something usefull */ fprintf(stderr, "Looks like we are looping"); ldns_pkt_free(p); return NULL; } ldns_pkt_free(p); if (verbosity >= 3) { fprintf(stdout, "This level ok. Continuing to next.\n\n"); } status = ldns_resolver_send(&p, res, name, t, c, 0); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error querying root servers: %s\n", ldns_get_errorstr_by_id(status)); return NULL; } if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { printf("Error in packet:\n"); ldns_pkt_print(stdout, p); return NULL; } if (verbosity >= 4) { ldns_pkt_print(stdout, p); printf("\n\n"); } ldns_rr_list_deep_free(new_nss_aaaa); ldns_rr_list_deep_free(new_nss_a); ldns_rr_list_deep_free(new_nss); new_nss_aaaa = NULL; new_nss_a = NULL; ns_addr = NULL; } ldns_rr_list_deep_free(answer_list); answer_list = NULL; /* clone the nameserver list, we are going to handle them one by one */ last_nameserver_count = 0; last_nameservers = LDNS_XMALLOC(ldns_rdf *, ldns_resolver_nameserver_count(res)); pop = NULL; while((pop = ldns_resolver_pop_nameserver(res))) { last_nameservers[last_nameserver_count] = pop; last_nameserver_count++; } for (nss_i = 0; nss_i < last_nameserver_count; nss_i++) { /* remove previous nameserver */ while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); } if (verbosity >= 1) { printf("Querying nameserver: "); ldns_rdf_print(stdout, last_nameservers[nss_i]); printf("\n"); } status = ldns_resolver_push_nameserver(res, last_nameservers[nss_i]); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status)); } ldns_pkt_free(p); status = ldns_resolver_send(&p, res, name, t, c, 0); if (!p) { fprintf(stderr, "no packet received\n"); return NULL; } if (status == LDNS_STATUS_RES_NO_NS) { fprintf(stderr, "Error: nameserver at "); ldns_rdf_print(stderr, last_nameservers[nss_i]); fprintf(stderr, " not responding. Unable to check RRset here, aborting.\n"); return NULL; } if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { printf("Error in packet:\n"); ldns_pkt_print(stdout, p); return NULL; } if (answer_list) { if (verbosity >= 2) { printf("1Comparing answer rr list of answer to previous\n"); } ldns_rr_list_sort(ldns_pkt_answer(p)); ldns_rr_list_sort(answer_list); if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) { printf("ERROR: different answer section in response from nameserver\n"); fprintf(stderr, "\nI had:\n"); ldns_rr_list_print(stderr, answer_list); fprintf(stderr, "\nI received (from nameserver at "); ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]); fprintf(stderr, "):\n"); ldns_rr_list_print(stderr, ldns_pkt_answer(p)); exit(EXIT_FAILURE); } } else { if (verbosity >= 2) { printf("First answer rr list for this set, nothing to compare with\n"); } answer_list = ldns_rr_list_clone(ldns_pkt_answer(p)); if (verbosity >= 3) { printf("DNSKEY RRset:\n"); ldns_rr_list_print(stdout, answer_list); } } } for (nss_i = 0; nss_i < last_nameserver_count; nss_i++) { ldns_rdf_deep_free(last_nameservers[nss_i]); } LDNS_FREE(last_nameservers); ldns_resolver_deep_free(res); ldns_pkt_free(p); return answer_list; }
void* run_server(void* data) { timeout_thread_data* tdata = (timeout_thread_data*)data; int fd; struct sockaddr_in serv_addr; uint8_t mesg[65536]; fd_set read_fds; ldns_rdf* answerfrom; ldns_resolver* resolver; int num_received = 0; queued_response responses[10]; ldns_resolver_new_frm_file(&resolver, NULL); fd=socket(AF_INET,SOCK_DGRAM,0); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); serv_addr.sin_port=htons(tdata->port); bind(fd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)); /* signal that it's listening */ /* dirty timing hack to yield */ sleep(1); tdata->running = 1; /* queue up query responses to send out, and delay sending them * for a second */ while (tdata->running) { struct sockaddr_in client_addr; FD_ZERO(&read_fds); FD_SET(fd, &read_fds); struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; int r = select(fd + 1, &read_fds, NULL, NULL, &tv); if (r > 0 && num_received < 10) { ldns_pkt* query; socklen_t len = sizeof(client_addr); int n = recvfrom(fd,mesg,65536,0,(struct sockaddr *)&(responses[num_received].client_addr),&len); ldns_wire2pkt(&query, mesg, n); ldns_resolver_send_pkt(&(responses[num_received].pkt), resolver, query); ldns_str2rdf_a(&answerfrom, "127.0.0.1"); ldns_pkt_set_answerfrom(responses[num_received].pkt, answerfrom); ldns_pkt_free(query); ++num_received; } else if (r == 0 && num_received > 0) { int i = 0; /* timeout - see if we have anything to send */ for (i = 0; i < num_received; ++i) { uint8_t* pkt_data; size_t pkt_len; ldns_pkt* answer = responses[i].pkt; ldns_pkt2wire(&pkt_data, answer, &pkt_len); sendto(fd,pkt_data,pkt_len,0,(struct sockaddr *)&(responses[i].client_addr),sizeof(client_addr)); free(pkt_data); ldns_pkt_free(answer); } num_received = 0; } } ldns_resolver_deep_free(resolver); return NULL; }
int getrrsetbyname(const char *hostname, unsigned int rdclass, unsigned int rdtype, unsigned int flags, struct rrsetinfo **res) { int result; unsigned int i, j, index_ans, index_sig; struct rrsetinfo *rrset = NULL; struct rdatainfo *rdata; size_t len; ldns_resolver *ldns_res; ldns_rdf *domain = NULL; ldns_pkt *pkt = NULL; ldns_rr_list *rrsigs = NULL, *rrdata = NULL; ldns_status err; ldns_rr *rr; /* check for invalid class and type */ if (rdclass > 0xffff || rdtype > 0xffff) { result = ERRSET_INVAL; goto fail; } /* don't allow queries of class or type ANY */ if (rdclass == 0xff || rdtype == 0xff) { result = ERRSET_INVAL; goto fail; } /* don't allow flags yet, unimplemented */ if (flags) { result = ERRSET_INVAL; goto fail; } /* Initialize resolver from resolv.conf */ domain = ldns_dname_new_frm_str(hostname); if ((err = ldns_resolver_new_frm_file(&ldns_res, NULL)) != \ LDNS_STATUS_OK) { result = ERRSET_FAIL; goto fail; } #ifdef LDNS_DEBUG ldns_resolver_set_debug(ldns_res, true); #endif /* LDNS_DEBUG */ ldns_resolver_set_dnssec(ldns_res, true); /* Use DNSSEC */ /* make query */ pkt = ldns_resolver_query(ldns_res, domain, rdtype, rdclass, LDNS_RD); /*** TODO: finer errcodes -- see original **/ if (!pkt || ldns_pkt_ancount(pkt) < 1) { result = ERRSET_FAIL; goto fail; } /* initialize rrset */ rrset = calloc(1, sizeof(struct rrsetinfo)); if (rrset == NULL) { result = ERRSET_NOMEMORY; goto fail; } rrdata = ldns_pkt_rr_list_by_type(pkt, rdtype, LDNS_SECTION_ANSWER); rrset->rri_nrdatas = ldns_rr_list_rr_count(rrdata); if (!rrset->rri_nrdatas) { result = ERRSET_NODATA; goto fail; } /* copy name from answer section */ len = ldns_rdf_size(ldns_rr_owner(ldns_rr_list_rr(rrdata, 0))); if ((rrset->rri_name = malloc(len)) == NULL) { result = ERRSET_NOMEMORY; goto fail; } memcpy(rrset->rri_name, ldns_rdf_data(ldns_rr_owner(ldns_rr_list_rr(rrdata, 0))), len); rrset->rri_rdclass = ldns_rr_get_class(ldns_rr_list_rr(rrdata, 0)); rrset->rri_rdtype = ldns_rr_get_type(ldns_rr_list_rr(rrdata, 0)); rrset->rri_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrdata, 0)); debug2("ldns: got %u answers from DNS", rrset->rri_nrdatas); /* Check for authenticated data */ if (ldns_pkt_ad(pkt)) { rrset->rri_flags |= RRSET_VALIDATED; } else { /* AD is not set, try autonomous validation */ ldns_rr_list * trusted_keys = ldns_rr_list_new(); debug2("ldns: trying to validate RRset"); /* Get eventual sigs */ rrsigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANSWER); rrset->rri_nsigs = ldns_rr_list_rr_count(rrsigs); debug2("ldns: got %u signature(s) (RRTYPE %u) from DNS", rrset->rri_nsigs, LDNS_RR_TYPE_RRSIG); if ((err = ldns_verify_trusted(ldns_res, rrdata, rrsigs, trusted_keys)) == LDNS_STATUS_OK) { rrset->rri_flags |= RRSET_VALIDATED; debug2("ldns: RRset is signed with a valid key"); } else { debug2("ldns: RRset validation failed: %s", ldns_get_errorstr_by_id(err)); } ldns_rr_list_deep_free(trusted_keys); } /* allocate memory for answers */ rrset->rri_rdatas = calloc(rrset->rri_nrdatas, sizeof(struct rdatainfo)); if (rrset->rri_rdatas == NULL) { result = ERRSET_NOMEMORY; goto fail; } /* allocate memory for signatures */ if (rrset->rri_nsigs > 0) { rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo)); if (rrset->rri_sigs == NULL) { result = ERRSET_NOMEMORY; goto fail; } } /* copy answers & signatures */ for (i=0, index_ans=0, index_sig=0; i< pkt->_header->_ancount; i++) { rdata = NULL; rr = ldns_rr_list_rr(ldns_pkt_answer(pkt), i); if (ldns_rr_get_class(rr) == rrset->rri_rdclass && ldns_rr_get_type(rr) == rrset->rri_rdtype) { rdata = &rrset->rri_rdatas[index_ans++]; } if (rr->_rr_class == rrset->rri_rdclass && rr->_rr_type == LDNS_RR_TYPE_RRSIG && rrset->rri_sigs) { rdata = &rrset->rri_sigs[index_sig++]; } if (rdata) { size_t rdata_offset = 0; rdata->rdi_length = 0; for (j=0; j< rr->_rd_count; j++) { rdata->rdi_length += ldns_rdf_size(ldns_rr_rdf(rr, j)); } rdata->rdi_data = malloc(rdata->rdi_length); if (rdata->rdi_data == NULL) { result = ERRSET_NOMEMORY; goto fail; } /* Re-create the raw DNS RDATA */ for (j=0; j< rr->_rd_count; j++) { len = ldns_rdf_size(ldns_rr_rdf(rr, j)); memcpy(rdata->rdi_data + rdata_offset, ldns_rdf_data(ldns_rr_rdf(rr, j)), len); rdata_offset += len; } } } *res = rrset; result = ERRSET_SUCCESS; fail: /* freerrset(rrset); */ ldns_rdf_deep_free(domain); ldns_pkt_free(pkt); ldns_rr_list_deep_free(rrsigs); ldns_rr_list_deep_free(rrdata); ldns_resolver_deep_free(ldns_res); return result; }
int main (int argc, char **argv) { /* Local Vars */ char *out = NULL; ldns_resolver *res; ldns_rdf *domain; ldns_rdf *host; ldns_rdf *example; ldns_pkt *pkt; ldns_rr *rr; ldns_status status; /* Set signal handling and alarm */ if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) critical("Setup SIGALRM trap failed!"); /* Process check arguments */ if (process_arguments(argc, argv) != OK) unknown("Parsing arguments failed!"); /* Start plugin timeout */ alarm(mp_timeout); // Create DNAME from domainname domain = ldns_dname_new_frm_str(domainname); if (!domain) usage("Invalid domainname '%s'", domainname); // Create rdf from hostaddr host = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, hostname); #ifdef USE_IPV6 if (!host) host = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, hostname); #endif if (!host) { ldns_rdf_deep_free(domain); usage("Invalid hostname '%s'", hostname); } // Create DNAME from example.com example = ldns_dname_new_frm_str("exmple.com"); if (!example) usage("Invalid domainname 'example.com'"); // Create resolver res = ldns_resolver_new(); if (!res) { ldns_rdf_deep_free(domain); ldns_rdf_deep_free(host); unknown("Create resolver failed."); } // Add ns to resolver status = ldns_resolver_push_nameserver(res, host); if (status != LDNS_STATUS_OK) { ldns_rdf_deep_free(domain); ldns_rdf_deep_free(host); ldns_resolver_deep_free(res); unknown("Adding %s as NS fails.", domainname); } if (udp) { // Disable TCP ldns_resolver_set_usevc(res, 0); // Fetch SOA pkt = mp_ldns_resolver_query(res, domain, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, 0); if (pkt == NULL || ldns_pkt_get_rcode(pkt) != LDNS_RCODE_NOERROR) { mp_strcat_comma(&out, "No UDP Answer"); } else if (ldns_pkt_aa(pkt) == 0) { mp_strcat_comma(&out, "Non Authoritative UDP Answer"); } if (mp_verbose > 2) { printf("[ SOA Answer ]----------\n"); ldns_pkt_print(stdout,pkt); } ldns_pkt_free(pkt); if (recursion) { // Fetch example.com SOA ldns_resolver_set_recursive(res, TRUE); pkt = mp_ldns_resolver_query(res, example, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, LDNS_RD); ldns_resolver_set_recursive(res, FALSE); if (pkt && (ldns_pkt_get_rcode(pkt) != LDNS_RCODE_REFUSED && ldns_pkt_get_rcode(pkt) != LDNS_RCODE_SERVFAIL)) { mp_strcat_comma(&out, "Recursive UDP Answer"); } if (mp_verbose > 2) { printf("[ SOA Answer ]----------\n"); ldns_pkt_print(stdout,pkt); } ldns_pkt_free(pkt); } } if (tcp) { // Enable TCP ldns_resolver_set_usevc(res, 1); // Fetch SOA pkt = mp_ldns_resolver_query(res, domain, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, 0); if (pkt == NULL || ldns_pkt_get_rcode(pkt) != LDNS_RCODE_NOERROR) { mp_strcat_comma(&out, "No TCP Answer"); } else if (ldns_pkt_aa(pkt) == 0) { mp_strcat_comma(&out, "Non Authoritative TCP Answer"); } if (mp_verbose > 2) { printf("[ SOA Answer ]----------\n"); ldns_pkt_print(stdout,pkt); } ldns_pkt_free(pkt); if (recursion) { // Fetch example.com SOA ldns_resolver_set_recursive(res, TRUE); pkt = mp_ldns_resolver_query(res, example, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, LDNS_RD); ldns_resolver_set_recursive(res, FALSE); if (pkt && (ldns_pkt_get_rcode(pkt) != LDNS_RCODE_REFUSED && ldns_pkt_get_rcode(pkt) != LDNS_RCODE_SERVFAIL)) { mp_strcat_comma(&out, "Recursive TCP Answer"); } if (mp_verbose > 2) { printf("[ SOA Answer ]----------\n"); ldns_pkt_print(stdout,pkt); } ldns_pkt_free(pkt); } } if (axfr) { status = ldns_axfr_start(res, domain, LDNS_RR_CLASS_IN); if (status == LDNS_STATUS_OK) { rr = NULL; rr = ldns_axfr_next(res); if (rr) { mp_strcat_comma(&out, "AXFR allowed."); } } } if (out) critical("Authoritative DNS for %s: %s", domainname, out); ok("Authoritative DNS for %s", domainname); }
ldns_rr_list* getaddr_rdf(ldns_resolver *res, ldns_rdf *hostrdf) { ldns_rdf *rdf; ldns_resolver *r = NULL; ldns_rr_list *rrl; ldns_rr_list *ret = NULL; ldns_pkt *pkt; ldns_status status; if (ldns_rdf_get_type(hostrdf) == LDNS_RDF_TYPE_A #ifdef USE_IPV6 || ldns_rdf_get_type(hostrdf) == LDNS_RDF_TYPE_AAAA #endif ) { rdf = ldns_rdf_address_reverse(hostrdf); r = res; if (res == NULL) { status = ldns_resolver_new_frm_file(&r, NULL); if (status != LDNS_STATUS_OK) return NULL; } // Fetch PTR pkt = ldns_resolver_query(r, rdf, LDNS_RR_TYPE_PTR, LDNS_RR_CLASS_IN, LDNS_RD); if (pkt == NULL || ldns_pkt_get_rcode(pkt) != LDNS_RCODE_NOERROR) return NULL; rrl = ldns_pkt_rr_list_by_name_and_type(pkt, rdf, LDNS_RR_TYPE_PTR, LDNS_SECTION_ANSWER); if (ldns_rr_list_rr_count(rrl) != 1) return NULL; ldns_rdf_deep_free(rdf); rdf = ldns_rdf_clone(ldns_rr_rdf(ldns_rr_list_rr(rrl,0),0)); ldns_pkt_free(pkt); ldns_rr_list_deep_free(rrl); } else if (ldns_rdf_get_type(hostrdf) == LDNS_RDF_TYPE_DNAME) { rdf = hostrdf; } else { return NULL; } if (r == NULL) { r = res; if (res == NULL) { status = ldns_resolver_new_frm_file(&r, NULL); if (status != LDNS_STATUS_OK) return NULL; } } #ifdef USE_IPV6 if (ldns_rdf_get_type(hostrdf) != LDNS_RDF_TYPE_A) { // Fetch AAAA pkt = ldns_resolver_query(r, rdf, LDNS_RR_TYPE_AAAA, LDNS_RR_CLASS_IN, LDNS_RD); if (pkt != NULL && ldns_pkt_get_rcode(pkt) == LDNS_RCODE_NOERROR) { rrl = ldns_pkt_rr_list_by_name_and_type(pkt, rdf, LDNS_RR_TYPE_AAAA, LDNS_SECTION_ANSWER); ldns_pkt_free(pkt); if (ldns_rr_list_rr_count(rrl) > 0) { ret = rrl; rrl = NULL; } else { ldns_rr_list_free(rrl); } } } if (ldns_rdf_get_type(hostrdf) != LDNS_RDF_TYPE_AAAA) { #else if (1) { #endif /* USE_IPV6 */ // Fetch AA pkt = ldns_resolver_query(r, rdf, LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, LDNS_RD); if (pkt != NULL && ldns_pkt_get_rcode(pkt) == LDNS_RCODE_NOERROR) { rrl = ldns_pkt_rr_list_by_name_and_type(pkt, rdf, LDNS_RR_TYPE_A, LDNS_SECTION_ANSWER); ldns_pkt_free(pkt); if (ldns_rr_list_rr_count(rrl) > 0) { if (ret == NULL) { ret = rrl; } else { ldns_rr_list_cat(ret, rrl); ldns_rr_list_free(rrl); } } else { ldns_rr_list_free(rrl); } } // if (pkt != NULL && ldns_pkt_ge... } if (res == NULL) ldns_resolver_deep_free(r); return ret; } ldns_rr_list* getaddr(ldns_resolver *res, const char *hostname) { ldns_rdf *rdf; /* Check if hostname is a ip */ rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, hostname); #ifdef USE_IPV6 if (!rdf) { rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, hostname); } #endif if (!rdf) { rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, hostname); } if (!rdf) return NULL; return getaddr_rdf(res, rdf); }
int main(int argc, char **argv) { /* Local Vars */ int i; int soa_valid = 0; int ns_valid = 0; ldns_rdf *rd_domain; ldns_rdf *rd_trace; ldns_rdf *rd_cdomain; ldns_pkt *pkt; ldns_resolver *res; ldns_rr *rr; ldns_rr_list *rrl; ldns_rr_list *rrl_domain_soa; ldns_rr_list *rrl_domain_soa_rrsig; ldns_rr_list *rrl_domain_ns; ldns_rr_list *rrl_domain_ns_rrsig; ldns_rr_list *rrl_valid_keys; ldns_status status; /* Set signal handling and alarm */ if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) critical("Setup SIGALRM trap failed!"); /* Process check arguments */ if (process_arguments(argc, argv) != OK) unknown("Parsing arguments failed!"); /* Start plugin timeout */ alarm(mp_timeout); rd_domain = ldns_dname_new_frm_str(domainname); if (!rd_domain) unknown("Illegal domain name"); rd_trace = ldns_dname_new_frm_str(domaintrace); if (!rd_trace) unknown("Illegal trace domain name"); /* Check domain is subdomain from trace start */ if (!ldns_dname_is_subdomain(rd_domain, rd_trace)) { ldns_rr_list_deep_free(trusted_keys); ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); unknown("'%s' is not a subdomain of '%s'.", domainname, domaintrace); } /* Add trusted keys for trace domain to rrl_valid_keys. */ rrl_valid_keys = ldns_rr_list_new(); for(i = 0; i < ldns_rr_list_rr_count(trusted_keys); i++) { rr = ldns_rr_list_rr(trusted_keys, i); if (ldns_dname_compare(ldns_rr_owner(rr),rd_trace) == 0) ldns_rr_list_push_rr(rrl_valid_keys, ldns_rr_clone(rr)); } ldns_rr_list_deep_free(trusted_keys); if (ldns_rr_list_rr_count(rrl_valid_keys) == 0) { ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_rr_list_deep_free(rrl_valid_keys); critical("No trusted key for trace start '%s'", domaintrace?domaintrace:"."); } if (mp_verbose >= 2) { printf("--[ Trusted keys used ]-------------------------------------\n"); ldns_rr_list_sort(rrl_valid_keys); ldns_rr_list_print(stdout, rrl_valid_keys); printf("------------------------------------------------------------\n"); } /* create a new resolver with dns_server or server from /etc/resolv.conf */ res = createResolver(hostname); if (!res) { ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_rr_list_deep_free(rrl_valid_keys); unknown("Creating resolver failed."); } resolverEnableDnssec(res); ldns_resolver_set_dnssec_anchors(res, rrl_valid_keys); /* check domain exists */ pkt = mp_ldns_resolver_query(res, rd_domain, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, LDNS_RD); if (pkt == NULL || ldns_pkt_get_rcode(pkt) != LDNS_RCODE_NOERROR) { ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_resolver_deep_free(res); if (pkt && ldns_pkt_get_rcode(pkt) == LDNS_RCODE_NXDOMAIN) { ldns_pkt_free(pkt); critical("Domain '%s' don't exist.", domainname); } ldns_pkt_free(pkt); critical("Unable to get SOA for %s.", domainname); } rrl_domain_soa = ldns_pkt_rr_list_by_name_and_type(pkt, rd_domain, LDNS_RR_TYPE_SOA, LDNS_SECTION_ANSWER); if (rrl_domain_soa == NULL || ldns_rr_list_rr_count(rrl_domain_soa) == 0) { ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_resolver_deep_free(res); ldns_pkt_free(pkt); critical("Domain '%s' not found.", domainname); } rrl_domain_soa_rrsig = ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt, rd_domain, LDNS_RR_TYPE_SOA); if (rrl_domain_soa_rrsig == NULL || ldns_rr_list_rr_count(rrl_domain_soa_rrsig) == 0) { free(domaintrace); ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_resolver_deep_free(res); ldns_pkt_free(pkt); ldns_rr_list_deep_free(rrl_domain_soa); critical("Domain '%s' not signed.", domainname); } ldns_pkt_free(pkt); pkt = ldns_resolver_query(res, rd_domain, LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN, LDNS_RD); rrl_domain_ns = ldns_pkt_rr_list_by_name_and_type(pkt, rd_domain, LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER); rrl_domain_ns_rrsig = ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt, rd_domain, LDNS_RR_TYPE_NS); ldns_pkt_free(pkt); if (mp_verbose >= 2) { printf("--[ Checked Domain ]----------------------------------------\n"); ldns_rr_list_print(stdout, rrl_domain_soa); printf("------------------------------------------------------------\n"); ldns_rr_list_print(stdout, rrl_domain_soa_rrsig); printf("------------------------------------------------------------\n"); ldns_rr_list_print(stdout, rrl_domain_ns); printf("------------------------------------------------------------\n"); ldns_rr_list_print(stdout, rrl_domain_ns_rrsig); printf("------------------------------------------------------------\n"); } /* create a new resolver with dns_server or server from /etc/resolv.conf */ ldns_resolver_free(res); res = createResolver(resolver); if (!res) { ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_rr_list_deep_free(rrl_valid_keys); unknown("Creating resolver failed."); } resolverEnableDnssec(res); ldns_resolver_set_dnssec_anchors(res, rrl_valid_keys); /* Fetch valid keys from top down */ i = ldns_dname_label_count(rd_domain) - ldns_dname_label_count(rd_trace); for (; i>=0; i--) { rd_cdomain = ldns_dname_clone_from(rd_domain, i); if (mp_verbose) { char *str = ldns_rdf2str(rd_cdomain); printf("Trace: %s\n", str); free(str); } rrl = ldns_fetch_valid_domain_keys(res, rd_cdomain, rrl_valid_keys, &status); if (mp_verbose >= 2) { printf("--[ Valid Keys ]----------------------------------------\n"); ldns_rr_list_sort(rrl); ldns_rr_list_print(stdout, rrl); printf("------------------------------------------------------------\n"); } ldns_rr_list_cat(rrl_valid_keys, rrl); ldns_rr_list_free(rrl); ldns_rdf_deep_free(rd_cdomain); } ldns_rdf_deep_free(rd_trace); ldns_rdf_deep_free(rd_domain); /* Validate SOA */ for(i = 0; i < ldns_rr_list_rr_count(rrl_domain_soa_rrsig); i++) { rr = ldns_rr_list_rr(rrl_domain_soa_rrsig, i); status = ldns_verify_rrsig_keylist(rrl_domain_soa, rr, rrl_valid_keys, NULL); if (status == LDNS_STATUS_OK) soa_valid++; else if (mp_verbose > 0) fprintf(stderr, "ldns_verify_rrsig_keylist SOA failed: %s\n", ldns_get_errorstr_by_id(status)); } ldns_rr_list_deep_free(rrl_domain_soa); ldns_rr_list_deep_free(rrl_domain_soa_rrsig); if (soa_valid == 0) { critical("No valid Signatur for SOA of '%s'", domainname); free(domainname); free(domaintrace); ldns_resolver_deep_free(res); ldns_rr_list_deep_free(rrl_domain_ns); ldns_rr_list_deep_free(rrl_domain_ns_rrsig); return checkState; } /* Validate NS */ for(i = 0; i < ldns_rr_list_rr_count(rrl_domain_ns_rrsig); i++) { rr = ldns_rr_list_rr(rrl_domain_ns_rrsig, i); status = ldns_verify_rrsig_keylist(rrl_domain_ns, rr, rrl_valid_keys, NULL); if (status == LDNS_STATUS_OK) ns_valid++; else if (mp_verbose > 0) fprintf(stderr, "ldns_verify_rrsig_keylist NS failed: %s\n", ldns_get_errorstr_by_id(status)); } ldns_rr_list_deep_free(rrl_domain_ns); ldns_rr_list_deep_free(rrl_domain_ns_rrsig); ldns_resolver_deep_free(res); if (ns_valid == 0) { critical("No valid Signatur for NS of '%s'", domainname); free(domainname); free(domaintrace); return checkState; } ok("Trust for '%s' successfull traces from '%s'", domainname, domaintrace); free(domainname); free(domaintrace); return checkState; }