MFC: An off-by-one malloc size was corrupting the installer's memory,
[dragonfly.git] / contrib / dhcp-3.0 / dst / dst_support.c
blob2d7a67f12036db234476ccb703311add6afbf51e
1 static const char rcsid[] = "$Header: /proj/cvs/prod/DHCP/dst/dst_support.c,v 1.1 2001/02/22 07:22:08 mellon Exp $";
4 /*
5 * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
7 * Permission to use, copy modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
12 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
13 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
14 * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
15 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
16 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
17 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
18 * WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <memory.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <sys/stat.h>
27 #include <netinet/in.h>
28 #include <sys/socket.h>
30 #include "minires/minires.h"
31 #include "arpa/nameser.h"
33 #include "dst_internal.h"
36 * dst_s_conv_bignum_u8_to_b64
37 * This function converts binary data stored as a u_char[] to a
38 * base-64 string. Leading zeroes are discarded. If a header is
39 * supplied, it is prefixed to the input prior to encoding. The
40 * output is \n\0 terminated (the \0 is not included in output length).
41 * Parameters
42 * out_buf binary data to convert
43 * header character string to prefix to the output (label)
44 * bin_data binary data
45 * bin_len size of binary data
46 * Return
47 * -1 not enough space in output work area
48 * 0 no output
49 * >0 number of bytes written to output work area
52 int
53 dst_s_conv_bignum_u8_to_b64(char *out_buf, const unsigned out_len,
54 const char *header, const u_char *bin_data,
55 const unsigned bin_len)
57 const u_char *bp = bin_data;
58 char *op = out_buf;
59 unsigned lenh = 0, len64 = 0;
60 unsigned local_in_len = bin_len;
61 unsigned local_out_len = out_len;
63 if (bin_data == NULL) /* no data no */
64 return (0);
66 if (out_buf == NULL || out_len <= 0) /* no output_work area */
67 return (-1);
69 /* suppress leading \0 */
70 for (; (*bp == 0x0) && (local_in_len > 0); local_in_len--)
71 bp++;
73 if (header) { /* add header to output string */
74 lenh = strlen(header);
75 if (lenh < out_len)
76 memcpy(op, header, lenh);
77 else
78 return (-1);
79 local_out_len -= lenh;
80 op += lenh;
82 len64 = b64_ntop(bp, local_in_len, op, local_out_len - 2);
83 if (len64 < 0)
84 return (-1);
85 op += len64++;
86 *(op++) = '\n'; /* put CR in the output */
87 *op = '\0'; /* make sure output is 0 terminated */
88 return (lenh + len64);
93 * dst_s_verify_str()
94 * Validate that the input string(*str) is at the head of the input
95 * buffer(**buf). If so, move the buffer head pointer (*buf) to
96 * the first byte of data following the string(*str).
97 * Parameters
98 * buf Input buffer.
99 * str Input string.
100 * Return
101 * 0 *str is not the head of **buff
102 * 1 *str is the head of **buff, *buf is is advanced to
103 * the tail of **buf.
107 dst_s_verify_str(const char **buf, const char *str)
109 unsigned b, s;
110 if (*buf == NULL) /* error checks */
111 return (0);
112 if (str == NULL || *str == '\0')
113 return (1);
115 b = strlen(*buf); /* get length of strings */
116 s = strlen(str);
117 if (s > b || strncmp(*buf, str, s)) /* check if same */
118 return (0); /* not a match */
119 (*buf) += s; /* advance pointer */
120 return (1);
125 * dst_s_conv_bignum_b64_to_u8
126 * Read a line of base-64 encoded string from the input buffer,
127 * convert it to binary, and store it in an output area. The
128 * input buffer is read until reaching a newline marker or the
129 * end of the buffer. The binary data is stored in the last X
130 * number of bytes of the output area where X is the size of the
131 * binary output. If the operation is successful, the input buffer
132 * pointer is advanced. This procedure does not do network to host
133 * byte order conversion.
134 * Parameters
135 * buf Pointer to encoded input string. Pointer is updated if
136 * function is successfull.
137 * loc Output area.
138 * loclen Size in bytes of output area.
139 * Return
140 * >0 Return = number of bytes of binary data stored in loc.
141 * 0 Failure.
145 dst_s_conv_bignum_b64_to_u8(const char **buf,
146 u_char *loc, const unsigned loclen)
148 unsigned blen;
149 char *bp;
150 u_char bstr[RAW_KEY_SIZE];
152 if (buf == NULL || *buf == NULL) { /* error checks */
153 EREPORT(("dst_s_conv_bignum_b64_to_u8: null input buffer.\n"));
154 return (0);
156 bp = strchr(*buf, '\n'); /* find length of input line */
157 if (bp != NULL)
158 *bp = (u_char) NULL;
160 blen = b64_pton(*buf, bstr, sizeof(bstr));
161 if (blen <= 0) {
162 EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is null.\n"));
163 return (0);
165 else if (loclen < blen) {
166 EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is longer than output buffer.\n"));
167 return (0);
169 if (bp)
170 *buf = bp; /* advancing buffer past \n */
171 memset(loc, 0, loclen - blen); /* clearing unused output area */
172 memcpy(loc + loclen - blen, bstr, blen); /* write last blen bytes */
173 return (blen);
178 * dst_s_calculate_bits
179 * Given a binary number represented in a u_char[], determine
180 * the number of significant bits used.
181 * Parameters
182 * str An input character string containing a binary number.
183 * max_bits The maximum possible significant bits.
184 * Return
185 * N The number of significant bits in str.
189 dst_s_calculate_bits(const u_char *str, const int max_bits)
191 const u_char *p = str;
192 u_char i, j = 0x80;
193 int bits;
194 for (bits = max_bits; *p == 0x00 && bits > 0; p++)
195 bits -= 8;
196 for (i = *p; (i & j) != j; j >>= 1)
197 bits--;
198 return (bits);
203 * calculates a checksum used in kmt for a id.
204 * takes an array of bytes and a length.
205 * returns a 16 bit checksum.
207 u_int16_t
208 dst_s_id_calc(const u_char *key, const unsigned keysize)
210 u_int32_t ac;
211 const u_char *kp = key;
212 unsigned size = keysize;
214 if (!key)
215 return 0;
217 for (ac = 0; size > 1; size -= 2, kp += 2)
218 ac += ((*kp) << 8) + *(kp + 1);
220 if (size > 0)
221 ac += ((*kp) << 8);
222 ac += (ac >> 16) & 0xffff;
224 return (ac & 0xffff);
228 * dst_s_dns_key_id() Function to calculated DNSSEC footprint from KEY reocrd
229 * rdata (all of record)
230 * Input:
231 * dns_key_rdata: the raw data in wire format
232 * rdata_len: the size of the input data
233 * Output:
234 * the key footprint/id calcuated from the key data
236 u_int16_t
237 dst_s_dns_key_id(const u_char *dns_key_rdata, const unsigned rdata_len)
239 unsigned key_data = 4;
241 if (!dns_key_rdata || (rdata_len < key_data))
242 return 0;
244 /* check the extended parameters bit in the DNS Key RR flags */
245 if (dst_s_get_int16(dns_key_rdata) & DST_EXTEND_FLAG)
246 key_data += 2;
248 /* compute id */
249 if (dns_key_rdata[3] == KEY_RSA) /* Algorithm RSA */
250 return dst_s_get_int16((const u_char *)
251 &dns_key_rdata[rdata_len - 3]);
252 else
253 /* compute a checksum on the key part of the key rr */
254 return dst_s_id_calc(&dns_key_rdata[key_data],
255 (rdata_len - key_data));
259 * dst_s_get_int16
260 * This routine extracts a 16 bit integer from a two byte character
261 * string. The character string is assumed to be in network byte
262 * order and may be unaligned. The number returned is in host order.
263 * Parameter
264 * buf A two byte character string.
265 * Return
266 * The converted integer value.
269 u_int16_t
270 dst_s_get_int16(const u_char *buf)
272 register u_int16_t a = 0;
273 a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1]));
274 return (a);
279 * dst_s_get_int32
280 * This routine extracts a 32 bit integer from a four byte character
281 * string. The character string is assumed to be in network byte
282 * order and may be unaligned. The number returned is in host order.
283 * Parameter
284 * buf A four byte character string.
285 * Return
286 * The converted integer value.
289 u_int32_t
290 dst_s_get_int32(const u_char *buf)
292 register u_int32_t a = 0;
293 a = ((u_int32_t)(buf[0] << 24)) | ((u_int32_t)(buf[1] << 16)) |
294 ((u_int32_t)(buf[2] << 8)) | ((u_int32_t)(buf[3]));
295 return (a);
300 * dst_s_put_int16
301 * Take a 16 bit integer and store the value in a two byte
302 * character string. The integer is assumed to be in network
303 * order and the string is returned in host order.
305 * Parameters
306 * buf Storage for a two byte character string.
307 * val 16 bit integer.
310 void
311 dst_s_put_int16(u_int8_t *buf, const u_int16_t val)
313 buf[0] = (u_int8_t)(val >> 8);
314 buf[1] = (u_int8_t)(val);
319 * dst_s_put_int32
320 * Take a 32 bit integer and store the value in a four byte
321 * character string. The integer is assumed to be in network
322 * order and the string is returned in host order.
324 * Parameters
325 * buf Storage for a four byte character string.
326 * val 32 bit integer.
329 void
330 dst_s_put_int32(u_int8_t *buf, const u_int32_t val)
332 buf[0] = (u_int8_t)(val >> 24);
333 buf[1] = (u_int8_t)(val >> 16);
334 buf[2] = (u_int8_t)(val >> 8);
335 buf[3] = (u_int8_t)(val);
340 * dst_s_filename_length
342 * This function returns the number of bytes needed to hold the
343 * filename for a key file. '/', '\' and ':' are not allowed.
344 * form: K<keyname>+<alg>+<id>.<suffix>
346 * Returns 0 if the filename would contain either '\', '/' or ':'
348 size_t
349 dst_s_filename_length(const char *name, const char *suffix)
351 if (name == NULL)
352 return (0);
353 if (strrchr(name, '\\'))
354 return (0);
355 if (strrchr(name, '/'))
356 return (0);
357 if (strrchr(name, ':'))
358 return (0);
359 if (suffix == NULL)
360 return (0);
361 if (strrchr(suffix, '\\'))
362 return (0);
363 if (strrchr(suffix, '/'))
364 return (0);
365 if (strrchr(suffix, ':'))
366 return (0);
367 return (1 + strlen(name) + 6 + strlen(suffix));
372 * dst_s_build_filename ()
373 * Builds a key filename from the key name, it's id, and a
374 * suffix. '\', '/' and ':' are not allowed. fA filename is of the
375 * form: K<keyname><id>.<suffix>
376 * form: K<keyname>+<alg>+<id>.<suffix>
378 * Returns -1 if the conversion fails:
379 * if the filename would be too long for space allotted
380 * if the filename would contain a '\', '/' or ':'
381 * Returns 0 on success
385 dst_s_build_filename(char *filename, const char *name, unsigned id,
386 int alg, const char *suffix, size_t filename_length)
388 unsigned my_id;
389 if (filename == NULL)
390 return (-1);
391 memset(filename, 0, filename_length);
392 if (name == NULL)
393 return (-1);
394 if (suffix == NULL)
395 return (-1);
396 if (filename_length < 1 + strlen(name) + 4 + 6 + 1 + strlen(suffix))
397 return (-1);
398 my_id = id;
399 sprintf(filename, "K%s+%03d+%05d.%s", name, alg, my_id,
400 (const char *) suffix);
401 if (strrchr(filename, '/'))
402 return (-1);
403 if (strrchr(filename, '\\'))
404 return (-1);
405 if (strrchr(filename, ':'))
406 return (-1);
407 return (0);
411 * dst_s_fopen ()
412 * Open a file in the dst_path directory. If perm is specified, the
413 * file is checked for existence first, and not opened if it exists.
414 * Parameters
415 * filename File to open
416 * mode Mode to open the file (passed directly to fopen)
417 * perm File permission, if creating a new file.
418 * Returns
419 * NULL Failure
420 * NON-NULL (FILE *) of opened file.
422 FILE *
423 dst_s_fopen(const char *filename, const char *mode, unsigned perm)
425 FILE *fp;
426 char pathname[PATH_MAX];
427 unsigned plen = sizeof(pathname);
429 if (*dst_path != '\0') {
430 strcpy(pathname, dst_path);
431 plen -= strlen(pathname);
433 else
434 pathname[0] = '\0';
436 if (plen > strlen(filename))
437 strncpy(&pathname[PATH_MAX - plen], filename, plen-1);
438 else
439 return (NULL);
441 fp = fopen(pathname, mode);
442 if (perm)
443 chmod(pathname, perm);
444 return (fp);
447 #if 0
448 void
449 dst_s_dump(const int mode, const u_char *data, const int size,
450 const char *msg)
452 if (size > 0) {
453 #ifdef LONG_TEST
454 static u_char scratch[1000];
455 int n ;
456 n = b64_ntop(data, scratch, size, sizeof(scratch));
457 printf("%s: %x %d %s\n", msg, mode, n, scratch);
458 #else
459 printf("%s,%x %d\n", msg, mode, size);
460 #endif
463 #endif