diff --git a/.gitignore b/.gitignore index f58099c..b4fd002 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ /libtool /ltmain.sh /m4 +/macaroon-test-runner /Makefile /Makefile.in /missing diff --git a/Makefile.am b/Makefile.am index 06c3315..fceee3d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -72,7 +72,9 @@ EXTRA_DIST += test/python-hmac-sanity-check.sh EXTRA_DIST += test/readme.sh check_LTLIBRARIES = libmacaroons-shim.la -check_PROGRAMS = test/varint +check_PROGRAMS = +check_PROGRAMS += test/varint +check_PROGRAMS += macaroon-test-runner libmacaroons_shim_la_SOURCES = shim.c explicit_bzero.c libmacaroons_shim_la_LDFLAGS = -module -avoid-version -rpath /evil/libtool/hack/to/force/shared/lib/creation @@ -87,6 +89,22 @@ TESTS += test/varint test_varint_SOURCES = test/varint.c varint.c test_varint_CFLAGS = $(AM_CFLAGS) $(CFLAGS) +macaroon_test_runner_SOURCES = test/macaroon-test-runner.c base64.c +macaroon_test_runner_LDADD = libmacaroons.la +macaroon_test_runner_CFLAGS = $(AM_CFLAGS) $(CFLAGS) + +macaroon_unit_test_stubs = +macaroon_unit_test_stubs += test/unit/caveat_v1_1.vtest.sh +macaroon_unit_test_stubs += test/unit/caveat_v1_2.vtest.sh +macaroon_unit_test_stubs += test/unit/caveat_v1_3.vtest.sh +macaroon_unit_test_stubs += test/unit/root_v1_1.vtest.sh +macaroon_unit_test_stubs += test/unit/root_v1_2.vtest.sh + +TESTS += $(macaroon_unit_test_stubs) +check_SCRIPTS = +check_SCRIPTS += $(macaroon_unit_test_stubs) + + #################################### Python #################################### pyexec_LTLIBRARIES = @@ -111,3 +129,12 @@ bindings_python_macaroons_la_LIBADD += $(PYTHON_LDFLAGS) bindings_python_macaroons_la_LDFLAGS = -module -avoid-version -export-symbols-regex $(PYTHON_SYMBOL)macaroons $(AM_LDFLAGS) $(LDFLAGS) bindings/python/macaroons.c: bindings/python/macaroons.pyx $(pyx_verbose)cython bindings/python/macaroons.pyx + +################################################################################ +################################## Maintenance ################################# +################################################################################ + +EXTRA_DIST += maint/generate-shell-stubs + +maintainer-generate: + maint/generate-shell-stubs diff --git a/bindings/python/macaroons.pyx b/bindings/python/macaroons.pyx index 126f6f2..fb25552 100644 --- a/bindings/python/macaroons.pyx +++ b/bindings/python/macaroons.pyx @@ -69,7 +69,7 @@ cdef extern from "macaroons.h": void macaroon_signature(const macaroon* M, const unsigned char** signature, size_t* signature_sz) size_t macaroon_serialize_size_hint(macaroon* M) int macaroon_serialize(macaroon* M, char* data, size_t data_sz, macaroon_returncode* err) - macaroon* macaroon_deserialize(char* data, macaroon_returncode* err) + macaroon* macaroon_deserialize(unsigned char* data, size_t data_sz, macaroon_returncode* err) size_t macaroon_inspect_size_hint(macaroon* M) int macaroon_inspect(macaroon* M, char* data, size_t data_sz, macaroon_returncode* err) macaroon* macaroon_copy(macaroon* M, macaroon_returncode* err) @@ -344,7 +344,7 @@ def deserialize(m): cdef Macaroon M = Macaroon() cdef macaroon_returncode err m = tobytes(m) - M._M = macaroon_deserialize(m, &err) + M._M = macaroon_deserialize(m, len(m), &err) if M._M == NULL: raise_error(err) return M diff --git a/doc/tests.txt b/doc/tests.txt new file mode 100644 index 0000000..21c99a1 --- /dev/null +++ b/doc/tests.txt @@ -0,0 +1,72 @@ +Tests +----- + +The test/unit/ directory of the libmacaroons repo contains several tests of +the macaroons serialization, deserialization, and verifier. This document +describes the format of these language-independent test files so that all +macaroon implementations may validate themselves against the same tests. + +Verification Tests +------------------ + +Verification tests test the verifier and for correctness. Each test is +contained within a single file that, by convention, ends in ".vtest". The +file describes the version of macaroons used by the test, whether the request +is authorized, the verifier, and the macaroons to be verified. The test file +is designed to be easy to parse in a variety of languages. A simple test +looks like: + + # a simple test of a macaroon with an exact caveat verified with the correct + # root key and verifier + version 1 + authorized + key this is the key + exact account = 3735928559 + MDAyMWxvY2F0aW9uIGh0dHA6Ly9leGFtcGxlLm9yZy8KMDAxNWlkZW50aWZpZXIga2V5aWQKMDAxZGNpZCBhY2NvdW50ID0gMzczNTkyODU1OQowMDJmc2lnbmF0dXJlIPVIB_bcbt-Ivw9zBrOCJWKjYlM9v3M5umF2XaS9JZ2HCg + +This test will construct a verifier that corresponds to this C code: + + struct macaroon_verifier* V = macaroon_verifier_create(); + macaroon_verifier_satisfy_exact(V, "account = 3735928559", 20, &err); + +and then verify the single macaroon with: + + macaroon_verify(V, M, "this is the key", 15, NULL, 0, &err); + +The format of the file is intended to be pretty easy to interpret. It adheres +to the following rules (references to the C implementation should be mapped to +their equivalents in other implementations): + + - Empty lines and lines beginning with a '#' are ignored; the remaining + bullets' description of line numbers assume no ignored lines + - The first line lists the version(s) the test requires of the + implementation. It starts with the literal "version " and then a + space-separated list of version numbers. A version number ending in "j" + indicates JSON format. Currently-supported versions are "1", "2", "2j". + - The second line indicates the outcome of the test. It must be either + "authorized" or "unauthorized" + - The third line provides the root secret for the macaroons tree. The line + starts with the literal "key " and then the key itself up to, but + excluding the '\n' that terminates the line. In the above example, the key + would be the literal "this is the key". The key is provided to the + function "macaroon_create" and not "macaroon_create_raw". + - The next 0 or more lines are caveats to be added to the verifier. Caveats + starting with the literal "exact " provide a predicate to be passed to the + function "macaroon_verifier_satisfy_exact". As with the key, the + predicate is the sequence of characters up to, but excluding the '\n' that + terminates the line. Caveats starting with the literal "general" followed + by any C-style identifier refer to a builtin general caveat. These caveats + are functions that match "macaroon_caveat_*" in the libmacaroons + implementation, where the wildcard is the identifier specified after the + literal "general". + - The remaining 1 or more lines are macaroons to be passed to the verifier. + The first of these macaroons corresponds to the "M" argument of the + "macaroon_verify" function and the remainder comprise the MS argument. + Each macaroon is base-64 encoded to avoid having to parse binary data from + the test file. The decoded form of the line corresponds to a macaroon in + one of the serialized formats specified in "version". + +Serialization Tests +------------------- + +XXX write these and some tests diff --git a/macaroons.c b/macaroons.c index 83308c6..35bac25 100644 --- a/macaroons.c +++ b/macaroons.c @@ -65,6 +65,10 @@ #error bad constants #endif +#define XSTR(x) #x +#define STR(x) XSTR(x) +#define STRINGIFY(x) case (x): return XSTR(x); + struct predicate { const unsigned char* data; @@ -88,6 +92,26 @@ struct macaroon_verifier size_t verifier_callbacks_cap; }; +MACAROON_API const char* +macaroon_error(enum macaroon_returncode err) +{ + switch (err) + { + STRINGIFY(MACAROON_SUCCESS); + STRINGIFY(MACAROON_OUT_OF_MEMORY); + STRINGIFY(MACAROON_HASH_FAILED); + STRINGIFY(MACAROON_INVALID); + STRINGIFY(MACAROON_TOO_MANY_CAVEATS); + STRINGIFY(MACAROON_CYCLE); + STRINGIFY(MACAROON_BUF_TOO_SMALL); + STRINGIFY(MACAROON_NOT_AUTHORIZED); + STRINGIFY(MACAROON_NO_JSON_SUPPORT); + STRINGIFY(MACAROON_UNSUPPORTED_FORMAT); + default: + return "unknown error"; + } +} + /* Allocate a new macaroon with space for "num_caveats" caveats and a body of * "body_data" bytes. Returns via _ptr a contiguous set of "body_data" bytes to * which the callee may write. @@ -944,10 +968,25 @@ macaroon_serialize(const struct macaroon* M, return macaroon_serialize_v1(M, data, data_sz, err); } +static const char v1_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/-_"; + MACAROON_API struct macaroon* -macaroon_deserialize(const char* data, enum macaroon_returncode* err) +macaroon_deserialize(const unsigned char* data, size_t data_sz, + enum macaroon_returncode* err) { - return macaroon_deserialize_v1(data, err); + if (data_sz == 0) + { + *err = MACAROON_INVALID; + return NULL; + } + + if (strchr(v1_chars, data[0])) + { + return macaroon_deserialize_v1((const char*)data, data_sz, err); + } + + abort(); + } MACAROON_API size_t diff --git a/macaroons.h b/macaroons.h index 2b163d4..35ec5a4 100644 --- a/macaroons.h +++ b/macaroons.h @@ -64,6 +64,9 @@ enum macaroon_returncode MACAROON_UNSUPPORTED_FORMAT=2057 }; +const char* +macaroon_error(enum macaroon_returncode err); + /* Create a new macaroon. * - location/location_sz is a hint to the target's location * - key/key_sz is the key used as a secret for macaroon construction @@ -183,7 +186,8 @@ macaroon_serialize(const struct macaroon* M, enum macaroon_returncode* err); struct macaroon* -macaroon_deserialize(const char* data, enum macaroon_returncode* err); +macaroon_deserialize(const unsigned char* data, size_t data_sz, + enum macaroon_returncode* err); /* Human-readable representation *FOR DEBUGGING ONLY* */ size_t diff --git a/maint/generate-shell-stubs b/maint/generate-shell-stubs new file mode 100755 index 0000000..f2f9452 --- /dev/null +++ b/maint/generate-shell-stubs @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +import glob +import stat +import os + +for x in glob.glob('test/unit/*.vtest'): + fname = x + '.sh' + f = open(fname, 'w') + f.write('''#!/bin/sh +exec macaroon-test-runner < {0} +'''.format(x)) + f.flush() + f.close() + os.chmod(fname, stat.S_IRWXU) diff --git a/test/env.sh b/test/env.sh index 3264020..c5e5f59 100644 --- a/test/env.sh +++ b/test/env.sh @@ -4,3 +4,4 @@ export MACAROONS_VERSION="$3" export LD_PRELOAD="${MACAROONS_BUILDDIR}/.libs/libmacaroons-shim.so" export PYTHONPATH="${MACAROONS_BUILDDIR}"/bindings/python/.libs:${PYTHONPATH} +export PATH=${MACAROONS_BUILDDIR}:${MACAROONS_SRCDIR}:${PATH} diff --git a/test/macaroon-test-runner.c b/test/macaroon-test-runner.c new file mode 100644 index 0000000..d4d676c --- /dev/null +++ b/test/macaroon-test-runner.c @@ -0,0 +1,267 @@ +/* Copyright (c) 2016, Robert Escriva + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of this project 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#define _WITH_GETLINE + +/* C */ +#include +#include +#include +#include + +/* macaroons */ +#include "macaroons.h" +#include "base64.h" + +#define STRLENOF(X) (sizeof(X) - 1) + +#define VERSION "version " +#define AUTHORIZED "authorized" +#define UNAUTHORIZED "unauthorized" +#define KEY "key " +#define EXACT "exact " +#define GENERAL "general " + +int +parse_version(const char* line) +{ + const char* ptr = line + STRLENOF(VERSION); + const char* const end = line + strlen(line); + + while (ptr < end) + { + const char* tmp = strchr(ptr, ' '); + tmp = tmp ? tmp : end; + + if (strncmp(ptr, "1", tmp - ptr) != 0 && + strncmp(ptr, "2", tmp - ptr) != 0 && + strncmp(ptr, "2j", tmp - ptr) != 0) + { + fprintf(stderr, "version %.*s not supported\n", (int)(tmp - ptr), ptr); + return -1; + } + + ptr = tmp + 1; + } + + return 0; +} + +int +parse_key(const char* line, unsigned char** key, size_t* key_sz) +{ + const char* ptr = line + STRLENOF(KEY); + *key_sz = strlen(ptr); + *key = malloc(*key_sz); + + if (!*key) + { + return -1; + } + + memmove(*key, ptr, *key_sz); + return 0; +} + +int +parse_exact_caveat(const char* line, struct macaroon_verifier* V) +{ + enum macaroon_returncode err; + const char* ptr = line + STRLENOF(EXACT); + size_t ptr_sz = strlen(ptr); + + if (macaroon_verifier_satisfy_exact(V, (const unsigned char*)ptr, ptr_sz, &err) < 0) + { + fprintf(stderr, "could not add exact caveat: %s\n", macaroon_error(err)); + return -1; + } + + return 0; +} + +int +parse_macaroon(const char* line, struct macaroon*** macaroons, size_t* macaroons_sz) +{ + size_t buf_sz = strlen(line); + unsigned char* buf = malloc(buf_sz); + + if (!buf) + { + return -1; + } + + int rc = b64_pton(line, buf, buf_sz); + + if (rc < 0) + { + fprintf(stderr, "could not unwrap serialized macaroon\n"); + return -1; + } + + enum macaroon_returncode err; + struct macaroon* M = macaroon_deserialize(buf, rc, &err); + + if (!M) + { + fprintf(stderr, "could not deserialize macaroon: %s\n", macaroon_error(err)); + return -1; + } + + ++*macaroons_sz; + *macaroons = realloc(*macaroons, *macaroons_sz * sizeof(struct macaroon*)); + + if (!*macaroons) + { + return -1; + } + + (*macaroons)[*macaroons_sz - 1] = M; + return 0; +} + +int +main(int argc, const char* argv[]) +{ + char* line = NULL; + size_t line_sz = 0; + int authorized = 0; + unsigned char* key = NULL; + size_t key_sz = 0; + struct macaroon_verifier* V = NULL; + struct macaroon** macaroons = NULL; + size_t macaroons_sz = 0; + + if (!(V = macaroon_verifier_create())) + { + fprintf(stderr, "could not create verifier: %s\n", strerror(ferror(stdin))); + return EXIT_FAILURE; + } + + while (1) + { + ssize_t amt = getline(&line, &line_sz, stdin); + + if (amt < 0) + { + if (feof(stdin) != 0) + { + break; + } + + fprintf(stderr, "could not read from stdin: %s\n", strerror(ferror(stdin))); + return EXIT_FAILURE; + } + + if (!line || amt == 0 || *line == '\n' || *line == '#') + { + continue; + } + + line[amt - 1] = '\0'; + + if (strncmp(line, VERSION, STRLENOF(VERSION)) == 0) + { + if (parse_version(line) < 0) + { + return EXIT_FAILURE; + } + } + else if (strcmp(line, AUTHORIZED) == 0) + { + authorized = 1; + } + else if (strcmp(line, UNAUTHORIZED) == 0) + { + authorized = 0; + } + else if (strncmp(line, KEY, STRLENOF(KEY)) == 0) + { + if (parse_key(line, &key, &key_sz) < 0) + { + return EXIT_FAILURE; + } + } + else if (strncmp(line, EXACT, STRLENOF(EXACT)) == 0) + { + if (parse_exact_caveat(line, V) < 0) + { + return EXIT_FAILURE; + } + } + else if (strncmp(line, GENERAL, STRLENOF(GENERAL)) == 0) + { + abort(); + } + else if (parse_macaroon(line, &macaroons, &macaroons_sz) < 0) + { + return EXIT_FAILURE; + } + } + + if (macaroons_sz == 0) + { + fprintf(stderr, "no macaroons provided\n"); + return EXIT_FAILURE; + } + + enum macaroon_returncode err; + int verify = macaroon_verify(V, macaroons[0], key, key_sz, + macaroons + 1, macaroons_sz - 1, &err); + + if (verify != 0 && err != MACAROON_NOT_AUTHORIZED) + { + fprintf(stderr, "verification encountered exceptional error: %s\n", macaroon_error(err)); + return -1; + } + + if (verify == 0 && !authorized) + { + fprintf(stderr, "verification passed for \"unauthorized\" scenario\n"); + return -1; + } + + if (verify != 0 && err == MACAROON_NOT_AUTHORIZED && authorized) + { + fprintf(stderr, "verification failed for \"authorized\" scenario\n"); + return -1; + } + + if (line) + { + free(line); + } + + if (key) + { + free(key); + } + + (void) argc; + (void) argv; + return EXIT_SUCCESS; +} diff --git a/test/unit/caveat_v1_1.vtest b/test/unit/caveat_v1_1.vtest new file mode 100644 index 0000000..67c4fa7 --- /dev/null +++ b/test/unit/caveat_v1_1.vtest @@ -0,0 +1,7 @@ +# a simple test of a macaroon with an exact caveat verified with the correct +# root key and verifier +version 1 +authorized +key this is the key +exact account = 3735928559 +TURBeU1XeHZZMkYwYVc5dUlHaDBkSEE2THk5bGVHRnRjR3hsTG05eVp5OEtNREF4Tldsa1pXNTBhV1pwWlhJZ2EyVjVhV1FLTURBeFpHTnBaQ0JoWTJOdmRXNTBJRDBnTXpjek5Ua3lPRFUxT1Fvd01ESm1jMmxuYm1GMGRYSmxJUFZJQl9iY2J0LUl2dzl6QnJPQ0pXS2pZbE05djNNNXVtRjJYYVM5SloySENn diff --git a/test/unit/caveat_v1_1.vtest.sh b/test/unit/caveat_v1_1.vtest.sh new file mode 100755 index 0000000..e82ef37 --- /dev/null +++ b/test/unit/caveat_v1_1.vtest.sh @@ -0,0 +1,2 @@ +#!/bin/sh +exec macaroon-test-runner < test/unit/caveat_v1_1.vtest diff --git a/test/unit/caveat_v1_2.vtest b/test/unit/caveat_v1_2.vtest new file mode 100644 index 0000000..a1edeb9 --- /dev/null +++ b/test/unit/caveat_v1_2.vtest @@ -0,0 +1,7 @@ +# a simple test of a macaroon with an exact caveat verified with an incorrect +# root key with a verifier built for another context +version 1 +unauthorized +key this is the key +exact account = 0000000000 +TURBeU1XeHZZMkYwYVc5dUlHaDBkSEE2THk5bGVHRnRjR3hsTG05eVp5OEtNREF4Tldsa1pXNTBhV1pwWlhJZ2EyVjVhV1FLTURBeFpHTnBaQ0JoWTJOdmRXNTBJRDBnTXpjek5Ua3lPRFUxT1Fvd01ESm1jMmxuYm1GMGRYSmxJUFZJQl9iY2J0LUl2dzl6QnJPQ0pXS2pZbE05djNNNXVtRjJYYVM5SloySENn diff --git a/test/unit/caveat_v1_2.vtest.sh b/test/unit/caveat_v1_2.vtest.sh new file mode 100755 index 0000000..5ec5ebf --- /dev/null +++ b/test/unit/caveat_v1_2.vtest.sh @@ -0,0 +1,2 @@ +#!/bin/sh +exec macaroon-test-runner < test/unit/caveat_v1_2.vtest diff --git a/test/unit/caveat_v1_3.vtest b/test/unit/caveat_v1_3.vtest new file mode 100644 index 0000000..26c9f16 --- /dev/null +++ b/test/unit/caveat_v1_3.vtest @@ -0,0 +1,6 @@ +# a simple test of a macaroon with an exact caveat verified with an incorrect +# root key with a verifier lacking the correct context +version 1 +unauthorized +key this is the key +TURBeU1XeHZZMkYwYVc5dUlHaDBkSEE2THk5bGVHRnRjR3hsTG05eVp5OEtNREF4Tldsa1pXNTBhV1pwWlhJZ2EyVjVhV1FLTURBeFpHTnBaQ0JoWTJOdmRXNTBJRDBnTXpjek5Ua3lPRFUxT1Fvd01ESm1jMmxuYm1GMGRYSmxJUFZJQl9iY2J0LUl2dzl6QnJPQ0pXS2pZbE05djNNNXVtRjJYYVM5SloySENn diff --git a/test/unit/caveat_v1_3.vtest.sh b/test/unit/caveat_v1_3.vtest.sh new file mode 100755 index 0000000..b71f166 --- /dev/null +++ b/test/unit/caveat_v1_3.vtest.sh @@ -0,0 +1,2 @@ +#!/bin/sh +exec macaroon-test-runner < test/unit/caveat_v1_3.vtest diff --git a/test/unit/root_v1_1.vtest b/test/unit/root_v1_1.vtest new file mode 100644 index 0000000..9a1ebe1 --- /dev/null +++ b/test/unit/root_v1_1.vtest @@ -0,0 +1,6 @@ +# a simple test of a plain macaroon with no caveats verified with the correct +# root key +version 1 +authorized +key this is the key +TURBeU1XeHZZMkYwYVc5dUlHaDBkSEE2THk5bGVHRnRjR3hsTG05eVp5OEtNREF4Tldsa1pXNTBhV1pwWlhJZ2EyVjVhV1FLTURBeVpuTnBaMjVoZEhWeVpTQjgzdWVTVVJ4Ynh2VW9TRmdGMy1teVRuaGVLT0twa3dINTF4SEdDZU9POXdv diff --git a/test/unit/root_v1_1.vtest.sh b/test/unit/root_v1_1.vtest.sh new file mode 100755 index 0000000..717f4e3 --- /dev/null +++ b/test/unit/root_v1_1.vtest.sh @@ -0,0 +1,2 @@ +#!/bin/sh +exec macaroon-test-runner < test/unit/root_v1_1.vtest diff --git a/test/unit/root_v1_2.vtest b/test/unit/root_v1_2.vtest new file mode 100644 index 0000000..d166900 --- /dev/null +++ b/test/unit/root_v1_2.vtest @@ -0,0 +1,6 @@ +# a simple test of a plain macaroon with no caveats verified with an incorrect +# root key +version 1 +unauthorized +key this is not the key +TURBeU1XeHZZMkYwYVc5dUlHaDBkSEE2THk5bGVHRnRjR3hsTG05eVp5OEtNREF4Tldsa1pXNTBhV1pwWlhJZ2EyVjVhV1FLTURBeVpuTnBaMjVoZEhWeVpTQjgzdWVTVVJ4Ynh2VW9TRmdGMy1teVRuaGVLT0twa3dINTF4SEdDZU9POXdv diff --git a/test/unit/root_v1_2.vtest.sh b/test/unit/root_v1_2.vtest.sh new file mode 100755 index 0000000..8ab6ba8 --- /dev/null +++ b/test/unit/root_v1_2.vtest.sh @@ -0,0 +1,2 @@ +#!/bin/sh +exec macaroon-test-runner < test/unit/root_v1_2.vtest diff --git a/v1.c b/v1.c index 2a78da3..85743c7 100644 --- a/v1.c +++ b/v1.c @@ -167,11 +167,10 @@ macaroon_serialize_v1(const struct macaroon* M, } struct macaroon* -macaroon_deserialize_v1(const char* _data, enum macaroon_returncode* err) +macaroon_deserialize_v1(const char* _data, const size_t _data_sz, enum macaroon_returncode* err) { size_t num_pkts = 0; struct packet pkt = EMPTY_PACKET; - const size_t _data_sz = strlen(_data); unsigned char* data = NULL; const unsigned char* end = NULL; const unsigned char* rptr = NULL; diff --git a/v1.h b/v1.h index f57e484..5ad8b18 100644 --- a/v1.h +++ b/v1.h @@ -47,7 +47,7 @@ macaroon_serialize_v1(const struct macaroon* M, enum macaroon_returncode* err); struct macaroon* -macaroon_deserialize_v1(const char* _data, enum macaroon_returncode* err); +macaroon_deserialize_v1(const char* _data, const size_t sz, enum macaroon_returncode* err); size_t macaroon_inspect_size_hint_v1(const struct macaroon* M);