/*% * Write key timing metadata to a file pointer, preceded by 'tag' */ static void printtime(const dst_key_t *key, int type, const char *tag, FILE *stream) { isc_result_t result; #ifdef ISC_PLATFORM_USETHREADS char output[26]; /* Minimum buffer as per ctime_r() specification. */ #else const char *output; #endif isc_stdtime_t when; time_t t; char utc[sizeof("YYYYMMDDHHSSMM")]; isc_buffer_t b; isc_region_t r; result = dst_key_gettime(key, type, &when); if (result == ISC_R_NOTFOUND) return; /* time_t and isc_stdtime_t might be different sizes */ t = when; #ifdef ISC_PLATFORM_USETHREADS #ifdef WIN32 if (ctime_s(output, sizeof(output), &t) != 0) goto error; #else if (ctime_r(&t, output) == NULL) goto error; #endif #else output = ctime(&t); #endif isc_buffer_init(&b, utc, sizeof(utc)); result = dns_time32_totext(when, &b); if (result != ISC_R_SUCCESS) goto error; isc_buffer_usedregion(&b, &r); fprintf(stream, "%s: %.*s (%.*s)\n", tag, (int)r.length, r.base, (int)strlen(output) - 1, output); return; error: fprintf(stream, "%s: (set, unable to display)\n", tag); }
ATF_TC_BODY(half_maxint, tc) { const char *test_text = "20380119031407"; const isc_uint32_t test_time = 0x7fffffff; isc_result_t result; isc_buffer_t target; isc_uint32_t when; char buf[128]; UNUSED(tc); result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); memset(buf, 0, sizeof(buf)); isc_buffer_init(&target, buf, sizeof(buf)); result = dns_time32_totext(test_time, &target); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_STREQ(buf, test_text); result = dns_time32_fromtext(test_text, &when); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_EQ(when, test_time); dns_test_end(); }
ATF_TC_BODY(epoch_minus_one, tc) { const char *test_text = "19691231235959"; const isc_uint32_t test_time = 0xffffffff; isc_result_t result; isc_buffer_t target; isc_uint32_t when; char buf[128]; UNUSED(tc); result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); memset(buf, 0, sizeof(buf)); isc_buffer_init(&target, buf, sizeof(buf)); result = dns_time32_totext(test_time, &target); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_STREQ(buf, test_text); result = dns_time32_fromtext(test_text, &when); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_EQ(when, test_time); dns_test_end(); }
ATF_TC_BODY(fifty_before, tc) { isc_result_t result; const char *test_text = "19610307130000"; const isc_uint32_t test_time = 0xef68f5d0; isc_buffer_t target; isc_uint32_t when; char buf[128]; UNUSED(tc); result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); memset(buf, 0, sizeof(buf)); isc_buffer_init(&target, buf, sizeof(buf)); result = dns_time32_totext(test_time, &target); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_STREQ(buf, test_text); result = dns_time32_fromtext(test_text, &when); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_EQ(when, test_time); dns_test_end(); }
static inline isc_result_t totext_keydata(ARGS_TOTEXT) { isc_region_t sr; char buf[sizeof("64000")]; unsigned int flags; unsigned char algorithm; unsigned long when; REQUIRE(rdata->type == 65533); REQUIRE(rdata->length != 0); dns_rdata_toregion(rdata, &sr); /* refresh timer */ when = uint32_fromregion(&sr); isc_region_consume(&sr, 4); RETERR(dns_time32_totext(when, target)); RETERR(str_totext(" ", target)); /* add hold-down */ when = uint32_fromregion(&sr); isc_region_consume(&sr, 4); RETERR(dns_time32_totext(when, target)); RETERR(str_totext(" ", target)); /* remove hold-down */ when = uint32_fromregion(&sr); isc_region_consume(&sr, 4); RETERR(dns_time32_totext(when, target)); RETERR(str_totext(" ", target)); /* flags */ flags = uint16_fromregion(&sr); isc_region_consume(&sr, 2); sprintf(buf, "%u", flags); RETERR(str_totext(buf, target)); RETERR(str_totext(" ", target)); /* protocol */ sprintf(buf, "%u", sr.base[0]); isc_region_consume(&sr, 1); RETERR(str_totext(buf, target)); RETERR(str_totext(" ", target)); /* algorithm */ algorithm = sr.base[0]; sprintf(buf, "%u", algorithm); isc_region_consume(&sr, 1); RETERR(str_totext(buf, target)); /* No Key? */ if ((flags & 0xc000) == 0xc000) return (ISC_R_SUCCESS); /* key */ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" (", target)); RETERR(str_totext(tctx->linebreak, target)); RETERR(isc_base64_totext(&sr, tctx->width - 2, tctx->linebreak, target)); if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0) RETERR(str_totext(tctx->linebreak, target)); else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" ", target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(")", target)); if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0) { isc_region_t tmpr; RETERR(str_totext(" ; key id = ", target)); dns_rdata_toregion(rdata, &tmpr); /* Skip over refresh, addhd, and removehd */ isc_region_consume(&tmpr, 12); sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm)); RETERR(str_totext(buf, target)); } return (ISC_R_SUCCESS); }
static inline isc_result_t totext_keydata(ARGS_TOTEXT) { isc_region_t sr; char buf[sizeof("64000")]; unsigned int flags; unsigned char algorithm; unsigned long when; char algbuf[DNS_NAME_FORMATSIZE]; const char *keyinfo; REQUIRE(rdata->type == 65533); REQUIRE(rdata->length != 0); dns_rdata_toregion(rdata, &sr); /* refresh timer */ when = uint32_fromregion(&sr); isc_region_consume(&sr, 4); RETERR(dns_time32_totext(when, target)); RETERR(str_totext(" ", target)); /* add hold-down */ when = uint32_fromregion(&sr); isc_region_consume(&sr, 4); RETERR(dns_time32_totext(when, target)); RETERR(str_totext(" ", target)); /* remove hold-down */ when = uint32_fromregion(&sr); isc_region_consume(&sr, 4); RETERR(dns_time32_totext(when, target)); RETERR(str_totext(" ", target)); /* flags */ flags = uint16_fromregion(&sr); isc_region_consume(&sr, 2); sprintf(buf, "%u", flags); RETERR(str_totext(buf, target)); RETERR(str_totext(" ", target)); if ((flags & DNS_KEYFLAG_KSK) != 0) { if (flags & DNS_KEYFLAG_REVOKE) keyinfo = "revoked KSK"; else keyinfo = "KSK"; } else keyinfo = "ZSK"; /* protocol */ sprintf(buf, "%u", sr.base[0]); isc_region_consume(&sr, 1); RETERR(str_totext(buf, target)); RETERR(str_totext(" ", target)); /* algorithm */ algorithm = sr.base[0]; sprintf(buf, "%u", algorithm); isc_region_consume(&sr, 1); RETERR(str_totext(buf, target)); /* No Key? */ if ((flags & 0xc000) == 0xc000) return (ISC_R_SUCCESS); /* key */ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" (", target)); RETERR(str_totext(tctx->linebreak, target)); if (tctx->width == 0) /* No splitting */ RETERR(isc_base64_totext(&sr, 60, "", target)); else RETERR(isc_base64_totext(&sr, tctx->width - 2, tctx->linebreak, target)); if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) RETERR(str_totext(tctx->linebreak, target)); else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" ", target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(")", target)); if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) { isc_region_t tmpr; RETERR(str_totext(" ; ", target)); RETERR(str_totext(keyinfo, target)); dns_secalg_format((dns_secalg_t) algorithm, algbuf, sizeof(algbuf)); RETERR(str_totext("; alg = ", target)); RETERR(str_totext(algbuf, target)); RETERR(str_totext("; key id = ", target)); dns_rdata_toregion(rdata, &tmpr); /* Skip over refresh, addhd, and removehd */ isc_region_consume(&tmpr, 12); sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm)); RETERR(str_totext(buf, target)); } return (ISC_R_SUCCESS); }
static inline isc_result_t totext_sig(ARGS_TOTEXT) { isc_region_t sr; char buf[sizeof("4294967295")]; dns_rdatatype_t covered; unsigned long ttl; unsigned long when; unsigned long exp; unsigned long foot; dns_name_t name; dns_name_t prefix; isc_boolean_t sub; REQUIRE(rdata->type == dns_rdatatype_sig); REQUIRE(rdata->length != 0); dns_rdata_toregion(rdata, &sr); /* * Type covered. */ covered = uint16_fromregion(&sr); isc_region_consume(&sr, 2); /* * XXXAG We should have something like dns_rdatatype_isknown() * that does the right thing with type 0. */ if (dns_rdatatype_isknown(covered) && covered != 0) { RETERR(dns_rdatatype_totext(covered, target)); } else { sprintf(buf, "%u", covered); RETERR(str_totext(buf, target)); } RETERR(str_totext(" ", target)); /* * Algorithm. */ sprintf(buf, "%u", sr.base[0]); isc_region_consume(&sr, 1); RETERR(str_totext(buf, target)); RETERR(str_totext(" ", target)); /* * Labels. */ sprintf(buf, "%u", sr.base[0]); isc_region_consume(&sr, 1); RETERR(str_totext(buf, target)); RETERR(str_totext(" ", target)); /* * Ttl. */ ttl = uint32_fromregion(&sr); isc_region_consume(&sr, 4); sprintf(buf, "%lu", ttl); RETERR(str_totext(buf, target)); RETERR(str_totext(" ", target)); /* * Sig exp. */ exp = uint32_fromregion(&sr); isc_region_consume(&sr, 4); RETERR(dns_time32_totext(exp, target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" (", target)); RETERR(str_totext(tctx->linebreak, target)); /* * Time signed. */ when = uint32_fromregion(&sr); isc_region_consume(&sr, 4); RETERR(dns_time32_totext(when, target)); RETERR(str_totext(" ", target)); /* * Footprint. */ foot = uint16_fromregion(&sr); isc_region_consume(&sr, 2); sprintf(buf, "%lu", foot); RETERR(str_totext(buf, target)); RETERR(str_totext(" ", target)); /* * Signer. */ dns_name_init(&name, NULL); dns_name_init(&prefix, NULL); dns_name_fromregion(&name, &sr); isc_region_consume(&sr, name_length(&name)); sub = name_prefix(&name, tctx->origin, &prefix); RETERR(dns_name_totext(&prefix, sub, target)); /* * Sig. */ RETERR(str_totext(tctx->linebreak, target)); if (tctx->width == 0) /* No splitting */ RETERR(isc_base64_totext(&sr, 60, "", target)); else RETERR(isc_base64_totext(&sr, tctx->width - 2, tctx->linebreak, target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" )", target)); return (ISC_R_SUCCESS); }
isc_result_t dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, const char *directory) { FILE *fp; isc_result_t result; char filename[ISC_DIR_NAMEMAX]; char buffer[MAXFIELDSIZE * 2]; isc_fsaccess_t access; isc_stdtime_t when; isc_uint32_t value; isc_buffer_t b; isc_region_t r; int major, minor; mode_t mode; int i, ret; REQUIRE(priv != NULL); ret = check_data(priv, dst_key_alg(key), ISC_FALSE, key->external); if (ret < 0) return (DST_R_INVALIDPRIVATEKEY); else if (ret != ISC_R_SUCCESS) return (ret); isc_buffer_init(&b, filename, sizeof(filename)); result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, &b); if (result != ISC_R_SUCCESS) return (result); result = isc_file_mode(filename, &mode); if (result == ISC_R_SUCCESS && mode != 0600) { /* File exists; warn that we are changing its permissions */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, "Permissions on the file %s " "have changed from 0%o to 0600 as " "a result of this operation.", filename, (unsigned int)mode); } if ((fp = fopen(filename, "w")) == NULL) return (DST_R_WRITEERROR); access = 0; isc_fsaccess_add(ISC_FSACCESS_OWNER, ISC_FSACCESS_READ | ISC_FSACCESS_WRITE, &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, 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: fprintf(fp, "(RSA)\n"); break; case DST_ALG_DH: fprintf(fp, "(DH)\n"); break; case DST_ALG_DSA: fprintf(fp, "(DSA)\n"); break; 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_ECCGOST: fprintf(fp, "(ECC-GOST)\n"); break; case DST_ALG_ECDSA256: fprintf(fp, "(ECDSAP256SHA256)\n"); break; case DST_ALG_ECDSA384: fprintf(fp, "(ECDSAP384SHA384)\n"); break; case DST_ALG_HMACMD5: fprintf(fp, "(HMAC_MD5)\n"); break; case DST_ALG_HMACSHA1: fprintf(fp, "(HMAC_SHA1)\n"); break; case DST_ALG_HMACSHA224: fprintf(fp, "(HMAC_SHA224)\n"); break; case DST_ALG_HMACSHA256: fprintf(fp, "(HMAC_SHA256)\n"); break; case DST_ALG_HMACSHA384: fprintf(fp, "(HMAC_SHA384)\n"); break; case DST_ALG_HMACSHA512: fprintf(fp, "(HMAC_SHA512)\n"); break; default: fprintf(fp, "(?)\n"); break; } for (i = 0; i < priv->nelements; i++) { 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)); 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\n", s, (int)r.length, r.base); } if (key->external) fprintf(fp, "External:\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) { fclose(fp); return (DST_R_INVALIDPRIVATEKEY); } isc_buffer_usedregion(&b, &r); fprintf(fp, "%s %.*s\n", timetags[i], (int)r.length, r.base); } } fflush(fp); result = ferror(fp) ? DST_R_WRITEERROR : ISC_R_SUCCESS; fclose(fp); return (result); }
static inline isc_result_t totext_keydata(ARGS_TOTEXT) { isc_region_t sr; char buf[sizeof("64000")]; unsigned int flags; unsigned char algorithm; unsigned long refresh, add, remove; char algbuf[DNS_NAME_FORMATSIZE]; const char *keyinfo; REQUIRE(rdata->type == 65533); if ((tctx->flags & DNS_STYLEFLAG_KEYDATA) == 0 || rdata->length < 16) return (unknown_totext(rdata, tctx, target)); dns_rdata_toregion(rdata, &sr); /* refresh timer */ refresh = uint32_fromregion(&sr); isc_region_consume(&sr, 4); RETERR(dns_time32_totext(refresh, target)); RETERR(str_totext(" ", target)); /* add hold-down */ add = uint32_fromregion(&sr); isc_region_consume(&sr, 4); RETERR(dns_time32_totext(add, target)); RETERR(str_totext(" ", target)); /* remove hold-down */ remove = uint32_fromregion(&sr); isc_region_consume(&sr, 4); RETERR(dns_time32_totext(remove, target)); RETERR(str_totext(" ", target)); /* flags */ flags = uint16_fromregion(&sr); isc_region_consume(&sr, 2); sprintf(buf, "%u", flags); RETERR(str_totext(buf, target)); RETERR(str_totext(" ", target)); if ((flags & DNS_KEYFLAG_KSK) != 0) { if (flags & DNS_KEYFLAG_REVOKE) keyinfo = "revoked KSK"; else keyinfo = "KSK"; } else keyinfo = "ZSK"; /* protocol */ sprintf(buf, "%u", sr.base[0]); isc_region_consume(&sr, 1); RETERR(str_totext(buf, target)); RETERR(str_totext(" ", target)); /* algorithm */ algorithm = sr.base[0]; sprintf(buf, "%u", algorithm); isc_region_consume(&sr, 1); RETERR(str_totext(buf, target)); /* No Key? */ if ((flags & 0xc000) == 0xc000) return (ISC_R_SUCCESS); /* key */ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" (", target)); RETERR(str_totext(tctx->linebreak, target)); if (tctx->width == 0) /* No splitting */ RETERR(isc_base64_totext(&sr, 60, "", target)); else RETERR(isc_base64_totext(&sr, tctx->width - 2, tctx->linebreak, target)); if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) RETERR(str_totext(tctx->linebreak, target)); else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" ", target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(")", target)); if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) { isc_region_t tmpr; char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; char abuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; char dbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; isc_time_t t; RETERR(str_totext(" ; ", target)); RETERR(str_totext(keyinfo, target)); dns_secalg_format((dns_secalg_t) algorithm, algbuf, sizeof(algbuf)); RETERR(str_totext("; alg = ", target)); RETERR(str_totext(algbuf, target)); RETERR(str_totext("; key id = ", target)); dns_rdata_toregion(rdata, &tmpr); /* Skip over refresh, addhd, and removehd */ isc_region_consume(&tmpr, 12); sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm)); RETERR(str_totext(buf, target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { isc_stdtime_t now; isc_stdtime_get(&now); RETERR(str_totext(tctx->linebreak, target)); RETERR(str_totext("; next refresh: ", target)); isc_time_set(&t, refresh, 0); isc_time_formathttptimestamp(&t, rbuf, sizeof(rbuf)); RETERR(str_totext(rbuf, target)); if (add == 0) { RETERR(str_totext(tctx->linebreak, target)); RETERR(str_totext("; no trust", target)); } else { RETERR(str_totext(tctx->linebreak, target)); if (add < now) { RETERR(str_totext("; trusted since: ", target)); } else { RETERR(str_totext("; trust pending: ", target)); } isc_time_set(&t, add, 0); isc_time_formathttptimestamp(&t, abuf, sizeof(abuf)); RETERR(str_totext(abuf, target)); } if (remove != 0) { RETERR(str_totext(tctx->linebreak, target)); RETERR(str_totext("; removal pending: ", target)); isc_time_set(&t, remove, 0); isc_time_formathttptimestamp(&t, dbuf, sizeof(dbuf)); RETERR(str_totext(dbuf, target)); } } } return (ISC_R_SUCCESS); }