summaryrefslogtreecommitdiffstats
path: root/lib/dns/dst_parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dns/dst_parse.c')
-rw-r--r--lib/dns/dst_parse.c193
1 files changed, 164 insertions, 29 deletions
diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c
index 37264be..4d7d784 100644
--- a/lib/dns/dst_parse.c
+++ b/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 */
OpenPOWER on IntegriCloud