Annotation of embedaddon/curl/lib/base64.c, revision 1.1
1.1 ! misho 1: /***************************************************************************
! 2: * _ _ ____ _
! 3: * Project ___| | | | _ \| |
! 4: * / __| | | | |_) | |
! 5: * | (__| |_| | _ <| |___
! 6: * \___|\___/|_| \_\_____|
! 7: *
! 8: * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
! 9: *
! 10: * This software is licensed as described in the file COPYING, which
! 11: * you should have received as part of this distribution. The terms
! 12: * are also available at https://curl.haxx.se/docs/copyright.html.
! 13: *
! 14: * You may opt to use, copy, modify, merge, publish, distribute and/or sell
! 15: * copies of the Software, and permit persons to whom the Software is
! 16: * furnished to do so, under the terms of the COPYING file.
! 17: *
! 18: * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
! 19: * KIND, either express or implied.
! 20: *
! 21: ***************************************************************************/
! 22:
! 23: /* Base64 encoding/decoding */
! 24:
! 25: #include "curl_setup.h"
! 26:
! 27: #if !defined(CURL_DISABLE_HTTP_AUTH) || defined(USE_SSH) || \
! 28: !defined(CURL_DISABLE_LDAP) || \
! 29: !defined(CURL_DISABLE_DOH) || defined(USE_SSL)
! 30:
! 31: #include "urldata.h" /* for the Curl_easy definition */
! 32: #include "warnless.h"
! 33: #include "curl_base64.h"
! 34: #include "non-ascii.h"
! 35:
! 36: /* The last 3 #include files should be in this order */
! 37: #include "curl_printf.h"
! 38: #include "curl_memory.h"
! 39: #include "memdebug.h"
! 40:
! 41: /* ---- Base64 Encoding/Decoding Table --- */
! 42: static const char base64[]=
! 43: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
! 44:
! 45: /* The Base 64 encoding with an URL and filename safe alphabet, RFC 4648
! 46: section 5 */
! 47: static const char base64url[]=
! 48: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
! 49:
! 50: static size_t decodeQuantum(unsigned char *dest, const char *src)
! 51: {
! 52: size_t padding = 0;
! 53: const char *s, *p;
! 54: unsigned long i, x = 0;
! 55:
! 56: for(i = 0, s = src; i < 4; i++, s++) {
! 57: if(*s == '=') {
! 58: x = (x << 6);
! 59: padding++;
! 60: }
! 61: else {
! 62: unsigned long v = 0;
! 63: p = base64;
! 64:
! 65: while(*p && (*p != *s)) {
! 66: v++;
! 67: p++;
! 68: }
! 69:
! 70: if(*p == *s)
! 71: x = (x << 6) + v;
! 72: else
! 73: return 0;
! 74: }
! 75: }
! 76:
! 77: if(padding < 1)
! 78: dest[2] = curlx_ultouc(x & 0xFFUL);
! 79:
! 80: x >>= 8;
! 81: if(padding < 2)
! 82: dest[1] = curlx_ultouc(x & 0xFFUL);
! 83:
! 84: x >>= 8;
! 85: dest[0] = curlx_ultouc(x & 0xFFUL);
! 86:
! 87: return 3 - padding;
! 88: }
! 89:
! 90: /*
! 91: * Curl_base64_decode()
! 92: *
! 93: * Given a base64 NUL-terminated string at src, decode it and return a
! 94: * pointer in *outptr to a newly allocated memory area holding decoded
! 95: * data. Size of decoded data is returned in variable pointed by outlen.
! 96: *
! 97: * Returns CURLE_OK on success, otherwise specific error code. Function
! 98: * output shall not be considered valid unless CURLE_OK is returned.
! 99: *
! 100: * When decoded data length is 0, returns NULL in *outptr.
! 101: *
! 102: * @unittest: 1302
! 103: */
! 104: CURLcode Curl_base64_decode(const char *src,
! 105: unsigned char **outptr, size_t *outlen)
! 106: {
! 107: size_t srclen = 0;
! 108: size_t length = 0;
! 109: size_t padding = 0;
! 110: size_t i;
! 111: size_t numQuantums;
! 112: size_t rawlen = 0;
! 113: unsigned char *pos;
! 114: unsigned char *newstr;
! 115:
! 116: *outptr = NULL;
! 117: *outlen = 0;
! 118: srclen = strlen(src);
! 119:
! 120: /* Check the length of the input string is valid */
! 121: if(!srclen || srclen % 4)
! 122: return CURLE_BAD_CONTENT_ENCODING;
! 123:
! 124: /* Find the position of any = padding characters */
! 125: while((src[length] != '=') && src[length])
! 126: length++;
! 127:
! 128: /* A maximum of two = padding characters is allowed */
! 129: if(src[length] == '=') {
! 130: padding++;
! 131: if(src[length + 1] == '=')
! 132: padding++;
! 133: }
! 134:
! 135: /* Check the = padding characters weren't part way through the input */
! 136: if(length + padding != srclen)
! 137: return CURLE_BAD_CONTENT_ENCODING;
! 138:
! 139: /* Calculate the number of quantums */
! 140: numQuantums = srclen / 4;
! 141:
! 142: /* Calculate the size of the decoded string */
! 143: rawlen = (numQuantums * 3) - padding;
! 144:
! 145: /* Allocate our buffer including room for a zero terminator */
! 146: newstr = malloc(rawlen + 1);
! 147: if(!newstr)
! 148: return CURLE_OUT_OF_MEMORY;
! 149:
! 150: pos = newstr;
! 151:
! 152: /* Decode the quantums */
! 153: for(i = 0; i < numQuantums; i++) {
! 154: size_t result = decodeQuantum(pos, src);
! 155: if(!result) {
! 156: free(newstr);
! 157:
! 158: return CURLE_BAD_CONTENT_ENCODING;
! 159: }
! 160:
! 161: pos += result;
! 162: src += 4;
! 163: }
! 164:
! 165: /* Zero terminate */
! 166: *pos = '\0';
! 167:
! 168: /* Return the decoded data */
! 169: *outptr = newstr;
! 170: *outlen = rawlen;
! 171:
! 172: return CURLE_OK;
! 173: }
! 174:
! 175: static CURLcode base64_encode(const char *table64,
! 176: struct Curl_easy *data,
! 177: const char *inputbuff, size_t insize,
! 178: char **outptr, size_t *outlen)
! 179: {
! 180: CURLcode result;
! 181: unsigned char ibuf[3];
! 182: unsigned char obuf[4];
! 183: int i;
! 184: int inputparts;
! 185: char *output;
! 186: char *base64data;
! 187: char *convbuf = NULL;
! 188:
! 189: const char *indata = inputbuff;
! 190:
! 191: *outptr = NULL;
! 192: *outlen = 0;
! 193:
! 194: if(!insize)
! 195: insize = strlen(indata);
! 196:
! 197: #if SIZEOF_SIZE_T == 4
! 198: if(insize > UINT_MAX/4)
! 199: return CURLE_OUT_OF_MEMORY;
! 200: #endif
! 201:
! 202: base64data = output = malloc(insize * 4 / 3 + 4);
! 203: if(!output)
! 204: return CURLE_OUT_OF_MEMORY;
! 205:
! 206: /*
! 207: * The base64 data needs to be created using the network encoding
! 208: * not the host encoding. And we can't change the actual input
! 209: * so we copy it to a buffer, translate it, and use that instead.
! 210: */
! 211: result = Curl_convert_clone(data, indata, insize, &convbuf);
! 212: if(result) {
! 213: free(output);
! 214: return result;
! 215: }
! 216:
! 217: if(convbuf)
! 218: indata = (char *)convbuf;
! 219:
! 220: while(insize > 0) {
! 221: for(i = inputparts = 0; i < 3; i++) {
! 222: if(insize > 0) {
! 223: inputparts++;
! 224: ibuf[i] = (unsigned char) *indata;
! 225: indata++;
! 226: insize--;
! 227: }
! 228: else
! 229: ibuf[i] = 0;
! 230: }
! 231:
! 232: obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2);
! 233: obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
! 234: ((ibuf[1] & 0xF0) >> 4));
! 235: obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
! 236: ((ibuf[2] & 0xC0) >> 6));
! 237: obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
! 238:
! 239: switch(inputparts) {
! 240: case 1: /* only one byte read */
! 241: msnprintf(output, 5, "%c%c==",
! 242: table64[obuf[0]],
! 243: table64[obuf[1]]);
! 244: break;
! 245:
! 246: case 2: /* two bytes read */
! 247: msnprintf(output, 5, "%c%c%c=",
! 248: table64[obuf[0]],
! 249: table64[obuf[1]],
! 250: table64[obuf[2]]);
! 251: break;
! 252:
! 253: default:
! 254: msnprintf(output, 5, "%c%c%c%c",
! 255: table64[obuf[0]],
! 256: table64[obuf[1]],
! 257: table64[obuf[2]],
! 258: table64[obuf[3]]);
! 259: break;
! 260: }
! 261: output += 4;
! 262: }
! 263:
! 264: /* Zero terminate */
! 265: *output = '\0';
! 266:
! 267: /* Return the pointer to the new data (allocated memory) */
! 268: *outptr = base64data;
! 269:
! 270: free(convbuf);
! 271:
! 272: /* Return the length of the new data */
! 273: *outlen = strlen(base64data);
! 274:
! 275: return CURLE_OK;
! 276: }
! 277:
! 278: /*
! 279: * Curl_base64_encode()
! 280: *
! 281: * Given a pointer to an input buffer and an input size, encode it and
! 282: * return a pointer in *outptr to a newly allocated memory area holding
! 283: * encoded data. Size of encoded data is returned in variable pointed by
! 284: * outlen.
! 285: *
! 286: * Input length of 0 indicates input buffer holds a NUL-terminated string.
! 287: *
! 288: * Returns CURLE_OK on success, otherwise specific error code. Function
! 289: * output shall not be considered valid unless CURLE_OK is returned.
! 290: *
! 291: * When encoded data length is 0, returns NULL in *outptr.
! 292: *
! 293: * @unittest: 1302
! 294: */
! 295: CURLcode Curl_base64_encode(struct Curl_easy *data,
! 296: const char *inputbuff, size_t insize,
! 297: char **outptr, size_t *outlen)
! 298: {
! 299: return base64_encode(base64, data, inputbuff, insize, outptr, outlen);
! 300: }
! 301:
! 302: /*
! 303: * Curl_base64url_encode()
! 304: *
! 305: * Given a pointer to an input buffer and an input size, encode it and
! 306: * return a pointer in *outptr to a newly allocated memory area holding
! 307: * encoded data. Size of encoded data is returned in variable pointed by
! 308: * outlen.
! 309: *
! 310: * Input length of 0 indicates input buffer holds a NUL-terminated string.
! 311: *
! 312: * Returns CURLE_OK on success, otherwise specific error code. Function
! 313: * output shall not be considered valid unless CURLE_OK is returned.
! 314: *
! 315: * When encoded data length is 0, returns NULL in *outptr.
! 316: *
! 317: * @unittest: 1302
! 318: */
! 319: CURLcode Curl_base64url_encode(struct Curl_easy *data,
! 320: const char *inputbuff, size_t insize,
! 321: char **outptr, size_t *outlen)
! 322: {
! 323: return base64_encode(base64url, data, inputbuff, insize, outptr, outlen);
! 324: }
! 325:
! 326: #endif /* no users so disabled */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>