]> granicus.if.org Git - sudo/commitdiff
Add base64_encode() by Jon Mayo.
authorTodd C. Miller <Todd.Miller@sudo.ws>
Sun, 20 May 2018 01:03:47 +0000 (19:03 -0600)
committerTodd C. Miller <Todd.Miller@sudo.ws>
Sun, 20 May 2018 01:03:47 +0000 (19:03 -0600)
plugins/sudoers/base64.c
plugins/sudoers/parse.h
plugins/sudoers/regress/parser/check_base64.c

index b80c285538d6889eebba03633e6f1e6a3b659dee..b97398efa3eec65f3614ac2dbebb06f4b30dcb3d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016 Todd C. Miller <Todd.Miller@sudo.ws>
+ * Copyright (c) 2013-2018 Todd C. Miller <Todd.Miller@sudo.ws>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -86,3 +86,41 @@ base64_decode(const char *in, unsigned char *out, size_t out_size)
     }
     debug_return_size_t((size_t)(out - out0));
 }
+
+static const unsigned char base64enc_tab[64] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+size_t
+base64_encode(const unsigned char *in, size_t in_len, char *out, size_t out_len)
+{
+    size_t ii, io;
+    unsigned int rem, v;
+    debug_decl(base64_encode, SUDOERS_DEBUG_MATCH)
+
+    for (io = 0, ii = 0, v = 0, rem = 0; ii < in_len; ii++) {
+       unsigned char ch = in[ii];
+       v = (v << 8) | ch;
+       rem += 8;
+       while (rem >= 6) {
+           rem -= 6;
+           if (io >= out_len)
+               debug_return_size_t((size_t)-1); /* truncation is failure */
+           out[io++] = base64enc_tab[(v >> rem) & 63];
+       }
+    }
+    if (rem != 0) {
+       v <<= (6 - rem);
+       if (io >= out_len)
+           debug_return_size_t((size_t)-1); /* truncation is failure */
+       out[io++] = base64enc_tab[v&63];
+    }
+    while (io & 3) {
+       if (io >= out_len)
+           debug_return_size_t((size_t)-1); /* truncation is failure */
+       out[io++] = '=';
+    }
+    if (io >= out_len)
+       debug_return_size_t((size_t)-1); /* no room for NUL terminator */
+    out[io] = '\0';
+    debug_return_size_t(io);
+}
index 4beef2926aaa22a8a3a0858eafeb5eb77ad283d1..51203baa237726d8c5c66938b68cfa86b72e07c0 100644 (file)
@@ -303,6 +303,7 @@ int hexchar(const char *s);
 
 /* base64.c */
 size_t base64_decode(const char *str, unsigned char *dst, size_t dsize);
+size_t base64_encode(const unsigned char *in, size_t in_len, char *out, size_t out_len);
 
 /* timeout.c */
 int parse_timeout(const char *timestr);
index 6faf1b91a339bc1a53b8ef48b2e49204eb164b92..04637ee41e0a29075bf663d071dc1fd300e5ce30 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ * Copyright (c) 2013-2018 Todd C. Miller <Todd.Miller@sudo.ws>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -36,7 +36,9 @@
 #include "sudo_compat.h"
 #include "sudo_util.h"
 
+/* From parse.h */
 extern size_t base64_decode(const char *str, unsigned char *dst, size_t dsize);
+extern size_t base64_encode(const unsigned char *in, size_t in_len, char *out, size_t out_len);
 
 __dso_public int main(int argc, char *argv[]);
 
@@ -75,22 +77,45 @@ struct base64_test {
 int
 main(int argc, char *argv[])
 {
-    const int ntests = nitems(test_strings);
+    int ntests = nitems(test_strings);
     int i, errors = 0;
-    unsigned char buf[32];
+    unsigned char buf[64];
     size_t len;
 
     initprogname(argc > 0 ? argv[0] : "check_base64");
 
     for (i = 0; i < ntests; i++) {
+       /* Test decode. */
        len = base64_decode(test_strings[i].encoded, buf, sizeof(buf));
-       buf[len] = '\0';
-       if (strcmp(test_strings[i].ascii, (char *)buf) != 0) {
-           fprintf(stderr, "check_base64: expected %s, got %s",
-               test_strings[i].ascii, buf);
+       if (len == (size_t)-1) {
+           fprintf(stderr, "check_base64: failed to decode %s\n",
+               test_strings[i].encoded);
            errors++;
+       } else {
+           buf[len] = '\0';
+           if (strcmp(test_strings[i].ascii, (char *)buf) != 0) {
+               fprintf(stderr, "check_base64: expected %s, got %s\n",
+                   test_strings[i].ascii, buf);
+               errors++;
+           }
+       }
+
+       /* Test encode. */
+       len = base64_encode(test_strings[i].ascii, strlen(test_strings[i].ascii), buf, sizeof(buf));
+       if (len == (size_t)-1) {
+           fprintf(stderr, "check_base64: failed to encode %s\n",
+               test_strings[i].ascii);
+           errors++;
+       } else {
+           if (strcmp(test_strings[i].encoded, (char *)buf) != 0) {
+               fprintf(stderr, "check_base64: expected %s, got %s\n",
+                   test_strings[i].encoded, buf);
+               errors++;
+           }
        }
     }
+    ntests *= 2;       /* we test in both directions */
+
     printf("check_base64: %d tests run, %d errors, %d%% success rate\n",
        ntests, errors, (ntests - errors) * 100 / ntests);
     exit(errors);