]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3819. [bug] NSEC3 hashes need to be able to be entered and
authorMark Andrews <marka@isc.org>
Thu, 24 Apr 2014 08:58:03 +0000 (18:58 +1000)
committerMark Andrews <marka@isc.org>
Thu, 24 Apr 2014 09:12:00 +0000 (19:12 +1000)
                        displayed without padding.  This is not a issue for
                        currently defined algorithms but may be for future
                        hash algorithms. [RT #27925]

(cherry picked from commit 36e5ac00333d89001f0c518a7d381d16c38d0402)

13 files changed:
CHANGES
bin/tests/system/checkzone/zones/bad-nsec3-padded.db [new file with mode: 0644]
bin/tests/system/checkzone/zones/bad-nsec3owner-padded.db [new file with mode: 0644]
bin/tests/system/checkzone/zones/good-nsec3-nopadhash.db [new file with mode: 0644]
bin/tools/nsec3hash.c
lib/dns/master.c
lib/dns/message.c
lib/dns/nsec3.c
lib/dns/rdata/generic/nsec3_50.c
lib/dns/validator.c
lib/dns/zone.c
lib/isc/base32.c
lib/isc/include/isc/base32.h

diff --git a/CHANGES b/CHANGES
index 847fc7d234d931283ec5051ea0f742e770940f35..46daf5743285a6af44398d133e6f9297df11db24 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+3819.  [bug]           NSEC3 hashes need to be able to be entered and
+                       displayed without padding.  This is not a issue for
+                       currently defined algorithms but may be for future
+                       hash algorithms. [RT #27925]
+                       
 3818.  [bug]           Stop lying to the optimizer that 'void *arg' is a
                        constant in isc_event_allocate.
 
diff --git a/bin/tests/system/checkzone/zones/bad-nsec3-padded.db b/bin/tests/system/checkzone/zones/bad-nsec3-padded.db
new file mode 100644 (file)
index 0000000..adf26cd
--- /dev/null
@@ -0,0 +1,24 @@
+; Copyright (C) 2014  Internet Systems Consortium, Inc. ("ISC")
+;
+; Permission to use, copy, modify, and/or distribute this software for any
+; purpose with or without fee is hereby granted, provided that the above
+; copyright notice and this permission notice appear in all copies.
+;
+; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+; AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+; PERFORMANCE OF THIS SOFTWARE.
+
+$TTL 600
+@              SOA     ns hostmaster 2011012708 3600 1200 604800 1200
+               NS      ns
+ns             A       192.0.2.1
+
+; The following NSEC3 RR is invalid as the Next Hashed Owner Name field
+; is padded. See RFC 5155.
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom NSEC3 1 1 12 aabbccdd (
+                       CPNMU=== MX DNSKEY NS
+                       SOA NSEC3PARAM RRSIG )
diff --git a/bin/tests/system/checkzone/zones/bad-nsec3owner-padded.db b/bin/tests/system/checkzone/zones/bad-nsec3owner-padded.db
new file mode 100644 (file)
index 0000000..0a0cf30
--- /dev/null
@@ -0,0 +1,22 @@
+; Copyright (C) 2014  Internet Systems Consortium, Inc. ("ISC")
+;
+; Permission to use, copy, modify, and/or distribute this software for any
+; purpose with or without fee is hereby granted, provided that the above
+; copyright notice and this permission notice appear in all copies.
+;
+; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+; AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+; PERFORMANCE OF THIS SOFTWARE.
+
+$TTL 600
+@              SOA     ns hostmaster 2011012708 3600 1200 604800 1200
+               NS      ns
+ns             A       192.0.2.1
+
+; The following NSEC3 RR owner is invalid as the owner name is padded.
+CPNMU===       NSEC3 2 1 12 aabbccdd ( CPNMU MX DNSKEY NS
+                       SOA NSEC3PARAM RRSIG )
diff --git a/bin/tests/system/checkzone/zones/good-nsec3-nopadhash.db b/bin/tests/system/checkzone/zones/good-nsec3-nopadhash.db
new file mode 100644 (file)
index 0000000..1215514
--- /dev/null
@@ -0,0 +1,22 @@
+; Copyright (C) 2014  Internet Systems Consortium, Inc. ("ISC")
+;
+; Permission to use, copy, modify, and/or distribute this software for any
+; purpose with or without fee is hereby granted, provided that the above
+; copyright notice and this permission notice appear in all copies.
+;
+; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+; AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+; PERFORMANCE OF THIS SOFTWARE.
+
+$TTL 600
+@              SOA     ns hostmaster 2011012708 3600 1200 604800 1200
+               NS      ns
+ns             A       192.0.2.1
+
+; a hash that isn't a multiple of 8 characters
+CPNMU          NSEC3 2 1 12 aabbccdd ( CPNMU MX DNSKEY NS
+                       SOA NSEC3PARAM RRSIG )
index 486037ff165308ebf001bc00eeb5c71f8b6e63c5..1a2a9558bf3f80780569484642ef8a9b3a645cf2 100644 (file)
@@ -116,7 +116,7 @@ main(int argc, char **argv) {
        region.base = hash;
        region.length = length;
        isc_buffer_init(&buffer, text, sizeof(text));
-       isc_base32hex_totext(&region, 1, "", &buffer);
+       isc_base32hexnp_totext(&region, 1, "", &buffer);
        fprintf(stdout, "%.*s (salt=%s, hash=%u, iterations=%u)\n",
                (int)isc_buffer_usedlength(&buffer), text, argv[1], hash_alg, iterations);
        return(0);
index 4b75843dea6ba9a01b0ca7fcb4524e8b2e5bc6a8..e6b1a0a80322dec694852c71e06dc82889ba9ff6 100644 (file)
@@ -91,6 +91,8 @@
 #define DNS_MASTER_LHS 2048
 #define DNS_MASTER_RHS MINTSIZ
 
+#define CHECKNAMESFAIL(x) (((x) & DNS_MASTER_CHECKNAMESFAIL) != 0)
+
 typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
 
 typedef struct dns_incctx dns_incctx_t;
@@ -1768,7 +1770,8 @@ load_text(dns_loadctx_t *lctx) {
                                dns_name_format(name, namebuf, sizeof(namebuf));
                                result = DNS_R_BADOWNERNAME;
                                desc = dns_result_totext(result);
-                               if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0) {
+                               if (CHECKNAMESFAIL(lctx->options) ||
+                                   type == dns_rdatatype_nsec3) {
                                        (*callbacks->error)(callbacks,
                                                            "%s:%lu: %s: %s",
                                                            source, line,
index 5137cb11d9b7aeaaad78d9e0c97cb5e46cfebe43..a062e951ba3e92e2db4f2771fc5f7e0588836d82 100644 (file)
@@ -1381,6 +1381,16 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
                } else
                        covers = 0;
 
+               /*
+                * Check the ownername of NSEC3 records
+                */
+               if (rdtype == dns_rdatatype_nsec3 &&
+                   !dns_rdata_checkowner(name, msg->rdclass, rdtype,
+                                         ISC_FALSE)) {
+                       result = DNS_R_BADOWNERNAME;
+                       goto cleanup;
+               }
+
                /*
                 * If we are doing a dynamic update or this is a meta-type,
                 * don't bother searching for a name, just append this one
index 00ccf0e7eb0243068d73a630e936b1eebde4460e..e66cc5a56fad7a4473f3227c4afe0be5e1cc037c 100644 (file)
@@ -253,11 +253,11 @@ dns_nsec3_hashname(dns_fixedname_t *result,
        if (hash_length != NULL)
                *hash_length = len;
 
-       /* convert the hash to base32hex */
+       /* convert the hash to base32hex non-padded */
        region.base = rethash;
        region.length = (unsigned int)len;
        isc_buffer_init(&namebuffer, nametext, sizeof nametext);
-       isc_base32hex_totext(&region, 1, "", &namebuffer);
+       isc_base32hexnp_totext(&region, 1, "", &namebuffer);
 
        /* convert the hex to a domain name */
        dns_fixedname_init(result);
@@ -269,7 +269,8 @@ unsigned int
 dns_nsec3_hashlength(dns_hash_t hash) {
 
        switch (hash) {
-       case dns_hash_sha1: return(ISC_SHA1_DIGESTLENGTH);
+       case dns_hash_sha1:
+               return(ISC_SHA1_DIGESTLENGTH);
        }
        return (0);
 }
@@ -277,7 +278,8 @@ dns_nsec3_hashlength(dns_hash_t hash) {
 isc_boolean_t
 dns_nsec3_supportedhash(dns_hash_t hash) {
        switch (hash) {
-       case dns_hash_sha1: return (ISC_TRUE);
+       case dns_hash_sha1:
+               return (ISC_TRUE);
        }
        return (ISC_FALSE);
 }
index 19b94efa06dcae2a515b998b0e55cfe38d102521..0b876896f73d1b3e1f01bcdfe222c0a52adf5f8b 100644 (file)
@@ -100,7 +100,7 @@ fromtext_nsec3(ARGS_FROMTEXT) {
        RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
                                      ISC_FALSE));
        isc_buffer_init(&b, bm, sizeof(bm));
-       RETTOK(isc_base32hex_decodestring(DNS_AS_STR(token), &b));
+       RETTOK(isc_base32hexnp_decodestring(DNS_AS_STR(token), &b));
        if (isc_buffer_usedlength(&b) > 0xffU)
                RETTOK(ISC_R_RANGE);
        RETERR(uint8_tobuffer(isc_buffer_usedlength(&b), target));
@@ -191,7 +191,7 @@ totext_nsec3(ARGS_TOTEXT) {
 
        i = sr.length;
        sr.length = j;
-       RETERR(isc_base32hex_totext(&sr, 1, "", target));
+       RETERR(isc_base32hexnp_totext(&sr, 1, "", target));
        sr.length = i - j;
 
        if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) == 0)
@@ -474,15 +474,26 @@ digest_nsec3(ARGS_DIGEST) {
 
 static inline isc_boolean_t
 checkowner_nsec3(ARGS_CHECKOWNER) {
+       unsigned char owner[NSEC3_MAX_HASH_LENGTH];
+       isc_buffer_t buffer;
+       dns_label_t label;
 
-       REQUIRE(type == 50);
+       REQUIRE(type == 50);
+
+       UNUSED(type);
+       UNUSED(rdclass);
+       UNUSED(wildcard);
 
-       UNUSED(name);
-       UNUSED(type);
-       UNUSED(rdclass);
-       UNUSED(wildcard);
+       /*
+        * First label is a base32hex string without padding.
+        */
+       dns_name_getlabel(name, 0, &label);
+       isc_region_consume(&label, 1);
+       isc_buffer_init(&buffer, owner, sizeof(owner));
+       if (isc_base32hexnp_decoderegion(&label, &buffer) == ISC_R_SUCCESS)
+               return (ISC_TRUE);
 
-       return (ISC_TRUE);
+       return (ISC_FALSE);
 }
 
 static inline isc_boolean_t
index 9985e62ca6ddd9aa05f0fc87c4565425ed1e5ec2..6e09762f60ef9d9754dfd838efc8fe46fb55eb80 100644 (file)
@@ -336,7 +336,7 @@ isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
                dns_name_getlabel(&nsec3name, 0, &hashlabel);
                isc_region_consume(&hashlabel, 1);
                isc_buffer_init(&buffer, owner, sizeof(owner));
-               result = isc_base32hex_decoderegion(&hashlabel, &buffer);
+               result = isc_base32hexnp_decoderegion(&hashlabel, &buffer);
                if (result != ISC_R_SUCCESS) {
                        dns_rdataset_disassociate(&set);
                        continue;
index c90488ed8a29ab9057eea80d29d6d7a46693c0a2..279a3304040670e65984888f15cd0b675c6bc93e 100644 (file)
@@ -16242,10 +16242,12 @@ dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
 
        REQUIRE(DNS_ZONE_VALID(zone));
 
-       if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
+       if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
+           rdata->type != dns_rdatatype_nsec3)
                return (ISC_R_SUCCESS);
 
-       if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
+       if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
+           rdata->type == dns_rdatatype_nsec3) {
                level = ISC_LOG_ERROR;
                fail = ISC_TRUE;
        }
index ad0b0da569e1fc0aa5f599cd644f4a75da173136..2ee99b182426b9a4a8d87305e0e553bd75ea6da9 100644 (file)
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: base32.c,v 1.6 2009/10/21 01:22:29 each Exp $ */
+/* $Id: base32.c,v 1.6.698.1 2012/02/15 05:00:16 marka Exp $ */
 
 /*! \file */
 
@@ -54,7 +54,7 @@ static const char base32hex[] =
 
 static isc_result_t
 base32_totext(isc_region_t *source, int wordlength, const char *wordbreak,
-             isc_buffer_t *target, const char base[])
+             isc_buffer_t *target, const char base[], char pad)
 {
        char buf[9];
        unsigned int loops = 0;
@@ -67,8 +67,8 @@ base32_totext(isc_region_t *source, int wordlength, const char *wordbreak,
                buf[0] = base[((source->base[0]>>3)&0x1f)];     /* 5 + */
                if (source->length == 1) {
                        buf[1] = base[(source->base[0]<<2)&0x1c];
-                       buf[2] = buf[3] = buf[4] = '=';
-                       buf[5] = buf[6] = buf[7] = '=';
+                       buf[2] = buf[3] = buf[4] = pad;
+                       buf[5] = buf[6] = buf[7] = pad;
                        RETERR(str_totext(buf, target));
                        break;
                }
@@ -77,7 +77,7 @@ base32_totext(isc_region_t *source, int wordlength, const char *wordbreak,
                buf[2] = base[((source->base[1]>>1)&0x1f)];     /* 5 + */
                if (source->length == 2) {
                        buf[3] = base[(source->base[1]<<4)&0x10];
-                       buf[4] = buf[5] = buf[6] = buf[7] = '=';
+                       buf[4] = buf[5] = buf[6] = buf[7] = pad;
                        RETERR(str_totext(buf, target));
                        break;
                }
@@ -85,7 +85,7 @@ base32_totext(isc_region_t *source, int wordlength, const char *wordbreak,
                              ((source->base[2]>>4)&0x0f)];     /* 4 + */
                if (source->length == 3) {
                        buf[4] = base[(source->base[2]<<1)&0x1e];
-                       buf[5] = buf[6] = buf[7] = '=';
+                       buf[5] = buf[6] = buf[7] = pad;
                        RETERR(str_totext(buf, target));
                        break;
                }
@@ -94,7 +94,7 @@ base32_totext(isc_region_t *source, int wordlength, const char *wordbreak,
                buf[5] = base[((source->base[3]>>2)&0x1f)];     /* 5 + */
                if (source->length == 4) {
                        buf[6] = base[(source->base[3]<<3)&0x18];
-                       buf[7] = '=';
+                       buf[7] = pad;
                        RETERR(str_totext(buf, target));
                        break;
                }
@@ -121,7 +121,8 @@ isc_result_t
 isc_base32_totext(isc_region_t *source, int wordlength,
                  const char *wordbreak, isc_buffer_t *target)
 {
-       return (base32_totext(source, wordlength, wordbreak, target, base32));
+       return (base32_totext(source, wordlength, wordbreak, target,
+                             base32, '='));
 }
 
 isc_result_t
@@ -129,7 +130,15 @@ isc_base32hex_totext(isc_region_t *source, int wordlength,
                     const char *wordbreak, isc_buffer_t *target)
 {
        return (base32_totext(source, wordlength, wordbreak, target,
-                             base32hex));
+                             base32hex, '='));
+}
+
+isc_result_t
+isc_base32hexnp_totext(isc_region_t *source, int wordlength,
+                    const char *wordbreak, isc_buffer_t *target)
+{
+       return (base32_totext(source, wordlength, wordbreak, target,
+                             base32hex, 0));
 }
 
 /*%
@@ -143,11 +152,12 @@ typedef struct {
        int val[8];
        const char *base;       /*%< Which encoding we are using */
        int seen_32;            /*%< Number of significant bytes if non zero */
+       isc_boolean_t pad;      /*%< Expect padding */
 } base32_decode_ctx_t;
 
 static inline void
-base32_decode_init(base32_decode_ctx_t *ctx, int length,
-                  const char base[], isc_buffer_t *target)
+base32_decode_init(base32_decode_ctx_t *ctx, int length, const char base[],
+                  isc_boolean_t pad, isc_buffer_t *target)
 {
        ctx->digits = 0;
        ctx->seen_end = ISC_FALSE;
@@ -155,6 +165,7 @@ base32_decode_init(base32_decode_ctx_t *ctx, int length,
        ctx->length = length;
        ctx->target = target;
        ctx->base = base;
+       ctx->pad = pad;
 }
 
 static inline isc_result_t
@@ -167,16 +178,25 @@ base32_decode_char(base32_decode_ctx_t *ctx, int c) {
        if ((s = strchr(ctx->base, c)) == NULL)
                return (ISC_R_BADBASE32);
        last = (unsigned int)(s - ctx->base);
+
        /*
         * Handle lower case.
         */
        if (last > 32)
                last -= 33;
+
        /*
         * Check that padding is contiguous.
         */
        if (last != 32 && ctx->seen_32 != 0)
                return (ISC_R_BADBASE32);
+
+       /*
+        * If padding is not permitted flag padding as a error.
+        */
+       if (last == 32 && !ctx->pad)
+               return (ISC_R_BADBASE32);
+
        /*
         * Check that padding starts at the right place and that
         * bits that should be zero are.
@@ -212,6 +232,7 @@ base32_decode_char(base32_decode_ctx_t *ctx, int c) {
                        ctx->seen_32 = 4;
                        break;
                }
+
        /*
         * Zero fill pad values.
         */
@@ -244,23 +265,33 @@ base32_decode_char(base32_decode_ctx_t *ctx, int c) {
 
 static inline isc_result_t
 base32_decode_finish(base32_decode_ctx_t *ctx) {
+
        if (ctx->length > 0)
                return (ISC_R_UNEXPECTEDEND);
+       /*
+        * Add missing padding if required.
+        */
+       if (!ctx->pad && ctx->digits != 0) {
+               ctx->pad = ISC_TRUE;
+               do {
+                       RETERR(base32_decode_char(ctx, '='));
+               } while (ctx->digits != 0);
+       }
        if (ctx->digits != 0)
                return (ISC_R_BADBASE32);
        return (ISC_R_SUCCESS);
 }
 
 static isc_result_t
-base32_tobuffer(isc_lex_t *lexer, const char base[], isc_buffer_t *target,
-               int length)
+base32_tobuffer(isc_lex_t *lexer, const char base[], isc_boolean_t pad,
+               isc_buffer_t *target, int length)
 {
        base32_decode_ctx_t ctx;
        isc_textregion_t *tr;
        isc_token_t token;
        isc_boolean_t eol;
 
-       base32_decode_init(&ctx, length, base, target);
+       base32_decode_init(&ctx, length, base, pad, target);
 
        while (!ctx.seen_end && (ctx.length != 0)) {
                unsigned int i;
@@ -285,19 +316,26 @@ base32_tobuffer(isc_lex_t *lexer, const char base[], isc_buffer_t *target,
 
 isc_result_t
 isc_base32_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
-       return (base32_tobuffer(lexer, base32, target, length));
+       return (base32_tobuffer(lexer, base32, ISC_TRUE, target, length));
 }
 
 isc_result_t
 isc_base32hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
-       return (base32_tobuffer(lexer, base32hex, target, length));
+       return (base32_tobuffer(lexer, base32hex, ISC_TRUE, target, length));
+}
+
+isc_result_t
+isc_base32hexnp_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
+       return (base32_tobuffer(lexer, base32hex, ISC_FALSE, target, length));
 }
 
 static isc_result_t
-base32_decodestring(const char *cstr, const char base[], isc_buffer_t *target) {
+base32_decodestring(const char *cstr, const char base[], isc_boolean_t pad,
+                   isc_buffer_t *target)
+{
        base32_decode_ctx_t ctx;
 
-       base32_decode_init(&ctx, -1, base, target);
+       base32_decode_init(&ctx, -1, base, pad, target);
        for (;;) {
                int c = *cstr++;
                if (c == '\0')
@@ -312,19 +350,26 @@ base32_decodestring(const char *cstr, const char base[], isc_buffer_t *target) {
 
 isc_result_t
 isc_base32_decodestring(const char *cstr, isc_buffer_t *target) {
-       return (base32_decodestring(cstr, base32, target));
+       return (base32_decodestring(cstr, base32, ISC_TRUE, target));
 }
 
 isc_result_t
 isc_base32hex_decodestring(const char *cstr, isc_buffer_t *target) {
-       return (base32_decodestring(cstr, base32hex, target));
+       return (base32_decodestring(cstr, base32hex, ISC_TRUE, target));
+}
+
+isc_result_t
+isc_base32hexnp_decodestring(const char *cstr, isc_buffer_t *target) {
+       return (base32_decodestring(cstr, base32hex, ISC_FALSE, target));
 }
 
 static isc_result_t
-base32_decoderegion(isc_region_t *source, const char base[], isc_buffer_t *target) {
+base32_decoderegion(isc_region_t *source, const char base[],
+                   isc_boolean_t pad, isc_buffer_t *target)
+{
        base32_decode_ctx_t ctx;
 
-       base32_decode_init(&ctx, -1, base, target);
+       base32_decode_init(&ctx, -1, base, pad, target);
        while (source->length != 0) {
                int c = *source->base;
                RETERR(base32_decode_char(&ctx, c));
@@ -336,12 +381,17 @@ base32_decoderegion(isc_region_t *source, const char base[], isc_buffer_t *targe
 
 isc_result_t
 isc_base32_decoderegion(isc_region_t *source, isc_buffer_t *target) {
-       return (base32_decoderegion(source, base32, target));
+       return (base32_decoderegion(source, base32, ISC_TRUE, target));
 }
 
 isc_result_t
 isc_base32hex_decoderegion(isc_region_t *source, isc_buffer_t *target) {
-       return (base32_decoderegion(source, base32hex, target));
+       return (base32_decoderegion(source, base32hex, ISC_TRUE, target));
+}
+
+isc_result_t
+isc_base32hexnp_decoderegion(isc_region_t *source, isc_buffer_t *target) {
+       return (base32_decoderegion(source, base32hex, ISC_FALSE, target));
 }
 
 static isc_result_t
index 978a8db463ae2737308f77d50afdbd3fc7a3c690..4144d25ebfd3545fbf41c2c2aeb2bd4b5c95097e 100644 (file)
@@ -14,8 +14,6 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: base32.h,v 1.3 2008/09/25 04:02:39 tbox Exp $ */
-
 #ifndef ISC_BASE32_H
 #define ISC_BASE32_H 1
 
@@ -27,6 +25,8 @@
  *
  * Base 32 hex preserves the sort order of data when it is encoded /
  * decoded.
+ *
+ * Base 32 hex "np" is base 32 hex but no padding is produced or accepted.
  */
 
 #include <isc/lang.h>
@@ -44,6 +44,9 @@ isc_base32_totext(isc_region_t *source, int wordlength,
 isc_result_t
 isc_base32hex_totext(isc_region_t *source, int wordlength,
                     const char *wordbreak, isc_buffer_t *target);
+isc_result_t
+isc_base32hexnp_totext(isc_region_t *source, int wordlength,
+                      const char *wordbreak, isc_buffer_t *target);
 /*!<
  * \brief Convert data into base32 encoded text.
  *
@@ -69,8 +72,11 @@ isc_result_t
 isc_base32_decodestring(const char *cstr, isc_buffer_t *target);
 isc_result_t
 isc_base32hex_decodestring(const char *cstr, isc_buffer_t *target);
+isc_result_t
+isc_base32hexnp_decodestring(const char *cstr, isc_buffer_t *target);
 /*!<
- * \brief Decode a null-terminated base32 string.
+ * \brief Decode a null-terminated string in base32, base32hex, or
+ * base32hex non-padded.
  *
  * Requires:
  *\li  'cstr' is non-null.
@@ -91,8 +97,11 @@ isc_result_t
 isc_base32_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
 isc_result_t
 isc_base32hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
+isc_result_t
+isc_base32hexnp_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
 /*!<
- * \brief Convert base32 encoded text from a lexer context into data.
+ * \brief Convert text encoded in base32, base32hex, or base32hex
+ * non-padded from a lexer context into data.
  *
  * Requires:
  *\li  'lex' is a valid lexer context
@@ -110,8 +119,11 @@ isc_result_t
 isc_base32_decoderegion(isc_region_t *source, isc_buffer_t *target);
 isc_result_t
 isc_base32hex_decoderegion(isc_region_t *source, isc_buffer_t *target);
+isc_result_t
+isc_base32hexnp_decoderegion(isc_region_t *source, isc_buffer_t *target);
 /*!<
- * \brief Decode a packed (no white space permitted) base32 region.
+ * \brief Decode a packed (no white space permitted) region in
+ * base32, base32hex or base32hex non-padded.
  *
  * Requires:
  *\li   'source' is a valid region.