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 "; 3 4 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") 9 * 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. 13 * 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. 22 */ 23 24 #include <sys/cdefs.h> 25 __RCSID("$NetBSD: dst_support.c,v 1.1.1.4 2014/07/12 11:57:50 spz Exp $"); 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 <sys/socket.h> 35 36 #include "cdefs.h" 37 #include "osdep.h" 38 #include "arpa/nameser.h" 39 40 #include "dst_internal.h" 41 42 /* 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 57 */ 58 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) 63 { 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; 70 71 if (bin_data == NULL) /* no data no */ 72 return (0); 73 74 if (out_buf == NULL || out_len <= 0) /* no output_work area */ 75 return (-1); 76 77 /* suppress leading \0 */ 78 for (; (*bp == 0x0) && (local_in_len > 0); local_in_len--) 79 bp++; 80 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; 89 } 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); 98 } 99 100 101 /* 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. 113 */ 114 115 int 116 dst_s_verify_str(const char **buf, const char *str) 117 { 118 unsigned b, s; 119 if (*buf == NULL) /* error checks */ 120 return (0); 121 if (str == NULL || *str == '\0') 122 return (1); 123 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); 130 } 131 132 133 /* 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. 151 */ 152 153 int 154 dst_s_conv_bignum_b64_to_u8(const char **buf, 155 u_char *loc, const unsigned loclen) 156 { 157 unsigned blen; 158 char *bp; 159 u_char bstr[RAW_KEY_SIZE]; 160 int res = 0; 161 162 if (buf == NULL || *buf == NULL) { /* error checks */ 163 EREPORT(("dst_s_conv_bignum_b64_to_u8: null input buffer.\n")); 164 return (0); 165 } 166 bp = strchr(*buf, '\n'); /* find length of input line */ 167 if (bp != NULL) 168 *bp = '\0'; 169 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); 174 } 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); 179 } 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); 185 } 186 187 188 /* 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. 197 */ 198 199 int 200 dst_s_calculate_bits(const u_char *str, const int max_bits) 201 { 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); 210 } 211 212 213 /* 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. 217 */ 218 u_int16_t 219 dst_s_id_calc(const u_char *key, const unsigned keysize) 220 { 221 u_int32_t ac; 222 const u_char *kp = key; 223 unsigned size = keysize; 224 225 if (!key) 226 return 0; 227 228 for (ac = 0; size > 1; size -= 2, kp += 2) 229 ac += ((*kp) << 8) + *(kp + 1); 230 231 if (size > 0) 232 ac += ((*kp) << 8); 233 ac += (ac >> 16) & 0xffff; 234 235 return (ac & 0xffff); 236 } 237 238 /* 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 246 */ 247 u_int16_t 248 dst_s_dns_key_id(const u_char *dns_key_rdata, const unsigned rdata_len) 249 { 250 unsigned key_data = 4; 251 252 if (!dns_key_rdata || (rdata_len < key_data)) 253 return 0; 254 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; 258 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)); 267 } 268 269 /* 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. 278 */ 279 280 u_int16_t 281 dst_s_get_int16(const u_char *buf) 282 { 283 register u_int16_t a = 0; 284 a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1])); 285 return (a); 286 } 287 288 289 /* 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. 298 */ 299 300 u_int32_t 301 dst_s_get_int32(const u_char *buf) 302 { 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); 307 } 308 309 310 /* 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. 315 * 316 * Parameters 317 * buf Storage for a two byte character string. 318 * val 16 bit integer. 319 */ 320 321 void 322 dst_s_put_int16(u_int8_t *buf, const u_int16_t val) 323 { 324 buf[0] = (u_int8_t)(val >> 8); 325 buf[1] = (u_int8_t)(val); 326 } 327 328 329 /* 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. 334 * 335 * Parameters 336 * buf Storage for a four byte character string. 337 * val 32 bit integer. 338 */ 339 340 void 341 dst_s_put_int32(u_int8_t *buf, const u_int32_t val) 342 { 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); 347 } 348 349 350 /* 351 * dst_s_filename_length 352 * 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> 356 * 357 * Returns 0 if the filename would contain either '\', '/' or ':' 358 */ 359 size_t 360 dst_s_filename_length(const char *name, const char *suffix) 361 { 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)); 379 } 380 381 382 /* 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> 388 * 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 393 */ 394 395 int 396 dst_s_build_filename(char *filename, const char *name, unsigned id, 397 int alg, const char *suffix, size_t filename_length) 398 { 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); 419 } 420 421 /* 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. 432 */ 433 FILE * 434 dst_s_fopen(const char *filename, const char *mode, unsigned perm) 435 { 436 FILE *fp; 437 char pathname[PATH_MAX]; 438 unsigned plen = sizeof(pathname); 439 440 if (*dst_path != '\0') { 441 strncpy(pathname, dst_path, PATH_MAX); 442 plen -= strlen(pathname); 443 } 444 else 445 pathname[0] = '\0'; 446 447 if (plen > strlen(filename)) 448 strncpy(&pathname[PATH_MAX - plen], filename, plen-1); 449 else 450 return (NULL); 451 452 fp = fopen(pathname, mode); 453 if (perm) 454 chmod(pathname, perm); 455 return (fp); 456 } 457 458 #if 0 459 void 460 dst_s_dump(const int mode, const u_char *data, const int size, 461 const char *msg) 462 { 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 472 } 473 } 474 #endif 475