1 /*
2  * ldns-rrsig prints out the inception and expiration dates in a more readable
3  * way than the normal RRSIG presentation format
4  *
5  * for a particularly domain
6  * (c) NLnet Labs, 2005 - 2008
7  * See the file LICENSE for the license
8  */
9 
10 #include "config.h"
11 
12 #include <ldns/ldns.h>
13 
14 static int
usage(FILE * fp,char * prog)15 usage(FILE *fp, char *prog) {
16 	fprintf(fp, "%s domain [type]\n", prog);
17 	fprintf(fp, "  print out the inception and expiration dates\n");
18 	fprintf(fp, "  in a more human readable form\n");
19 	fprintf(fp, "  <type>\tquery for RRSIG(<type>), defaults to SOA\n");
20 	return 0;
21 }
22 
23 int
main(int argc,char * argv[])24 main(int argc, char *argv[])
25 {
26 	ldns_resolver *res;
27 	ldns_resolver *localres;
28 	ldns_rdf *domain;
29 	ldns_pkt *p;
30 	ldns_rr_list *rrsig;
31 	ldns_rr_list *rrsig_type;
32 	ldns_rr_list *ns;
33 	ldns_rr_list *ns_ip;
34 	uint8_t i, j;
35 	ldns_rr_type t;
36 	const char * type_name;
37 	struct tm incep, expir;
38 	char incep_buf[26];
39 	char expir_buf[26];
40 	ldns_status s;
41 	time_t now = time(NULL);
42 
43 	p = NULL;
44 	rrsig = NULL;
45 	rrsig_type = NULL;
46 	domain = NULL;
47 
48 	/* option parsing */
49 
50 	if (argc < 2) {
51 		usage(stdout, argv[0]);
52 		exit(EXIT_FAILURE);
53 	} else {
54 		/* create a rdf from the command line arg */
55 		domain = ldns_dname_new_frm_str(argv[1]);
56 		if (!domain) {
57 			usage(stdout, argv[0]);
58 			exit(EXIT_FAILURE);
59 		}
60 	}
61 
62 	if (argc == 3) {
63 		/* optional type arg */
64 		type_name = argv[2];
65 		t = ldns_rdf2rr_type(
66 			ldns_rdf_new_frm_str(LDNS_RDF_TYPE_TYPE, type_name));
67 		if (t == 0) {
68 			fprintf(stderr, " *** %s is not a valid RR type\n", type_name);
69 			exit(EXIT_FAILURE);
70 		}
71 	} else {
72 		t = LDNS_RR_TYPE_SOA;
73 		type_name = "SOA";
74 	}
75 
76 	/* create a new resolver from /etc/resolv.conf */
77 	s = ldns_resolver_new_frm_file(&localres, NULL);
78 	if (s != LDNS_STATUS_OK) {
79 		exit(EXIT_FAILURE);
80 	}
81 
82 	/* first get the nameserver of the domain in question */
83 	p = ldns_resolver_query(localres, domain, LDNS_RR_TYPE_NS,
84 				LDNS_RR_CLASS_IN, LDNS_RD);
85 	if (!p) {
86 		fprintf(stderr," *** Could not find any nameserver for %s", argv[1]);
87 		ldns_resolver_deep_free(localres);
88 		exit(EXIT_FAILURE);
89 	}
90 	ns = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER);
91 
92 	if (!ns) {
93 		fprintf(stderr," *** Could not find any nameserver for %s", argv[1]);
94 		ldns_pkt_free(p);
95 		ldns_resolver_deep_free(localres);
96 		exit(EXIT_FAILURE);
97 	}
98 
99 	/* use our local resolver to resolv the names in the for usage in our
100 	 * new resolver */
101 	res = ldns_resolver_new();
102 	if (!res) {
103 		ldns_pkt_free(p);
104 		ldns_resolver_deep_free(localres);
105 		ldns_rr_list_deep_free(ns);
106 		exit(EXIT_FAILURE);
107 	}
108 	for(i = 0; i < ldns_rr_list_rr_count(ns); i++) {
109 		ns_ip = ldns_get_rr_list_addr_by_name(localres,
110 			ldns_rr_ns_nsdname(ldns_rr_list_rr(ns, i)),
111 			LDNS_RR_CLASS_IN, LDNS_RD);
112 		/* add these to new resolver */
113 		for(j = 0; j < ldns_rr_list_rr_count(ns_ip); j++) {
114 			if (ldns_resolver_push_nameserver(res,
115 				ldns_rr_a_address(ldns_rr_list_rr(ns_ip, j))) != LDNS_STATUS_OK) {
116 				printf("Error adding nameserver to resolver\n");
117                 		ldns_pkt_free(p);
118                 		ldns_resolver_deep_free(res);
119                                 ldns_resolver_deep_free(localres);
120                 		ldns_rr_list_deep_free(ns);
121 				exit(EXIT_FAILURE);
122 			}
123 		}
124        		ldns_rr_list_deep_free(ns_ip);
125 
126 	}
127 
128 	/* enable DNSSEC */
129 	ldns_resolver_set_dnssec(res, true);
130 	/* also set CD, we want EVERYTHING! */
131 	ldns_resolver_set_dnssec_cd(res, true);
132 
133 	/* use the resolver to send it a query for the soa
134 	 * records of the domain given on the command line
135 	 */
136 	ldns_pkt_free(p);
137 	p = ldns_resolver_query(res, domain, LDNS_RR_TYPE_RRSIG, LDNS_RR_CLASS_IN, LDNS_RD);
138 
139 	ldns_rdf_deep_free(domain);
140 
141         if (!p)  {
142 		ldns_resolver_deep_free(localres);
143     		ldns_rr_list_deep_free(ns);
144 		exit(EXIT_FAILURE);
145         } else {
146 		/* retrieve the RRSIG records from the answer section of that
147 		 * packet
148 		 */
149 		rrsig = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANSWER);
150 		if (!rrsig) {
151 			fprintf(stderr,
152 					" *** invalid answer name %s after RRSIG query for %s\n",
153 					argv[1], argv[1]);
154                         ldns_pkt_free(p);
155                         ldns_resolver_deep_free(res);
156         		ldns_rr_list_deep_free(ns);
157 			exit(EXIT_FAILURE);
158 		} else {
159 			rrsig_type = ldns_rr_list_new();
160 
161 			for(i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
162 				if (ldns_rdf2rr_type(
163 					ldns_rr_rrsig_typecovered(
164 					ldns_rr_list_rr(rrsig, i))) == t) {
165 					ldns_rr_list_push_rr(rrsig_type,
166 						ldns_rr_list_rr(rrsig, i));
167 				}
168 			}
169 			if (ldns_rr_list_rr_count(rrsig_type) == 0) {
170 				fprintf(stderr, " *** No RRSIG(%s) type found\n",
171 					type_name);
172                 		ldns_resolver_deep_free(localres);
173                 		ldns_resolver_deep_free(res);
174                 		ldns_pkt_free(p);
175                 		ldns_rr_list_deep_free(ns);
176                 		ldns_rr_list_free(rrsig);
177                 		ldns_rr_list_deep_free(rrsig_type);
178 				exit(EXIT_FAILURE);
179 			}
180 
181 			for(i = 0; i < ldns_rr_list_rr_count(rrsig_type); i++) {
182 				memset(&incep, 0, sizeof(incep));
183 				if (ldns_serial_arithmetics_gmtime_r(
184 						ldns_rdf2native_time_t(
185 						ldns_rr_rrsig_inception(
186 						ldns_rr_list_rr(rrsig_type, i))),
187 					       	now, &incep
188 					)
189 				    && asctime_r(&incep, incep_buf)) {
190 					incep_buf[24] = '\0';
191 				} else {
192 					incep_buf[0] = '\0';
193 				}
194 				memset(&expir, 0, sizeof(expir));
195 				if (ldns_serial_arithmetics_gmtime_r(
196 						ldns_rdf2native_time_t(
197 						ldns_rr_rrsig_expiration(
198 						ldns_rr_list_rr(rrsig_type, i))),
199 					       	now, &expir
200 					)
201 				    && asctime_r(&expir, expir_buf)) {
202 					expir_buf[24] = '\0';
203 				} else {
204 					expir_buf[0] = '\0';
205 				}
206 
207 				fprintf(stdout, "%s RRSIG(%s):  %s - %s\n",
208 					argv[1], type_name, incep_buf, expir_buf);
209 			}
210                         ldns_rr_list_free(rrsig);
211                         ldns_rr_list_deep_free(rrsig_type);
212 		}
213         }
214         ldns_pkt_free(p);
215         ldns_resolver_deep_free(localres);
216         ldns_resolver_deep_free(res);
217         ldns_rr_list_deep_free(ns);
218         return 0;
219 }
220