From: Ted Lemon Date: Fri, 1 Sep 2000 23:07:35 +0000 (+0000) Subject: Fix base64 decoder. X-Git-Tag: V3-BETA-2-PATCH-1~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8f01f9ec85e883b07d25c2eedf3f0e04cb1fbc34;p=thirdparty%2Fdhcp.git Fix base64 decoder. --- diff --git a/common/parse.c b/common/parse.c index 2373074a3..336d95ba4 100644 --- a/common/parse.c +++ b/common/parse.c @@ -43,7 +43,7 @@ #ifndef lint static char copyright[] = -"$Id: parse.c,v 1.81 2000/08/28 21:22:34 neild Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: parse.c,v 1.82 2000/09/01 23:07:35 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -1137,7 +1137,7 @@ int parse_base64 (data, cfile) { enum dhcp_token token; const char *val; - int i, j; + int i, j, k; unsigned acc = 0; static unsigned char from64 [] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */ @@ -1152,9 +1152,15 @@ int parse_base64 (data, cfile) 33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */ 41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */ 59, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~ */ + struct string_list *bufs = (struct string_list *)0, + *last = (struct string_list *)0, + *t; + int cc = 0; + int terminated = 0; - token = next_token (&val, cfile); + token = peek_token (&val, cfile); if (token == STRING) { + token = next_token (&val, cfile); data -> len = strlen (val) + 1; if (!buffer_allocate (&data -> buffer, data -> len, MDL)) { parse_warn (cfile, "can't allocate string buffer"); @@ -1166,7 +1172,30 @@ int parse_base64 (data, cfile) return 1; } - data -> len = strlen (val); + /* It's possible for a + or a / to cause a base64 quantity to be + tokenized into more than one token, so we have to parse them all + in before decoding. */ + do { + int l; + + token = next_token (&val, cfile); + l = strlen (val); + t = dmalloc (l + sizeof *t, MDL); + if (!t) + log_fatal ("no memory for base64 buffer."); + memset (t, 0, (sizeof *t) - 1); + strcpy (t -> string, val); + cc += l; + if (last) + last -> next = t; + else + bufs = t; + last = t; + token = peek_token (&val, cfile); + } while (token == NUMBER_OR_NAME || token == NAME || token == EQUAL || + token == NUMBER || token == PLUS || token == SLASH); + + data -> len = cc; data -> len = (data -> len * 3) / 4; if (!buffer_allocate (&data -> buffer, data -> len, MDL)) { parse_warn (cfile, "can't allocate buffer for base64 data."); @@ -1175,43 +1204,71 @@ int parse_base64 (data, cfile) return 0; } - j = 0; - for (i = 0; val [i] != '=' && val [i]; i++) { - unsigned foo = val [i]; + j = k = 0; + for (t = bufs; t; t = t -> next) { + for (i = 0; t -> string [i]; i++) { + unsigned foo = t -> string [i]; + if (terminated && foo != '=') { + parse_warn (cfile, + "stuff after base64 '=' terminator: %s.", + &t -> string [i]); + goto bad; + } if (foo < ' ' || foo > 'z') { bad64: parse_warn (cfile, - "invalid base64 character %d.", val [i]); + "invalid base64 character %d.", + t -> string [i]); + bad: data_string_forget (data, MDL); - return 0; + goto out; } - foo = from64 [foo - ' ']; - if (foo == 64) - goto bad64; - acc = (acc << 6) + foo; - switch (i % 4) { - case 0: - break; - case 1: - data -> buffer -> data [j++] = (acc >> 4); - acc = acc & 0x0f; - break; - - case 2: - data -> buffer -> data [j++] = (acc >> 2); - acc = acc & 0x03; - break; - case 3: - data -> buffer -> data [j++] = acc; - acc = 0; - break; + if (foo == '=') + terminated = 1; + else { + foo = from64 [foo - ' ']; + if (foo == 64) + goto bad64; + acc = (acc << 6) + foo; + switch (k % 4) { + case 0: + break; + case 1: + data -> buffer -> data [j++] = (acc >> 4); + acc = acc & 0x0f; + break; + + case 2: + data -> buffer -> data [j++] = (acc >> 2); + acc = acc & 0x03; + break; + case 3: + data -> buffer -> data [j++] = acc; + acc = 0; + break; + } + } + k++; + } + } + if (k % 4) { + if (acc) { + parse_warn (cfile, + "partial base64 value left over: %d.", + acc); } } - if (i % 4) - parse_warn (cfile, "partial base64 value left over: %d.", acc); data -> len = j; data -> data = data -> buffer -> data; - return 1; + out: + for (t = bufs; t; t = last) { + last = t -> next; + dfree (t, MDL); + } + if (data -> len) + return 1; + else + return 0; }