mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 14:35:26 +00:00
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]
This commit is contained in:
164
lib/isc/base64.c
164
lib/isc/base64.c
@@ -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;
|
||||
base64_decode_ctx_t ctx;
|
||||
|
||||
REQUIRE(mctx != NULL);
|
||||
REQUIRE(cstr != NULL);
|
||||
REQUIRE(ISC_BUFFER_VALID(target));
|
||||
UNUSED(mctx);
|
||||
|
||||
isc_buffer_init(&source, cstr, strlen(cstr));
|
||||
isc_buffer_add(&source, strlen(cstr));
|
||||
|
||||
result = isc_lex_create(mctx, 256, &lex);
|
||||
|
||||
if (result == ISC_R_SUCCESS)
|
||||
result = isc_lex_openbuffer(lex, &source);
|
||||
|
||||
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;
|
||||
|
Reference in New Issue
Block a user