(linenum→info "unix/slp.c:2238")

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