etc/protocols - sync with NetBSD-8
[minix.git] / external / bsd / dhcp / dist / dst / dst_support.c
blob7ea6164fc266ca205b65c3d595ec93905092d884
1 /* $NetBSD: dst_support.c,v 1.1.1.4 2014/07/12 11:57:50 spz Exp $ */
2 static const char rcsid[] = "Header: /tmp/cvstest/DHCP/dst/dst_support.c,v 1.7 2009/11/24 02:06:56 sar Exp ";
5 /*
6 * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
7 * Portions Copyright (c) 2007,2009 by Internet Systems Consortium, Inc. ("ISC")
8 * Portions Copyright (c) 2012 by Internet Systems Consortium, Inc. ("ISC")
10 * Permission to use, copy modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
14 * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
15 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
17 * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
18 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
19 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
24 #include <sys/cdefs.h>
25 __RCSID("$NetBSD: dst_support.c,v 1.1.1.4 2014/07/12 11:57:50 spz Exp $");
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 <sys/socket.h>
36 #include "cdefs.h"
37 #include "osdep.h"
38 #include "arpa/nameser.h"
40 #include "dst_internal.h"
43 * dst_s_conv_bignum_u8_to_b64
44 * This function converts binary data stored as a u_char[] to a
45 * base-64 string. Leading zeroes are discarded. If a header is
46 * supplied, it is prefixed to the input prior to encoding. The
47 * output is \n\0 terminated (the \0 is not included in output length).
48 * Parameters
49 * out_buf binary data to convert
50 * header character string to prefix to the output (label)
51 * bin_data binary data
52 * bin_len size of binary data
53 * Return
54 * -1 not enough space in output work area
55 * 0 no output
56 * >0 number of bytes written to output work area
59 int
60 dst_s_conv_bignum_u8_to_b64(char *out_buf, const unsigned out_len,
61 const char *header, const u_char *bin_data,
62 const unsigned bin_len)
64 const u_char *bp = bin_data;
65 char *op = out_buf;
66 int res = 0;
67 unsigned lenh = 0, len64 = 0;
68 unsigned local_in_len = bin_len;
69 unsigned local_out_len = out_len;
71 if (bin_data == NULL) /* no data no */
72 return (0);
74 if (out_buf == NULL || out_len <= 0) /* no output_work area */
75 return (-1);
77 /* suppress leading \0 */
78 for (; (*bp == 0x0) && (local_in_len > 0); local_in_len--)
79 bp++;
81 if (header) { /* add header to output string */
82 lenh = strlen(header);
83 if (lenh < out_len)
84 memcpy(op, header, lenh);
85 else
86 return (-1);
87 local_out_len -= lenh;
88 op += lenh;
90 res = b64_ntop(bp, local_in_len, op, local_out_len - 2);
91 if (res < 0)
92 return (-1);
93 len64 = (unsigned) res;
94 op += len64++;
95 *(op++) = '\n'; /* put CR in the output */
96 *op = '\0'; /* make sure output is 0 terminated */
97 return (lenh + len64);
102 * dst_s_verify_str()
103 * Validate that the input string(*str) is at the head of the input
104 * buffer(**buf). If so, move the buffer head pointer (*buf) to
105 * the first byte of data following the string(*str).
106 * Parameters
107 * buf Input buffer.
108 * str Input string.
109 * Return
110 * 0 *str is not the head of **buff
111 * 1 *str is the head of **buff, *buf is is advanced to
112 * the tail of **buf.
116 dst_s_verify_str(const char **buf, const char *str)
118 unsigned b, s;
119 if (*buf == NULL) /* error checks */
120 return (0);
121 if (str == NULL || *str == '\0')
122 return (1);
124 b = strlen(*buf); /* get length of strings */
125 s = strlen(str);
126 if (s > b || strncmp(*buf, str, s)) /* check if same */
127 return (0); /* not a match */
128 (*buf) += s; /* advance pointer */
129 return (1);
134 * dst_s_conv_bignum_b64_to_u8
135 * Read a line of base-64 encoded string from the input buffer,
136 * convert it to binary, and store it in an output area. The
137 * input buffer is read until reaching a newline marker or the
138 * end of the buffer. The binary data is stored in the last X
139 * number of bytes of the output area where X is the size of the
140 * binary output. If the operation is successful, the input buffer
141 * pointer is advanced. This procedure does not do network to host
142 * byte order conversion.
143 * Parameters
144 * buf Pointer to encoded input string. Pointer is updated if
145 * function is successful.
146 * loc Output area.
147 * loclen Size in bytes of output area.
148 * Return
149 * >0 Return = number of bytes of binary data stored in loc.
150 * 0 Failure.
154 dst_s_conv_bignum_b64_to_u8(const char **buf,
155 u_char *loc, const unsigned loclen)
157 unsigned blen;
158 char *bp;
159 u_char bstr[RAW_KEY_SIZE];
160 int res = 0;
162 if (buf == NULL || *buf == NULL) { /* error checks */
163 EREPORT(("dst_s_conv_bignum_b64_to_u8: null input buffer.\n"));
164 return (0);
166 bp = strchr(*buf, '\n'); /* find length of input line */
167 if (bp != NULL)
168 *bp = '\0';
170 res = b64_pton(*buf, bstr, sizeof(bstr));
171 if (res <= 0) {
172 EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is null.\n"));
173 return (0);
175 blen = (unsigned) res;
176 if (loclen < blen) {
177 EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is longer than output buffer.\n"));
178 return (0);
180 if (bp)
181 *buf = bp; /* advancing buffer past \n */
182 memset(loc, 0, loclen - blen); /* clearing unused output area */
183 memcpy(loc + loclen - blen, bstr, blen); /* write last blen bytes */
184 return (blen);
189 * dst_s_calculate_bits
190 * Given a binary number represented in a u_char[], determine
191 * the number of significant bits used.
192 * Parameters
193 * str An input character string containing a binary number.
194 * max_bits The maximum possible significant bits.
195 * Return
196 * N The number of significant bits in str.
200 dst_s_calculate_bits(const u_char *str, const int max_bits)
202 const u_char *p = str;
203 u_char i, j = 0x80;
204 int bits;
205 for (bits = max_bits; *p == 0x00 && bits > 0; p++)
206 bits -= 8;
207 for (i = *p; (i & j) != j; j >>= 1)
208 bits--;
209 return (bits);
214 * calculates a checksum used in kmt for a id.
215 * takes an array of bytes and a length.
216 * returns a 16 bit checksum.
218 u_int16_t
219 dst_s_id_calc(const u_char *key, const unsigned keysize)
221 u_int32_t ac;
222 const u_char *kp = key;
223 unsigned size = keysize;
225 if (!key)
226 return 0;
228 for (ac = 0; size > 1; size -= 2, kp += 2)
229 ac += ((*kp) << 8) + *(kp + 1);
231 if (size > 0)
232 ac += ((*kp) << 8);
233 ac += (ac >> 16) & 0xffff;
235 return (ac & 0xffff);
239 * dst_s_dns_key_id() Function to calculated DNSSEC footprint from KEY record
240 * rdata (all of record)
241 * Input:
242 * dns_key_rdata: the raw data in wire format
243 * rdata_len: the size of the input data
244 * Output:
245 * the key footprint/id calculated from the key data
247 u_int16_t
248 dst_s_dns_key_id(const u_char *dns_key_rdata, const unsigned rdata_len)
250 unsigned key_data = 4;
252 if (!dns_key_rdata || (rdata_len < key_data))
253 return 0;
255 /* check the extended parameters bit in the DNS Key RR flags */
256 if (dst_s_get_int16(dns_key_rdata) & DST_EXTEND_FLAG)
257 key_data += 2;
259 /* compute id */
260 if (dns_key_rdata[3] == KEY_RSA) /* Algorithm RSA */
261 return dst_s_get_int16((const u_char *)
262 &dns_key_rdata[rdata_len - 3]);
263 else
264 /* compute a checksum on the key part of the key rr */
265 return dst_s_id_calc(&dns_key_rdata[key_data],
266 (rdata_len - key_data));
270 * dst_s_get_int16
271 * This routine extracts a 16 bit integer from a two byte character
272 * string. The character string is assumed to be in network byte
273 * order and may be unaligned. The number returned is in host order.
274 * Parameter
275 * buf A two byte character string.
276 * Return
277 * The converted integer value.
280 u_int16_t
281 dst_s_get_int16(const u_char *buf)
283 register u_int16_t a = 0;
284 a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1]));
285 return (a);
290 * dst_s_get_int32
291 * This routine extracts a 32 bit integer from a four byte character
292 * string. The character string is assumed to be in network byte
293 * order and may be unaligned. The number returned is in host order.
294 * Parameter
295 * buf A four byte character string.
296 * Return
297 * The converted integer value.
300 u_int32_t
301 dst_s_get_int32(const u_char *buf)
303 register u_int32_t a = 0;
304 a = ((u_int32_t)(buf[0] << 24)) | ((u_int32_t)(buf[1] << 16)) |
305 ((u_int32_t)(buf[2] << 8)) | ((u_int32_t)(buf[3]));
306 return (a);
311 * dst_s_put_int16
312 * Take a 16 bit integer and store the value in a two byte
313 * character string. The integer is assumed to be in network
314 * order and the string is returned in host order.
316 * Parameters
317 * buf Storage for a two byte character string.
318 * val 16 bit integer.
321 void
322 dst_s_put_int16(u_int8_t *buf, const u_int16_t val)
324 buf[0] = (u_int8_t)(val >> 8);
325 buf[1] = (u_int8_t)(val);
330 * dst_s_put_int32
331 * Take a 32 bit integer and store the value in a four byte
332 * character string. The integer is assumed to be in network
333 * order and the string is returned in host order.
335 * Parameters
336 * buf Storage for a four byte character string.
337 * val 32 bit integer.
340 void
341 dst_s_put_int32(u_int8_t *buf, const u_int32_t val)
343 buf[0] = (u_int8_t)(val >> 24);
344 buf[1] = (u_int8_t)(val >> 16);
345 buf[2] = (u_int8_t)(val >> 8);
346 buf[3] = (u_int8_t)(val);
351 * dst_s_filename_length
353 * This function returns the number of bytes needed to hold the
354 * filename for a key file. '/', '\' and ':' are not allowed.
355 * form: K<keyname>+<alg>+<id>.<suffix>
357 * Returns 0 if the filename would contain either '\', '/' or ':'
359 size_t
360 dst_s_filename_length(const char *name, const char *suffix)
362 if (name == NULL)
363 return (0);
364 if (strrchr(name, '\\'))
365 return (0);
366 if (strrchr(name, '/'))
367 return (0);
368 if (strrchr(name, ':'))
369 return (0);
370 if (suffix == NULL)
371 return (0);
372 if (strrchr(suffix, '\\'))
373 return (0);
374 if (strrchr(suffix, '/'))
375 return (0);
376 if (strrchr(suffix, ':'))
377 return (0);
378 return (1 + strlen(name) + 6 + strlen(suffix));
383 * dst_s_build_filename ()
384 * Builds a key filename from the key name, it's id, and a
385 * suffix. '\', '/' and ':' are not allowed. fA filename is of the
386 * form: K<keyname><id>.<suffix>
387 * form: K<keyname>+<alg>+<id>.<suffix>
389 * Returns -1 if the conversion fails:
390 * if the filename would be too long for space allotted
391 * if the filename would contain a '\', '/' or ':'
392 * Returns 0 on success
396 dst_s_build_filename(char *filename, const char *name, unsigned id,
397 int alg, const char *suffix, size_t filename_length)
399 unsigned my_id;
400 if (filename == NULL)
401 return (-1);
402 memset(filename, 0, filename_length);
403 if (name == NULL)
404 return (-1);
405 if (suffix == NULL)
406 return (-1);
407 if (filename_length < 1 + strlen(name) + 4 + 6 + 1 + strlen(suffix))
408 return (-1);
409 my_id = id;
410 sprintf(filename, "K%s+%03d+%05d.%s", name, alg, my_id,
411 (const char *) suffix);
412 if (strrchr(filename, '/'))
413 return (-1);
414 if (strrchr(filename, '\\'))
415 return (-1);
416 if (strrchr(filename, ':'))
417 return (-1);
418 return (0);
422 * dst_s_fopen ()
423 * Open a file in the dst_path directory. If perm is specified, the
424 * file is checked for existence first, and not opened if it exists.
425 * Parameters
426 * filename File to open
427 * mode Mode to open the file (passed directly to fopen)
428 * perm File permission, if creating a new file.
429 * Returns
430 * NULL Failure
431 * NON-NULL (FILE *) of opened file.
433 FILE *
434 dst_s_fopen(const char *filename, const char *mode, unsigned perm)
436 FILE *fp;
437 char pathname[PATH_MAX];
438 unsigned plen = sizeof(pathname);
440 if (*dst_path != '\0') {
441 strncpy(pathname, dst_path, PATH_MAX);
442 plen -= strlen(pathname);
444 else
445 pathname[0] = '\0';
447 if (plen > strlen(filename))
448 strncpy(&pathname[PATH_MAX - plen], filename, plen-1);
449 else
450 return (NULL);
452 fp = fopen(pathname, mode);
453 if (perm)
454 chmod(pathname, perm);
455 return (fp);
458 #if 0
459 void
460 dst_s_dump(const int mode, const u_char *data, const int size,
461 const char *msg)
463 if (size > 0) {
464 #ifdef LONG_TEST
465 static u_char scratch[1000];
466 int n ;
467 n = b64_ntop(data, scratch, size, sizeof(scratch));
468 printf("%s: %x %d %s\n", msg, mode, n, scratch);
469 #else
470 printf("%s,%x %d\n", msg, mode, size);
471 #endif
474 #endif