1 /*
2   Linux DNS client library implementation
3   Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
4   Copyright (C) 2006 Gerald Carter <jerry@samba.org>
5 
6      ** NOTE! The following LGPL license applies to the libaddns
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9 
10   This library is free software; you can redistribute it and/or
11   modify it under the terms of the GNU Lesser General Public
12   License as published by the Free Software Foundation; either
13   version 2.1 of the License, or (at your option) any later version.
14 
15   This library is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18   Lesser General Public License for more details.
19 
20   You should have received a copy of the GNU Lesser General Public
21   License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 */
23 
24 #include "dns.h"
25 #include "lib/util/genrand.h"
26 
dns_create_query(TALLOC_CTX * mem_ctx,const char * name,uint16_t q_type,uint16_t q_class,struct dns_request ** preq)27 DNS_ERROR dns_create_query( TALLOC_CTX *mem_ctx, const char *name,
28 			    uint16_t q_type, uint16_t q_class,
29 			    struct dns_request **preq )
30 {
31 	struct dns_request *req = NULL;
32 	struct dns_question *q = NULL;
33 	DNS_ERROR err;
34 
35 	if (!(req = talloc_zero(mem_ctx, struct dns_request)) ||
36 	    !(req->questions = talloc_array(req, struct dns_question *, 1)) ||
37 	    !(req->questions[0] = talloc(req->questions,
38 					 struct dns_question))) {
39 		TALLOC_FREE(req);
40 		return ERROR_DNS_NO_MEMORY;
41 	}
42 
43 	generate_random_buffer((uint8_t *)&req->id, sizeof(req->id));
44 
45 	req->num_questions = 1;
46 	q = req->questions[0];
47 
48 	err = dns_domain_name_from_string(q, name, &q->name);
49 	if (!ERR_DNS_IS_OK(err)) {
50 		TALLOC_FREE(req);
51 		return err;
52 	}
53 
54 	q->q_type = q_type;
55 	q->q_class = q_class;
56 
57 	*preq = req;
58 	return ERROR_DNS_SUCCESS;
59 }
60 
dns_create_update(TALLOC_CTX * mem_ctx,const char * name,struct dns_update_request ** preq)61 DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name,
62 			     struct dns_update_request **preq )
63 {
64 	struct dns_update_request *req = NULL;
65 	struct dns_zone *z = NULL;
66 	DNS_ERROR err;
67 
68 	if (!(req = talloc_zero(mem_ctx, struct dns_update_request)) ||
69 	    !(req->zones = talloc_array(req, struct dns_zone *, 1)) ||
70 	    !(req->zones[0] = talloc(req->zones, struct dns_zone))) {
71 		TALLOC_FREE(req);
72 		return ERROR_DNS_NO_MEMORY;
73 	}
74 
75 	req->id = random();
76 	req->flags = 0x2800;	/* Dynamic update */
77 
78 	req->num_zones = 1;
79 	z = req->zones[0];
80 
81 	err = dns_domain_name_from_string(z, name, &z->name);
82 	if (!ERR_DNS_IS_OK(err)) {
83 		TALLOC_FREE(req);
84 		return err;
85 	}
86 
87 	z->z_type = QTYPE_SOA;
88 	z->z_class = DNS_CLASS_IN;
89 
90 	*preq = req;
91 	return ERROR_DNS_SUCCESS;
92 }
93 
dns_create_rrec(TALLOC_CTX * mem_ctx,const char * name,uint16_t type,uint16_t r_class,uint32_t ttl,uint16_t data_length,uint8_t * data,struct dns_rrec ** prec)94 DNS_ERROR dns_create_rrec(TALLOC_CTX *mem_ctx, const char *name,
95 			  uint16_t type, uint16_t r_class, uint32_t ttl,
96 			  uint16_t data_length, uint8_t *data,
97 			  struct dns_rrec **prec)
98 {
99 	struct dns_rrec *rec = NULL;
100 	DNS_ERROR err;
101 
102 	if (!(rec = talloc(mem_ctx, struct dns_rrec))) {
103 		return ERROR_DNS_NO_MEMORY;
104 	}
105 
106 	err = dns_domain_name_from_string(rec, name, &rec->name);
107 	if (!(ERR_DNS_IS_OK(err))) {
108 		TALLOC_FREE(rec);
109 		return err;
110 	}
111 
112 	rec->type = type;
113 	rec->r_class = r_class;
114 	rec->ttl = ttl;
115 	rec->data_length = data_length;
116 	rec->data = talloc_move(rec, &data);
117 
118 	*prec = rec;
119 	return ERROR_DNS_SUCCESS;
120 }
121 
dns_create_a_record(TALLOC_CTX * mem_ctx,const char * host,uint32_t ttl,const struct sockaddr_storage * pss,struct dns_rrec ** prec)122 DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host,
123 			      uint32_t ttl, const struct sockaddr_storage *pss,
124 			      struct dns_rrec **prec)
125 {
126 	uint8_t *data;
127 	DNS_ERROR err;
128 	struct in_addr ip;
129 
130 	if (pss->ss_family != AF_INET) {
131 		return ERROR_DNS_INVALID_PARAMETER;
132 	}
133 
134 	ip = ((const struct sockaddr_in *)pss)->sin_addr;
135 	if (!(data = (uint8_t *)talloc_memdup(mem_ctx, (const void *)&ip.s_addr,
136 					    sizeof(ip.s_addr)))) {
137 		return ERROR_DNS_NO_MEMORY;
138 	}
139 
140 	err = dns_create_rrec(mem_ctx, host, QTYPE_A, DNS_CLASS_IN, ttl,
141 			      sizeof(ip.s_addr), data, prec);
142 
143 	if (!ERR_DNS_IS_OK(err)) {
144 		TALLOC_FREE(data);
145 	}
146 
147 	return err;
148 }
149 
dns_create_aaaa_record(TALLOC_CTX * mem_ctx,const char * host,uint32_t ttl,const struct sockaddr_storage * pss,struct dns_rrec ** prec)150 DNS_ERROR dns_create_aaaa_record(TALLOC_CTX *mem_ctx, const char *host,
151 				 uint32_t ttl, const struct sockaddr_storage *pss,
152 				 struct dns_rrec **prec)
153 {
154 #ifdef HAVE_IPV6
155 	uint8_t *data;
156 	DNS_ERROR err;
157 	struct in6_addr ip6;
158 
159 	if (pss->ss_family != AF_INET6) {
160 		return ERROR_DNS_INVALID_PARAMETER;
161 	}
162 
163 	ip6 = ((const struct sockaddr_in6 *)pss)->sin6_addr;
164 	if (!(data = (uint8_t *)talloc_memdup(mem_ctx, (const void *)&ip6.s6_addr,
165 					    sizeof(ip6.s6_addr)))) {
166 		return ERROR_DNS_NO_MEMORY;
167 	}
168 
169 	err = dns_create_rrec(mem_ctx, host, QTYPE_AAAA, DNS_CLASS_IN, ttl,
170 			      sizeof(ip6.s6_addr), data, prec);
171 
172 	if (!ERR_DNS_IS_OK(err)) {
173 		TALLOC_FREE(data);
174 	}
175 
176 	return err;
177 #else
178 	return ERROR_DNS_INVALID_PARAMETER;
179 #endif
180 }
181 
dns_create_name_in_use_record(TALLOC_CTX * mem_ctx,const char * name,const struct sockaddr_storage * ss,struct dns_rrec ** prec)182 DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx,
183 					const char *name,
184 					const struct sockaddr_storage *ss,
185 					struct dns_rrec **prec)
186 {
187 	if (ss != NULL) {
188 		switch (ss->ss_family) {
189 		case AF_INET:
190 			return dns_create_a_record(mem_ctx, name, 0, ss, prec);
191 #ifdef HAVE_IPV6
192 		case AF_INET6:
193 			return dns_create_aaaa_record(mem_ctx, name, 0, ss, prec);
194 #endif
195 		default:
196 			return ERROR_DNS_INVALID_PARAMETER;
197 		}
198 	}
199 
200 	return dns_create_rrec(mem_ctx, name, QTYPE_ANY, DNS_CLASS_IN, 0, 0,
201 			       NULL, prec);
202 }
203 
dns_create_name_not_in_use_record(TALLOC_CTX * mem_ctx,const char * name,uint32_t type,struct dns_rrec ** prec)204 DNS_ERROR dns_create_name_not_in_use_record(TALLOC_CTX *mem_ctx,
205 					    const char *name, uint32_t type,
206 					    struct dns_rrec **prec)
207 {
208 	return dns_create_rrec(mem_ctx, name, type, DNS_CLASS_NONE, 0,
209 			       0, NULL, prec);
210 }
211 
dns_create_delete_record(TALLOC_CTX * mem_ctx,const char * name,uint16_t type,uint16_t r_class,struct dns_rrec ** prec)212 DNS_ERROR dns_create_delete_record(TALLOC_CTX *mem_ctx, const char *name,
213 				   uint16_t type, uint16_t r_class,
214 				   struct dns_rrec **prec)
215 {
216 	return dns_create_rrec(mem_ctx, name, type, r_class, 0, 0, NULL, prec);
217 }
218 
dns_create_tkey_record(TALLOC_CTX * mem_ctx,const char * keyname,const char * algorithm_name,time_t inception,time_t expiration,uint16_t mode,uint16_t error,uint16_t key_length,const uint8_t * key,struct dns_rrec ** prec)219 DNS_ERROR dns_create_tkey_record(TALLOC_CTX *mem_ctx, const char *keyname,
220 				 const char *algorithm_name, time_t inception,
221 				 time_t expiration, uint16_t mode, uint16_t error,
222 				 uint16_t key_length, const uint8_t *key,
223 				 struct dns_rrec **prec)
224 {
225 	struct dns_buffer *buf = NULL;
226 	struct dns_domain_name *algorithm = NULL;
227 	DNS_ERROR err;
228 
229 	if (!(buf = dns_create_buffer(mem_ctx))) {
230 		return ERROR_DNS_NO_MEMORY;
231 	}
232 
233 	err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
234 	if (!ERR_DNS_IS_OK(err)) goto error;
235 
236 	dns_marshall_domain_name(buf, algorithm);
237 	dns_marshall_uint32(buf, inception);
238 	dns_marshall_uint32(buf, expiration);
239 	dns_marshall_uint16(buf, mode);
240 	dns_marshall_uint16(buf, error);
241 	dns_marshall_uint16(buf, key_length);
242 	dns_marshall_buffer(buf, key, key_length);
243 	dns_marshall_uint16(buf, 0); /* Other Size */
244 
245 	if (!ERR_DNS_IS_OK(buf->error)) {
246 		err = buf->error;
247 		goto error;
248 	}
249 
250 	err = dns_create_rrec(mem_ctx, keyname, QTYPE_TKEY, DNS_CLASS_ANY, 0,
251 			      buf->offset, buf->data, prec);
252 
253  error:
254 	TALLOC_FREE(buf);
255 	return err;
256 }
257 
dns_unmarshall_tkey_record(TALLOC_CTX * mem_ctx,struct dns_rrec * rec,struct dns_tkey_record ** ptkey)258 DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
259 				     struct dns_tkey_record **ptkey)
260 {
261 	struct dns_tkey_record *tkey;
262 	struct dns_buffer buf;
263 	uint32_t tmp_inception, tmp_expiration;
264 
265 	if (!(tkey = talloc(mem_ctx, struct dns_tkey_record))) {
266 		return ERROR_DNS_NO_MEMORY;
267 	}
268 
269 	buf.data = rec->data;
270 	buf.size = rec->data_length;
271 	buf.offset = 0;
272 	buf.error = ERROR_DNS_SUCCESS;
273 
274 	dns_unmarshall_domain_name(tkey, &buf, &tkey->algorithm);
275 	dns_unmarshall_uint32(&buf, &tmp_inception);
276 	dns_unmarshall_uint32(&buf, &tmp_expiration);
277 	dns_unmarshall_uint16(&buf, &tkey->mode);
278 	dns_unmarshall_uint16(&buf, &tkey->error);
279 	dns_unmarshall_uint16(&buf, &tkey->key_length);
280 
281 	if (!ERR_DNS_IS_OK(buf.error)) goto error;
282 
283 	if (tkey->key_length) {
284 		if (!(tkey->key = talloc_array(tkey, uint8_t, tkey->key_length))) {
285 			buf.error = ERROR_DNS_NO_MEMORY;
286 			goto error;
287 		}
288 	} else {
289 		tkey->key = NULL;
290 	}
291 
292 	dns_unmarshall_buffer(&buf, tkey->key, tkey->key_length);
293 	if (!ERR_DNS_IS_OK(buf.error)) goto error;
294 
295 	tkey->inception = (time_t)tmp_inception;
296 	tkey->expiration = (time_t)tmp_expiration;
297 
298 	*ptkey = tkey;
299 	return ERROR_DNS_SUCCESS;
300 
301  error:
302 	TALLOC_FREE(tkey);
303 	return buf.error;
304 }
305 
dns_create_tsig_record(TALLOC_CTX * mem_ctx,const char * keyname,const char * algorithm_name,time_t time_signed,uint16_t fudge,uint16_t mac_length,const uint8_t * mac,uint16_t original_id,uint16_t error,struct dns_rrec ** prec)306 DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname,
307 				 const char *algorithm_name,
308 				 time_t time_signed, uint16_t fudge,
309 				 uint16_t mac_length, const uint8_t *mac,
310 				 uint16_t original_id, uint16_t error,
311 				 struct dns_rrec **prec)
312 {
313 	struct dns_buffer *buf = NULL;
314 	struct dns_domain_name *algorithm = NULL;
315 	DNS_ERROR err;
316 
317 	if (!(buf = dns_create_buffer(mem_ctx))) {
318 		return ERROR_DNS_NO_MEMORY;
319 	}
320 
321 	err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
322 	if (!ERR_DNS_IS_OK(err)) goto error;
323 
324 	dns_marshall_domain_name(buf, algorithm);
325 	dns_marshall_uint16(buf, 0); /* time prefix */
326 	dns_marshall_uint32(buf, time_signed);
327 	dns_marshall_uint16(buf, fudge);
328 	dns_marshall_uint16(buf, mac_length);
329 	dns_marshall_buffer(buf, mac, mac_length);
330 	dns_marshall_uint16(buf, original_id);
331 	dns_marshall_uint16(buf, error);
332 	dns_marshall_uint16(buf, 0); /* Other Size */
333 
334 	if (!ERR_DNS_IS_OK(buf->error)) {
335 		err = buf->error;
336 		goto error;
337 	}
338 
339 	err = dns_create_rrec(mem_ctx, keyname, QTYPE_TSIG, DNS_CLASS_ANY, 0,
340 			      buf->offset, buf->data, prec);
341 
342  error:
343 	TALLOC_FREE(buf);
344 	return err;
345 }
346 
dns_add_rrec(TALLOC_CTX * mem_ctx,struct dns_rrec * rec,uint16_t * num_records,struct dns_rrec *** records)347 DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
348 		       uint16_t *num_records, struct dns_rrec ***records)
349 {
350 	struct dns_rrec **new_records;
351 
352 	if (!(new_records = talloc_realloc(mem_ctx, *records,
353 						 struct dns_rrec *,
354 						 (*num_records)+1))) {
355 		return ERROR_DNS_NO_MEMORY;
356 	}
357 
358 	new_records[*num_records] = talloc_move(new_records, &rec);
359 
360 	*num_records += 1;
361 	*records = new_records;
362 	return ERROR_DNS_SUCCESS;
363 }
364 
365 /*
366  * Create a request that probes a server whether the list of IP addresses
367  * provides meets our expectations
368  */
369 
dns_create_probe(TALLOC_CTX * mem_ctx,const char * zone,const char * host,int num_ips,const struct sockaddr_storage * sslist,struct dns_update_request ** preq)370 DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone,
371 			   const char *host, int num_ips,
372 			   const struct sockaddr_storage *sslist,
373 			   struct dns_update_request **preq)
374 {
375 	struct dns_update_request *req = NULL;
376 	struct dns_rrec *rec = NULL;
377 	DNS_ERROR err;
378 	uint16_t i;
379 
380 	err = dns_create_update(mem_ctx, zone, &req);
381 	if (!ERR_DNS_IS_OK(err)) return err;
382 
383 	err = dns_create_name_not_in_use_record(req, host, QTYPE_CNAME,	&rec);
384 	if (!ERR_DNS_IS_OK(err)) goto error;
385 
386 	err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
387 	if (!ERR_DNS_IS_OK(err)) goto error;
388 
389 	for (i=0; i<num_ips; i++) {
390 		err = dns_create_name_in_use_record(req, host,
391 						    &sslist[i], &rec);
392 		if (!ERR_DNS_IS_OK(err)) goto error;
393 
394 		err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
395 		if (!ERR_DNS_IS_OK(err)) goto error;
396 	}
397 
398 	*preq = req;
399 	return ERROR_DNS_SUCCESS;
400 
401  error:
402 	TALLOC_FREE(req);
403 	return err;
404 }
405 
dns_create_update_request(TALLOC_CTX * mem_ctx,const char * domainname,const char * hostname,const struct sockaddr_storage * ss_addrs,size_t num_addrs,struct dns_update_request ** preq)406 DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx,
407 				    const char *domainname,
408 				    const char *hostname,
409 				    const struct sockaddr_storage *ss_addrs,
410 				    size_t num_addrs,
411 				    struct dns_update_request **preq)
412 {
413 	struct dns_update_request *req = NULL;
414 	struct dns_rrec *rec = NULL;
415 	DNS_ERROR err;
416 	size_t i;
417 
418 	err = dns_create_update(mem_ctx, domainname, &req);
419 	if (!ERR_DNS_IS_OK(err)) return err;
420 
421 	/*
422 	 * Use the same prereq as WinXP -- No CNAME records for this host.
423 	 */
424 
425 	err = dns_create_rrec(req, hostname, QTYPE_CNAME, DNS_CLASS_NONE,
426 			      0, 0, NULL, &rec);
427 	if (!ERR_DNS_IS_OK(err)) goto error;
428 
429 	err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
430 	if (!ERR_DNS_IS_OK(err)) goto error;
431 
432 	/*
433 	 * Delete any existing A records
434 	 */
435 
436 	err = dns_create_delete_record(req, hostname, QTYPE_A, DNS_CLASS_ANY,
437 				       &rec);
438 	if (!ERR_DNS_IS_OK(err)) goto error;
439 
440 	err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
441 	if (!ERR_DNS_IS_OK(err)) goto error;
442 
443 	/*
444 	 * .. and add our IPs
445 	 */
446 
447 	for ( i=0; i<num_addrs; i++ ) {
448 
449 		switch(ss_addrs[i].ss_family) {
450 		case AF_INET:
451 			err = dns_create_a_record(req, hostname, 3600, &ss_addrs[i], &rec);
452 			break;
453 #ifdef HAVE_IPV6
454 		case AF_INET6:
455 			err = dns_create_aaaa_record(req, hostname, 3600, &ss_addrs[i], &rec);
456 			break;
457 #endif
458 		default:
459 			continue;
460 		}
461 		if (!ERR_DNS_IS_OK(err))
462 			goto error;
463 
464 		err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
465 		if (!ERR_DNS_IS_OK(err))
466 			goto error;
467 	}
468 
469 	*preq = req;
470 	return ERROR_DNS_SUCCESS;
471 
472  error:
473 	TALLOC_FREE(req);
474 	return err;
475 }
476