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