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