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