1#ifndef __APPLE__
2static const char rcsid[] = "$Header: /Users/Shared/libresolv_2/libresolv/dst_support.c,v 1.1 2006/03/01 19:01:36 majka Exp $";
3#endif
4
5
6/*
7 * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
8 *
9 * Permission to use, copy modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
14 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL
16 * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
17 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
18 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
19 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
20 * WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
21 */
22
23#ifndef __APPLE__
24#include "port_before.h"
25#endif
26
27#include <stdio.h>
28#include <unistd.h>
29#include <memory.h>
30#include <string.h>
31#include <errno.h>
32#include <sys/stat.h>
33#include <netinet/in.h>
34#include <arpa/nameser.h>
35#include <resolv.h>
36
37#include "dst_internal.h"
38
39#ifndef __APPLE__
40#include "port_after.h"
41#endif
42
43/*
44 * dst_s_verify_str()
45 *     Validate that the input string(*str) is at the head of the input
46 *     buffer(**buf).  If so, move the buffer head pointer (*buf) to
47 *     the first byte of data following the string(*str).
48 * Parameters
49 *     buf     Input buffer.
50 *     str     Input string.
51 * Return
52 *	0       *str is not the head of **buff
53 *	1       *str is the head of **buff, *buf is is advanced to
54 *	the tail of **buf.
55 */
56
57int
58dst_s_verify_str(const char **buf, const char *str)
59{
60	int b, s;
61	if (*buf == NULL)	/* error checks */
62		return (0);
63	if (str == NULL || *str == '\0')
64		return (1);
65
66	b = strlen(*buf);	/* get length of strings */
67	s = strlen(str);
68	if (s > b || strncmp(*buf, str, s))	/* check if same */
69		return (0);	/* not a match */
70	(*buf) += s;		/* advance pointer */
71	return (1);
72}
73
74#ifdef _UNUSED_API_
75/*
76 * dst_s_calculate_bits
77 *     Given a binary number represented in a u_char[], determine
78 *     the number of significant bits used.
79 * Parameters
80 *     str       An input character string containing a binary number.
81 *     max_bits The maximum possible significant bits.
82 * Return
83 *     N       The number of significant bits in str.
84 */
85
86int
87dst_s_calculate_bits(const u_char *str, const int max_bits)
88{
89	const u_char *p = str;
90	u_char i, j = 0x80;
91	int bits;
92	for (bits = max_bits; *p == 0x00 && bits > 0; p++)
93		bits -= 8;
94	for (i = *p; (i & j) != j; j >>= 1)
95		bits--;
96	return (bits);
97}
98#endif
99
100/*
101 * calculates a checksum used in dst for an id.
102 * takes an array of bytes and a length.
103 * returns a 16  bit checksum.
104 */
105#ifdef __APPLE__
106static
107#endif
108u_int16_t
109dst_s_id_calc(const u_char *key, const int keysize)
110{
111	u_int32_t ac;
112	const u_char *kp = key;
113	int size = keysize;
114
115	if (!key || (keysize <= 0))
116		return (-1);
117
118	for (ac = 0; size > 1; size -= 2, kp += 2)
119		ac += ((*kp) << 8) + *(kp + 1);
120
121	if (size > 0)
122		ac += ((*kp) << 8);
123	ac += (ac >> 16) & 0xffff;
124
125	return (ac & 0xffff);
126}
127
128/*
129 * dst_s_dns_key_id() Function to calculate DNSSEC footprint from KEY record
130 *   rdata
131 * Input:
132 *	dns_key_rdata: the raw data in wire format
133 *      rdata_len: the size of the input data
134 * Output:
135 *      the key footprint/id calculated from the key data
136 */
137u_int16_t
138dst_s_dns_key_id(const u_char *dns_key_rdata, const int rdata_len)
139{
140	if (!dns_key_rdata)
141		return 0;
142
143	/* compute id */
144	if (dns_key_rdata[3] == KEY_RSA)	/* Algorithm RSA */
145		return dst_s_get_int16((const u_char *)
146				       &dns_key_rdata[rdata_len - 3]);
147	else if (dns_key_rdata[3] == KEY_HMAC_MD5)
148		/* compatibility */
149		return 0;
150	else
151		/* compute a checksum on the key part of the key rr */
152		return dst_s_id_calc(dns_key_rdata, rdata_len);
153}
154
155/*
156 * dst_s_get_int16
157 *     This routine extracts a 16 bit integer from a two byte character
158 *     string.  The character string is assumed to be in network byte
159 *     order and may be unaligned.  The number returned is in host order.
160 * Parameter
161 *     buf     A two byte character string.
162 * Return
163 *     The converted integer value.
164 */
165
166u_int16_t
167dst_s_get_int16(const u_char *buf)
168{
169	register u_int16_t a = 0;
170	a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1]));
171	return (a);
172}
173
174
175#ifdef _UNUSED_API_
176/*
177 * dst_s_get_int32
178 *     This routine extracts a 32 bit integer from a four byte character
179 *     string.  The character string is assumed to be in network byte
180 *     order and may be unaligned.  The number returned is in host order.
181 * Parameter
182 *     buf     A four byte character string.
183 * Return
184 *     The converted integer value.
185 */
186
187u_int32_t
188dst_s_get_int32(const u_char *buf)
189{
190	register u_int32_t a = 0;
191	a = ((u_int32_t)(buf[0] << 24)) | ((u_int32_t)(buf[1] << 16)) |
192		((u_int32_t)(buf[2] << 8)) | ((u_int32_t)(buf[3]));
193	return (a);
194}
195#endif
196
197/*
198 * dst_s_put_int16
199 *     Take a 16 bit integer and store the value in a two byte
200 *     character string.  The integer is assumed to be in network
201 *     order and the string is returned in host order.
202 *
203 * Parameters
204 *     buf     Storage for a two byte character string.
205 *     val     16 bit integer.
206 */
207
208void
209dst_s_put_int16(u_int8_t *buf, const u_int16_t val)
210{
211	buf[0] = (u_int8_t)(val >> 8);
212	buf[1] = (u_int8_t)(val);
213}
214
215#ifdef _UNUSED_API_
216/*
217 * dst_s_put_int32
218 *     Take a 32 bit integer and store the value in a four byte
219 *     character string.  The integer is assumed to be in network
220 *     order and the string is returned in host order.
221 *
222 * Parameters
223 *     buf     Storage for a four byte character string.
224 *     val     32 bit integer.
225 */
226
227void
228dst_s_put_int32(u_int8_t *buf, const u_int32_t val)
229{
230	buf[0] = (u_int8_t)(val >> 24);
231	buf[1] = (u_int8_t)(val >> 16);
232	buf[2] = (u_int8_t)(val >> 8);
233	buf[3] = (u_int8_t)(val);
234}
235#endif
236
237
238#ifdef _UNUSED_API_
239/*
240 *  dst_s_filename_length
241 *
242 *	This function returns the number of bytes needed to hold the
243 *	filename for a key file.  '/', '\' and ':' are not allowed.
244 *	form:  K<keyname>+<alg>+<id>.<suffix>
245 *
246 *	Returns 0 if the filename would contain either '\', '/' or ':'
247 */
248size_t
249dst_s_filename_length(const char *name, const char *suffix)
250{
251	if (name == NULL)
252		return (0);
253	if (strrchr(name, '\\'))
254		return (0);
255	if (strrchr(name, '/'))
256		return (0);
257	if (strrchr(name, ':'))
258		return (0);
259	if (suffix == NULL)
260		return (0);
261	if (strrchr(suffix, '\\'))
262		return (0);
263	if (strrchr(suffix, '/'))
264		return (0);
265	if (strrchr(suffix, ':'))
266		return (0);
267	return (1 + strlen(name) + 6 + strlen(suffix));
268}
269#endif
270
271/*
272 *  dst_s_build_filename ()
273 *	Builds a key filename from the key name, it's id, and a
274 *	suffix.  '\', '/' and ':' are not allowed. fA filename is of the
275 *	form:  K<keyname><id>.<suffix>
276 *	form: K<keyname>+<alg>+<id>.<suffix>
277 *
278 *	Returns -1 if the conversion fails:
279 *	  if the filename would be too long for space allotted
280 *	  if the filename would contain a '\', '/' or ':'
281 *	Returns 0 on success
282 */
283
284int
285dst_s_build_filename(char *filename, const char *name, u_int16_t id,
286		     int alg, const char *suffix, size_t filename_length)
287{
288	u_int32_t my_id;
289	if (filename == NULL)
290		return (-1);
291	memset(filename, 0, filename_length);
292	if (name == NULL)
293		return (-1);
294	if (suffix == NULL)
295		return (-1);
296	if (filename_length < 1 + strlen(name) + 4 + 6 + 1 + strlen(suffix))
297		return (-1);
298	my_id = id;
299	sprintf(filename, "K%s+%03d+%05d.%s", name, alg, my_id,
300		(const char *) suffix);
301	if (strrchr(filename, '/'))
302		return (-1);
303	if (strrchr(filename, '\\'))
304		return (-1);
305	if (strrchr(filename, ':'))
306		return (-1);
307	return (0);
308}
309
310/*
311 *  dst_s_fopen ()
312 *     Open a file in the dst_path directory.  If perm is specified, the
313 *     file is checked for existence first, and not opened if it exists.
314 *  Parameters
315 *     filename  File to open
316 *     mode       Mode to open the file (passed directly to fopen)
317 *     perm       File permission, if creating a new file.
318 *  Returns
319 *     NULL       Failure
320 *     NON-NULL  (FILE *) of opened file.
321 */
322FILE *
323dst_s_fopen(const char *filename, const char *mode, int perm)
324{
325	FILE *fp;
326	char pathname[PATH_MAX];
327	size_t plen = sizeof(pathname);
328
329	if (*dst_path != '\0') {
330		strcpy(pathname, dst_path);
331		plen -= strlen(pathname);
332	}
333	else
334		pathname[0] = '\0';
335
336	if (plen > strlen(filename))
337		strncpy(&pathname[PATH_MAX - plen], filename, plen-1);
338	else
339		return (NULL);
340
341	fp = fopen(pathname, mode);
342	if (perm)
343		chmod(pathname, perm);
344	return (fp);
345}
346
347#ifdef _UNUSED_API_
348void
349dst_s_dump(const int mode, const u_char *data, const int size,
350	    const char *msg)
351{
352#ifndef __APPLE__
353	UNUSED(data);
354#endif
355
356	if (size > 0) {
357#ifdef LONG_TEST
358		static u_char scratch[1000];
359		int n ;
360		n = b64_ntop(data, scratch, size, sizeof(scratch));
361		printf("%s: %x %d %s\n", msg, mode, n, scratch);
362#else
363		printf("%s,%x %d\n", msg, mode, size);
364#endif
365	}
366}
367#endif
368