]> granicus.if.org Git - sudo/commitdiff
When decoding base64, avoid using '=' in the decoded temporary array
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 1 Sep 2015 16:24:59 +0000 (10:24 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 1 Sep 2015 16:24:59 +0000 (10:24 -0600)
as a sentinel as it can legitimately be present.  Instead, just use
the count of bytes stored in the temp array to determine which bytes
to fold into the destination.

plugins/sudoers/base64.c
plugins/sudoers/match.c
plugins/sudoers/regress/parser/check_base64.c

index 23b4020077e7ad3de6c2d6e2ce4a8cf9f63ab025..d85bfbf59f9f4138124195f8168244aca51ee155 100644 (file)
@@ -53,27 +53,19 @@ base64_decode(const char *str, unsigned char *dst, size_t dsize)
      */
     while (*str != '\0') {
        for (i = 0; i < 4; i++) {
-           switch (*str) {
-           case '=':
-               str++;
-               /* FALLTHROUGH */
-           case '\0':
-               ch[i] = '=';
+           if (*str == '=' || *str == '\0')
                break;
-           default:
-               if ((pos = strchr(b64, *str++)) == NULL)
-                   debug_return_size_t((size_t)-1);
-               ch[i] = (unsigned char)(pos - b64);
-               break;
-           }
+           if ((pos = strchr(b64, *str++)) == NULL)
+               debug_return_size_t((size_t)-1);
+           ch[i] = (unsigned char)(pos - b64);
        }
-       if (ch[0] == '=' || ch[1] == '=' || dst == dend)
+       if (i == 0 || i == 1 || dst == dend)
            break;
        *dst++ = (ch[0] << 2) | ((ch[1] & 0x30) >> 4);
-       if (ch[2] == '=' || dst == dend)
+       if (i == 2 || dst == dend)
            break;
        *dst++ = ((ch[1] & 0x0f) << 4) | ((ch[2] & 0x3c) >> 2);
-       if (ch[3] == '=' || dst == dend)
+       if (i == 3 || dst == dend)
            break;
        *dst++ = ((ch[2] & 0x03) << 6) | ch[3];
     }
index 524ab5bd172b35d334f99a931875978dde75645f..e41e7219243c6106fbe35adf9b5156bb3e6e2e3d 100644 (file)
@@ -617,8 +617,12 @@ digest_matches(const char *file, const struct sudo_digest *sd)
     } else {
        size_t len = base64_decode(sd->digest_str, sudoers_digest,
            sizeof(sudoers_digest));
-       if (len != func->digest_len)
+       if (len != func->digest_len) {
+           sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+               "incorrect length for digest, expected %u, got %zu",
+               func->digest_len, len);
            goto bad_format;
+       }
     }
 
     if ((fp = fopen(file, "r")) == NULL) {
index 53753020a02aa21a354b3c4a0a30ff9d4df60c0a..7c9afa6fea3a11dd73551ebbfe15e6a220e19318 100644 (file)
@@ -39,10 +39,16 @@ extern size_t base64_decode(const char *str, unsigned char *dst, size_t dsize);
 
 __dso_public int main(int argc, char *argv[]);
 
+static char bstring1[] = { 0xea, 0xb8, 0xa2, 0x71, 0xef, 0x67, 0xc1, 0xcd, 0x0d, 0xd9, 0xa6, 0xaa, 0xa8, 0x24, 0x77, 0x2a, 0xfc, 0x6f, 0x76, 0x37, 0x1b, 0xed, 0x9e, 0x1a, 0x90, 0x5f, 0xcf, 0xbc, 0x00 };
+
 struct base64_test {
     const char *ascii;
     const char *encoded;
 } test_strings[] = {
+    {
+       bstring1,
+       "6riice9nwc0N2aaqqCR3Kvxvdjcb7Z4akF/PvA=="
+    },
     {
        "any carnal pleasure.",
        "YW55IGNhcm5hbCBwbGVhc3VyZS4="