]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Add internal base64 encoding and decoding support
authorGreg Hudson <ghudson@mit.edu>
Mon, 27 Aug 2012 08:18:57 +0000 (04:18 -0400)
committerGreg Hudson <ghudson@mit.edu>
Tue, 11 Sep 2012 05:14:06 +0000 (01:14 -0400)
Add base64 support based on Heimdal's libroken base64 code.

.gitignore
src/include/k5-base64.h [new file with mode: 0644]
src/util/support/Makefile.in
src/util/support/base64.c [new file with mode: 0644]
src/util/support/t_base64.c [new file with mode: 0644]

index 9c14c221e8f5f2062055889f087baaf209bc3e03..77d4d26379d8d97317b063a52ad962cffb175ca4 100644 (file)
@@ -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 (file)
index 0000000..a7cc48f
--- /dev/null
@@ -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 */
index 6ac91755b4d1fa24003f3525fe0f4b61303c88e0..ca04ad7134f9397484e2ed09b81faaf4ea4706ed 100644 (file)
@@ -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 (file)
index 0000000..e964a38
--- /dev/null
@@ -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 (file)
index 0000000..3b1fd45
--- /dev/null
@@ -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;
+}