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, ®ion);
! 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>