Make setthetime() static per the prototype.
[dragonfly.git] / contrib / isc-dhcp / dst / dst_support.c
1 static const char rcsid[] = "$Header: /rc0/proj/cvs/isc/DHCP/dst/dst_support.c,v 1.1 2001/02/22 07:22:08 mellon Exp $";
2
3
4 /*
5  * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
6  *
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.
10  *
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.
19  */
20
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>
29
30 #include "minires/minires.h"
31 #include "arpa/nameser.h"
32
33 #include "dst_internal.h"
34
35 /*
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
50  */
51
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)
56 {
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;
62
63         if (bin_data == NULL)   /* no data no */
64                 return (0);
65
66         if (out_buf == NULL || out_len <= 0)    /* no output_work area */
67                 return (-1);
68
69         /* suppress leading \0  */
70         for (; (*bp == 0x0) && (local_in_len > 0); local_in_len--)
71                 bp++;
72
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;
81         }
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);
89 }
90
91
92 /*
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.
104  */
105
106 int
107 dst_s_verify_str(const char **buf, const char *str)
108 {
109         unsigned b, s;
110         if (*buf == NULL)       /* error checks */
111                 return (0);
112         if (str == NULL || *str == '\0')
113                 return (1);
114
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);
121 }
122
123
124 /*
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.
142  */
143
144 int
145 dst_s_conv_bignum_b64_to_u8(const char **buf,
146                             u_char *loc, const unsigned loclen)
147 {
148         unsigned blen;
149         char *bp;
150         u_char bstr[RAW_KEY_SIZE];
151
152         if (buf == NULL || *buf == NULL) {      /* error checks */
153                 EREPORT(("dst_s_conv_bignum_b64_to_u8: null input buffer.\n"));
154                 return (0);
155         }
156         bp = strchr(*buf, '\n');        /* find length of input line */
157         if (bp != NULL)
158                 *bp = (u_char) NULL;
159
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);
164         }
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);
168         }
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);
174 }
175
176
177 /*
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.
186  */
187
188 int
189 dst_s_calculate_bits(const u_char *str, const int max_bits)
190 {
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);
199 }
200
201
202 /*
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.
206  */
207 u_int16_t
208 dst_s_id_calc(const u_char *key, const unsigned keysize)
209 {
210         u_int32_t ac;
211         const u_char *kp = key;
212         unsigned size = keysize;
213
214         if (!key)
215                 return 0;
216  
217         for (ac = 0; size > 1; size -= 2, kp += 2)
218                 ac += ((*kp) << 8) + *(kp + 1);
219
220         if (size > 0)
221                 ac += ((*kp) << 8);
222         ac += (ac >> 16) & 0xffff;
223
224         return (ac & 0xffff);
225 }
226
227 /* 
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 
235  */ 
236 u_int16_t
237 dst_s_dns_key_id(const u_char *dns_key_rdata, const unsigned rdata_len)
238 {
239         unsigned key_data = 4;
240
241         if (!dns_key_rdata || (rdata_len < key_data))
242                 return 0;
243
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;
247
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));
256 }
257
258 /*
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.
267  */
268
269 u_int16_t
270 dst_s_get_int16(const u_char *buf)
271 {
272         register u_int16_t a = 0;
273         a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1]));
274         return (a);
275 }
276
277
278 /*
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.
287  */
288
289 u_int32_t
290 dst_s_get_int32(const u_char *buf)
291 {
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);
296 }
297
298
299 /*
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.
304  *
305  * Parameters
306  *     buf     Storage for a two byte character string.
307  *     val     16 bit integer.
308  */
309
310 void
311 dst_s_put_int16(u_int8_t *buf, const u_int16_t val)
312 {
313         buf[0] = (u_int8_t)(val >> 8);
314         buf[1] = (u_int8_t)(val);
315 }
316
317
318 /*
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.
323  *
324  * Parameters
325  *     buf     Storage for a four byte character string.
326  *     val     32 bit integer.
327  */
328
329 void
330 dst_s_put_int32(u_int8_t *buf, const u_int32_t val)
331 {
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);
336 }
337
338
339 /*
340  *  dst_s_filename_length
341  *
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>
345  *
346  *      Returns 0 if the filename would contain either '\', '/' or ':'
347  */
348 size_t
349 dst_s_filename_length(const char *name, const char *suffix)
350 {
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));
368 }
369
370
371 /*
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>
377  *
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
382  */
383
384 int
385 dst_s_build_filename(char *filename, const char *name, unsigned id,
386                      int alg, const char *suffix, size_t filename_length)
387 {
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);
408 }
409
410 /*
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.
421  */
422 FILE *
423 dst_s_fopen(const char *filename, const char *mode, unsigned perm)
424 {
425         FILE *fp;
426         char pathname[PATH_MAX];
427         unsigned plen = sizeof(pathname);
428
429         if (*dst_path != '\0') {
430                 strcpy(pathname, dst_path);
431                 plen -= strlen(pathname);
432         }
433         else 
434                 pathname[0] = '\0';
435
436         if (plen > strlen(filename))
437                 strncpy(&pathname[PATH_MAX - plen], filename, plen-1);
438         else 
439                 return (NULL);
440         
441         fp = fopen(pathname, mode);
442         if (perm)
443                 chmod(pathname, perm);
444         return (fp);
445 }
446
447 #if 0
448 void
449 dst_s_dump(const int mode, const u_char *data, const int size, 
450             const char *msg)
451 {
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
461         }
462 }
463 #endif