File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / dst / base64.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:06:54 2012 UTC (11 years, 8 months ago) by misho
Branches: dhcp, MAIN
CVS tags: v4_1_R7p0, v4_1_R7, v4_1_R4, HEAD
dhcp 4.1 r7

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>