/*
- * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
/*%
* Principal Author: Brian Wellington
- * $Id: dst_parse.c,v 1.14.120.2 2009/03/02 23:47:11 tbox Exp $
+ * $Id: dst_parse.c,v 1.23.36.3 2010/01/13 19:31:52 each Exp $
*/
#include <config.h>
#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"
#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;
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 *
}
}
+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;
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)
{
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);
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);
/*
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)
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);
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);
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);
&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:
case DST_ALG_RSASHA1:
fprintf(fp, "(RSASHA1)\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_HMACMD5:
fprintf(fp, "(HMAC_MD5)\n");
break;
}
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);
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);
}
isc_buffer_usedregion(&b, &r);
fprintf(fp, "%s ", s);
- fwrite(r.base, 1, r.length, fp);
+ isc_util_fwrite(r.base, 1, r.length, fp);
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 */