Home | History | Annotate | Download | only in BsdSocketLib
      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
    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
    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