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