diff options
Diffstat (limited to 'openbsd-compat/getrrsetbyname-ldns.c')
-rw-r--r-- | openbsd-compat/getrrsetbyname-ldns.c | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/openbsd-compat/getrrsetbyname-ldns.c b/openbsd-compat/getrrsetbyname-ldns.c new file mode 100644 index 000000000..8ce5678c9 --- /dev/null +++ b/openbsd-compat/getrrsetbyname-ldns.c | |||
@@ -0,0 +1,284 @@ | |||
1 | /* $OpenBSD: getrrsetbyname.c,v 1.10 2005/03/30 02:58:28 tedu Exp $ */ | ||
2 | |||
3 | /* | ||
4 | * Copyright (c) 2007 Simon Vallet / Genoscope <svallet@genoscope.cns.fr> | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions | ||
8 | * are met: | ||
9 | * | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
27 | */ | ||
28 | |||
29 | /* | ||
30 | * Portions Copyright (c) 1999-2001 Internet Software Consortium. | ||
31 | * | ||
32 | * Permission to use, copy, modify, and distribute this software for any | ||
33 | * purpose with or without fee is hereby granted, provided that the above | ||
34 | * copyright notice and this permission notice appear in all copies. | ||
35 | * | ||
36 | * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM | ||
37 | * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL | ||
38 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL | ||
39 | * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
40 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING | ||
41 | * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, | ||
42 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | ||
43 | * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
44 | */ | ||
45 | |||
46 | #include "includes.h" | ||
47 | |||
48 | #if !defined (HAVE_GETRRSETBYNAME) && defined (HAVE_LDNS) | ||
49 | |||
50 | #include <stdlib.h> | ||
51 | #include <string.h> | ||
52 | |||
53 | #include <ldns/ldns.h> | ||
54 | |||
55 | #include "getrrsetbyname.h" | ||
56 | #include "log.h" | ||
57 | #include "xmalloc.h" | ||
58 | |||
59 | #define malloc(x) (xmalloc(x)) | ||
60 | #define calloc(x, y) (xcalloc((x),(y))) | ||
61 | #define free(x) (xfree(x)) | ||
62 | |||
63 | int | ||
64 | getrrsetbyname(const char *hostname, unsigned int rdclass, | ||
65 | unsigned int rdtype, unsigned int flags, | ||
66 | struct rrsetinfo **res) | ||
67 | { | ||
68 | int result; | ||
69 | unsigned int i, j, index_ans, index_sig; | ||
70 | struct rrsetinfo *rrset = NULL; | ||
71 | struct rdatainfo *rdata; | ||
72 | size_t len; | ||
73 | ldns_resolver *ldns_res; | ||
74 | ldns_rdf *domain = NULL; | ||
75 | ldns_pkt *pkt = NULL; | ||
76 | ldns_rr_list *rrsigs = NULL, *rrdata = NULL; | ||
77 | ldns_status err; | ||
78 | ldns_rr *rr; | ||
79 | |||
80 | /* check for invalid class and type */ | ||
81 | if (rdclass > 0xffff || rdtype > 0xffff) { | ||
82 | result = ERRSET_INVAL; | ||
83 | goto fail; | ||
84 | } | ||
85 | |||
86 | /* don't allow queries of class or type ANY */ | ||
87 | if (rdclass == 0xff || rdtype == 0xff) { | ||
88 | result = ERRSET_INVAL; | ||
89 | goto fail; | ||
90 | } | ||
91 | |||
92 | /* don't allow flags yet, unimplemented */ | ||
93 | if (flags) { | ||
94 | result = ERRSET_INVAL; | ||
95 | goto fail; | ||
96 | } | ||
97 | |||
98 | /* Initialize resolver from resolv.conf */ | ||
99 | domain = ldns_dname_new_frm_str(hostname); | ||
100 | if ((err = ldns_resolver_new_frm_file(&ldns_res, NULL)) != \ | ||
101 | LDNS_STATUS_OK) { | ||
102 | result = ERRSET_FAIL; | ||
103 | goto fail; | ||
104 | } | ||
105 | |||
106 | #ifdef LDNS_DEBUG | ||
107 | ldns_resolver_set_debug(ldns_res, true); | ||
108 | #endif /* LDNS_DEBUG */ | ||
109 | |||
110 | ldns_resolver_set_dnssec(ldns_res, true); /* Use DNSSEC */ | ||
111 | |||
112 | /* make query */ | ||
113 | pkt = ldns_resolver_query(ldns_res, domain, rdtype, rdclass, LDNS_RD); | ||
114 | |||
115 | /*** TODO: finer errcodes -- see original **/ | ||
116 | if (!pkt || ldns_pkt_ancount(pkt) < 1) { | ||
117 | result = ERRSET_FAIL; | ||
118 | goto fail; | ||
119 | } | ||
120 | |||
121 | /* initialize rrset */ | ||
122 | rrset = calloc(1, sizeof(struct rrsetinfo)); | ||
123 | if (rrset == NULL) { | ||
124 | result = ERRSET_NOMEMORY; | ||
125 | goto fail; | ||
126 | } | ||
127 | |||
128 | rrdata = ldns_pkt_rr_list_by_type(pkt, rdtype, LDNS_SECTION_ANSWER); | ||
129 | rrset->rri_nrdatas = ldns_rr_list_rr_count(rrdata); | ||
130 | if (!rrset->rri_nrdatas) { | ||
131 | result = ERRSET_NODATA; | ||
132 | goto fail; | ||
133 | } | ||
134 | |||
135 | /* copy name from answer section */ | ||
136 | len = ldns_rdf_size(ldns_rr_owner(ldns_rr_list_rr(rrdata, 0))); | ||
137 | if ((rrset->rri_name = malloc(len)) == NULL) { | ||
138 | result = ERRSET_NOMEMORY; | ||
139 | goto fail; | ||
140 | } | ||
141 | memcpy(rrset->rri_name, | ||
142 | ldns_rdf_data(ldns_rr_owner(ldns_rr_list_rr(rrdata, 0))), len); | ||
143 | |||
144 | rrset->rri_rdclass = ldns_rr_get_class(ldns_rr_list_rr(rrdata, 0)); | ||
145 | rrset->rri_rdtype = ldns_rr_get_type(ldns_rr_list_rr(rrdata, 0)); | ||
146 | rrset->rri_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrdata, 0)); | ||
147 | |||
148 | debug2("ldns: got %u answers from DNS", rrset->rri_nrdatas); | ||
149 | |||
150 | /* Check for authenticated data */ | ||
151 | if (ldns_pkt_ad(pkt)) { | ||
152 | rrset->rri_flags |= RRSET_VALIDATED; | ||
153 | } else { /* AD is not set, try autonomous validation */ | ||
154 | ldns_rr_list * trusted_keys = ldns_rr_list_new(); | ||
155 | |||
156 | debug2("ldns: trying to validate RRset"); | ||
157 | /* Get eventual sigs */ | ||
158 | rrsigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG, | ||
159 | LDNS_SECTION_ANSWER); | ||
160 | |||
161 | rrset->rri_nsigs = ldns_rr_list_rr_count(rrsigs); | ||
162 | debug2("ldns: got %u signature(s) (RRTYPE %u) from DNS", | ||
163 | rrset->rri_nsigs, LDNS_RR_TYPE_RRSIG); | ||
164 | |||
165 | if ((err = ldns_verify_trusted(ldns_res, rrdata, rrsigs, | ||
166 | trusted_keys)) == LDNS_STATUS_OK) { | ||
167 | rrset->rri_flags |= RRSET_VALIDATED; | ||
168 | debug2("ldns: RRset is signed with a valid key"); | ||
169 | } else { | ||
170 | debug2("ldns: RRset validation failed: %s", | ||
171 | ldns_get_errorstr_by_id(err)); | ||
172 | } | ||
173 | |||
174 | ldns_rr_list_deep_free(trusted_keys); | ||
175 | } | ||
176 | |||
177 | /* allocate memory for answers */ | ||
178 | rrset->rri_rdatas = calloc(rrset->rri_nrdatas, | ||
179 | sizeof(struct rdatainfo)); | ||
180 | |||
181 | if (rrset->rri_rdatas == NULL) { | ||
182 | result = ERRSET_NOMEMORY; | ||
183 | goto fail; | ||
184 | } | ||
185 | |||
186 | /* allocate memory for signatures */ | ||
187 | if (rrset->rri_nsigs > 0) { | ||
188 | rrset->rri_sigs = calloc(rrset->rri_nsigs, | ||
189 | sizeof(struct rdatainfo)); | ||
190 | |||
191 | if (rrset->rri_sigs == NULL) { | ||
192 | result = ERRSET_NOMEMORY; | ||
193 | goto fail; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | /* copy answers & signatures */ | ||
198 | for (i=0, index_ans=0, index_sig=0; i< pkt->_header->_ancount; i++) { | ||
199 | rdata = NULL; | ||
200 | rr = ldns_rr_list_rr(ldns_pkt_answer(pkt), i); | ||
201 | |||
202 | if (ldns_rr_get_class(rr) == rrset->rri_rdclass && | ||
203 | ldns_rr_get_type(rr) == rrset->rri_rdtype) { | ||
204 | rdata = &rrset->rri_rdatas[index_ans++]; | ||
205 | } | ||
206 | |||
207 | if (rr->_rr_class == rrset->rri_rdclass && | ||
208 | rr->_rr_type == LDNS_RR_TYPE_RRSIG) { | ||
209 | rdata = &rrset->rri_sigs[index_sig++]; | ||
210 | } | ||
211 | |||
212 | if (rdata) { | ||
213 | size_t rdata_offset = 0; | ||
214 | |||
215 | rdata->rdi_length = 0; | ||
216 | for (j=0; j< rr->_rd_count; j++) { | ||
217 | rdata->rdi_length += | ||
218 | ldns_rdf_size(ldns_rr_rdf(rr, j)); | ||
219 | } | ||
220 | |||
221 | rdata->rdi_data = malloc(rdata->rdi_length); | ||
222 | if (rdata->rdi_data == NULL) { | ||
223 | result = ERRSET_NOMEMORY; | ||
224 | goto fail; | ||
225 | } | ||
226 | |||
227 | /* Re-create the raw DNS RDATA */ | ||
228 | for (j=0; j< rr->_rd_count; j++) { | ||
229 | len = ldns_rdf_size(ldns_rr_rdf(rr, j)); | ||
230 | memcpy(rdata->rdi_data + rdata_offset, | ||
231 | ldns_rdf_data(ldns_rr_rdf(rr, j)), len); | ||
232 | rdata_offset += len; | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | |||
237 | *res = rrset; | ||
238 | result = ERRSET_SUCCESS; | ||
239 | |||
240 | fail: | ||
241 | /* freerrset(rrset); */ | ||
242 | ldns_rdf_deep_free(domain); | ||
243 | ldns_pkt_free(pkt); | ||
244 | ldns_rr_list_deep_free(rrsigs); | ||
245 | ldns_rr_list_deep_free(rrdata); | ||
246 | ldns_resolver_deep_free(ldns_res); | ||
247 | |||
248 | return result; | ||
249 | } | ||
250 | |||
251 | |||
252 | void | ||
253 | freerrset(struct rrsetinfo *rrset) | ||
254 | { | ||
255 | u_int16_t i; | ||
256 | |||
257 | if (rrset == NULL) | ||
258 | return; | ||
259 | |||
260 | if (rrset->rri_rdatas) { | ||
261 | for (i = 0; i < rrset->rri_nrdatas; i++) { | ||
262 | if (rrset->rri_rdatas[i].rdi_data == NULL) | ||
263 | break; | ||
264 | free(rrset->rri_rdatas[i].rdi_data); | ||
265 | } | ||
266 | free(rrset->rri_rdatas); | ||
267 | } | ||
268 | |||
269 | if (rrset->rri_sigs) { | ||
270 | for (i = 0; i < rrset->rri_nsigs; i++) { | ||
271 | if (rrset->rri_sigs[i].rdi_data == NULL) | ||
272 | break; | ||
273 | free(rrset->rri_sigs[i].rdi_data); | ||
274 | } | ||
275 | free(rrset->rri_sigs); | ||
276 | } | ||
277 | |||
278 | if (rrset->rri_name) | ||
279 | free(rrset->rri_name); | ||
280 | free(rrset); | ||
281 | } | ||
282 | |||
283 | |||
284 | #endif /* !defined (HAVE_GETRRSETBYNAME) && defined (HAVE_LDNS) */ | ||