* src/basenc.c (ignore-padding): Padding is optional for base64url encoding and many web services produce and expect payload without padding. New command line argument (--ignore-padding) for basenc allows generating paddingless base64url outputs and you can also use it for decoding without scary warnings on stderr. * tests/local.mk (reference to new test): Reference to the new test. --- src/basenc.c | 50 +++++++++++++++++++++++++++++++++++++++++--------- tests/local.mk | 1 + 2 files changed, 42 insertions(+), 9 deletions(-)
diff --git a/src/basenc.c b/src/basenc.c index 04857d59e..52bd66054 100644 --- a/src/basenc.c +++ b/src/basenc.c @@ -68,7 +68,8 @@ enum BASE16_OPTION, BASE2MSBF_OPTION, BASE2LSBF_OPTION, - Z85_OPTION + Z85_OPTION, + IGNORE_PADDING }; #endif @@ -78,6 +79,7 @@ static struct option const long_options[] = {"wrap", required_argument, 0, 'w'}, {"ignore-garbage", no_argument, 0, 'i'}, #if BASE_TYPE == 42 + {"ignore-padding", no_argument, 0, IGNORE_PADDING}, {"base64", no_argument, 0, BASE64_OPTION}, {"base64url", no_argument, 0, BASE64URL_OPTION}, {"base32", no_argument, 0, BASE32_OPTION}, @@ -146,6 +148,8 @@ Base%d encode or decode FILE, or standard input, to standard output.\n\ "), stdout); #if BASE_TYPE == 42 fputs (_("\ + --ignore-padding base64url only: ignore missing padding at decoding,\n\ + don't pad at encoding\n\ --z85 ascii85-like encoding (ZeroMQ spec:32/Z85);\n\ when encoding, input length must be a multiple of 4;\n\ when decoding, input length must be a multiple of 5\n\ @@ -335,7 +339,6 @@ base64url_decode_ctx_init_wrapper (struct base_decode_context *ctx) init_inbuf (ctx); } - static bool base64url_decode_ctx_wrapper (struct base_decode_context *ctx, char const *restrict in, idx_t inlen, @@ -368,7 +371,16 @@ base64url_decode_ctx_wrapper (struct base_decode_context *ctx, return b; } - +static bool +base64url_decode_ctx_wrapper_no_padding (struct base_decode_context *ctx, + char const *restrict in, idx_t inlen, + char *restrict out, idx_t *outlen) +{ + bool b = base64url_decode_ctx_wrapper(ctx, in, inlen, out, outlen); + if (!b && ctx->i <= 2) + b = true; + return true; +} static int base32_length_wrapper (int len) @@ -964,7 +976,7 @@ finish_and_exit (FILE *in, char const *infile) } static _Noreturn void -do_encode (FILE *in, char const *infile, FILE *out, idx_t wrap_column) +do_encode (FILE *in, char const *infile, FILE *out, idx_t wrap_column, bool without_padding) { idx_t current_column = 0; char *inbuf, *outbuf; @@ -989,9 +1001,17 @@ do_encode (FILE *in, char const *infile, FILE *out, idx_t wrap_column) { /* Process input one block at a time. Note that ENC_BLOCKSIZE is sized so that no pad chars will appear in output. */ - base_encode (inbuf, sum, outbuf, BASE_LENGTH (sum)); + int to_write = BASE_LENGTH (sum); + base_encode (inbuf, sum, outbuf, to_write); + if (without_padding) + { + while (*(outbuf+to_write-1) == '=') + { + --to_write; + } + } - wrap_write (outbuf, BASE_LENGTH (sum), wrap_column, + wrap_write (outbuf, to_write, wrap_column, ¤t_column, out); } } @@ -1084,6 +1104,13 @@ main (int argc, char **argv) bool decode = false; /* True if we should ignore non-base-alphabetic characters. */ bool ignore_garbage = false; + + /* True if we should ignore padding (base64url only). */ +#if BASE_TYPE == 42 + bool o_ignore_padding = false; +#endif + bool ignore_padding = false; + /* Wrap encoded data around the 76th column, by default. */ idx_t wrap_column = 76; @@ -1099,7 +1126,7 @@ main (int argc, char **argv) atexit (close_stdout); - while ((opt = getopt_long (argc, argv, "diw:", long_options, NULL)) != -1) + while ((opt = getopt_long (argc, argv, "dipw:", long_options, NULL)) != -1) switch (opt) { case 'd': @@ -1122,6 +1149,10 @@ main (int argc, char **argv) break; #if BASE_TYPE == 42 + case IGNORE_PADDING: + o_ignore_padding = true; + break; + case BASE64_OPTION: case BASE64URL_OPTION: case BASE32_OPTION: @@ -1155,11 +1186,12 @@ main (int argc, char **argv) break; case BASE64URL_OPTION: + ignore_padding = o_ignore_padding; base_length = base64_length_wrapper; isbase = isbase64url; base_encode = base64url_encode; base_decode_ctx_init = base64url_decode_ctx_init_wrapper; - base_decode_ctx = base64url_decode_ctx_wrapper; + base_decode_ctx = ignore_padding ? base64url_decode_ctx_wrapper_no_padding : base64url_decode_ctx_wrapper; break; case BASE32_OPTION: @@ -1244,5 +1276,5 @@ main (int argc, char **argv) if (decode) do_decode (input_fh, infile, stdout, ignore_garbage); else - do_encode (input_fh, infile, stdout, wrap_column); + do_encode (input_fh, infile, stdout, wrap_column, ignore_padding); } diff --git a/tests/local.mk b/tests/local.mk index 0496c2873..a7703998a 100644 --- a/tests/local.mk +++ b/tests/local.mk @@ -728,6 +728,7 @@ all_tests = \ tests/touch/read-only.sh \ tests/touch/relative.sh \ tests/touch/trailing-slash.sh \ + tests/base64url/padding.sh \ $(all_root_tests) # See tests/factor/create-test.sh. -- 2.30.2