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