1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #ifndef GENERIC_KEYDATA_65533_C
18 #define GENERIC_KEYDATA_65533_C 1
19
20 #include <time.h>
21
22 #include <dst/dst.h>
23
24 /*
25 * ISC_FORMATHTTPTIMESTAMP_SIZE needs to be 30 in C locale and potentially
26 * more for other locales to handle longer national abbreviations when
27 * expanding strftime's %a and %b.
28 */
29 #define ISC_FORMATHTTPTIMESTAMP_SIZE 50
30
31 static void
isc_time_formathttptimestamp(const struct timespec * t,char * buf,size_t len)32 isc_time_formathttptimestamp(const struct timespec *t, char *buf, size_t len) {
33 size_t flen;
34 /*
35 * 5 spaces, 1 comma, 3 GMT, 2 %d, 4 %Y, 8 %H:%M:%S, 3+ %a, 3+ %b (29+)
36 */
37
38 flen = strftime(buf, len, "%a, %d %b %Y %H:%M:%S GMT",
39 gmtime(&t->tv_sec));
40 INSIST(flen < len);
41 }
42
43 static inline isc_result_t
totext_keydata(ARGS_TOTEXT)44 totext_keydata(ARGS_TOTEXT) {
45 isc_region_t sr;
46 char buf[sizeof("64000")];
47 unsigned int flags;
48 unsigned char algorithm;
49 unsigned long refresh, add, deltime;
50 char algbuf[DNS_NAME_FORMATSIZE];
51 const char *keyinfo;
52
53 REQUIRE(rdata->type == dns_rdatatype_keydata);
54
55 if ((tctx->flags & DNS_STYLEFLAG_KEYDATA) == 0 || rdata->length < 16)
56 return (unknown_totext(rdata, tctx, target));
57
58 dns_rdata_toregion(rdata, &sr);
59
60 /* refresh timer */
61 refresh = uint32_fromregion(&sr);
62 isc_region_consume(&sr, 4);
63 RETERR(dns_time32_totext(refresh, target));
64 RETERR(isc_str_tobuffer(" ", target));
65
66 /* add hold-down */
67 add = uint32_fromregion(&sr);
68 isc_region_consume(&sr, 4);
69 RETERR(dns_time32_totext(add, target));
70 RETERR(isc_str_tobuffer(" ", target));
71
72 /* remove hold-down */
73 deltime = uint32_fromregion(&sr);
74 isc_region_consume(&sr, 4);
75 RETERR(dns_time32_totext(deltime, target));
76 RETERR(isc_str_tobuffer(" ", target));
77
78 /* flags */
79 flags = uint16_fromregion(&sr);
80 isc_region_consume(&sr, 2);
81 snprintf(buf, sizeof(buf), "%u", flags);
82 RETERR(isc_str_tobuffer(buf, target));
83 RETERR(isc_str_tobuffer(" ", target));
84 if ((flags & DNS_KEYFLAG_KSK) != 0) {
85 if (flags & DNS_KEYFLAG_REVOKE)
86 keyinfo = "revoked KSK";
87 else
88 keyinfo = "KSK";
89 } else
90 keyinfo = "ZSK";
91
92 /* protocol */
93 snprintf(buf, sizeof(buf), "%u", sr.base[0]);
94 isc_region_consume(&sr, 1);
95 RETERR(isc_str_tobuffer(buf, target));
96 RETERR(isc_str_tobuffer(" ", target));
97
98 /* algorithm */
99 algorithm = sr.base[0];
100 snprintf(buf, sizeof(buf), "%u", algorithm);
101 isc_region_consume(&sr, 1);
102 RETERR(isc_str_tobuffer(buf, target));
103
104 /* No Key? */
105 if ((flags & 0xc000) == 0xc000)
106 return (ISC_R_SUCCESS);
107
108 /* key */
109 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
110 RETERR(isc_str_tobuffer(" (", target));
111 RETERR(isc_str_tobuffer(tctx->linebreak, target));
112 if (tctx->width == 0) /* No splitting */
113 RETERR(isc_base64_totext(&sr, 60, "", target));
114 else
115 RETERR(isc_base64_totext(&sr, tctx->width - 2,
116 tctx->linebreak, target));
117
118 if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0)
119 RETERR(isc_str_tobuffer(tctx->linebreak, target));
120 else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
121 RETERR(isc_str_tobuffer(" ", target));
122
123 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
124 RETERR(isc_str_tobuffer(")", target));
125
126 if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
127 isc_region_t tmpr;
128 char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
129 char abuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
130 char dbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
131 struct timespec t;
132
133 RETERR(isc_str_tobuffer(" ; ", target));
134 RETERR(isc_str_tobuffer(keyinfo, target));
135 dns_secalg_format((dns_secalg_t) algorithm, algbuf,
136 sizeof(algbuf));
137 RETERR(isc_str_tobuffer("; alg = ", target));
138 RETERR(isc_str_tobuffer(algbuf, target));
139 RETERR(isc_str_tobuffer("; key id = ", target));
140 dns_rdata_toregion(rdata, &tmpr);
141 /* Skip over refresh, addhd, and removehd */
142 isc_region_consume(&tmpr, 12);
143 snprintf(buf, sizeof(buf), "%u",
144 dst_region_computeid(&tmpr, algorithm));
145 RETERR(isc_str_tobuffer(buf, target));
146
147 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
148 time_t now;
149
150 time(&now);
151
152 RETERR(isc_str_tobuffer(tctx->linebreak, target));
153 RETERR(isc_str_tobuffer("; next refresh: ", target));
154 t.tv_sec = refresh;
155 t.tv_nsec = 0;
156 isc_time_formathttptimestamp(&t, rbuf, sizeof(rbuf));
157 RETERR(isc_str_tobuffer(rbuf, target));
158
159 if (add == 0U) {
160 RETERR(isc_str_tobuffer(tctx->linebreak, target));
161 RETERR(isc_str_tobuffer("; no trust", target));
162 } else {
163 RETERR(isc_str_tobuffer(tctx->linebreak, target));
164 if ((time_t)add < now) {
165 RETERR(isc_str_tobuffer("; trusted since: ",
166 target));
167 } else {
168 RETERR(isc_str_tobuffer("; trust pending: ",
169 target));
170 }
171 t.tv_sec = add;
172 t.tv_nsec = 0;
173 isc_time_formathttptimestamp(&t, abuf,
174 sizeof(abuf));
175 RETERR(isc_str_tobuffer(abuf, target));
176 }
177
178 if (deltime != 0U) {
179 RETERR(isc_str_tobuffer(tctx->linebreak, target));
180 RETERR(isc_str_tobuffer("; removal pending: ",
181 target));
182 t.tv_sec = deltime;
183 t.tv_nsec = 0;
184 isc_time_formathttptimestamp(&t, dbuf,
185 sizeof(dbuf));
186 RETERR(isc_str_tobuffer(dbuf, target));
187 }
188 }
189
190 }
191 return (ISC_R_SUCCESS);
192 }
193
194 static inline isc_result_t
fromwire_keydata(ARGS_FROMWIRE)195 fromwire_keydata(ARGS_FROMWIRE) {
196 isc_region_t sr;
197
198 REQUIRE(type == dns_rdatatype_keydata);
199
200 UNUSED(type);
201 UNUSED(rdclass);
202 UNUSED(dctx);
203 UNUSED(options);
204
205 isc_buffer_activeregion(source, &sr);
206 isc_buffer_forward(source, sr.length);
207 return (isc_mem_tobuffer(target, sr.base, sr.length));
208 }
209
210 static inline isc_result_t
towire_keydata(ARGS_TOWIRE)211 towire_keydata(ARGS_TOWIRE) {
212 isc_region_t sr;
213
214 REQUIRE(rdata->type == dns_rdatatype_keydata);
215
216 UNUSED(cctx);
217
218 dns_rdata_toregion(rdata, &sr);
219 return (isc_mem_tobuffer(target, sr.base, sr.length));
220 }
221
222 #endif /* GENERIC_KEYDATA_65533_C */
223