[mod_auth] fix base64_decode (#2484)

git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2871 152afb58-edef-0310-8abb-c4023f1b3aa9
This commit is contained in:
Stefan Bühler 2013-05-15 10:31:04 +00:00
parent c26b50d9ad
commit ce4bc0c0f7
2 changed files with 38 additions and 23 deletions

1
NEWS
View File

@ -12,6 +12,7 @@ NEWS
* reject non ASCII characters in HTTP header names
* [mod_auth] use crypt() on encrypted password instead of extracting salt first (fixes #2483)
* [mod_auth] add htpasswd -s (SHA1) support if openssl is used (needs openssl for SHA1). This doesn't use any salt, md5 with salt is probably better.
* [mod_auth] fix base64_decode (#2484)
- 1.4.32 - 2012-11-21
* Code cleanup with clang/sparse (fixes #2437, thx kibi)

View File

@ -91,7 +91,8 @@ static const short base64_reverse_table[256] = {
static unsigned char * base64_decode(buffer *out, const char *in) {
unsigned char *result;
int ch, j = 0, k;
unsigned int j = 0; /* current output character (position) that is decoded. can contain partial result */
unsigned int group = 0; /* how many base64 digits in the current group were decoded already. each group has up to 4 digits */
size_t i;
size_t in_len = strlen(in);
@ -100,51 +101,64 @@ static unsigned char * base64_decode(buffer *out, const char *in) {
result = (unsigned char *)out->ptr;
ch = in[0];
/* run through the whole string, converting as we go */
for (i = 0; i < in_len; i++) {
ch = (unsigned char) in[i];
unsigned char c = (unsigned char) in[i];
short ch;
if (ch == '\0') break;
if (c == '\0') break;
if (ch == base64_pad) break;
if (c == base64_pad) {
/* pad character can only come after 2 base64 digits in a group */
if (group < 2) return NULL;
break;
}
ch = base64_reverse_table[ch];
if (ch < 0) continue;
ch = base64_reverse_table[c];
if (ch < 0) continue; /* skip invalid characters */
switch(i % 4) {
switch(group) {
case 0:
result[j] = ch << 2;
group = 1;
break;
case 1:
result[j++] |= ch >> 4;
result[j] = (ch & 0x0f) << 4;
group = 2;
break;
case 2:
result[j++] |= ch >>2;
result[j] = (ch & 0x03) << 6;
group = 3;
break;
case 3:
result[j++] |= ch;
group = 0;
break;
}
}
k = j;
/* mop things up if we ended on a boundary */
if (ch == base64_pad) {
switch(i % 4) {
case 0:
case 1:
return NULL;
case 2:
k++;
case 3:
result[k++] = 0;
}
}
result[k] = '\0';
out->used = k;
switch(group) {
case 0:
/* ended on boundary */
break;
case 1:
/* need at least 2 base64 digits per group */
return NULL;
case 2:
/* have 2 base64 digits in last group => one real octect, two zeroes padded */
case 3:
/* have 3 base64 digits in last group => two real octects, one zero padded */
/* for both cases the current index already is on the first zero padded octet
* - check it really is zero (overlapping bits) */
if (0 != result[j]) return NULL;
break;
}
result[j] = '\0';
out->used = j;
return result;
}