1 /*
2  * Copyright (C) 2004, 2006, 2007, 2009, 2011-2013, 2015  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /* $Id$ */
19 
20 /* RFC 4255 */
21 
22 #ifndef RDATA_GENERIC_SSHFP_44_C
23 #define RDATA_GENERIC_SSHFP_44_C
24 
25 #define RRTYPE_SSHFP_ATTRIBUTES (0)
26 
27 static inline isc_result_t
fromtext_sshfp(ARGS_FROMTEXT)28 fromtext_sshfp(ARGS_FROMTEXT) {
29 	isc_token_t token;
30 
31 	REQUIRE(type == dns_rdatatype_sshfp);
32 
33 	UNUSED(type);
34 	UNUSED(rdclass);
35 	UNUSED(origin);
36 	UNUSED(options);
37 	UNUSED(callbacks);
38 
39 	/*
40 	 * Algorithm.
41 	 */
42 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
43 				      ISC_FALSE));
44 	if (token.value.as_ulong > 0xffU)
45 		RETTOK(ISC_R_RANGE);
46 	RETERR(uint8_tobuffer(token.value.as_ulong, target));
47 
48 	/*
49 	 * Digest type.
50 	 */
51 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
52 				      ISC_FALSE));
53 	if (token.value.as_ulong > 0xffU)
54 		RETTOK(ISC_R_RANGE);
55 	RETERR(uint8_tobuffer(token.value.as_ulong, target));
56 
57 	/*
58 	 * Digest.
59 	 */
60 	return (isc_hex_tobuffer(lexer, target, -1));
61 }
62 
63 static inline isc_result_t
totext_sshfp(ARGS_TOTEXT)64 totext_sshfp(ARGS_TOTEXT) {
65 	isc_region_t sr;
66 	char buf[sizeof("64000 ")];
67 	unsigned int n;
68 
69 	REQUIRE(rdata->type == dns_rdatatype_sshfp);
70 	REQUIRE(rdata->length != 0);
71 
72 	UNUSED(tctx);
73 
74 	dns_rdata_toregion(rdata, &sr);
75 
76 	/*
77 	 * Algorithm.
78 	 */
79 	n = uint8_fromregion(&sr);
80 	isc_region_consume(&sr, 1);
81 	sprintf(buf, "%u ", n);
82 	RETERR(str_totext(buf, target));
83 
84 	/*
85 	 * Digest type.
86 	 */
87 	n = uint8_fromregion(&sr);
88 	isc_region_consume(&sr, 1);
89 	sprintf(buf, "%u", n);
90 	RETERR(str_totext(buf, target));
91 
92 	/*
93 	 * Digest.
94 	 */
95 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
96 		RETERR(str_totext(" (", target));
97 	RETERR(str_totext(tctx->linebreak, target));
98 	if (tctx->width == 0) /* No splitting */
99 		RETERR(isc_hex_totext(&sr, 0, "", target));
100 	else
101 		RETERR(isc_hex_totext(&sr, tctx->width - 2,
102 				      tctx->linebreak, target));
103 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
104 		RETERR(str_totext(" )", target));
105 	return (ISC_R_SUCCESS);
106 }
107 
108 static inline isc_result_t
fromwire_sshfp(ARGS_FROMWIRE)109 fromwire_sshfp(ARGS_FROMWIRE) {
110 	isc_region_t sr;
111 
112 	REQUIRE(type == dns_rdatatype_sshfp);
113 
114 	UNUSED(type);
115 	UNUSED(rdclass);
116 	UNUSED(dctx);
117 	UNUSED(options);
118 
119 	isc_buffer_activeregion(source, &sr);
120 	if (sr.length < 4)
121 		return (ISC_R_UNEXPECTEDEND);
122 
123 	isc_buffer_forward(source, sr.length);
124 	return (mem_tobuffer(target, sr.base, sr.length));
125 }
126 
127 static inline isc_result_t
towire_sshfp(ARGS_TOWIRE)128 towire_sshfp(ARGS_TOWIRE) {
129 	isc_region_t sr;
130 
131 	REQUIRE(rdata->type == dns_rdatatype_sshfp);
132 	REQUIRE(rdata->length != 0);
133 
134 	UNUSED(cctx);
135 
136 	dns_rdata_toregion(rdata, &sr);
137 	return (mem_tobuffer(target, sr.base, sr.length));
138 }
139 
140 static inline int
compare_sshfp(ARGS_COMPARE)141 compare_sshfp(ARGS_COMPARE) {
142 	isc_region_t r1;
143 	isc_region_t r2;
144 
145 	REQUIRE(rdata1->type == rdata2->type);
146 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
147 	REQUIRE(rdata1->type == dns_rdatatype_sshfp);
148 	REQUIRE(rdata1->length != 0);
149 	REQUIRE(rdata2->length != 0);
150 
151 	dns_rdata_toregion(rdata1, &r1);
152 	dns_rdata_toregion(rdata2, &r2);
153 	return (isc_region_compare(&r1, &r2));
154 }
155 
156 static inline isc_result_t
fromstruct_sshfp(ARGS_FROMSTRUCT)157 fromstruct_sshfp(ARGS_FROMSTRUCT) {
158 	dns_rdata_sshfp_t *sshfp = source;
159 
160 	REQUIRE(type == dns_rdatatype_sshfp);
161 	REQUIRE(source != NULL);
162 	REQUIRE(sshfp->common.rdtype == type);
163 	REQUIRE(sshfp->common.rdclass == rdclass);
164 
165 	UNUSED(type);
166 	UNUSED(rdclass);
167 
168 	RETERR(uint8_tobuffer(sshfp->algorithm, target));
169 	RETERR(uint8_tobuffer(sshfp->digest_type, target));
170 
171 	return (mem_tobuffer(target, sshfp->digest, sshfp->length));
172 }
173 
174 static inline isc_result_t
tostruct_sshfp(ARGS_TOSTRUCT)175 tostruct_sshfp(ARGS_TOSTRUCT) {
176 	dns_rdata_sshfp_t *sshfp = target;
177 	isc_region_t region;
178 
179 	REQUIRE(rdata->type == dns_rdatatype_sshfp);
180 	REQUIRE(target != NULL);
181 	REQUIRE(rdata->length != 0);
182 
183 	sshfp->common.rdclass = rdata->rdclass;
184 	sshfp->common.rdtype = rdata->type;
185 	ISC_LINK_INIT(&sshfp->common, link);
186 
187 	dns_rdata_toregion(rdata, &region);
188 
189 	sshfp->algorithm = uint8_fromregion(&region);
190 	isc_region_consume(&region, 1);
191 	sshfp->digest_type = uint8_fromregion(&region);
192 	isc_region_consume(&region, 1);
193 	sshfp->length = region.length;
194 
195 	sshfp->digest = mem_maybedup(mctx, region.base, region.length);
196 	if (sshfp->digest == NULL)
197 		return (ISC_R_NOMEMORY);
198 
199 	sshfp->mctx = mctx;
200 	return (ISC_R_SUCCESS);
201 }
202 
203 static inline void
freestruct_sshfp(ARGS_FREESTRUCT)204 freestruct_sshfp(ARGS_FREESTRUCT) {
205 	dns_rdata_sshfp_t *sshfp = source;
206 
207 	REQUIRE(sshfp != NULL);
208 	REQUIRE(sshfp->common.rdtype == dns_rdatatype_sshfp);
209 
210 	if (sshfp->mctx == NULL)
211 		return;
212 
213 	if (sshfp->digest != NULL)
214 		isc_mem_free(sshfp->mctx, sshfp->digest);
215 	sshfp->mctx = NULL;
216 }
217 
218 static inline isc_result_t
additionaldata_sshfp(ARGS_ADDLDATA)219 additionaldata_sshfp(ARGS_ADDLDATA) {
220 	REQUIRE(rdata->type == dns_rdatatype_sshfp);
221 
222 	UNUSED(rdata);
223 	UNUSED(add);
224 	UNUSED(arg);
225 
226 	return (ISC_R_SUCCESS);
227 }
228 
229 static inline isc_result_t
digest_sshfp(ARGS_DIGEST)230 digest_sshfp(ARGS_DIGEST) {
231 	isc_region_t r;
232 
233 	REQUIRE(rdata->type == dns_rdatatype_sshfp);
234 
235 	dns_rdata_toregion(rdata, &r);
236 
237 	return ((digest)(arg, &r));
238 }
239 
240 static inline isc_boolean_t
checkowner_sshfp(ARGS_CHECKOWNER)241 checkowner_sshfp(ARGS_CHECKOWNER) {
242 
243 	REQUIRE(type == dns_rdatatype_sshfp);
244 
245 	UNUSED(name);
246 	UNUSED(type);
247 	UNUSED(rdclass);
248 	UNUSED(wildcard);
249 
250 	return (ISC_TRUE);
251 }
252 
253 static inline isc_boolean_t
checknames_sshfp(ARGS_CHECKNAMES)254 checknames_sshfp(ARGS_CHECKNAMES) {
255 
256 	REQUIRE(rdata->type == dns_rdatatype_sshfp);
257 
258 	UNUSED(rdata);
259 	UNUSED(owner);
260 	UNUSED(bad);
261 
262 	return (ISC_TRUE);
263 }
264 
265 static inline int
casecompare_sshfp(ARGS_COMPARE)266 casecompare_sshfp(ARGS_COMPARE) {
267 	return (compare_sshfp(rdata1, rdata2));
268 }
269 
270 #endif	/* RDATA_GENERIC_SSHFP_44_C */
271