Annotation of embedaddon/dhcp/dst/base64.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (c) 2004,2009 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:  *   https://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)
1.1.1.1 ! misho      50: static const char rcsid[] = "$Id: base64.c,v 1.2.786.2 2009/07/24 22:04:52 sar Exp $";
1.1       misho      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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>