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 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 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 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 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