Commit 2c9c7c5b authored by Andreas Gustafsson's avatar Andreas Gustafsson
Browse files

433. [func] isc_base64_decodestring() now accepts newlines

                        within the base64 data.  This makes it possible
                        to break up the key data in a trusted-keys
                        statement into multiple lines. [RT #284]
parent 8cf8a042
433. [func] isc_base64_decodestring() now accepts newlines
within the base64 data. This makes it possible
to break up the key data in a "trusted-keys"
statement into multiple lines. [RT #284]
432. [func] Added refresh/retry jitter. This is currently
hard-coded to be no more than 20% of the SOA
provided time or 10 minutes, whichever is less.
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: base64.c,v 1.18 2000/08/01 01:29:14 tale Exp $ */
/* $Id: base64.c,v 1.19 2000/09/08 00:34:21 gson Exp $ */
#include <config.h>
......@@ -94,20 +94,86 @@ isc_base64_totext(isc_region_t *source, int wordlength,
return (ISC_R_SUCCESS);
}
/*
* State of a base64 decoding process in progress.
*/
typedef struct {
int length; /* Desired length of binary data or -1 */
isc_buffer_t *target; /* Buffer for resulting binary data */
int digits; /* Number of buffered base64 digits */
isc_boolean_t seen_end; /* True if "=" end marker seen */
int val[4];
} base64_decode_ctx_t;
static inline void
base64_decode_init(base64_decode_ctx_t *ctx, int length, isc_buffer_t *target)
{
ctx->digits = 0;
ctx->seen_end = ISC_FALSE;
ctx->length = length;
ctx->target = target;
}
static inline isc_result_t
base64_decode_char(base64_decode_ctx_t *ctx, int c) {
char *s;
if (ctx->seen_end)
return (ISC_R_BADBASE64);
if ((s = strchr(base64, c)) == NULL)
return (ISC_R_BADBASE64);
ctx->val[ctx->digits++] = s - base64;
if (ctx->digits == 4) {
int n;
unsigned char buf[3];
if (ctx->val[0] == 64 || ctx->val[1] == 64)
return (ISC_R_BADBASE64);
if (ctx->val[2] == 64 && ctx->val[3] != 64)
return (ISC_R_BADBASE64);
n = (ctx->val[2] == 64) ? 1 :
(ctx->val[3] == 64) ? 2 : 3;
if (n != 3) {
ctx->seen_end = ISC_TRUE;
if (ctx->val[2] == 64)
ctx->val[2] = 0;
if (ctx->val[3] == 64)
ctx->val[3] = 0;
}
buf[0] = (ctx->val[0]<<2)|(ctx->val[1]>>4);
buf[1] = (ctx->val[1]<<4)|(ctx->val[2]>>2);
buf[2] = (ctx->val[2]<<6)|(ctx->val[3]);
RETERR(mem_tobuffer(ctx->target, buf, n));
if (ctx->length >= 0) {
if (n > ctx->length)
return (ISC_R_BADBASE64);
else
ctx->length -= n;
}
ctx->digits = 0;
}
return (ISC_R_SUCCESS);
}
static inline isc_result_t
base64_decode_finish(base64_decode_ctx_t *ctx) {
if (ctx->length > 0)
return (ISC_R_UNEXPECTEDEND);
if (ctx->digits != 0)
return (ISC_R_BADBASE64);
return (ISC_R_SUCCESS);
}
isc_result_t
isc_base64_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
int digits = 0;
base64_decode_ctx_t ctx;
isc_textregion_t *tr;
int val[4];
unsigned char buf[3];
int seen_end = 0;
unsigned int i;
isc_token_t token;
char *s;
int n;
base64_decode_init(&ctx, length, target);
while (!ctx.seen_end && (ctx.length != 0)) {
unsigned int i;
while (!seen_end && (length != 0)) {
if (length > 0)
RETERR(gettoken(lexer, &token, isc_tokentype_string,
ISC_FALSE));
......@@ -117,82 +183,34 @@ isc_base64_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
if (token.type != isc_tokentype_string)
break;
tr = &token.value.as_textregion;
for (i = 0 ;i < tr->length; i++) {
if (seen_end)
return (ISC_R_BADBASE64);
if ((s = strchr(base64, tr->base[i])) == NULL)
return (ISC_R_BADBASE64);
val[digits++] = s - base64;
if (digits == 4) {
if (val[0] == 64 || val[1] == 64)
return (ISC_R_BADBASE64);
if (val[2] == 64 && val[3] != 64)
return (ISC_R_BADBASE64);
n = (val[2] == 64) ? 1 :
(val[3] == 64) ? 2 : 3;
if (n != 3) {
seen_end = 1;
if (val[2] == 64)
val[2] = 0;
if (val[3] == 64)
val[3] = 0;
}
buf[0] = (val[0]<<2)|(val[1]>>4);
buf[1] = (val[1]<<4)|(val[2]>>2);
buf[2] = (val[2]<<6)|(val[3]);
RETERR(mem_tobuffer(target, buf, n));
if (length >= 0) {
if (n > length)
return (ISC_R_BADBASE64);
else
length -= n;
}
digits = 0;
}
}
for (i = 0 ;i < tr->length; i++)
RETERR(base64_decode_char(&ctx, tr->base[i]));
}
if (length < 0 && !seen_end)
if (ctx.length < 0 && !ctx.seen_end)
isc_lex_ungettoken(lexer, &token);
if (length > 0)
return (ISC_R_UNEXPECTEDEND);
if (digits != 0)
return (ISC_R_BADBASE64);
RETERR(base64_decode_finish(&ctx));
return (ISC_R_SUCCESS);
}
isc_result_t
isc_base64_decodestring(isc_mem_t *mctx, char *cstr, isc_buffer_t *target) {
isc_result_t result;
isc_buffer_t source;
isc_lex_t *lex = NULL;
isc_boolean_t isopen = ISC_FALSE;
REQUIRE(mctx != NULL);
REQUIRE(cstr != NULL);
REQUIRE(ISC_BUFFER_VALID(target));
isc_buffer_init(&source, cstr, strlen(cstr));
isc_buffer_add(&source, strlen(cstr));
result = isc_lex_create(mctx, 256, &lex);
base64_decode_ctx_t ctx;
if (result == ISC_R_SUCCESS)
result = isc_lex_openbuffer(lex, &source);
UNUSED(mctx);
if (result == ISC_R_SUCCESS) {
isopen = ISC_TRUE;
result = isc_base64_tobuffer(lex, target, -1);
base64_decode_init(&ctx, -1, target);
for (;;) {
int c = *cstr++;
if (c == '\0')
break;
if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
continue;
RETERR(base64_decode_char(&ctx, c));
}
if (isopen)
(void)isc_lex_close(lex);
if (lex != NULL)
isc_lex_destroy(&lex);
return (result);
RETERR(base64_decode_finish(&ctx));
return (ISC_R_SUCCESS);
}
static isc_result_t
str_totext(const char *source, isc_buffer_t *target) {
unsigned int l;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment