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