diff options
Diffstat (limited to 'contrib/bind9/lib/dns/dst_parse.c')
-rw-r--r-- | contrib/bind9/lib/dns/dst_parse.c | 193 |
1 files changed, 164 insertions, 29 deletions
diff --git a/contrib/bind9/lib/dns/dst_parse.c b/contrib/bind9/lib/dns/dst_parse.c index 37264be35188..4d7d784f6370 100644 --- a/contrib/bind9/lib/dns/dst_parse.c +++ b/contrib/bind9/lib/dns/dst_parse.c @@ -31,7 +31,7 @@ /*% * Principal Author: Brian Wellington - * $Id: dst_parse.c,v 1.14.120.6 2010-01-15 19:38:53 each Exp $ + * $Id: dst_parse.c,v 1.27 2010-12-23 04:07:58 marka Exp $ */ #include <config.h> @@ -41,9 +41,12 @@ #include <isc/fsaccess.h> #include <isc/lex.h> #include <isc/mem.h> +#include <isc/stdtime.h> #include <isc/string.h> #include <isc/util.h> +#include <dns/time.h> + #include "dst_internal.h" #include "dst_parse.h" #include "dst/result.h" @@ -53,6 +56,25 @@ #define PRIVATE_KEY_STR "Private-key-format:" #define ALGORITHM_STR "Algorithm:" +#define TIMING_NTAGS (DST_MAX_TIMES + 1) +static const char *timetags[TIMING_NTAGS] = { + "Created:", + "Publish:", + "Activate:", + "Revoke:", + "Inactive:", + "Delete:", + "DSPublish:" +}; + +#define NUMERIC_NTAGS (DST_MAX_NUMERIC + 1) +static const char *numerictags[NUMERIC_NTAGS] = { + "Predecessor:", + "Successor:", + "MaxTTL:", + "RollPeriod:" +}; + struct parse_map { const int value; const char *tag; @@ -82,6 +104,8 @@ static struct parse_map map[] = { {TAG_DSA_PRIVATE, "Private_value(x):"}, {TAG_DSA_PUBLIC, "Public_value(y):"}, + {TAG_GOST_PRIVASN1, "GostAsn1:"}, + {TAG_HMACMD5_KEY, "Key:"}, {TAG_HMACMD5_BITS, "Bits:"}, @@ -107,13 +131,12 @@ static int find_value(const char *s, const unsigned int alg) { int i; - for (i = 0; ; i++) { - if (map[i].tag == NULL) - return (-1); - else if (strcasecmp(s, map[i].tag) == 0 && - TAG_ALG(map[i].value) == alg) + for (i = 0; map[i].tag != NULL; i++) { + if (strcasecmp(s, map[i].tag) == 0 && + (TAG_ALG(map[i].value) == alg)) return (map[i].value); } + return (-1); } static const char * @@ -129,6 +152,28 @@ find_tag(const int value) { } static int +find_metadata(const char *s, const char *tags[], int ntags) { + int i; + + for (i = 0; i < ntags; i++) { + if (strcasecmp(s, tags[i]) == 0) + return (i); + } + + return (-1); +} + +static int +find_timedata(const char *s) { + return (find_metadata(s, timetags, TIMING_NTAGS)); +} + +static int +find_numericdata(const char *s) { + return (find_metadata(s, numerictags, NUMERIC_NTAGS)); +} + +static int check_rsa(const dst_private_t *priv) { int i, j; isc_boolean_t have[RSA_NTAGS]; @@ -197,6 +242,15 @@ check_dsa(const dst_private_t *priv) { } static int +check_gost(const dst_private_t *priv) { + if (priv->nelements != GOST_NTAGS) + return (-1); + if (priv->elements[0].tag != TAG(DST_ALG_ECCGOST, 0)) + return (-1); + return (0); +} + +static int check_hmac_md5(const dst_private_t *priv, isc_boolean_t old) { int i, j; @@ -253,6 +307,8 @@ check_data(const dst_private_t *priv, const unsigned int alg, return (check_dh(priv)); case DST_ALG_DSA: return (check_dsa(priv)); + case DST_ALG_ECCGOST: + return (check_gost(priv)); case DST_ALG_HMACMD5: return (check_hmac_md5(priv, old)); case DST_ALG_HMACSHA1: @@ -285,7 +341,7 @@ dst__privstruct_free(dst_private_t *priv, isc_mem_t *mctx) { priv->nelements = 0; } -int +isc_result_t dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, isc_mem_t *mctx, dst_private_t *priv) { @@ -294,6 +350,7 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, isc_token_t token; unsigned char *data = NULL; unsigned int opt = ISC_LEXOPT_EOL; + isc_stdtime_t when; isc_result_t ret; REQUIRE(priv != NULL); @@ -341,13 +398,16 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, goto fail; } - if (major > MAJOR_VERSION || - (major == MAJOR_VERSION && minor > MINOR_VERSION)) - { + if (major > DST_MAJOR_VERSION) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } + /* + * Store the private key format version number + */ + dst_key_setprivateformat(key, major, minor); + READLINE(lex, opt, &token); /* @@ -377,7 +437,6 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, for (n = 0; n < MAXFIELDS; n++) { int tag; isc_region_t r; - do { ret = isc_lex_gettoken(lex, opt, &token); if (ret == ISC_R_EOF) @@ -391,11 +450,50 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, goto fail; } + /* Numeric metadata */ + tag = find_numericdata(DST_AS_STR(token)); + if (tag >= 0) { + INSIST(tag < NUMERIC_NTAGS); + + NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token); + if (token.type != isc_tokentype_number) { + ret = DST_R_INVALIDPRIVATEKEY; + goto fail; + } + + dst_key_setnum(key, tag, token.value.as_ulong); + goto next; + } + + /* Timing metadata */ + tag = find_timedata(DST_AS_STR(token)); + if (tag >= 0) { + INSIST(tag < TIMING_NTAGS); + + NEXTTOKEN(lex, opt, &token); + if (token.type != isc_tokentype_string) { + ret = DST_R_INVALIDPRIVATEKEY; + goto fail; + } + + ret = dns_time32_fromtext(DST_AS_STR(token), &when); + if (ret != ISC_R_SUCCESS) + goto fail; + + dst_key_settime(key, tag, when); + + goto next; + } + + /* Key data */ tag = find_value(DST_AS_STR(token), alg); - if (tag < 0 || TAG_ALG(tag) != alg) { + if (tag < 0 && minor > DST_MINOR_VERSION) + goto next; + else if (tag < 0) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } + priv->elements[n].tag = tag; data = (unsigned char *) isc_mem_get(mctx, MAXFIELDSIZE); @@ -406,23 +504,23 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, ret = isc_base64_tobuffer(lex, &b, -1); if (ret != ISC_R_SUCCESS) goto fail; + isc_buffer_usedregion(&b, &r); priv->elements[n].length = r.length; priv->elements[n].data = r.base; + priv->nelements++; + next: READLINE(lex, opt, &token); data = NULL; } done: - priv->nelements = n; - if (check_data(priv, alg, ISC_TRUE) < 0) goto fail; return (ISC_R_SUCCESS); fail: - priv->nelements = n; dst__privstruct_free(priv, mctx); if (data != NULL) isc_mem_put(mctx, data, MAXFIELDSIZE); @@ -430,17 +528,21 @@ fail: return (ret); } -int +isc_result_t dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, const char *directory) { FILE *fp; int ret, i; - isc_result_t iret; + isc_result_t result; char filename[ISC_DIR_NAMEMAX]; char buffer[MAXFIELDSIZE * 2]; - isc_buffer_t b; isc_fsaccess_t access; + isc_stdtime_t when; + isc_uint32_t value; + isc_buffer_t b; + isc_region_t r; + int major, minor; REQUIRE(priv != NULL); @@ -461,11 +563,17 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, &access); (void)isc_fsaccess_set(filename, access); + dst_key_getprivateformat(key, &major, &minor); + if (major == 0 && minor == 0) { + major = DST_MAJOR_VERSION; + minor = DST_MINOR_VERSION; + } + /* XXXDCL return value should be checked for full filesystem */ - fprintf(fp, "%s v%d.%d\n", PRIVATE_KEY_STR, MAJOR_VERSION, - MINOR_VERSION); + fprintf(fp, "%s v%d.%d\n", PRIVATE_KEY_STR, major, minor); fprintf(fp, "%s %d ", ALGORITHM_STR, dst_key_alg(key)); + /* XXXVIX this switch statement is too sparse to gen a jump table. */ switch (dst_key_alg(key)) { case DST_ALG_RSAMD5: @@ -480,18 +588,21 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, case DST_ALG_RSASHA1: fprintf(fp, "(RSASHA1)\n"); break; - case DST_ALG_NSEC3DSA: - fprintf(fp, "(NSEC3DSA)\n"); - break; case DST_ALG_NSEC3RSASHA1: fprintf(fp, "(NSEC3RSASHA1)\n"); break; + case DST_ALG_NSEC3DSA: + fprintf(fp, "(NSEC3DSA)\n"); + break; case DST_ALG_RSASHA256: fprintf(fp, "(RSASHA256)\n"); break; case DST_ALG_RSASHA512: fprintf(fp, "(RSASHA512)\n"); break; + case DST_ALG_ECCGOST: + fprintf(fp, "(ECC-GOST)\n"); + break; case DST_ALG_HMACMD5: fprintf(fp, "(HMAC_MD5)\n"); break; @@ -516,8 +627,6 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, } for (i = 0; i < priv->nelements; i++) { - isc_buffer_t b; - isc_region_t r; const char *s; s = find_tag(priv->elements[i].tag); @@ -525,8 +634,8 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, r.base = priv->elements[i].data; r.length = priv->elements[i].length; isc_buffer_init(&b, buffer, sizeof(buffer)); - iret = isc_base64_totext(&r, sizeof(buffer), "", &b); - if (iret != ISC_R_SUCCESS) { + result = isc_base64_totext(&r, sizeof(buffer), "", &b); + if (result != ISC_R_SUCCESS) { fclose(fp); return (DST_R_INVALIDPRIVATEKEY); } @@ -537,10 +646,36 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, fprintf(fp, "\n"); } + /* Add the metadata tags */ + if (major > 1 || (major == 1 && minor >= 3)) { + for (i = 0; i < NUMERIC_NTAGS; i++) { + result = dst_key_getnum(key, i, &value); + if (result != ISC_R_SUCCESS) + continue; + fprintf(fp, "%s %u\n", numerictags[i], value); + } + for (i = 0; i < TIMING_NTAGS; i++) { + result = dst_key_gettime(key, i, &when); + if (result != ISC_R_SUCCESS) + continue; + + isc_buffer_init(&b, buffer, sizeof(buffer)); + result = dns_time32_totext(when, &b); + if (result != ISC_R_SUCCESS) + continue; + + isc_buffer_usedregion(&b, &r); + + fprintf(fp, "%s ", timetags[i]); + isc_util_fwrite(r.base, 1, r.length, fp); + fprintf(fp, "\n"); + } + } + fflush(fp); - iret = ferror(fp) ? DST_R_WRITEERROR : ISC_R_SUCCESS; + result = ferror(fp) ? DST_R_WRITEERROR : ISC_R_SUCCESS; fclose(fp); - return (iret); + return (result); } /*! \file */ |