Annotation of embedaddon/curl/lib/base64.c, revision 1.1.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>