1 /*
2 * These are helping routines for the main module of CNTLM
3 *
4 * CNTLM is free software; you can redistribute it and/or modify it under the
5 * terms of the GNU General Public License as published by the Free Software
6 * Foundation; either version 2 of the License, or (at your option) any later
7 * version.
8 *
9 * CNTLM is distributed in the hope that it will be useful, but WITHOUT ANY
10 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 * details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
16 * St, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 * Copyright (c) 2007 David Kubicek
19 *
20 */
21
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <string.h>
25 #include <strings.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <stdio.h>
29 #include <errno.h>
30 #include <ctype.h>
31 #include <syslog.h>
32
33 #include "config/config.h"
34 #include "swap.h"
35 #include "utils.h"
36 #include "socket.h"
37
38 char hextab[17] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 0};
39 int hexindex[128] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
40 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
41 -1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
42 -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
43 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,
44 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
45
myexit(int rc)46 void myexit(int rc) {
47 if (rc)
48 fprintf(stderr, "Exitting with error. Check daemon logs or run with -v.\n");
49
50 exit(rc);
51 }
52
croak(const char * msg,int console)53 void croak(const char *msg, int console) {
54 if (console)
55 printf("%s", msg);
56 else
57 syslog(LOG_ERR, "%s", msg);
58
59 myexit(1);
60 }
61
62 /*
63 * Add a new item to a list. Every plist_t variable must be
64 * initialized to NULL (or pass NULL for "list" when adding
65 * the first item). This is for simplicity's sake (we don't
66 * need any plist_new).
67 *
68 * This list type allows to store an arbitrary pointer
69 * associating it with the key.
70 */
plist_add(plist_t list,unsigned long key,void * aux)71 plist_t plist_add(plist_t list, unsigned long key, void *aux) {
72 plist_t tmp, t = list;
73
74 tmp = malloc(sizeof(struct plist_s));
75 tmp->key = key;
76 tmp->aux = aux;
77 tmp->next = NULL;
78
79 if (list == NULL)
80 return tmp;
81
82 while (t->next)
83 t = t->next;
84
85 t->next = tmp;
86
87 return list;
88 }
89
90 /*
91 * Delete an item from the list, possibly returning NULL when
92 * the list is empty or nothing was found.
93 */
plist_del(plist_t list,unsigned long key)94 plist_t plist_del(plist_t list, unsigned long key) {
95 plist_t ot = NULL, t = list;
96
97 while (t) {
98 if (t->key == key)
99 break;
100 ot = t;
101 t = t->next;
102 }
103
104 if (t) {
105 plist_t tmp = t->next;
106
107 if (t->aux)
108 free(t->aux);
109 free(t);
110 if (ot == NULL)
111 return tmp;
112
113 ot->next = tmp;
114 }
115
116 return list;
117 }
118
119 /*
120 * Return true if an item is present in the list.
121 */
plist_in(plist_t list,unsigned long key)122 int plist_in(plist_t list, unsigned long key) {
123 plist_t t = list;
124
125 while (t) {
126 if (t->key == key)
127 break;
128 t = t->next;
129 }
130
131 return (t != NULL);
132 }
133
134 /*
135 * For debugging purposes - dump the entire contents
136 * of a list.
137 */
plist_dump(plist_t list)138 void plist_dump(plist_t list) {
139 plist_t t;
140
141 t = list;
142 while (t) {
143 printf("List data: %lu => 0x%8p\n", (unsigned long int)t->key, t->aux);
144 t = t->next;
145 }
146 }
147
148 /*
149 * Return the pointer associated with the key.
150 */
plist_get(plist_t list,int key)151 char *plist_get(plist_t list, int key) {
152 plist_t t = list;
153
154 while (t) {
155 if (t->key == key)
156 break;
157 t = t->next;
158 }
159
160 return (t == NULL ? NULL : t->aux);
161 }
162
163 /*
164 * Scan the list for an open descriptor (socket), possibly
165 * discarding all closed ones on the way. Return the first
166 * match.
167 *
168 * Use this method only for lists of descriptors!
169 *
170 * In conjunction with plist_add, the list behaves as a FIFO.
171 * This feature is used for rotating cached connections in the
172 * list, so that none is left too long unused (proxy timeout).
173 *
174 * Returns key value (descriptor) and if aux != NULL, *aux gets
175 * aux pointer value (which caller must free if != NULL).
176 */
177
plist_pop(plist_t * list,void ** aux)178 int plist_pop(plist_t *list, void **aux) {
179 plist_t tmp, t;
180 int id = 0;
181 int ok = 0;
182 void *a = NULL;
183
184 if (list == NULL || *list == NULL)
185 return 0;
186
187 t = *list;
188 while (!ok && t) {
189 id = t->key;
190 a = t->aux;
191 tmp = t->next;
192
193 if (so_closed(id)) {
194 close(id);
195 if (t->aux)
196 free(t->aux);
197 } else
198 ok = 1;
199
200 free(t);
201 t = tmp;
202 }
203
204 *list = t;
205
206 if (ok) {
207 if (aux != NULL)
208 *aux = a;
209 return id;
210 }
211
212 return 0;
213 }
214
215 /*
216 * Return the number of items in a list.
217 */
plist_count(plist_t list)218 int plist_count(plist_t list) {
219 plist_t t = list;
220 int rc = 0;
221
222 while (t) {
223 rc++;
224 t = t->next;
225 }
226
227 return rc;
228 }
229
230 /*
231 * Free the list.
232 */
plist_free(plist_t list)233 plist_t plist_free(plist_t list) {
234 plist_t t = list;
235
236 while (list) {
237 t = list->next;
238 if (list->aux)
239 free(list->aux);
240 free(list);
241 list = t;
242 }
243
244 return NULL;
245 }
246
247 /*
248 * The same as plist_add. Here we have two other arguments.
249 * They are boolean flags - HLIST_ALLOC means to duplicate a
250 * key/value, HLIST_NOALLOC means to store the pointer directly.
251 *
252 * Caller decides this on a by-call basis. Part of the manipulation
253 * routines is a "free". That method always deallocates both the
254 * key and the value. So for static or temporary keys/values,
255 * the caller can instruct us to duplicate the necessary amount
256 * of heap. This mechanism is used to minimize memory-related
257 * bugs throughout the code and tons of free's.
258 */
hlist_add(hlist_t list,char * key,char * value,hlist_add_t allockey,hlist_add_t allocvalue)259 hlist_t hlist_add(hlist_t list, char *key, char *value, hlist_add_t allockey, hlist_add_t allocvalue) {
260 hlist_t tmp, t = list;
261
262 if (key == NULL || value == NULL)
263 return list;
264
265 tmp = malloc(sizeof(struct hlist_s));
266 tmp->key = (allockey == HLIST_ALLOC ? strdup(key) : key);
267 tmp->value = (allocvalue == HLIST_ALLOC ? strdup(value) : value);
268 tmp->next = NULL;
269 tmp->islist = 0;
270
271 if (list == NULL)
272 return tmp;
273
274 while (t->next)
275 t = t->next;
276
277 t->next = tmp;
278
279 return list;
280 }
281
282 /*
283 * Return a duplicate of the list (copy).
284 */
hlist_dup(hlist_t list)285 hlist_t hlist_dup(hlist_t list) {
286 hlist_t tmp = NULL, t = list;
287
288 while (t) {
289 tmp = hlist_add(tmp, t->key, t->value, HLIST_ALLOC, HLIST_ALLOC);
290 t = t->next;
291 }
292
293 return tmp;
294 }
295
296 /*
297 * Remove an item from the list.
298 */
hlist_del(hlist_t list,const char * key)299 hlist_t hlist_del(hlist_t list, const char *key) {
300 hlist_t ot = NULL, t = list;
301
302 while (t) {
303 if (!strcasecmp(t->key, key))
304 break;
305 ot = t;
306 t = t->next;
307 }
308
309 if (t) {
310 hlist_t tmp = t->next;
311
312 free(t->key);
313 free(t->value);
314 free(t);
315
316 if (ot == NULL)
317 return tmp;
318
319 ot->next = tmp;
320 }
321
322 return list;
323 }
324
325 /*
326 * Change the value of a key. If add is true, we store it in the
327 * list if the key is not found. Unlike hlist_add, which offers
328 * pointer storage or memory duplication for both the key and the
329 * value separately, hlist_mod always duplicates.
330 *
331 * Used to add a header, which might already be present.
332 */
hlist_mod(hlist_t list,char * key,char * value,int add)333 hlist_t hlist_mod(hlist_t list, char *key, char *value, int add) {
334 hlist_t t = list;
335
336 while (t) {
337 if (!strcasecmp(t->key, key))
338 break;
339 t = t->next;
340 }
341
342 if (t) {
343 free(t->value);
344 t->value = strdup(value);
345 } else if (add) {
346 list = hlist_add(list, key, value, HLIST_ALLOC, HLIST_ALLOC);
347 }
348
349 return list;
350 }
351
352 /*
353 * Return true is the key is in the list.
354 */
hlist_in(hlist_t list,const char * key)355 int hlist_in(hlist_t list, const char *key) {
356 hlist_t t = list;
357
358 while (t) {
359 if (!strcasecmp(t->key, key))
360 break;
361 t = t->next;
362 }
363
364 return (t != NULL);
365 }
366
367 /*
368 * Return the number of items in a list.
369 */
hlist_count(hlist_t list)370 int hlist_count(hlist_t list) {
371 hlist_t t = list;
372 int rc = 0;
373
374 while (t) {
375 rc++;
376 t = t->next;
377 }
378
379 return rc;
380 }
381
382 /*
383 * Return the value for the key.
384 */
hlist_get(hlist_t list,const char * key)385 char *hlist_get(hlist_t list, const char *key) {
386 hlist_t t = list;
387
388 while (t) {
389 if (!strcasecmp(t->key, key))
390 break;
391 t = t->next;
392 }
393
394 return (t == NULL ? NULL : t->value);
395 }
396
397 /*
398 * Test if substr is part of the header's value.
399 * Both case-insensitive.
400 */
hlist_subcmp(hlist_t list,const char * key,const char * substr)401 int hlist_subcmp(hlist_t list, const char *key, const char *substr) {
402 int found = 0;
403 char *tmp, *low;
404
405 lowercase(low = strdup(substr));
406 tmp = hlist_get(list, key);
407 if (tmp) {
408 lowercase(tmp = strdup(tmp));
409 if (strstr(tmp, low))
410 found = 1;
411
412 free(tmp);
413 }
414
415 free(low);
416 return found;
417 }
418
419 /*
420 * Test if substr is part of the header's value.
421 * Both case-insensitive, checks all headers, not just first one.
422 */
hlist_subcmp_all(hlist_t list,const char * key,const char * substr)423 int hlist_subcmp_all(hlist_t list, const char *key, const char *substr) {
424 hlist_t t = list;
425 int found = 0;
426 char *tmp, *low;
427
428 lowercase(low = strdup(substr));
429 while (t) {
430 if (!strcasecmp(t->key, key)) {
431 lowercase(tmp = strdup(t->value));
432 if (strstr(tmp, low))
433 found = 1;
434
435 free(tmp);
436 }
437 t = t->next;
438 }
439
440 free(low);
441 return found;
442 }
443
444 /*
445 * Free the list. For more about list memory management,
446 * se hlist_add.
447 */
hlist_free(hlist_t list)448 hlist_t hlist_free(hlist_t list) {
449 hlist_t t = list;
450
451 while (list) {
452 t = list->next;
453
454 free(list->key);
455 free(list->value);
456 free(list);
457
458 list = t;
459 }
460
461 return NULL;
462 }
463
464 /*
465 * This is for debugging purposes.
466 */
hlist_dump(hlist_t list)467 void hlist_dump(hlist_t list) {
468 hlist_t t;
469
470 t = list;
471 while (t) {
472 printf("%-30s => %s\n", t->key, t->value);
473 t = t->next;
474 }
475 }
476
477 /*
478 * Standard substr. To prevent modification of the source
479 * (terminating \x0), return the result in a new memory.
480 */
substr(const char * src,int pos,int len)481 char *substr(const char *src, int pos, int len) {
482 int l;
483 char *tmp;
484
485 if (len == 0)
486 len = strlen(src);
487
488 l = MIN(len, strlen(src)-pos);
489 if (l <= 0)
490 return new(1);
491
492 tmp = new(l+1);
493 strlcpy(tmp, src+pos, l+1);
494
495 return tmp;
496 }
497
498 /*
499 * Allocate memory and initialize a new rr_data_t structure.
500 */
new_rr_data(void)501 rr_data_t new_rr_data(void) {
502 rr_data_t data;
503
504 data = malloc(sizeof(struct rr_data_s));
505 data->req = 0;
506 data->code = 0;
507 data->skip_http = 0;
508 data->body_len = 0;
509 data->empty = 1;
510 data->port = 0;
511 data->headers = NULL;
512 data->method = NULL;
513 data->url = NULL;
514 data->rel_url = NULL;
515 data->hostname = NULL;
516 data->http = NULL;
517 data->msg = NULL;
518 data->body = NULL;
519 data->errmsg = NULL; /* for static strings - we don't free, dup, nor copy */
520
521 return data;
522 }
523
524 /*
525 * Copy the req/res data.
526 */
copy_rr_data(rr_data_t dst,rr_data_t src)527 rr_data_t copy_rr_data(rr_data_t dst, rr_data_t src) {
528 if (src == NULL || dst == NULL)
529 return NULL;
530
531 reset_rr_data(dst);
532 dst->req = src->req;
533 dst->code = src->code;
534 dst->skip_http = src->skip_http;
535 dst->body_len = src->body_len;
536 dst->empty = src->empty;
537 dst->port = src->port;
538
539 if (src->headers)
540 dst->headers = hlist_dup(src->headers);
541 if (src->method)
542 dst->method = strdup(src->method);
543 if (src->url)
544 dst->url = strdup(src->url);
545 if (src->rel_url)
546 dst->rel_url = strdup(src->rel_url);
547 if (src->hostname)
548 dst->hostname = strdup(src->hostname);
549 if (src->http)
550 dst->http = strdup(src->http);
551 if (src->msg)
552 dst->msg = strdup(src->msg);
553 if (src->body && src->body_len > 0) {
554 dst->body = new(src->body_len);
555 memcpy(dst->body, src->body, src->body_len);
556 }
557
558 return dst;
559 }
560
561 /*
562 * Duplicate the req/res data.
563 */
dup_rr_data(rr_data_t data)564 rr_data_t dup_rr_data(rr_data_t data) {
565 rr_data_t tmp;
566
567 if (data == NULL)
568 return NULL;
569
570 tmp = new_rr_data();
571 return copy_rr_data(tmp, data);
572 }
573
574 /*
575 * Reset, freeing if neccessary
576 */
reset_rr_data(rr_data_t data)577 rr_data_t reset_rr_data(rr_data_t data) {
578 if (data == NULL)
579 return NULL;
580
581 data->req = 0;
582 data->code = 0;
583 data->skip_http = 0;
584 data->body_len = 0;
585 data->empty = 1;
586 data->port = 0;
587
588 if (data->headers) hlist_free(data->headers);
589 if (data->method) free(data->method);
590 if (data->url) free(data->url);
591 if (data->rel_url) free(data->rel_url);
592 if (data->hostname) free(data->hostname);
593 if (data->http) free(data->http);
594 if (data->msg) free(data->msg);
595 if (data->body) free(data->body);
596
597 data->headers = NULL;
598 data->method = NULL;
599 data->url = NULL;
600 data->rel_url = NULL;
601 data->hostname = NULL;
602 data->http = NULL;
603 data->msg = NULL;
604 data->body = NULL;
605 data->errmsg = NULL;
606
607 return data;
608 }
609
610 /*
611 * Free rr_data_t structure. We also take care of freeing
612 * the memory of its members.
613 */
free_rr_data(rr_data_t data)614 void free_rr_data(rr_data_t data) {
615 if (data == NULL)
616 return;
617
618 if (data->headers) hlist_free(data->headers);
619 if (data->method) free(data->method);
620 if (data->url) free(data->url);
621 if (data->rel_url) free(data->rel_url);
622 if (data->hostname) free(data->hostname);
623 if (data->http) free(data->http);
624 if (data->msg) free(data->msg);
625 if (data->body) free(data->body);
626 free(data);
627 }
628
629 /*
630 * Cut the whitespace at the end of a string.
631 */
trimr(char * buf)632 char *trimr(char *buf) {
633 int i;
634
635 for (i = strlen(buf)-1; i >= 0 && isspace(buf[i]); --i);
636 buf[i+1] = 0;
637
638 return buf;
639 }
640
641 #if config_strdup == 0
642 /*
643 * Our implementation of non-POSIX strdup()
644 */
strdup(const char * src)645 char *strdup(const char *src) {
646 size_t len;
647 char *tmp;
648
649 if (!src)
650 return NULL;
651
652 len = strlen(src)+1;
653 tmp = calloc(1, len);
654 memcpy(tmp, src, len-1);
655
656 return tmp;
657 }
658 #endif
659
660 /*
661 * More intuitive version of strncpy with string termination
662 * from OpenBSD
663 */
strlcpy(char * dst,const char * src,size_t siz)664 size_t strlcpy(char *dst, const char *src, size_t siz) {
665 char *d = dst;
666 const char *s = src;
667 size_t n = siz;
668
669 /* Copy as many bytes as will fit */
670 if (n != 0) {
671 while (--n != 0) {
672 if ((*d++ = *s++) == '\0')
673 break;
674 }
675 }
676
677 /* Not enough room in dst, add NUL and traverse rest of src */
678 if (n == 0) {
679 if (siz != 0)
680 *d = '\0'; /* NUL-terminate dst */
681 while (*s++);
682 }
683
684 return (s - src - 1); /* count does not include NUL */
685 }
686
687 /*
688 * More intuitive version os strncat with string termination
689 * from OpenBSD
690 */
strlcat(char * dst,const char * src,size_t siz)691 size_t strlcat(char *dst, const char *src, size_t siz) {
692 char *d = dst;
693 const char *s = src;
694 size_t n = siz;
695 size_t dlen;
696
697 /* Find the end of dst and adjust bytes left but don't go past end */
698 while (n-- != 0 && *d != '\0')
699 d++;
700
701 dlen = d - dst;
702 n = siz - dlen;
703
704 if (n == 0)
705 return(dlen + strlen(s));
706
707 while (*s != '\0') {
708 if (n != 1) {
709 *d++ = *s;
710 n--;
711 }
712 s++;
713 }
714 *d = '\0';
715
716 return (dlen + (s - src)); /* count does not include NUL */
717 }
718
719 /*
720 * Shortcut for malloc/memset zero.
721 */
new(size_t size)722 char *new(size_t size) {
723 char *tmp;
724
725 tmp = malloc(size);
726 memset(tmp, 0, size);
727
728 return tmp;
729 }
730
731 /*
732 * Self-explanatory.
733 */
lowercase(char * str)734 char *lowercase(char *str) {
735 int i;
736
737 for (i = 0; i < strlen(str); ++i)
738 str[i] = tolower(str[i]);
739
740 return str;
741 }
742
743 /*
744 * Self-explanatory.
745 */
uppercase(char * str)746 char *uppercase(char *str) {
747 int i;
748
749 for (i = 0; i < strlen(str); ++i)
750 str[i] = toupper(str[i]);
751
752 return str;
753 }
754
unicode(char ** dst,char * src)755 int unicode(char **dst, char *src) {
756 char *tmp;
757 int l, i;
758
759 if (!src) {
760 *dst = NULL;
761 return 0;
762 }
763
764 l = MIN(64, strlen(src));
765 tmp = new(2*l);
766 for (i = 0; i < l; ++i)
767 tmp[2*i] = src[i];
768
769 *dst = tmp;
770 return 2*l;
771 }
772
urlencode(const char * str)773 char *urlencode(const char *str) {
774 char *tmp;
775 int i, pos;
776
777 tmp = new(strlen(str)*3 + 1);
778 for (pos = 0, i = 0; i < strlen(str); ++i) {
779 if (isdigit(str[i]) || (tolower(str[i]) >= 'a' && tolower(str[i]) <= 'z') || str[i] == '.' || str[i] == '-' || str[i] == '_' || str[i] == '~') {
780 tmp[pos++] = str[i];
781 } else {
782 sprintf(tmp+pos, "%%%X", (unsigned char)str[i]);
783 pos += 3;
784 }
785 }
786
787 return tmp;
788 }
789
printmem(char * src,size_t len,int bitwidth)790 char *printmem(char *src, size_t len, int bitwidth) {
791 char *tmp;
792 int i;
793
794 tmp = new(2*len+1);
795 for (i = 0; i < len; ++i) {
796 tmp[i*2] = hextab[((uint8_t)src[i] ^ (uint8_t)(7-bitwidth)) >> 4];
797 tmp[i*2+1] = hextab[(src[i] ^ (uint8_t)(7-bitwidth)) & 0x0F];
798 }
799
800 return tmp;
801 }
802
scanmem(char * src,int bitwidth)803 char *scanmem(char *src, int bitwidth) {
804 int h, l, i, bytes;
805 char *tmp;
806
807 if (strlen(src) % 2)
808 return NULL;
809
810 bytes = strlen(src)/2;
811 tmp = new(bytes+1);
812 for (i = 0; i < bytes; ++i) {
813 h = hexindex[(int)src[i*2]];
814 l = hexindex[(int)src[i*2+1]];
815 if (h < 0 || l < 0) {
816 free(tmp);
817 return NULL;
818 }
819 tmp[i] = ((h << 4) + l) ^ (uint8_t)(7-bitwidth);
820 }
821 tmp[i] = 0;
822
823 return tmp;
824 }
825
826
827
828 /*
829 * BASE64 CODE FROM MUTT BEGIN - ORIGINAL COPYRIGHT APPLIES:
830 *
831 * Copyright (C) 1996-2001 Michael R. Elkins <me@cs.hmc.edu>
832 * Copyright (C) 1996-2001 Brandon Long <blong@fiction.net>
833 * Copyright (C) 1997-2001 Thomas Roessler <roessler@guug.de>
834 * Copyright (C) 1998-2001 Werner Koch <wk@isil.d.shuttle.de>
835 * Copyright (C) 1999-2001 Brendan Cully <brendan@kublai.com>
836 * Copyright (C) 1999-2001 Tommi Komulainen <Tommi.Komulainen@iki.fi>
837 * Copyright (C) 2000-2001 Edmund Grimley Evans <edmundo@rano.org>
838 *
839 */
840
841 #define BAD -1
842 #define base64val(c) index64[(unsigned int)(c)]
843
844 char base64[64] = {
845 'A','B','C','D','E','F','G','H','I','J','K','L','M','N',
846 'O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b',
847 'c','d','e','f','g','h','i','j','k','l','m','n','o','p',
848 'q','r','s','t','u','v','w','x','y','z','0','1','2','3',
849 '4','5','6','7','8','9','+','/'
850 };
851
852 int index64[128] = {
853 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
854 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
855 -1,-1,-1,-1,-1,62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,
856 61,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,
857 14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,
858 27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,
859 46,47,48,49,50,51,-1,-1,-1,-1,-1
860 };
861
to_base64(unsigned char * out,const unsigned char * in,size_t len,size_t olen)862 void to_base64(unsigned char *out, const unsigned char *in, size_t len, size_t olen) {
863 while (len >= 3 && olen > 10) {
864 *out++ = base64[in[0] >> 2];
865 *out++ = base64[((in[0] << 4) & 0x30) | (in[1] >> 4)];
866 *out++ = base64[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
867 *out++ = base64[in[2] & 0x3f];
868 olen -= 4;
869 len -= 3;
870 in += 3;
871 }
872
873 /* clean up remainder */
874 if (len > 0 && olen > 4) {
875 unsigned char fragment;
876
877 *out++ = base64[in[0] >> 2];
878 fragment = (in[0] << 4) & 0x30;
879 if (len > 1)
880 fragment |= in[1] >> 4;
881 *out++ = base64[fragment];
882 *out++ = (len < 2) ? '=' : base64[(in[1] << 2) & 0x3c];
883 *out++ = '=';
884 }
885 *out = '\0';
886 }
887
888 /* Convert '\0'-terminated base 64 string to raw bytes.
889 * Returns length of returned buffer, or -1 on error */
from_base64(char * out,const char * in)890 int from_base64(char *out, const char *in)
891 {
892 int len = 0;
893 register unsigned char digit1, digit2, digit3, digit4;
894
895 do {
896 digit1 = in[0];
897 if (digit1 > 127 || base64val (digit1) == BAD)
898 return -1;
899
900 digit2 = in[1];
901 if (digit2 > 127 || base64val (digit2) == BAD)
902 return -1;
903
904 digit3 = in[2];
905 if (digit3 > 127 || ((digit3 != '=') && (base64val (digit3) == BAD)))
906 return -1;
907
908 digit4 = in[3];
909 if (digit4 > 127 || ((digit4 != '=') && (base64val (digit4) == BAD)))
910 return -1;
911
912 in += 4;
913
914 /* digits are already sanity-checked */
915 *out++ = (base64val(digit1) << 2) | (base64val(digit2) >> 4);
916 len++;
917 if (digit3 != '=') {
918 *out++ = ((base64val(digit2) << 4) & 0xf0) | (base64val(digit3) >> 2);
919 len++;
920 if (digit4 != '=') {
921 *out++ = ((base64val(digit3) << 6) & 0xc0) | base64val(digit4);
922 len++;
923 }
924 }
925 } while (*in && digit4 != '=');
926
927 return len;
928 }
929 /*
930 * CODE FROM MUTT END
931 */
932