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