
1: /* 2: * Copyright (c) 1996-1999 by Internet Software Consortium. 3: * 4: * Permission to use, copy, modify, and distribute this software for any 5: * purpose with or without fee is hereby granted, provided that the above 6: * copyright notice and this permission notice appear in all copies. 7: * 8: * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 9: * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 10: * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 11: * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 12: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 13: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 14: * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 15: * SOFTWARE. 16: */ 17: 18: /* 19: * Portions Copyright (c) 1995 by International Business Machines, Inc. 20: * 21: * International Business Machines, Inc. (hereinafter called IBM) grants 22: * permission under its copyrights to use, copy, modify, and distribute this 23: * Software with or without fee, provided that the above copyright notice and 24: * all paragraphs of this notice appear in all copies, and that the name of IBM 25: * not be used in connection with the marketing of any product incorporating 26: * the Software or modifications thereof, without specific, written prior 27: * permission. 28: * 29: * To the extent it has a right to do so, IBM grants an immunity from suit 30: * under its patents, if any, for the use, sale or manufacture of products to 31: * the extent that such products are used for performing Domain Name System 32: * dynamic updates in TCP/IP networks by means of the Software. No immunity is 33: * granted for any product per se or for any other function of any product. 34: * 35: * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, 36: * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 37: * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, 38: * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING 39: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN 40: * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. 41: */ 42: 43: #if !defined(LINT) && !defined(CODECENTER) 44: static const char rcsid[] = "$BINDId: base64.c,v 8.7 1999/10/13 16:39:33 vixie Exp $"; 45: #endif /* not lint */ 46: 47: #include <sys/types.h> 48: #include <sys/param.h> 49: #include <sys/socket.h> 50: 51: #include <netinet/in.h> 52: #include <arpa/inet.h> 53: #include <arpa/nameser.h> 54: 55: #include <ctype.h> 56: #include <resolv.h> 57: #include <stdio.h> 58: #include <stdlib.h> 59: #include <string.h> 60: 61: #define Assert(Cond) if (!(Cond)) abort() 62: 63: static const char Base64[] = 64: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 65: static const char Pad64 = '='; 66: 67: /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) 68: The following encoding technique is taken from RFC 1521 by Borenstein 69: and Freed. It is reproduced here in a slightly edited form for 70: convenience. 71: 72: A 65-character subset of US-ASCII is used, enabling 6 bits to be 73: represented per printable character. (The extra 65th character, "=", 74: is used to signify a special processing function.) 75: 76: The encoding process represents 24-bit groups of input bits as output 77: strings of 4 encoded characters. Proceeding from left to right, a 78: 24-bit input group is formed by concatenating 3 8-bit input groups. 79: These 24 bits are then treated as 4 concatenated 6-bit groups, each 80: of which is translated into a single digit in the base64 alphabet. 81: 82: Each 6-bit group is used as an index into an array of 64 printable 83: characters. The character referenced by the index is placed in the 84: output string. 85: 86: Table 1: The Base64 Alphabet 87: 88: Value Encoding Value Encoding Value Encoding Value Encoding 89: 0 A 17 R 34 i 51 z 90: 1 B 18 S 35 j 52 0 91: 2 C 19 T 36 k 53 1 92: 3 D 20 U 37 l 54 2 93: 4 E 21 V 38 m 55 3 94: 5 F 22 W 39 n 56 4 95: 6 G 23 X 40 o 57 5 96: 7 H 24 Y 41 p 58 6 97: 8 I 25 Z 42 q 59 7 98: 9 J 26 a 43 r 60 8 99: 10 K 27 b 44 s 61 9 100: 11 L 28 c 45 t 62 + 101: 12 M 29 d 46 u 63 / 102: 13 N 30 e 47 v 103: 14 O 31 f 48 w (pad) = 104: 15 P 32 g 49 x 105: 16 Q 33 h 50 y 106: 107: Special processing is performed if fewer than 24 bits are available 108: at the end of the data being encoded. A full encoding quantum is 109: always completed at the end of a quantity. When fewer than 24 input 110: bits are available in an input group, zero bits are added (on the 111: right) to form an integral number of 6-bit groups. Padding at the 112: end of the data is performed using the '=' character. 113: 114: Since all base64 input is an integral number of octets, only the 115: ------------------------------------------------- 116: following cases can arise: 117: 118: (1) the final quantum of encoding input is an integral 119: multiple of 24 bits; here, the final unit of encoded 120: output will be an integral multiple of 4 characters 121: with no "=" padding, 122: (2) the final quantum of encoding input is exactly 8 bits; 123: here, the final unit of encoded output will be two 124: characters followed by two "=" padding characters, or 125: (3) the final quantum of encoding input is exactly 16 bits; 126: here, the final unit of encoded output will be three 127: characters followed by one "=" padding character. 128: */ 129: 130: int 131: b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { 132: size_t datalength = 0; 133: u_char input[3]; 134: u_char output[4]; 135: size_t i; 136: 137: while (2 < srclength) { 138: input[0] = *src++; 139: input[1] = *src++; 140: input[2] = *src++; 141: srclength -= 3; 142: 143: output[0] = input[0] >> 2; 144: output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 145: output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 146: output[3] = input[2] & 0x3f; 147: Assert(output[0] < 64); 148: Assert(output[1] < 64); 149: Assert(output[2] < 64); 150: Assert(output[3] < 64); 151: 152: if (datalength + 4 > targsize) 153: return (-1); 154: target[datalength++] = Base64[output[0]]; 155: target[datalength++] = Base64[output[1]]; 156: target[datalength++] = Base64[output[2]]; 157: target[datalength++] = Base64[output[3]]; 158: } 159: 160: /* Now we worry about padding. */ 161: if (0 != srclength) { 162: /* Get what's left. */ 163: input[0] = input[1] = input[2] = '\0'; 164: for (i = 0; i < srclength; i++) 165: input[i] = *src++; 166: 167: output[0] = input[0] >> 2; 168: output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 169: output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 170: Assert(output[0] < 64); 171: Assert(output[1] < 64); 172: Assert(output[2] < 64); 173: 174: if (datalength + 4 > targsize) 175: return (-1); 176: target[datalength++] = Base64[output[0]]; 177: target[datalength++] = Base64[output[1]]; 178: if (srclength == 1) 179: target[datalength++] = Pad64; 180: else 181: target[datalength++] = Base64[output[2]]; 182: target[datalength++] = Pad64; 183: } 184: if (datalength >= targsize) 185: return (-1); 186: target[datalength] = '\0'; /* Returned value doesn't count \0. */ 187: return (datalength); 188: } 189: libresolv_hidden_def (b64_ntop) 190: 191: /* skips all whitespace anywhere. 192: converts characters, four at a time, starting at (or after) 193: src from base - 64 numbers into three 8 bit bytes in the target area. 194: it returns the number of data bytes stored at the target, or -1 on error. 195: */ 196: 197: int 198: b64_pton(src, target, targsize) 199: char const *src; 200: u_char *target; 201: size_t targsize; 202: { 203: int tarindex, state, ch; 204: char *pos; 205: 206: state = 0; 207: tarindex = 0; 208: 209: while ((ch = *src++) != '\0') { 210: if (isspace(ch)) /* Skip whitespace anywhere. */ 211: continue; 212: 213: if (ch == Pad64) 214: break; 215: 216: pos = strchr(Base64, ch); 217: if (pos == 0) /* A non-base64 character. */ 218: return (-1); 219: 220: switch (state) { 221: case 0: 222: if (target) { 223: if ((size_t)tarindex >= targsize) 224: return (-1); 225: target[tarindex] = (pos - Base64) << 2; 226: } 227: state = 1; 228: break; 229: case 1: 230: if (target) { 231: if ((size_t)tarindex + 1 >= targsize) 232: return (-1); 233: target[tarindex] |= (pos - Base64) >> 4; 234: target[tarindex+1] = ((pos - Base64) & 0x0f) 235: << 4 ; 236: } 237: tarindex++; 238: state = 2; 239: break; 240: case 2: 241: if (target) { 242: if ((size_t)tarindex + 1 >= targsize) 243: return (-1); 244: target[tarindex] |= (pos - Base64) >> 2; 245: target[tarindex+1] = ((pos - Base64) & 0x03) 246: << 6; 247: } 248: tarindex++; 249: state = 3; 250: break; 251: case 3: 252: if (target) { 253: if ((size_t)tarindex >= targsize) 254: return (-1); 255: target[tarindex] |= (pos - Base64); 256: } 257: tarindex++; 258: state = 0; 259: break; 260: default: 261: abort(); 262: } 263: } 264: 265: /* 266: * We are done decoding Base-64 chars. Let's see if we ended 267: * on a byte boundary, and/or with erroneous trailing characters. 268: */ 269: 270: if (ch == Pad64) { /* We got a pad char. */ 271: ch = *src++; /* Skip it, get next. */ 272: switch (state) { 273: case 0: /* Invalid = in first position */ 274: case 1: /* Invalid = in second position */ 275: return (-1); 276: 277: case 2: /* Valid, means one byte of info */ 278: /* Skip any number of spaces. */ 279: for ((void)NULL; ch != '\0'; ch = *src++) 280: if (!isspace(ch)) 281: break; 282: /* Make sure there is another trailing = sign. */ 283: if (ch != Pad64) 284: return (-1); 285: ch = *src++; /* Skip the = */ 286: /* Fall through to "single trailing =" case. */ 287: /* FALLTHROUGH */ 288: 289: case 3: /* Valid, means two bytes of info */ 290: /* 291: * We know this char is an =. Is there anything but 292: * whitespace after it? 293: */ 294: for ((void)NULL; ch != '\0'; ch = *src++) 295: if (!isspace(ch)) 296: return (-1); 297: 298: /* 299: * Now make sure for cases 2 and 3 that the "extra" 300: * bits that slopped past the last full byte were 301: * zeros. If we don't check them, they become a 302: * subliminal channel. 303: */ 304: if (target && target[tarindex] != 0) 305: return (-1); 306: } 307: } else { 308: /* 309: * We ended by seeing the end of the string. Make sure we 310: * have no partial bytes lying around. 311: */ 312: if (state != 0) 313: return (-1); 314: } 315: 316: return (tarindex); 317: }