15185a700Sflorian /*
25185a700Sflorian * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
35185a700Sflorian *
45185a700Sflorian * Permission to use, copy, modify, and/or distribute this software for any
55185a700Sflorian * purpose with or without fee is hereby granted, provided that the above
65185a700Sflorian * copyright notice and this permission notice appear in all copies.
75185a700Sflorian *
85185a700Sflorian * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
95185a700Sflorian * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
105185a700Sflorian * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
115185a700Sflorian * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
125185a700Sflorian * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
135185a700Sflorian * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
145185a700Sflorian * PERFORMANCE OF THIS SOFTWARE.
155185a700Sflorian */
165185a700Sflorian
175185a700Sflorian #ifndef GENERIC_KEYDATA_65533_C
185185a700Sflorian #define GENERIC_KEYDATA_65533_C 1
195185a700Sflorian
204465bcfbSjsg #include <time.h>
215185a700Sflorian
225185a700Sflorian #include <dst/dst.h>
235185a700Sflorian
2498bc8dccSflorian /*
2598bc8dccSflorian * ISC_FORMATHTTPTIMESTAMP_SIZE needs to be 30 in C locale and potentially
2698bc8dccSflorian * more for other locales to handle longer national abbreviations when
2798bc8dccSflorian * expanding strftime's %a and %b.
2898bc8dccSflorian */
2998bc8dccSflorian #define ISC_FORMATHTTPTIMESTAMP_SIZE 50
3098bc8dccSflorian
3198bc8dccSflorian static void
isc_time_formathttptimestamp(const struct timespec * t,char * buf,size_t len)3298bc8dccSflorian isc_time_formathttptimestamp(const struct timespec *t, char *buf, size_t len) {
3398bc8dccSflorian size_t flen;
3498bc8dccSflorian /*
3598bc8dccSflorian * 5 spaces, 1 comma, 3 GMT, 2 %d, 4 %Y, 8 %H:%M:%S, 3+ %a, 3+ %b (29+)
3698bc8dccSflorian */
3798bc8dccSflorian
3898bc8dccSflorian flen = strftime(buf, len, "%a, %d %b %Y %H:%M:%S GMT",
3998bc8dccSflorian gmtime(&t->tv_sec));
4098bc8dccSflorian INSIST(flen < len);
4198bc8dccSflorian }
4298bc8dccSflorian
435185a700Sflorian static inline isc_result_t
totext_keydata(ARGS_TOTEXT)445185a700Sflorian totext_keydata(ARGS_TOTEXT) {
455185a700Sflorian isc_region_t sr;
465185a700Sflorian char buf[sizeof("64000")];
475185a700Sflorian unsigned int flags;
485185a700Sflorian unsigned char algorithm;
495185a700Sflorian unsigned long refresh, add, deltime;
505185a700Sflorian char algbuf[DNS_NAME_FORMATSIZE];
515185a700Sflorian const char *keyinfo;
525185a700Sflorian
535185a700Sflorian REQUIRE(rdata->type == dns_rdatatype_keydata);
545185a700Sflorian
555185a700Sflorian if ((tctx->flags & DNS_STYLEFLAG_KEYDATA) == 0 || rdata->length < 16)
565185a700Sflorian return (unknown_totext(rdata, tctx, target));
575185a700Sflorian
585185a700Sflorian dns_rdata_toregion(rdata, &sr);
595185a700Sflorian
605185a700Sflorian /* refresh timer */
615185a700Sflorian refresh = uint32_fromregion(&sr);
625185a700Sflorian isc_region_consume(&sr, 4);
635185a700Sflorian RETERR(dns_time32_totext(refresh, target));
64*873f12b9Sflorian RETERR(isc_str_tobuffer(" ", target));
655185a700Sflorian
665185a700Sflorian /* add hold-down */
675185a700Sflorian add = uint32_fromregion(&sr);
685185a700Sflorian isc_region_consume(&sr, 4);
695185a700Sflorian RETERR(dns_time32_totext(add, target));
70*873f12b9Sflorian RETERR(isc_str_tobuffer(" ", target));
715185a700Sflorian
725185a700Sflorian /* remove hold-down */
735185a700Sflorian deltime = uint32_fromregion(&sr);
745185a700Sflorian isc_region_consume(&sr, 4);
755185a700Sflorian RETERR(dns_time32_totext(deltime, target));
76*873f12b9Sflorian RETERR(isc_str_tobuffer(" ", target));
775185a700Sflorian
785185a700Sflorian /* flags */
795185a700Sflorian flags = uint16_fromregion(&sr);
805185a700Sflorian isc_region_consume(&sr, 2);
815185a700Sflorian snprintf(buf, sizeof(buf), "%u", flags);
82*873f12b9Sflorian RETERR(isc_str_tobuffer(buf, target));
83*873f12b9Sflorian RETERR(isc_str_tobuffer(" ", target));
845185a700Sflorian if ((flags & DNS_KEYFLAG_KSK) != 0) {
855185a700Sflorian if (flags & DNS_KEYFLAG_REVOKE)
865185a700Sflorian keyinfo = "revoked KSK";
875185a700Sflorian else
885185a700Sflorian keyinfo = "KSK";
895185a700Sflorian } else
905185a700Sflorian keyinfo = "ZSK";
915185a700Sflorian
925185a700Sflorian /* protocol */
935185a700Sflorian snprintf(buf, sizeof(buf), "%u", sr.base[0]);
945185a700Sflorian isc_region_consume(&sr, 1);
95*873f12b9Sflorian RETERR(isc_str_tobuffer(buf, target));
96*873f12b9Sflorian RETERR(isc_str_tobuffer(" ", target));
975185a700Sflorian
985185a700Sflorian /* algorithm */
995185a700Sflorian algorithm = sr.base[0];
1005185a700Sflorian snprintf(buf, sizeof(buf), "%u", algorithm);
1015185a700Sflorian isc_region_consume(&sr, 1);
102*873f12b9Sflorian RETERR(isc_str_tobuffer(buf, target));
1035185a700Sflorian
1045185a700Sflorian /* No Key? */
1055185a700Sflorian if ((flags & 0xc000) == 0xc000)
1065185a700Sflorian return (ISC_R_SUCCESS);
1075185a700Sflorian
1085185a700Sflorian /* key */
1095185a700Sflorian if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
110*873f12b9Sflorian RETERR(isc_str_tobuffer(" (", target));
111*873f12b9Sflorian RETERR(isc_str_tobuffer(tctx->linebreak, target));
1125185a700Sflorian if (tctx->width == 0) /* No splitting */
1135185a700Sflorian RETERR(isc_base64_totext(&sr, 60, "", target));
1145185a700Sflorian else
1155185a700Sflorian RETERR(isc_base64_totext(&sr, tctx->width - 2,
1165185a700Sflorian tctx->linebreak, target));
1175185a700Sflorian
1185185a700Sflorian if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0)
119*873f12b9Sflorian RETERR(isc_str_tobuffer(tctx->linebreak, target));
1205185a700Sflorian else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
121*873f12b9Sflorian RETERR(isc_str_tobuffer(" ", target));
1225185a700Sflorian
1235185a700Sflorian if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
124*873f12b9Sflorian RETERR(isc_str_tobuffer(")", target));
1255185a700Sflorian
1265185a700Sflorian if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
1275185a700Sflorian isc_region_t tmpr;
1285185a700Sflorian char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
1295185a700Sflorian char abuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
1305185a700Sflorian char dbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
1317238a213Sflorian struct timespec t;
1325185a700Sflorian
133*873f12b9Sflorian RETERR(isc_str_tobuffer(" ; ", target));
134*873f12b9Sflorian RETERR(isc_str_tobuffer(keyinfo, target));
1355185a700Sflorian dns_secalg_format((dns_secalg_t) algorithm, algbuf,
1365185a700Sflorian sizeof(algbuf));
137*873f12b9Sflorian RETERR(isc_str_tobuffer("; alg = ", target));
138*873f12b9Sflorian RETERR(isc_str_tobuffer(algbuf, target));
139*873f12b9Sflorian RETERR(isc_str_tobuffer("; key id = ", target));
1405185a700Sflorian dns_rdata_toregion(rdata, &tmpr);
1415185a700Sflorian /* Skip over refresh, addhd, and removehd */
1425185a700Sflorian isc_region_consume(&tmpr, 12);
1435185a700Sflorian snprintf(buf, sizeof(buf), "%u",
1445185a700Sflorian dst_region_computeid(&tmpr, algorithm));
145*873f12b9Sflorian RETERR(isc_str_tobuffer(buf, target));
1465185a700Sflorian
1475185a700Sflorian if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
148c576c3baSflorian time_t now;
1495185a700Sflorian
150c576c3baSflorian time(&now);
1515185a700Sflorian
152*873f12b9Sflorian RETERR(isc_str_tobuffer(tctx->linebreak, target));
153*873f12b9Sflorian RETERR(isc_str_tobuffer("; next refresh: ", target));
154bb7ec108Sflorian t.tv_sec = refresh;
155bb7ec108Sflorian t.tv_nsec = 0;
1565185a700Sflorian isc_time_formathttptimestamp(&t, rbuf, sizeof(rbuf));
157*873f12b9Sflorian RETERR(isc_str_tobuffer(rbuf, target));
1585185a700Sflorian
1595185a700Sflorian if (add == 0U) {
160*873f12b9Sflorian RETERR(isc_str_tobuffer(tctx->linebreak, target));
161*873f12b9Sflorian RETERR(isc_str_tobuffer("; no trust", target));
1625185a700Sflorian } else {
163*873f12b9Sflorian RETERR(isc_str_tobuffer(tctx->linebreak, target));
164c576c3baSflorian if ((time_t)add < now) {
165*873f12b9Sflorian RETERR(isc_str_tobuffer("; trusted since: ",
1665185a700Sflorian target));
1675185a700Sflorian } else {
168*873f12b9Sflorian RETERR(isc_str_tobuffer("; trust pending: ",
1695185a700Sflorian target));
1705185a700Sflorian }
171bb7ec108Sflorian t.tv_sec = add;
172bb7ec108Sflorian t.tv_nsec = 0;
1735185a700Sflorian isc_time_formathttptimestamp(&t, abuf,
1745185a700Sflorian sizeof(abuf));
175*873f12b9Sflorian RETERR(isc_str_tobuffer(abuf, target));
1765185a700Sflorian }
1775185a700Sflorian
1785185a700Sflorian if (deltime != 0U) {
179*873f12b9Sflorian RETERR(isc_str_tobuffer(tctx->linebreak, target));
180*873f12b9Sflorian RETERR(isc_str_tobuffer("; removal pending: ",
1815185a700Sflorian target));
182bb7ec108Sflorian t.tv_sec = deltime;
183bb7ec108Sflorian t.tv_nsec = 0;
1845185a700Sflorian isc_time_formathttptimestamp(&t, dbuf,
1855185a700Sflorian sizeof(dbuf));
186*873f12b9Sflorian RETERR(isc_str_tobuffer(dbuf, target));
1875185a700Sflorian }
1885185a700Sflorian }
1895185a700Sflorian
1905185a700Sflorian }
1915185a700Sflorian return (ISC_R_SUCCESS);
1925185a700Sflorian }
1935185a700Sflorian
1945185a700Sflorian static inline isc_result_t
fromwire_keydata(ARGS_FROMWIRE)1955185a700Sflorian fromwire_keydata(ARGS_FROMWIRE) {
1965185a700Sflorian isc_region_t sr;
1975185a700Sflorian
1985185a700Sflorian REQUIRE(type == dns_rdatatype_keydata);
1995185a700Sflorian
2005185a700Sflorian UNUSED(type);
2015185a700Sflorian UNUSED(rdclass);
2025185a700Sflorian UNUSED(dctx);
2035185a700Sflorian UNUSED(options);
2045185a700Sflorian
2055185a700Sflorian isc_buffer_activeregion(source, &sr);
2065185a700Sflorian isc_buffer_forward(source, sr.length);
207637d8eb6Sflorian return (isc_mem_tobuffer(target, sr.base, sr.length));
2085185a700Sflorian }
2095185a700Sflorian
2105185a700Sflorian static inline isc_result_t
towire_keydata(ARGS_TOWIRE)2115185a700Sflorian towire_keydata(ARGS_TOWIRE) {
2125185a700Sflorian isc_region_t sr;
2135185a700Sflorian
2145185a700Sflorian REQUIRE(rdata->type == dns_rdatatype_keydata);
2155185a700Sflorian
2165185a700Sflorian UNUSED(cctx);
2175185a700Sflorian
2185185a700Sflorian dns_rdata_toregion(rdata, &sr);
219637d8eb6Sflorian return (isc_mem_tobuffer(target, sr.base, sr.length));
2205185a700Sflorian }
2215185a700Sflorian
2225185a700Sflorian #endif /* GENERIC_KEYDATA_65533_C */
223