base64.c

Go to the documentation of this file.
00001 /* base64 routines.
00002  *
00003  * (C) 2003-2007 Anope Team
00004  * Contact us at info@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church. 
00010  * 
00011  *
00012  */
00013 
00014 /*
00015    This is borrowed from Unreal
00016 */
00017 
00018 #include "services.h"
00019 
00020 static char *int_to_base64(long);
00021 static long base64_to_int(char *);
00022 
00023 char *base64enc(long i)
00024 {
00025     if (i < 0)
00026         return ("0");
00027     return int_to_base64(i);
00028 }
00029 
00030 long base64dec(char *b64)
00031 {
00032     if (b64)
00033         return base64_to_int(b64);
00034     else
00035         return 0;
00036 }
00037 
00038 
00039 static const char Base64[] =
00040     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00041 static const char Pad64 = '=';
00042 
00043 /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
00044    The following encoding technique is taken from RFC 1521 by Borenstein
00045    and Freed.  It is reproduced here in a slightly edited form for
00046    convenience.
00047 
00048    A 65-character subset of US-ASCII is used, enabling 6 bits to be
00049    represented per printable character. (The extra 65th character, "=",
00050    is used to signify a special processing function.)
00051 
00052    The encoding process represents 24-bit groups of input bits as output
00053    strings of 4 encoded characters. Proceeding from left to right, a
00054    24-bit input group is formed by concatenating 3 8-bit input groups.
00055    These 24 bits are then treated as 4 concatenated 6-bit groups, each
00056    of which is translated into a single digit in the base64 alphabet.
00057 
00058    Each 6-bit group is used as an index into an array of 64 printable
00059    characters. The character referenced by the index is placed in the
00060    output string.
00061 
00062                          Table 1: The Base64 Alphabet
00063 
00064       Value Encoding  Value Encoding  Value Encoding  Value Encoding
00065           0 A            17 R            34 i            51 z
00066           1 B            18 S            35 j            52 0
00067           2 C            19 T            36 k            53 1
00068           3 D            20 U            37 l            54 2
00069           4 E            21 V            38 m            55 3
00070           5 F            22 W            39 n            56 4
00071           6 G            23 X            40 o            57 5
00072           7 H            24 Y            41 p            58 6
00073           8 I            25 Z            42 q            59 7
00074           9 J            26 a            43 r            60 8
00075          10 K            27 b            44 s            61 9
00076          11 L            28 c            45 t            62 +
00077          12 M            29 d            46 u            63 /
00078          13 N            30 e            47 v
00079          14 O            31 f            48 w         (pad) =
00080          15 P            32 g            49 x
00081          16 Q            33 h            50 y
00082 
00083    Special processing is performed if fewer than 24 bits are available
00084    at the end of the data being encoded.  A full encoding quantum is
00085    always completed at the end of a quantity.  When fewer than 24 input
00086    bits are available in an input group, zero bits are added (on the
00087    right) to form an integral number of 6-bit groups.  Padding at the
00088    end of the data is performed using the '=' character.
00089 
00090    Since all base64 input is an integral number of octets, only the
00091          -------------------------------------------------                       
00092    following cases can arise:
00093    
00094        (1) the final quantum of encoding input is an integral
00095            multiple of 24 bits; here, the final unit of encoded
00096        output will be an integral multiple of 4 characters
00097        with no "=" padding,
00098        (2) the final quantum of encoding input is exactly 8 bits;
00099            here, the final unit of encoded output will be two
00100        characters followed by two "=" padding characters, or
00101        (3) the final quantum of encoding input is exactly 16 bits;
00102            here, the final unit of encoded output will be three
00103        characters followed by one "=" padding character.
00104    */
00105 
00106 int b64_encode(char *src, size_t srclength, char *target, size_t targsize)
00107 {
00108     size_t datalength = 0;
00109     unsigned char input[3];
00110     unsigned char output[4];
00111     size_t i;
00112 
00113     while (2 < srclength) {
00114         input[0] = *src++;
00115         input[1] = *src++;
00116         input[2] = *src++;
00117         srclength -= 3;
00118 
00119         output[0] = input[0] >> 2;
00120         output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
00121         output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
00122         output[3] = input[2] & 0x3f;
00123 
00124         if (datalength + 4 > targsize)
00125             return (-1);
00126         target[datalength++] = Base64[output[0]];
00127         target[datalength++] = Base64[output[1]];
00128         target[datalength++] = Base64[output[2]];
00129         target[datalength++] = Base64[output[3]];
00130     }
00131 
00132     /* Now we worry about padding. */
00133     if (0 != srclength) {
00134         /* Get what's left. */
00135         input[0] = input[1] = input[2] = '\0';
00136         for (i = 0; i < srclength; i++)
00137             input[i] = *src++;
00138 
00139         output[0] = input[0] >> 2;
00140         output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
00141         output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
00142 
00143         if (datalength + 4 > targsize)
00144             return (-1);
00145         target[datalength++] = Base64[output[0]];
00146         target[datalength++] = Base64[output[1]];
00147         if (srclength == 1)
00148             target[datalength++] = Pad64;
00149         else
00150             target[datalength++] = Base64[output[2]];
00151         target[datalength++] = Pad64;
00152     }
00153     if (datalength >= targsize)
00154         return (-1);
00155     target[datalength] = '\0';  /* Returned value doesn't count \0. */
00156     return (datalength);
00157 }
00158 
00159 /* skips all whitespace anywhere.
00160    converts characters, four at a time, starting at (or after)
00161    src from base - 64 numbers into three 8 bit bytes in the target area.
00162    it returns the number of data bytes stored at the target, or -1 on error.
00163  */
00164 
00165 int b64_decode(char *src, char *target, size_t targsize)
00166 {
00167     int tarindex, state, ch;
00168     char *pos;
00169 
00170     state = 0;
00171     tarindex = 0;
00172 
00173     while ((ch = *src++) != '\0') {
00174         if (isspace(ch))        /* Skip whitespace anywhere. */
00175             continue;
00176 
00177         if (ch == Pad64)
00178             break;
00179 
00180         pos = strchr(Base64, ch);
00181         if (pos == 0)           /* A non-base64 character. */
00182             return (-1);
00183 
00184         switch (state) {
00185         case 0:
00186             if (target) {
00187                 if ((size_t) tarindex >= targsize)
00188                     return (-1);
00189                 target[tarindex] = (pos - Base64) << 2;
00190             }
00191             state = 1;
00192             break;
00193         case 1:
00194             if (target) {
00195                 if ((size_t) tarindex + 1 >= targsize)
00196                     return (-1);
00197                 target[tarindex] |= (pos - Base64) >> 4;
00198                 target[tarindex + 1] = ((pos - Base64) & 0x0f)
00199                     << 4;
00200             }
00201             tarindex++;
00202             state = 2;
00203             break;
00204         case 2:
00205             if (target) {
00206                 if ((size_t) tarindex + 1 >= targsize)
00207                     return (-1);
00208                 target[tarindex] |= (pos - Base64) >> 2;
00209                 target[tarindex + 1] = ((pos - Base64) & 0x03)
00210                     << 6;
00211             }
00212             tarindex++;
00213             state = 3;
00214             break;
00215         case 3:
00216             if (target) {
00217                 if ((size_t) tarindex >= targsize)
00218                     return (-1);
00219                 target[tarindex] |= (pos - Base64);
00220             }
00221             tarindex++;
00222             state = 0;
00223             break;
00224         default:
00225             abort();
00226         }
00227     }
00228 
00229     /*
00230      * We are done decoding Base-64 chars.  Let's see if we ended
00231      * on a byte boundary, and/or with erroneous trailing characters.
00232      */
00233 
00234     if (ch == Pad64) {          /* We got a pad char. */
00235         ch = *src++;            /* Skip it, get next. */
00236         switch (state) {
00237         case 0:                /* Invalid = in first position */
00238         case 1:                /* Invalid = in second position */
00239             return (-1);
00240 
00241         case 2:                /* Valid, means one byte of info */
00242             /* Skip any number of spaces. */
00243             for ((void) NULL; ch != '\0'; ch = *src++)
00244                 if (!isspace(ch))
00245                     break;
00246             /* Make sure there is another trailing = sign. */
00247             if (ch != Pad64)
00248                 return (-1);
00249             ch = *src++;        /* Skip the = */
00250             /* Fall through to "single trailing =" case. */
00251             /* FALLTHROUGH */
00252 
00253         case 3:                /* Valid, means two bytes of info */
00254             /*
00255              * We know this char is an =.  Is there anything but
00256              * whitespace after it?
00257              */
00258             for ((void) NULL; ch != '\0'; ch = *src++)
00259                 if (!isspace(ch))
00260                     return (-1);
00261 
00262             /*
00263              * Now make sure for cases 2 and 3 that the "extra"
00264              * bits that slopped past the last full byte were
00265              * zeros.  If we don't check them, they become a
00266              * subliminal channel.
00267              */
00268             if (target && target[tarindex] != 0)
00269                 return (-1);
00270         }
00271     } else {
00272         /*
00273          * We ended by seeing the end of the string.  Make sure we
00274          * have no partial bytes lying around.
00275          */
00276         if (state != 0)
00277             return (-1);
00278     }
00279 
00280     return (tarindex);
00281 }
00282 
00283 char *encode_ip(unsigned char *ip)
00284 {
00285     static char buf[25];
00286     unsigned char *cp;
00287     struct in_addr ia;          /* For IPv4 */
00288     char *s_ip;                 /* Signed ip string */
00289 
00290     if (!ip)
00291         return "*";
00292 
00293     if (strchr((char *) ip, ':')) {
00294         return NULL;
00295     } else {
00296         s_ip = str_signed(ip);
00297         ia.s_addr = inet_addr(s_ip);
00298         cp = (unsigned char *) ia.s_addr;
00299         b64_encode((char *) &cp, sizeof(struct in_addr), buf, 25);
00300     }
00301     return buf;
00302 }
00303 
00304 int decode_ip(char *buf)
00305 {
00306     int len = strlen(buf);
00307     char targ[25];
00308     struct in_addr ia;
00309 
00310     b64_decode(buf, targ, 25);
00311     ia = *(struct in_addr *) targ;
00312     if (len == 24) {            /* IPv6 */
00313         return 0;
00314     } else if (len == 8)        /* IPv4 */
00315         return ia.s_addr;
00316     else                        /* Error?? */
00317         return 0;
00318 }
00319 
00320 /* ':' and '#' and '&' and '+' and '@' must never be in this table. */
00321 /* these tables must NEVER CHANGE! >) */
00322 char int6_to_base64_map[] = {
00323     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
00324     'E', 'F',
00325     'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
00326     'U', 'V',
00327     'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
00328     'k', 'l',
00329     'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
00330     '{', '}'
00331 };
00332 
00333 char base64_to_int6_map[] = {
00334     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00335     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00336     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00337     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
00338     -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
00339     25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
00340     -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
00341     51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1, 63, -1, -1,
00342     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00343     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00344     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00345     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00346     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00347     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00348     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00349     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
00350 };
00351 
00352 static char *int_to_base64(long val)
00353 {
00354     /* 32/6 == max 6 bytes for representation, 
00355      * +1 for the null, +1 for byte boundaries 
00356      */
00357     static char base64buf[8];
00358     long i = 7;
00359 
00360     base64buf[i] = '\0';
00361 
00362     /* Temporary debugging code.. remove before 2038 ;p.
00363      * This might happen in case of 64bit longs (opteron/ia64),
00364      * if the value is then too large it can easily lead to
00365      * a buffer underflow and thus to a crash. -- Syzop
00366      */
00367     if (val > 2147483647L) {
00368         abort();
00369     }
00370 
00371     do {
00372         base64buf[--i] = int6_to_base64_map[val & 63];
00373     }
00374     while (val >>= 6);
00375 
00376     return base64buf + i;
00377 }
00378 
00379 static long base64_to_int(char *b64)
00380 {
00381     int v = base64_to_int6_map[(unsigned char) *b64++];
00382 
00383     if (!b64)
00384         return 0;
00385 
00386     while (*b64) {
00387         v <<= 6;
00388         v += base64_to_int6_map[(unsigned char) *b64++];
00389     }
00390 
00391     return v;
00392 }
00393 
00394 long base64dects(char *ts)
00395 {
00396     char *token;
00397     long value;
00398 
00399     if (!ts) {
00400         return 0;
00401     }
00402     token = myStrGetToken(ts, '!', 1);
00403 
00404     if (!token) {
00405         return strtoul(ts, NULL, 10);
00406     }
00407     value = base64dec(token);
00408     Anope_Free(token);
00409     return value;
00410 }

Generated on Sun Dec 30 09:26:45 2007 for Anope by  doxygen 1.5.1-20070107