Annotation of embedaddon/tmux/compat/base64.c, revision 1.1.1.1

1.1       misho       1: /*     $OpenBSD: base64.c,v 1.8 2015/01/16 16:48:51 deraadt Exp $      */
                      2: 
                      3: /*
                      4:  * Copyright (c) 1996 by Internet Software Consortium.
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
                     11:  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
                     12:  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
                     13:  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
                     14:  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
                     15:  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
                     16:  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                     17:  * SOFTWARE.
                     18:  */
                     19: 
                     20: /*
                     21:  * Portions Copyright (c) 1995 by International Business Machines, Inc.
                     22:  *
                     23:  * International Business Machines, Inc. (hereinafter called IBM) grants
                     24:  * permission under its copyrights to use, copy, modify, and distribute this
                     25:  * Software with or without fee, provided that the above copyright notice and
                     26:  * all paragraphs of this notice appear in all copies, and that the name of IBM
                     27:  * not be used in connection with the marketing of any product incorporating
                     28:  * the Software or modifications thereof, without specific, written prior
                     29:  * permission.
                     30:  *
                     31:  * To the extent it has a right to do so, IBM grants an immunity from suit
                     32:  * under its patents, if any, for the use, sale or manufacture of products to
                     33:  * the extent that such products are used for performing Domain Name System
                     34:  * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
                     35:  * granted for any product per se or for any other function of any product.
                     36:  *
                     37:  * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
                     38:  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
                     39:  * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
                     40:  * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
                     41:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
                     42:  * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
                     43:  */
                     44: 
                     45: #include <sys/types.h>
                     46: #include <sys/socket.h>
                     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: 
                     55: #include <stdlib.h>
                     56: #include <string.h>
                     57: 
                     58: static const char Base64[] =
                     59:        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
                     60: static const char Pad64 = '=';
                     61: 
                     62: /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
                     63:    The following encoding technique is taken from RFC 1521 by Borenstein
                     64:    and Freed.  It is reproduced here in a slightly edited form for
                     65:    convenience.
                     66: 
                     67:    A 65-character subset of US-ASCII is used, enabling 6 bits to be
                     68:    represented per printable character. (The extra 65th character, "=",
                     69:    is used to signify a special processing function.)
                     70: 
                     71:    The encoding process represents 24-bit groups of input bits as output
                     72:    strings of 4 encoded characters. Proceeding from left to right, a
                     73:    24-bit input group is formed by concatenating 3 8-bit input groups.
                     74:    These 24 bits are then treated as 4 concatenated 6-bit groups, each
                     75:    of which is translated into a single digit in the base64 alphabet.
                     76: 
                     77:    Each 6-bit group is used as an index into an array of 64 printable
                     78:    characters. The character referenced by the index is placed in the
                     79:    output string.
                     80: 
                     81:                          Table 1: The Base64 Alphabet
                     82: 
                     83:       Value Encoding  Value Encoding  Value Encoding  Value Encoding
                     84:           0 A            17 R            34 i            51 z
                     85:           1 B            18 S            35 j            52 0
                     86:           2 C            19 T            36 k            53 1
                     87:           3 D            20 U            37 l            54 2
                     88:           4 E            21 V            38 m            55 3
                     89:           5 F            22 W            39 n            56 4
                     90:           6 G            23 X            40 o            57 5
                     91:           7 H            24 Y            41 p            58 6
                     92:           8 I            25 Z            42 q            59 7
                     93:           9 J            26 a            43 r            60 8
                     94:          10 K            27 b            44 s            61 9
                     95:          11 L            28 c            45 t            62 +
                     96:          12 M            29 d            46 u            63 /
                     97:          13 N            30 e            47 v
                     98:          14 O            31 f            48 w         (pad) =
                     99:          15 P            32 g            49 x
                    100:          16 Q            33 h            50 y
                    101: 
                    102:    Special processing is performed if fewer than 24 bits are available
                    103:    at the end of the data being encoded.  A full encoding quantum is
                    104:    always completed at the end of a quantity.  When fewer than 24 input
                    105:    bits are available in an input group, zero bits are added (on the
                    106:    right) to form an integral number of 6-bit groups.  Padding at the
                    107:    end of the data is performed using the '=' character.
                    108: 
                    109:    Since all base64 input is an integral number of octets, only the
                    110:          -------------------------------------------------                       
                    111:    following cases can arise:
                    112:    
                    113:        (1) the final quantum of encoding input is an integral
                    114:            multiple of 24 bits; here, the final unit of encoded
                    115:           output will be an integral multiple of 4 characters
                    116:           with no "=" padding,
                    117:        (2) the final quantum of encoding input is exactly 8 bits;
                    118:            here, the final unit of encoded output will be two
                    119:           characters followed by two "=" padding characters, or
                    120:        (3) the final quantum of encoding input is exactly 16 bits;
                    121:            here, the final unit of encoded output will be three
                    122:           characters followed by one "=" padding character.
                    123:    */
                    124: 
                    125: int
                    126: b64_ntop(src, srclength, target, targsize)
                    127:        u_char const *src;
                    128:        size_t srclength;
                    129:        char *target;
                    130:        size_t targsize;
                    131: {
                    132:        size_t datalength = 0;
                    133:        u_char input[3];
                    134:        u_char output[4];
                    135:        int i;
                    136: 
                    137:        while (2 < srclength) {
                    138:                input[0] = *src++;
                    139:                input[1] = *src++;
                    140:                input[2] = *src++;
                    141:                srclength -= 3;
                    142: 
                    143:                output[0] = input[0] >> 2;
                    144:                output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
                    145:                output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
                    146:                output[3] = input[2] & 0x3f;
                    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: 
                    167:                if (datalength + 4 > targsize)
                    168:                        return (-1);
                    169:                target[datalength++] = Base64[output[0]];
                    170:                target[datalength++] = Base64[output[1]];
                    171:                if (srclength == 1)
                    172:                        target[datalength++] = Pad64;
                    173:                else
                    174:                        target[datalength++] = Base64[output[2]];
                    175:                target[datalength++] = Pad64;
                    176:        }
                    177:        if (datalength >= targsize)
                    178:                return (-1);
                    179:        target[datalength] = '\0';      /* Returned value doesn't count \0. */
                    180:        return (datalength);
                    181: }
                    182: 
                    183: /* skips all whitespace anywhere.
                    184:    converts characters, four at a time, starting at (or after)
                    185:    src from base - 64 numbers into three 8 bit bytes in the target area.
                    186:    it returns the number of data bytes stored at the target, or -1 on error.
                    187:  */
                    188: 
                    189: int
                    190: b64_pton(src, target, targsize)
                    191:        char const *src;
                    192:        u_char *target;
                    193:        size_t targsize;
                    194: {
                    195:        int tarindex, state, ch;
                    196:        u_char nextbyte;
                    197:        char *pos;
                    198: 
                    199:        state = 0;
                    200:        tarindex = 0;
                    201: 
                    202:        while ((ch = (unsigned char)*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 (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 (tarindex >= targsize)
                    225:                                        return (-1);
                    226:                                target[tarindex]   |=  (pos - Base64) >> 4;
                    227:                                nextbyte = ((pos - Base64) & 0x0f) << 4;
                    228:                                if (tarindex + 1 < targsize)
                    229:                                        target[tarindex+1] = nextbyte;
                    230:                                else if (nextbyte)
                    231:                                        return (-1);
                    232:                        }
                    233:                        tarindex++;
                    234:                        state = 2;
                    235:                        break;
                    236:                case 2:
                    237:                        if (target) {
                    238:                                if (tarindex >= targsize)
                    239:                                        return (-1);
                    240:                                target[tarindex]   |=  (pos - Base64) >> 2;
                    241:                                nextbyte = ((pos - Base64) & 0x03) << 6;
                    242:                                if (tarindex + 1 < targsize)
                    243:                                        target[tarindex+1] = nextbyte;
                    244:                                else if (nextbyte)
                    245:                                        return (-1);
                    246:                        }
                    247:                        tarindex++;
                    248:                        state = 3;
                    249:                        break;
                    250:                case 3:
                    251:                        if (target) {
                    252:                                if (tarindex >= targsize)
                    253:                                        return (-1);
                    254:                                target[tarindex] |= (pos - Base64);
                    255:                        }
                    256:                        tarindex++;
                    257:                        state = 0;
                    258:                        break;
                    259:                }
                    260:        }
                    261: 
                    262:        /*
                    263:         * We are done decoding Base-64 chars.  Let's see if we ended
                    264:         * on a byte boundary, and/or with erroneous trailing characters.
                    265:         */
                    266: 
                    267:        if (ch == Pad64) {                      /* We got a pad char. */
                    268:                ch = (unsigned char)*src++;     /* Skip it, get next. */
                    269:                switch (state) {
                    270:                case 0:         /* Invalid = in first position */
                    271:                case 1:         /* Invalid = in second position */
                    272:                        return (-1);
                    273: 
                    274:                case 2:         /* Valid, means one byte of info */
                    275:                        /* Skip any number of spaces. */
                    276:                        for (; ch != '\0'; ch = (unsigned char)*src++)
                    277:                                if (!isspace(ch))
                    278:                                        break;
                    279:                        /* Make sure there is another trailing = sign. */
                    280:                        if (ch != Pad64)
                    281:                                return (-1);
                    282:                        ch = (unsigned char)*src++;             /* Skip the = */
                    283:                        /* Fall through to "single trailing =" case. */
                    284:                        /* FALLTHROUGH */
                    285: 
                    286:                case 3:         /* Valid, means two bytes of info */
                    287:                        /*
                    288:                         * We know this char is an =.  Is there anything but
                    289:                         * whitespace after it?
                    290:                         */
                    291:                        for (; ch != '\0'; ch = (unsigned char)*src++)
                    292:                                if (!isspace(ch))
                    293:                                        return (-1);
                    294: 
                    295:                        /*
                    296:                         * Now make sure for cases 2 and 3 that the "extra"
                    297:                         * bits that slopped past the last full byte were
                    298:                         * zeros.  If we don't check them, they become a
                    299:                         * subliminal channel.
                    300:                         */
                    301:                        if (target && tarindex < targsize &&
                    302:                            target[tarindex] != 0)
                    303:                                return (-1);
                    304:                }
                    305:        } else {
                    306:                /*
                    307:                 * We ended by seeing the end of the string.  Make sure we
                    308:                 * have no partial bytes lying around.
                    309:                 */
                    310:                if (state != 0)
                    311:                        return (-1);
                    312:        }
                    313: 
                    314:        return (tarindex);
                    315: }

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