krb5 commit: Add internal base64 encoding and decoding support

Greg Hudson ghudson at MIT.EDU
Tue Sep 11 01:18:58 EDT 2012


https://github.com/krb5/krb5/commit/3b55b8aba850fa54a4d0c5017a91641538c16835
commit 3b55b8aba850fa54a4d0c5017a91641538c16835
Author: Greg Hudson <ghudson at mit.edu>
Date:   Mon Aug 27 04:18:57 2012 -0400

    Add internal base64 encoding and decoding support
    
    Add base64 support based on Heimdal's libroken base64 code.

 .gitignore                   |    1 +
 src/include/k5-base64.h      |   52 +++++++++++++++
 src/util/support/Makefile.in |   14 +++-
 src/util/support/base64.c    |  145 ++++++++++++++++++++++++++++++++++++++++++
 src/util/support/t_base64.c  |  110 ++++++++++++++++++++++++++++++++
 5 files changed, 319 insertions(+), 3 deletions(-)

diff --git a/.gitignore b/.gitignore
index 9c14c22..77d4d26 100644
--- a/.gitignore
+++ b/.gitignore
@@ -340,6 +340,7 @@ testlog
 /src/util/ss/std_rqs.c
 
 /src/util/support/libkrb5support.exports
+/src/util/support/t_base64
 /src/util/support/t_k5buf
 /src/util/support/t_path
 /src/util/support/t_path_win
diff --git a/src/include/k5-base64.h b/src/include/k5-base64.h
new file mode 100644
index 0000000..a7cc48f
--- /dev/null
+++ b/src/include/k5-base64.h
@@ -0,0 +1,52 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/k5-base64.h - base64 declarations */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef K5_BASE64_H
+#define K5_BASE64_H
+
+#include <stddef.h>
+
+/* base64-encode data and return it in an allocated buffer.  Return NULL if out
+ * of memory. */
+char *k5_base64_encode(const void *data, size_t len);
+
+/*
+ * Decode str as base64 and return the result in an allocated buffer, setting
+ * *len_out to the length.  Return NULL and *len_out == 0 if out of memory,
+ * NULL and *len_out == SIZE_MAX on invalid input.
+ */
+void *k5_base64_decode(const char *str, size_t *len_out);
+
+#endif /* K5_BASE64_H */
diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in
index 6ac9175..ca04ad7 100644
--- a/src/util/support/Makefile.in
+++ b/src/util/support/Makefile.in
@@ -74,6 +74,7 @@ STLIBOBJS= \
 	utf8_conv.o \
 	zap.o \
 	path.o \
+	base64.o \
 	$(GETTIMEOFDAY_ST_OBJ) \
 	$(IPC_ST_OBJ) \
 	$(STRLCPY_ST_OBJ) \
@@ -93,6 +94,7 @@ LIBOBJS= \
 	$(OUTPRE)utf8_conv.$(OBJEXT) \
 	$(OUTPRE)zap.$(OBJEXT) \
 	$(OUTPRE)path.$(OBJEXT) \
+	$(OUTPRE)base64.$(OBJECT) \
 	$(GETTIMEOFDAY_OBJ) \
 	$(IPC_OBJ) \
 	$(STRLCPY_OBJ) \
@@ -123,7 +125,8 @@ SRCS=\
 	$(srcdir)/t_k5buf.c \
 	$(srcdir)/t_unal.c \
 	$(srcdir)/zap.c \
-	$(srcdir)/path.c
+	$(srcdir)/path.c \
+	$(srcdir)/base64.c
 
 SHLIB_EXPDEPS =
 # Add -lm if dumping thread stats, for sqrt.
@@ -186,20 +189,25 @@ t_path_win.o: $(srcdir)/t_path.c
 path_win.o: $(srcdir)/path.c
 	$(CC) $(ALL_CFLAGS) -DWINDOWS_PATHS -c $(srcdir)/path.c -o $@
 
+t_base64: t_base64.o base64.o
+	$(CC_LINK) -o $@ t_base64.o base64.o
+
 t_unal: t_unal.o
 	$(CC_LINK) -o t_unal t_unal.o
 
-TEST_PROGS= t_k5buf t_path t_path_win t_unal
+TEST_PROGS= t_k5buf t_path t_path_win t_base64 t_unal
 
 check-unix:: $(TEST_PROGS)
 	./t_k5buf
 	./t_path
 	./t_path_win
+	./t_base64
 	./t_unal
 
 clean::
 	$(RM) t_k5buf.o t_k5buf t_unal.o t_unal path_win.o path_win
-	$(RM) t_path_win.o t_path_win t_path.o t_path libkrb5support.exports
+	$(RM) t_path_win.o t_path_win t_path.o t_path t_base64.o t_base64
+	$(RM) libkrb5support.exports
 
 @lib_frag@
 @libobj_frag@
diff --git a/src/util/support/base64.c b/src/util/support/base64.c
new file mode 100644
index 0000000..e964a38
--- /dev/null
+++ b/src/util/support/base64.c
@@ -0,0 +1,145 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* util/support/base64.c - base64 encoder and decoder */
+/*
+ * Copyright (c) 1995-2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <k5-platform.h>
+#include <k5-base64.h>
+
+static const char base64_chars[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+char *
+k5_base64_encode(const void *data, size_t len)
+{
+    char *s, *p;
+    size_t i;
+    unsigned int c;
+    const unsigned char *q;
+
+    if (len > SIZE_MAX / 4)
+        return NULL;
+
+    p = s = malloc(len * 4 / 3 + 4);
+    if (p == NULL)
+        return NULL;
+    q = (const unsigned char *)data;
+
+    for (i = 0; i < len;) {
+        c = q[i++];
+        c *= 256;
+        if (i < len)
+            c += q[i];
+        i++;
+        c *= 256;
+        if (i < len)
+            c += q[i];
+        i++;
+        p[0] = base64_chars[(c & 0x00fc0000) >> 18];
+        p[1] = base64_chars[(c & 0x0003f000) >> 12];
+        p[2] = base64_chars[(c & 0x00000fc0) >> 6];
+        p[3] = base64_chars[(c & 0x0000003f) >> 0];
+        if (i > len)
+            p[3] = '=';
+        if (i > len + 1)
+            p[2] = '=';
+        p += 4;
+    }
+    *p = '\0';
+    return s;
+}
+
+#define DECODE_ERROR 0xffffffff
+
+/* Decode token, which must be four bytes long. */
+static unsigned int
+decode_token(const char *token)
+{
+    int i, marker = 0;
+    unsigned int val = 0;
+    const char *p;
+
+    for (i = 0; i < 4; i++) {
+        val *= 64;
+        if (token[i] == '=') {
+            marker++;
+        } else if (marker > 0) {
+            return DECODE_ERROR;
+        } else {
+            p = strchr(base64_chars, token[i]);
+            if (p == NULL)
+                return DECODE_ERROR;
+            val += p - base64_chars;
+        }
+    }
+    if (marker > 2)
+        return DECODE_ERROR;
+    return (marker << 24) | val;
+}
+
+void *
+k5_base64_decode(const char *str, size_t *len_out)
+{
+    unsigned char *data, *q;
+    unsigned int val, marker;
+    size_t len;
+
+    *len_out = SIZE_MAX;
+
+    /* Allocate the output buffer. */
+    len = strlen(str);
+    if (len % 4)
+        return NULL;
+    q = data = malloc(len / 4 * 3);
+    if (data == NULL) {
+        *len_out = 0;
+        return NULL;
+    }
+
+    /* Decode the string. */
+    for (; *str != '\0'; str += 4) {
+        val = decode_token(str);
+        if (val == DECODE_ERROR) {
+            free(data);
+            return NULL;
+        }
+        marker = (val >> 24) & 0xff;
+        *q++ = (val >> 16) & 0xff;
+        if (marker < 2)
+            *q++ = (val >> 8) & 0xff;
+        if (marker < 1)
+            *q++ = val & 0xff;
+    }
+    *len_out = q - data;
+    return data;
+}
diff --git a/src/util/support/t_base64.c b/src/util/support/t_base64.c
new file mode 100644
index 0000000..3b1fd45
--- /dev/null
+++ b/src/util/support/t_base64.c
@@ -0,0 +1,110 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* util/support/t_base64.c - base64 encoding and decoding tests */
+/*
+ * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <k5-platform.h>
+#include <k5-base64.h>
+
+static struct test {
+    void *data;
+    size_t len;
+    const char *result;
+} tests[] = {
+    { "", 0 , "" },
+    { "1", 1, "MQ==" },
+    { "22", 2, "MjI=" },
+    { "333", 3, "MzMz" },
+    { "4444", 4, "NDQ0NA==" },
+    { "55555", 5, "NTU1NTU=" },
+    { "abc:def", 7, "YWJjOmRlZg==" },
+    { "f", 1, "Zg==" },
+    { "fo", 2, "Zm8=" },
+    { "foo", 3, "Zm9v" },
+    { "foob", 4, "Zm9vYg==" },
+    { "fooba", 5, "Zm9vYmE=" },
+    { "foobar", 6, "Zm9vYmFy" },
+    { NULL, 0, NULL }
+};
+
+static char *negative_tests[] = {
+    "M=M=",
+    "MM=M",
+    "MQ===",
+    "====",
+    "M===",
+    NULL
+};
+
+int
+main(int argc, char **argv)
+{
+    char *str, **ntest;
+    void *data;
+    int numerr = 0, numtest = 1;
+    const struct test *t;
+    size_t len;
+
+    for (t = tests; t->data != NULL; t++) {
+        str = k5_base64_encode(t->data, t->len);
+        if (strcmp(str, t->result) != 0) {
+            fprintf(stderr, "failed test %d: %s != %s\n", numtest,
+                    str, t->result);
+            numerr++;
+        }
+        free(str);
+        data = k5_base64_decode(t->result, &len);
+        if (len != t->len) {
+            fprintf(stderr, "failed test %d: len %lu != %lu\n", numtest,
+                    (unsigned long)len, (unsigned long)t->len);
+            numerr++;
+        } else if (memcmp(data, t->data, t->len) != 0) {
+            fprintf(stderr, "failed test %d: data\n", numtest);
+            numerr++;
+        }
+        free(data);
+        numtest++;
+    }
+
+    for (ntest = negative_tests; *ntest != NULL; ntest++) {
+        data = k5_base64_decode(*ntest, &len);
+        if (data != NULL || len != SIZE_MAX) {
+            fprintf(stderr, "failed test %d: successful decode: %s\n",
+                    numtest, *ntest);
+            numerr++;
+        }
+        numtest++;
+    }
+
+    return numerr ? 1 : 0;
+}


More information about the cvs-krb5 mailing list