Blame resolv/base64.c

Packit Service 82fcde
/*
Packit Service 82fcde
 * Copyright (c) 1996-1999 by Internet Software Consortium.
Packit Service 82fcde
 *
Packit Service 82fcde
 * Permission to use, copy, modify, and distribute this software for any
Packit Service 82fcde
 * purpose with or without fee is hereby granted, provided that the above
Packit Service 82fcde
 * copyright notice and this permission notice appear in all copies.
Packit Service 82fcde
 *
Packit Service 82fcde
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
Packit Service 82fcde
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
Packit Service 82fcde
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
Packit Service 82fcde
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
Packit Service 82fcde
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
Packit Service 82fcde
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
Packit Service 82fcde
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
Packit Service 82fcde
 * SOFTWARE.
Packit Service 82fcde
 */
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * Portions Copyright (c) 1995 by International Business Machines, Inc.
Packit Service 82fcde
 *
Packit Service 82fcde
 * International Business Machines, Inc. (hereinafter called IBM) grants
Packit Service 82fcde
 * permission under its copyrights to use, copy, modify, and distribute this
Packit Service 82fcde
 * Software with or without fee, provided that the above copyright notice and
Packit Service 82fcde
 * all paragraphs of this notice appear in all copies, and that the name of IBM
Packit Service 82fcde
 * not be used in connection with the marketing of any product incorporating
Packit Service 82fcde
 * the Software or modifications thereof, without specific, written prior
Packit Service 82fcde
 * permission.
Packit Service 82fcde
 *
Packit Service 82fcde
 * To the extent it has a right to do so, IBM grants an immunity from suit
Packit Service 82fcde
 * under its patents, if any, for the use, sale or manufacture of products to
Packit Service 82fcde
 * the extent that such products are used for performing Domain Name System
Packit Service 82fcde
 * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
Packit Service 82fcde
 * granted for any product per se or for any other function of any product.
Packit Service 82fcde
 *
Packit Service 82fcde
 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
Packit Service 82fcde
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
Packit Service 82fcde
 * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
Packit Service 82fcde
 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
Packit Service 82fcde
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
Packit Service 82fcde
 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
Packit Service 82fcde
 */
Packit Service 82fcde
Packit Service 82fcde
#include <sys/types.h>
Packit Service 82fcde
#include <sys/param.h>
Packit Service 82fcde
#include <sys/socket.h>
Packit Service 82fcde
Packit Service 82fcde
#include <netinet/in.h>
Packit Service 82fcde
#include <arpa/inet.h>
Packit Service 82fcde
#include <arpa/nameser.h>
Packit Service 82fcde
Packit Service 82fcde
#include <ctype.h>
Packit Service 82fcde
#include <resolv.h>
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
Packit Service 82fcde
#define Assert(Cond) if (!(Cond)) abort()
Packit Service 82fcde
Packit Service 82fcde
static const char Base64[] =
Packit Service 82fcde
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
Packit Service 82fcde
static const char Pad64 = '=';
Packit Service 82fcde
Packit Service 82fcde
/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
Packit Service 82fcde
   The following encoding technique is taken from RFC 1521 by Borenstein
Packit Service 82fcde
   and Freed.  It is reproduced here in a slightly edited form for
Packit Service 82fcde
   convenience.
Packit Service 82fcde
Packit Service 82fcde
   A 65-character subset of US-ASCII is used, enabling 6 bits to be
Packit Service 82fcde
   represented per printable character. (The extra 65th character, "=",
Packit Service 82fcde
   is used to signify a special processing function.)
Packit Service 82fcde
Packit Service 82fcde
   The encoding process represents 24-bit groups of input bits as output
Packit Service 82fcde
   strings of 4 encoded characters. Proceeding from left to right, a
Packit Service 82fcde
   24-bit input group is formed by concatenating 3 8-bit input groups.
Packit Service 82fcde
   These 24 bits are then treated as 4 concatenated 6-bit groups, each
Packit Service 82fcde
   of which is translated into a single digit in the base64 alphabet.
Packit Service 82fcde
Packit Service 82fcde
   Each 6-bit group is used as an index into an array of 64 printable
Packit Service 82fcde
   characters. The character referenced by the index is placed in the
Packit Service 82fcde
   output string.
Packit Service 82fcde
Packit Service 82fcde
                         Table 1: The Base64 Alphabet
Packit Service 82fcde
Packit Service 82fcde
      Value Encoding  Value Encoding  Value Encoding  Value Encoding
Packit Service 82fcde
          0 A            17 R            34 i            51 z
Packit Service 82fcde
          1 B            18 S            35 j            52 0
Packit Service 82fcde
          2 C            19 T            36 k            53 1
Packit Service 82fcde
          3 D            20 U            37 l            54 2
Packit Service 82fcde
          4 E            21 V            38 m            55 3
Packit Service 82fcde
          5 F            22 W            39 n            56 4
Packit Service 82fcde
          6 G            23 X            40 o            57 5
Packit Service 82fcde
          7 H            24 Y            41 p            58 6
Packit Service 82fcde
          8 I            25 Z            42 q            59 7
Packit Service 82fcde
          9 J            26 a            43 r            60 8
Packit Service 82fcde
         10 K            27 b            44 s            61 9
Packit Service 82fcde
         11 L            28 c            45 t            62 +
Packit Service 82fcde
         12 M            29 d            46 u            63 /
Packit Service 82fcde
         13 N            30 e            47 v
Packit Service 82fcde
         14 O            31 f            48 w         (pad) =
Packit Service 82fcde
         15 P            32 g            49 x
Packit Service 82fcde
         16 Q            33 h            50 y
Packit Service 82fcde
Packit Service 82fcde
   Special processing is performed if fewer than 24 bits are available
Packit Service 82fcde
   at the end of the data being encoded.  A full encoding quantum is
Packit Service 82fcde
   always completed at the end of a quantity.  When fewer than 24 input
Packit Service 82fcde
   bits are available in an input group, zero bits are added (on the
Packit Service 82fcde
   right) to form an integral number of 6-bit groups.  Padding at the
Packit Service 82fcde
   end of the data is performed using the '=' character.
Packit Service 82fcde
Packit Service 82fcde
   Since all base64 input is an integral number of octets, only the
Packit Service 82fcde
         -------------------------------------------------
Packit Service 82fcde
   following cases can arise:
Packit Service 82fcde
Packit Service 82fcde
       (1) the final quantum of encoding input is an integral
Packit Service 82fcde
           multiple of 24 bits; here, the final unit of encoded
Packit Service 82fcde
	   output will be an integral multiple of 4 characters
Packit Service 82fcde
	   with no "=" padding,
Packit Service 82fcde
       (2) the final quantum of encoding input is exactly 8 bits;
Packit Service 82fcde
           here, the final unit of encoded output will be two
Packit Service 82fcde
	   characters followed by two "=" padding characters, or
Packit Service 82fcde
       (3) the final quantum of encoding input is exactly 16 bits;
Packit Service 82fcde
           here, the final unit of encoded output will be three
Packit Service 82fcde
	   characters followed by one "=" padding character.
Packit Service 82fcde
   */
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) {
Packit Service 82fcde
	size_t datalength = 0;
Packit Service 82fcde
	u_char input[3];
Packit Service 82fcde
	u_char output[4];
Packit Service 82fcde
	size_t i;
Packit Service 82fcde
Packit Service 82fcde
	while (2 < srclength) {
Packit Service 82fcde
		input[0] = *src++;
Packit Service 82fcde
		input[1] = *src++;
Packit Service 82fcde
		input[2] = *src++;
Packit Service 82fcde
		srclength -= 3;
Packit Service 82fcde
Packit Service 82fcde
		output[0] = input[0] >> 2;
Packit Service 82fcde
		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
Packit Service 82fcde
		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
Packit Service 82fcde
		output[3] = input[2] & 0x3f;
Packit Service 82fcde
		Assert(output[0] < 64);
Packit Service 82fcde
		Assert(output[1] < 64);
Packit Service 82fcde
		Assert(output[2] < 64);
Packit Service 82fcde
		Assert(output[3] < 64);
Packit Service 82fcde
Packit Service 82fcde
		if (datalength + 4 > targsize)
Packit Service 82fcde
			return (-1);
Packit Service 82fcde
		target[datalength++] = Base64[output[0]];
Packit Service 82fcde
		target[datalength++] = Base64[output[1]];
Packit Service 82fcde
		target[datalength++] = Base64[output[2]];
Packit Service 82fcde
		target[datalength++] = Base64[output[3]];
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
	/* Now we worry about padding. */
Packit Service 82fcde
	if (0 != srclength) {
Packit Service 82fcde
		/* Get what's left. */
Packit Service 82fcde
		input[0] = input[1] = input[2] = '\0';
Packit Service 82fcde
		for (i = 0; i < srclength; i++)
Packit Service 82fcde
			input[i] = *src++;
Packit Service 82fcde
Packit Service 82fcde
		output[0] = input[0] >> 2;
Packit Service 82fcde
		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
Packit Service 82fcde
		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
Packit Service 82fcde
		Assert(output[0] < 64);
Packit Service 82fcde
		Assert(output[1] < 64);
Packit Service 82fcde
		Assert(output[2] < 64);
Packit Service 82fcde
Packit Service 82fcde
		if (datalength + 4 > targsize)
Packit Service 82fcde
			return (-1);
Packit Service 82fcde
		target[datalength++] = Base64[output[0]];
Packit Service 82fcde
		target[datalength++] = Base64[output[1]];
Packit Service 82fcde
		if (srclength == 1)
Packit Service 82fcde
			target[datalength++] = Pad64;
Packit Service 82fcde
		else
Packit Service 82fcde
			target[datalength++] = Base64[output[2]];
Packit Service 82fcde
		target[datalength++] = Pad64;
Packit Service 82fcde
	}
Packit Service 82fcde
	if (datalength >= targsize)
Packit Service 82fcde
		return (-1);
Packit Service 82fcde
	target[datalength] = '\0';	/* Returned value doesn't count \0. */
Packit Service 82fcde
	return (datalength);
Packit Service 82fcde
}
Packit Service 82fcde
libresolv_hidden_def (b64_ntop)
Packit Service 82fcde
Packit Service 82fcde
/* skips all whitespace anywhere.
Packit Service 82fcde
   converts characters, four at a time, starting at (or after)
Packit Service 82fcde
   src from base - 64 numbers into three 8 bit bytes in the target area.
Packit Service 82fcde
   it returns the number of data bytes stored at the target, or -1 on error.
Packit Service 82fcde
 */
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
b64_pton (char const *src, u_char *target, size_t targsize)
Packit Service 82fcde
{
Packit Service 82fcde
	int tarindex, state, ch;
Packit Service 82fcde
	char *pos;
Packit Service 82fcde
Packit Service 82fcde
	state = 0;
Packit Service 82fcde
	tarindex = 0;
Packit Service 82fcde
Packit Service 82fcde
	while ((ch = *src++) != '\0') {
Packit Service 82fcde
		if (isspace(ch))	/* Skip whitespace anywhere. */
Packit Service 82fcde
			continue;
Packit Service 82fcde
Packit Service 82fcde
		if (ch == Pad64)
Packit Service 82fcde
			break;
Packit Service 82fcde
Packit Service 82fcde
		pos = strchr(Base64, ch);
Packit Service 82fcde
		if (pos == 0) 		/* A non-base64 character. */
Packit Service 82fcde
			return (-1);
Packit Service 82fcde
Packit Service 82fcde
		switch (state) {
Packit Service 82fcde
		case 0:
Packit Service 82fcde
			if (target) {
Packit Service 82fcde
				if ((size_t)tarindex >= targsize)
Packit Service 82fcde
					return (-1);
Packit Service 82fcde
				target[tarindex] = (pos - Base64) << 2;
Packit Service 82fcde
			}
Packit Service 82fcde
			state = 1;
Packit Service 82fcde
			break;
Packit Service 82fcde
		case 1:
Packit Service 82fcde
			if (target) {
Packit Service 82fcde
				if ((size_t)tarindex + 1 >= targsize)
Packit Service 82fcde
					return (-1);
Packit Service 82fcde
				target[tarindex]   |=  (pos - Base64) >> 4;
Packit Service 82fcde
				target[tarindex+1]  = ((pos - Base64) & 0x0f)
Packit Service 82fcde
							<< 4 ;
Packit Service 82fcde
			}
Packit Service 82fcde
			tarindex++;
Packit Service 82fcde
			state = 2;
Packit Service 82fcde
			break;
Packit Service 82fcde
		case 2:
Packit Service 82fcde
			if (target) {
Packit Service 82fcde
				if ((size_t)tarindex + 1 >= targsize)
Packit Service 82fcde
					return (-1);
Packit Service 82fcde
				target[tarindex]   |=  (pos - Base64) >> 2;
Packit Service 82fcde
				target[tarindex+1]  = ((pos - Base64) & 0x03)
Packit Service 82fcde
							<< 6;
Packit Service 82fcde
			}
Packit Service 82fcde
			tarindex++;
Packit Service 82fcde
			state = 3;
Packit Service 82fcde
			break;
Packit Service 82fcde
		case 3:
Packit Service 82fcde
			if (target) {
Packit Service 82fcde
				if ((size_t)tarindex >= targsize)
Packit Service 82fcde
					return (-1);
Packit Service 82fcde
				target[tarindex] |= (pos - Base64);
Packit Service 82fcde
			}
Packit Service 82fcde
			tarindex++;
Packit Service 82fcde
			state = 0;
Packit Service 82fcde
			break;
Packit Service 82fcde
		default:
Packit Service 82fcde
			abort();
Packit Service 82fcde
		}
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
	/*
Packit Service 82fcde
	 * We are done decoding Base-64 chars.  Let's see if we ended
Packit Service 82fcde
	 * on a byte boundary, and/or with erroneous trailing characters.
Packit Service 82fcde
	 */
Packit Service 82fcde
Packit Service 82fcde
	if (ch == Pad64) {		/* We got a pad char. */
Packit Service 82fcde
		ch = *src++;		/* Skip it, get next. */
Packit Service 82fcde
		switch (state) {
Packit Service 82fcde
		case 0:		/* Invalid = in first position */
Packit Service 82fcde
		case 1:		/* Invalid = in second position */
Packit Service 82fcde
			return (-1);
Packit Service 82fcde
Packit Service 82fcde
		case 2:		/* Valid, means one byte of info */
Packit Service 82fcde
			/* Skip any number of spaces. */
Packit Service 82fcde
			for ((void)NULL; ch != '\0'; ch = *src++)
Packit Service 82fcde
				if (!isspace(ch))
Packit Service 82fcde
					break;
Packit Service 82fcde
			/* Make sure there is another trailing = sign. */
Packit Service 82fcde
			if (ch != Pad64)
Packit Service 82fcde
				return (-1);
Packit Service 82fcde
			ch = *src++;		/* Skip the = */
Packit Service 82fcde
			/* Fall through to "single trailing =" case. */
Packit Service 82fcde
			/* FALLTHROUGH */
Packit Service 82fcde
Packit Service 82fcde
		case 3:		/* Valid, means two bytes of info */
Packit Service 82fcde
			/*
Packit Service 82fcde
			 * We know this char is an =.  Is there anything but
Packit Service 82fcde
			 * whitespace after it?
Packit Service 82fcde
			 */
Packit Service 82fcde
			for ((void)NULL; ch != '\0'; ch = *src++)
Packit Service 82fcde
				if (!isspace(ch))
Packit Service 82fcde
					return (-1);
Packit Service 82fcde
Packit Service 82fcde
			/*
Packit Service 82fcde
			 * Now make sure for cases 2 and 3 that the "extra"
Packit Service 82fcde
			 * bits that slopped past the last full byte were
Packit Service 82fcde
			 * zeros.  If we don't check them, they become a
Packit Service 82fcde
			 * subliminal channel.
Packit Service 82fcde
			 */
Packit Service 82fcde
			if (target && target[tarindex] != 0)
Packit Service 82fcde
				return (-1);
Packit Service 82fcde
		}
Packit Service 82fcde
	} else {
Packit Service 82fcde
		/*
Packit Service 82fcde
		 * We ended by seeing the end of the string.  Make sure we
Packit Service 82fcde
		 * have no partial bytes lying around.
Packit Service 82fcde
		 */
Packit Service 82fcde
		if (state != 0)
Packit Service 82fcde
			return (-1);
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
	return (tarindex);
Packit Service 82fcde
}