Annotation of embedaddon/ntp/lib/isc/base64.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
        !             3:  * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
        !             4:  *
        !             5:  * Permission to use, copy, modify, and/or 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 WITH
        !            10:  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
        !            11:  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
        !            12:  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
        !            13:  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
        !            14:  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
        !            15:  * PERFORMANCE OF THIS SOFTWARE.
        !            16:  */
        !            17: 
        !            18: /* $Id: base64.c,v 1.32 2007/06/19 23:47:17 tbox Exp $ */
        !            19: 
        !            20: /*! \file */
        !            21: 
        !            22: #include <config.h>
        !            23: 
        !            24: #include <isc/base64.h>
        !            25: #include <isc/buffer.h>
        !            26: #include <isc/lex.h>
        !            27: #include <isc/string.h>
        !            28: #include <isc/util.h>
        !            29: 
        !            30: #define RETERR(x) do { \
        !            31:        isc_result_t _r = (x); \
        !            32:        if (_r != ISC_R_SUCCESS) \
        !            33:                return (_r); \
        !            34:        } while (0)
        !            35: 
        !            36: 
        !            37: /*@{*/
        !            38: /*!
        !            39:  * These static functions are also present in lib/dns/rdata.c.  I'm not
        !            40:  * sure where they should go. -- bwelling
        !            41:  */
        !            42: static isc_result_t
        !            43: str_totext(const char *source, isc_buffer_t *target);
        !            44: 
        !            45: static isc_result_t
        !            46: mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
        !            47: 
        !            48: static const char base64[] =
        !            49:        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
        !            50: /*@}*/
        !            51: 
        !            52: isc_result_t
        !            53: isc_base64_totext(isc_region_t *source, int wordlength,
        !            54:                  const char *wordbreak, isc_buffer_t *target)
        !            55: {
        !            56:        char buf[5];
        !            57:        unsigned int loops = 0;
        !            58: 
        !            59:        if (wordlength < 4)
        !            60:                wordlength = 4;
        !            61: 
        !            62:        memset(buf, 0, sizeof(buf));
        !            63:        while (source->length > 2) {
        !            64:                buf[0] = base64[(source->base[0]>>2)&0x3f];
        !            65:                buf[1] = base64[((source->base[0]<<4)&0x30)|
        !            66:                                ((source->base[1]>>4)&0x0f)];
        !            67:                buf[2] = base64[((source->base[1]<<2)&0x3c)|
        !            68:                                ((source->base[2]>>6)&0x03)];
        !            69:                buf[3] = base64[source->base[2]&0x3f];
        !            70:                RETERR(str_totext(buf, target));
        !            71:                isc_region_consume(source, 3);
        !            72: 
        !            73:                loops++;
        !            74:                if (source->length != 0 &&
        !            75:                    (int)((loops + 1) * 4) >= wordlength)
        !            76:                {
        !            77:                        loops = 0;
        !            78:                        RETERR(str_totext(wordbreak, target));
        !            79:                }
        !            80:        }
        !            81:        if (source->length == 2) {
        !            82:                buf[0] = base64[(source->base[0]>>2)&0x3f];
        !            83:                buf[1] = base64[((source->base[0]<<4)&0x30)|
        !            84:                                ((source->base[1]>>4)&0x0f)];
        !            85:                buf[2] = base64[((source->base[1]<<2)&0x3c)];
        !            86:                buf[3] = '=';
        !            87:                RETERR(str_totext(buf, target));
        !            88:        } else if (source->length == 1) {
        !            89:                buf[0] = base64[(source->base[0]>>2)&0x3f];
        !            90:                buf[1] = base64[((source->base[0]<<4)&0x30)];
        !            91:                buf[2] = buf[3] = '=';
        !            92:                RETERR(str_totext(buf, target));
        !            93:        }
        !            94:        return (ISC_R_SUCCESS);
        !            95: }
        !            96: 
        !            97: /*%
        !            98:  * State of a base64 decoding process in progress.
        !            99:  */
        !           100: typedef struct {
        !           101:        int length;             /*%< Desired length of binary data or -1 */
        !           102:        isc_buffer_t *target;   /*%< Buffer for resulting binary data */
        !           103:        int digits;             /*%< Number of buffered base64 digits */
        !           104:        isc_boolean_t seen_end; /*%< True if "=" end marker seen */
        !           105:        int val[4];
        !           106: } base64_decode_ctx_t;
        !           107: 
        !           108: static inline void
        !           109: base64_decode_init(base64_decode_ctx_t *ctx, int length, isc_buffer_t *target)
        !           110: {
        !           111:        ctx->digits = 0;
        !           112:        ctx->seen_end = ISC_FALSE;
        !           113:        ctx->length = length;
        !           114:        ctx->target = target;
        !           115: }
        !           116: 
        !           117: static inline isc_result_t
        !           118: base64_decode_char(base64_decode_ctx_t *ctx, int c) {
        !           119:        char *s;
        !           120: 
        !           121:        if (ctx->seen_end)
        !           122:                return (ISC_R_BADBASE64);
        !           123:        if ((s = strchr(base64, c)) == NULL)
        !           124:                return (ISC_R_BADBASE64);
        !           125:        ctx->val[ctx->digits++] = s - base64;
        !           126:        if (ctx->digits == 4) {
        !           127:                int n;
        !           128:                unsigned char buf[3];
        !           129:                if (ctx->val[0] == 64 || ctx->val[1] == 64)
        !           130:                        return (ISC_R_BADBASE64);
        !           131:                if (ctx->val[2] == 64 && ctx->val[3] != 64)
        !           132:                        return (ISC_R_BADBASE64);
        !           133:                /*
        !           134:                 * Check that bits that should be zero are.
        !           135:                 */
        !           136:                if (ctx->val[2] == 64 && (ctx->val[1] & 0xf) != 0)
        !           137:                        return (ISC_R_BADBASE64);
        !           138:                /*
        !           139:                 * We don't need to test for ctx->val[2] != 64 as
        !           140:                 * the bottom two bits of 64 are zero.
        !           141:                 */
        !           142:                if (ctx->val[3] == 64 && (ctx->val[2] & 0x3) != 0)
        !           143:                        return (ISC_R_BADBASE64);
        !           144:                n = (ctx->val[2] == 64) ? 1 :
        !           145:                        (ctx->val[3] == 64) ? 2 : 3;
        !           146:                if (n != 3) {
        !           147:                        ctx->seen_end = ISC_TRUE;
        !           148:                        if (ctx->val[2] == 64)
        !           149:                                ctx->val[2] = 0;
        !           150:                        if (ctx->val[3] == 64)
        !           151:                                ctx->val[3] = 0;
        !           152:                }
        !           153:                buf[0] = (ctx->val[0]<<2)|(ctx->val[1]>>4);
        !           154:                buf[1] = (ctx->val[1]<<4)|(ctx->val[2]>>2);
        !           155:                buf[2] = (ctx->val[2]<<6)|(ctx->val[3]);
        !           156:                RETERR(mem_tobuffer(ctx->target, buf, n));
        !           157:                if (ctx->length >= 0) {
        !           158:                        if (n > ctx->length)
        !           159:                                return (ISC_R_BADBASE64);
        !           160:                        else
        !           161:                                ctx->length -= n;
        !           162:                }
        !           163:                ctx->digits = 0;
        !           164:        }
        !           165:        return (ISC_R_SUCCESS);
        !           166: }
        !           167: 
        !           168: static inline isc_result_t
        !           169: base64_decode_finish(base64_decode_ctx_t *ctx) {
        !           170:        if (ctx->length > 0)
        !           171:                return (ISC_R_UNEXPECTEDEND);
        !           172:        if (ctx->digits != 0)
        !           173:                return (ISC_R_BADBASE64);
        !           174:        return (ISC_R_SUCCESS);
        !           175: }
        !           176: 
        !           177: isc_result_t
        !           178: isc_base64_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
        !           179:        base64_decode_ctx_t ctx;
        !           180:        isc_textregion_t *tr;
        !           181:        isc_token_t token;
        !           182:        isc_boolean_t eol;
        !           183: 
        !           184:        base64_decode_init(&ctx, length, target);
        !           185: 
        !           186:        while (!ctx.seen_end && (ctx.length != 0)) {
        !           187:                unsigned int i;
        !           188: 
        !           189:                if (length > 0)
        !           190:                        eol = ISC_FALSE;
        !           191:                else
        !           192:                        eol = ISC_TRUE;
        !           193:                RETERR(isc_lex_getmastertoken(lexer, &token,
        !           194:                                              isc_tokentype_string, eol));
        !           195:                if (token.type != isc_tokentype_string)
        !           196:                        break;
        !           197:                tr = &token.value.as_textregion;
        !           198:                for (i = 0; i < tr->length; i++)
        !           199:                        RETERR(base64_decode_char(&ctx, tr->base[i]));
        !           200:        }
        !           201:        if (ctx.length < 0 && !ctx.seen_end)
        !           202:                isc_lex_ungettoken(lexer, &token);
        !           203:        RETERR(base64_decode_finish(&ctx));
        !           204:        return (ISC_R_SUCCESS);
        !           205: }
        !           206: 
        !           207: isc_result_t
        !           208: isc_base64_decodestring(const char *cstr, isc_buffer_t *target) {
        !           209:        base64_decode_ctx_t ctx;
        !           210: 
        !           211:        base64_decode_init(&ctx, -1, target);
        !           212:        for (;;) {
        !           213:                int c = *cstr++;
        !           214:                if (c == '\0')
        !           215:                        break;
        !           216:                if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
        !           217:                        continue;
        !           218:                RETERR(base64_decode_char(&ctx, c));
        !           219:        }
        !           220:        RETERR(base64_decode_finish(&ctx));     
        !           221:        return (ISC_R_SUCCESS);
        !           222: }
        !           223: 
        !           224: static isc_result_t
        !           225: str_totext(const char *source, isc_buffer_t *target) {
        !           226:        unsigned int l;
        !           227:        isc_region_t region;
        !           228: 
        !           229:        isc_buffer_availableregion(target, &region);
        !           230:        l = strlen(source);
        !           231: 
        !           232:        if (l > region.length)
        !           233:                return (ISC_R_NOSPACE);
        !           234: 
        !           235:        memcpy(region.base, source, l);
        !           236:        isc_buffer_add(target, l);
        !           237:        return (ISC_R_SUCCESS);
        !           238: }
        !           239: 
        !           240: static isc_result_t
        !           241: mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
        !           242:        isc_region_t tr;
        !           243: 
        !           244:        isc_buffer_availableregion(target, &tr);
        !           245:        if (length > tr.length)
        !           246:                return (ISC_R_NOSPACE);
        !           247:        memcpy(tr.base, base, length);
        !           248:        isc_buffer_add(target, length);
        !           249:        return (ISC_R_SUCCESS);
        !           250: }

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