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