Merge from vendor branch FILE:
[dragonfly.git] / contrib / dhcp-3.0 / dst / base64.c
1 /*
2  * Copyright (c) 2004 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  *   http://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.2.1 2004/06/10 17:59:28 dhankins 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 }