/* * ldns-rrsig prints out the inception and expiration dates in a more readable * way than the normal RRSIG presentation format * * for a particulary domain * (c) NLnet Labs, 2005 - 2008 * See the file LICENSE for the license */ #include "config.h" #include static int usage(FILE *fp, char *prog) { fprintf(fp, "%s domain [type]\n", prog); fprintf(fp, " print out the inception and expiration dates\n"); fprintf(fp, " in a more human readable form\n"); fprintf(fp, " \tquery for RRSIG(), defaults to SOA\n"); return 0; } int main(int argc, char *argv[]) { ldns_resolver *res; ldns_resolver *localres; ldns_rdf *domain; ldns_pkt *p; ldns_rr_list *rrsig; ldns_rr_list *rrsig_type; ldns_rr_list *ns; ldns_rr_list *ns_ip; uint8_t i, j; ldns_rr_type t; char * type_name; time_t incep, expir; char incep_buf[26]; char expir_buf[26]; ldns_status s; p = NULL; rrsig = NULL; rrsig_type = NULL; domain = NULL; /* option parsing */ 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); } } if (argc == 3) { /* optional type arg */ type_name = strdup(argv[2]); t = ldns_rdf2rr_type( ldns_rdf_new_frm_str(LDNS_RDF_TYPE_TYPE, type_name)); if (t == 0) { fprintf(stderr, " *** %s is not a valid RR type\n", type_name); exit(EXIT_FAILURE); } } else { t = LDNS_RR_TYPE_SOA; type_name = "SOA"; } /* create a new resolver from /etc/resolv.conf */ s = ldns_resolver_new_frm_file(&localres, NULL); if (s != LDNS_STATUS_OK) { exit(EXIT_FAILURE); } /* first get the nameserver of the domain in question */ p = ldns_resolver_query(localres, domain, LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN, LDNS_RD); if (!p) { fprintf(stderr," *** Could not find any nameserver for %s", argv[1]); ldns_resolver_deep_free(localres); exit(EXIT_FAILURE); } ns = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER); if (!ns) { fprintf(stderr," *** Could not find any nameserver for %s", argv[1]); ldns_pkt_free(p); ldns_resolver_deep_free(localres); exit(EXIT_FAILURE); } /* use our local resolver to resolv the names in the for usage in our * new resolver */ res = ldns_resolver_new(); if (!res) { ldns_pkt_free(p); ldns_resolver_deep_free(localres); ldns_rr_list_deep_free(ns); exit(EXIT_FAILURE); } for(i = 0; i < ldns_rr_list_rr_count(ns); i++) { ns_ip = ldns_get_rr_list_addr_by_name(localres, ldns_rr_ns_nsdname(ldns_rr_list_rr(ns, i)), LDNS_RR_CLASS_IN, LDNS_RD); /* add these to new resolver */ for(j = 0; j < ldns_rr_list_rr_count(ns_ip); j++) { if (ldns_resolver_push_nameserver(res, ldns_rr_a_address(ldns_rr_list_rr(ns_ip, j))) != LDNS_STATUS_OK) { printf("Error adding nameserver to resolver\n"); ldns_pkt_free(p); ldns_resolver_deep_free(res); ldns_resolver_deep_free(localres); ldns_rr_list_deep_free(ns); exit(EXIT_FAILURE); } } ldns_rr_list_deep_free(ns_ip); } /* enable DNSSEC */ ldns_resolver_set_dnssec(res, true); /* also set CD, we want EVERYTHING! */ ldns_resolver_set_dnssec_cd(res, true); /* use the resolver to send it a query for the soa * records of the domain given on the command line */ ldns_pkt_free(p); p = ldns_resolver_query(res, domain, LDNS_RR_TYPE_RRSIG, LDNS_RR_CLASS_IN, LDNS_RD); ldns_rdf_deep_free(domain); if (!p) { ldns_resolver_deep_free(localres); ldns_rr_list_deep_free(ns); exit(EXIT_FAILURE); } else { /* retrieve the RRSIG records from the answer section of that * packet */ rrsig = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANSWER); if (!rrsig) { fprintf(stderr, " *** invalid answer name %s after RRSIG query for %s\n", argv[1], argv[1]); ldns_pkt_free(p); ldns_resolver_deep_free(res); ldns_rr_list_deep_free(ns); exit(EXIT_FAILURE); } else { rrsig_type = ldns_rr_list_new(); for(i = 0; i < ldns_rr_list_rr_count(rrsig); i++) { if (ldns_rdf2rr_type( ldns_rr_rrsig_typecovered( ldns_rr_list_rr(rrsig, i))) == t) { ldns_rr_list_push_rr(rrsig_type, ldns_rr_list_rr(rrsig, i)); } } if (ldns_rr_list_rr_count(rrsig_type) == 0) { fprintf(stderr, " *** No RRSIG(%s) type found\n", type_name); ldns_resolver_deep_free(localres); ldns_resolver_deep_free(res); ldns_pkt_free(p); ldns_rr_list_deep_free(ns); ldns_rr_list_free(rrsig); ldns_rr_list_deep_free(rrsig_type); exit(EXIT_FAILURE); } for(i = 0; i < ldns_rr_list_rr_count(rrsig_type); i++) { incep = ldns_rdf2native_time_t( ldns_rr_rrsig_inception( ldns_rr_list_rr(rrsig_type, i))); expir = ldns_rdf2native_time_t( ldns_rr_rrsig_expiration( ldns_rr_list_rr(rrsig_type, i))); /* convert to human readable */ ctime_r(&incep, incep_buf); ctime_r(&expir, expir_buf); /* kill the newline */ incep_buf[24] = '\0'; expir_buf[24] = '\0'; fprintf(stdout, "%s RRSIG(%s): %s - %s\n", argv[1], type_name, incep_buf, expir_buf); } ldns_rr_list_free(rrsig); ldns_rr_list_deep_free(rrsig_type); } } ldns_pkt_free(p); ldns_resolver_deep_free(localres); ldns_resolver_deep_free(res); ldns_rr_list_deep_free(ns); return 0; }