1 /*
2  * Copyright (c) 2014 by Farsight Security, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include "fstrm-private.h"
25 
26 struct fstrm_control {
27 	fstrm_control_type	type;
28 	fs_bufvec		*content_types;
29 };
30 
31 const char *
fstrm_control_type_to_str(fstrm_control_type type)32 fstrm_control_type_to_str(fstrm_control_type type)
33 {
34 	switch (type) {
35 	case FSTRM_CONTROL_ACCEPT:
36 		return "FSTRM_CONTROL_ACCEPT";
37 	case FSTRM_CONTROL_START:
38 		return "FSTRM_CONTROL_START";
39 	case FSTRM_CONTROL_STOP:
40 		return "FSTRM_CONTROL_STOP";
41 	case FSTRM_CONTROL_READY:
42 		return "FSTRM_CONTROL_READY";
43 	case FSTRM_CONTROL_FINISH:
44 		return "FSTRM_CONTROL_FINISH";
45 	default:
46 		return "FSTRM_CONTROL_UNKNOWN";
47 	}
48 }
49 
50 const char *
fstrm_control_field_type_to_str(fstrm_control_field f_type)51 fstrm_control_field_type_to_str(fstrm_control_field f_type)
52 {
53 	switch (f_type) {
54 	case FSTRM_CONTROL_FIELD_CONTENT_TYPE:
55 		return "FSTRM_CONTROL_FIELD_CONTENT_TYPE";
56 	default:
57 		return "FSTRM_CONTROL_FIELD_UNKNOWN";
58 	}
59 }
60 
61 struct fstrm_control *
fstrm_control_init(void)62 fstrm_control_init(void)
63 {
64 	struct fstrm_control *c;
65 	c = my_calloc(1, sizeof(*c));
66 	c->content_types = fs_bufvec_init(1);
67 	return c;
68 }
69 
70 void
fstrm_control_destroy(struct fstrm_control ** c)71 fstrm_control_destroy(struct fstrm_control **c)
72 {
73 	if (*c != NULL) {
74 		fstrm_control_reset(*c);
75 		fs_bufvec_destroy(&(*c)->content_types);
76 		my_free(*c);
77 	}
78 }
79 
80 void
fstrm_control_reset(struct fstrm_control * c)81 fstrm_control_reset(struct fstrm_control *c)
82 {
83 	for (size_t i = 0; i < fs_bufvec_size(c->content_types); i++) {
84 		fs_buf buf = fs_bufvec_value(c->content_types, i);
85 		my_free(buf.data);
86 	}
87 	fs_bufvec_reset(c->content_types);
88 	c->type = 0;
89 }
90 
91 fstrm_res
fstrm_control_get_type(const struct fstrm_control * c,fstrm_control_type * type)92 fstrm_control_get_type(const struct fstrm_control *c, fstrm_control_type *type)
93 {
94 	switch (c->type) {
95 	case FSTRM_CONTROL_ACCEPT:	/* FALLTHROUGH */
96 	case FSTRM_CONTROL_START:	/* FALLTHROUGH */
97 	case FSTRM_CONTROL_STOP:	/* FALLTHROUGH */
98 	case FSTRM_CONTROL_READY:	/* FALLTHROUGH */
99 	case FSTRM_CONTROL_FINISH:
100 		*type = c->type;
101 		return fstrm_res_success;
102 	default:
103 		return fstrm_res_failure;
104 	}
105 }
106 
107 fstrm_res
fstrm_control_set_type(struct fstrm_control * c,fstrm_control_type type)108 fstrm_control_set_type(struct fstrm_control *c, fstrm_control_type type)
109 {
110 	switch (type) {
111 	case FSTRM_CONTROL_ACCEPT:	/* FALLTHROUGH */
112 	case FSTRM_CONTROL_START:	/* FALLTHROUGH */
113 	case FSTRM_CONTROL_STOP:	/* FALLTHROUGH */
114 	case FSTRM_CONTROL_READY:	/* FALLTHROUGH */
115 	case FSTRM_CONTROL_FINISH:
116 		c->type = type;
117 		return fstrm_res_success;
118 	default:
119 		return fstrm_res_failure;
120 	}
121 }
122 
123 fstrm_res
fstrm_control_get_num_field_content_type(const struct fstrm_control * c,size_t * n_content_type)124 fstrm_control_get_num_field_content_type(const struct fstrm_control *c,
125 					 size_t *n_content_type)
126 {
127 	*n_content_type = fs_bufvec_size(c->content_types);
128 
129 	switch (c->type) {
130 	case FSTRM_CONTROL_STOP:	/* FALLTHROUGH */
131 	case FSTRM_CONTROL_FINISH:	/* FALLTHROUGH */
132 		/*
133 		 * STOP and FINISH frames may not have any content type fields.
134 		 */
135 		*n_content_type = 0;
136 		break;
137 	case FSTRM_CONTROL_START:
138 		/* START frames may not have more than one content type field. */
139 		if (*n_content_type > 1)
140 			*n_content_type = 1;
141 		break;
142 	default:
143 		break;
144 	}
145 
146 	return fstrm_res_success;
147 }
148 
149 fstrm_res
fstrm_control_get_field_content_type(const struct fstrm_control * c,const size_t idx,const uint8_t ** content_type,size_t * len_content_type)150 fstrm_control_get_field_content_type(const struct fstrm_control *c,
151 				     const size_t idx,
152 				     const uint8_t **content_type,
153 				     size_t *len_content_type)
154 {
155 	if (idx < fs_bufvec_size(c->content_types)) {
156 		fs_buf buf = fs_bufvec_value(c->content_types, idx);
157 		*content_type = buf.data;
158 		*len_content_type = buf.len;
159 		return fstrm_res_success;
160 	}
161 	return fstrm_res_failure;
162 }
163 
164 fstrm_res
fstrm_control_add_field_content_type(struct fstrm_control * c,const uint8_t * content_type,size_t len_content_type)165 fstrm_control_add_field_content_type(struct fstrm_control *c,
166 				     const uint8_t *content_type,
167 				     size_t len_content_type)
168 {
169 	fs_buf ctype;
170 	ctype.len = len_content_type;
171 	ctype.data = my_malloc(ctype.len);
172 	memcpy(ctype.data, content_type, ctype.len);
173 	fs_bufvec_add(c->content_types, ctype);
174 
175 	return fstrm_res_success;
176 }
177 
178 fstrm_res
fstrm_control_match_field_content_type(const struct fstrm_control * c,const uint8_t * match,const size_t len_match)179 fstrm_control_match_field_content_type(const struct fstrm_control *c,
180 				       const uint8_t *match,
181 				       const size_t len_match)
182 {
183 	fstrm_res res;
184 	size_t n_ctype = 0;
185 
186 	/*
187 	 * STOP and FINISH frames don't have a content type. They never match.
188 	 */
189 	if (c->type == FSTRM_CONTROL_STOP || c->type == FSTRM_CONTROL_FINISH)
190 		return fstrm_res_failure;
191 
192 	res = fstrm_control_get_num_field_content_type(c, &n_ctype);
193 	if (res != fstrm_res_success)
194 		return res;
195 
196 	if (n_ctype == 0) {
197 		/* Control frame doesn't set any content type. */
198 		return fstrm_res_success;
199 	} else {
200 		/*
201 		 * The content type must match one of the control frame's
202 		 * content types.
203 		 */
204 
205 		if (match == NULL) {
206 			/*
207 			 * The control frame has at least one content type set,
208 			 * which cannot match an unset content type.
209 			 */
210 			return fstrm_res_failure;
211 		}
212 
213 		for (size_t idx = 0; idx < n_ctype; idx++) {
214 			/*
215 			 * Check against all the content types in the control
216 			 * frame.
217 			 */
218 			const uint8_t *content_type = NULL;
219 			size_t len_content_type = 0;
220 
221 			res = fstrm_control_get_field_content_type(c, idx,
222 				&content_type, &len_content_type);
223 			if (res != fstrm_res_success)
224 				return res;
225 
226 			if (len_content_type != len_match)
227 				continue;
228 			if (memcmp(content_type, match, len_match) == 0) {
229 				/* Exact match. */
230 				return fstrm_res_success;
231 			}
232 		}
233 	}
234 
235 	return fstrm_res_failure;
236 }
237 
238 fstrm_res
fstrm_control_decode(struct fstrm_control * c,const void * control_frame,size_t len_control_frame,const uint32_t flags)239 fstrm_control_decode(struct fstrm_control *c,
240 		     const void *control_frame,
241 		     size_t len_control_frame,
242 		     const uint32_t flags)
243 {
244 	const uint8_t *buf = control_frame;
245 	size_t len = len_control_frame;
246 	uint32_t val;
247 
248 	fstrm_control_reset(c);
249 
250 	if (flags & FSTRM_CONTROL_FLAG_WITH_HEADER) {
251 		/* Read the outer frame length. */
252 		if (!fs_load_be32(&buf, &len, &val))
253 			return fstrm_res_failure;
254 
255 		/* The outer frame length must be zero, since this is a control frame. */
256 		if (val != 0)
257 			return fstrm_res_failure;
258 
259 		/* Read the control frame length. */
260 		if (!fs_load_be32(&buf, &len, &val))
261 			return fstrm_res_failure;
262 
263 		/* Enforce maximum control frame size. */
264 		if (val > FSTRM_CONTROL_FRAME_LENGTH_MAX)
265 			return fstrm_res_failure;
266 
267 		/*
268 		 * Require that the control frame length matches the number of
269 		 * bytes remaining in 'buf'.
270 		 */
271 		if (val != len)
272 			return fstrm_res_failure;
273 	} else {
274 		/* Enforce maximum control frame size. */
275 		if (len_control_frame > FSTRM_CONTROL_FRAME_LENGTH_MAX)
276 			return fstrm_res_failure;
277 	}
278 
279 	/* Read the control frame type. */
280 	if (!fs_load_be32(&buf, &len, &val))
281 		return fstrm_res_failure;
282 	switch (val) {
283 	case FSTRM_CONTROL_ACCEPT:	/* FALLTHROUGH */
284 	case FSTRM_CONTROL_START:	/* FALLTHROUGH */
285 	case FSTRM_CONTROL_STOP:	/* FALLTHROUGH */
286 	case FSTRM_CONTROL_READY:	/* FALLTHROUGH */
287 	case FSTRM_CONTROL_FINISH:
288 		c->type = (fstrm_control_type) val;
289 		break;
290 	default:
291 		return fstrm_res_failure;
292 	}
293 
294 	/* Read any control frame fields. */
295 	while (len > 0) {
296 		/* Read the control frame field type. */
297 		if (!fs_load_be32(&buf, &len, &val))
298 			return fstrm_res_failure;
299 
300 		switch (val) {
301 		case FSTRM_CONTROL_FIELD_CONTENT_TYPE: {
302 			fs_buf c_type;
303 
304 			/* Read the length of the "Content Type" payload. */
305 			if (!fs_load_be32(&buf, &len, &val))
306 				return fstrm_res_failure;
307 			c_type.len = val;
308 
309 			/*
310 			 * Sanity check the length field. It cannot be larger
311 			 * than 'len', the number of bytes remaining in 'buf'.
312 			 */
313 			if (c_type.len > len)
314 				return fstrm_res_failure;
315 
316 			/* Enforce limit on "Content Type" payload length. */
317 			if (c_type.len > FSTRM_CONTROL_FIELD_CONTENT_TYPE_LENGTH_MAX)
318 				return fstrm_res_failure;
319 
320 			/* Read the "Content Type" payload. */
321 			c_type.data = my_malloc(c_type.len);
322 			if (!fs_load_bytes(c_type.data, c_type.len, &buf, &len))
323 			{
324 				my_free(c_type.data);
325 				return fstrm_res_failure;
326 			}
327 
328 			/* Insert the "Content Type" field. */
329 			fs_bufvec_add(c->content_types, c_type);
330 
331 			break;
332 		}
333 		default:
334 			return fstrm_res_failure;
335 		}
336 	}
337 
338 	/* Enforce limits on the number of "Content Type" fields. */
339 	const size_t n_ctype = fs_bufvec_size(c->content_types);
340 	switch (c->type) {
341 	case FSTRM_CONTROL_START:
342 		if (n_ctype > 1)
343 			return fstrm_res_failure;
344 		break;
345 	case FSTRM_CONTROL_STOP:
346 		/* FALLTHROUGH */
347 	case FSTRM_CONTROL_FINISH:
348 		if (n_ctype > 0)
349 			return fstrm_res_failure;
350 		break;
351 	case FSTRM_CONTROL_ACCEPT:
352 		/* FALLTHROUGH */
353 	case FSTRM_CONTROL_READY:
354 		/* FALLTHROUGH */
355 	default:
356 		break;
357 	}
358 
359 	return fstrm_res_success;
360 }
361 
362 fstrm_res
fstrm_control_encoded_size(const struct fstrm_control * c,size_t * len_control_frame,const uint32_t flags)363 fstrm_control_encoded_size(const struct fstrm_control *c,
364 			   size_t *len_control_frame,
365 			   const uint32_t flags)
366 {
367 	size_t len = 0;
368 
369 	if (flags & FSTRM_CONTROL_FLAG_WITH_HEADER) {
370 		/* Escape: 32-bit BE integer. */
371 		len += sizeof(uint32_t);
372 
373 		/* Frame length: 32-bit BE integer. */
374 		len += sizeof(uint32_t);
375 	}
376 
377 	/* Control type: 32-bit BE integer. */
378 	len += sizeof(uint32_t);
379 
380 	/* "Content Type" fields. */
381 	for (size_t i = 0; i < fs_bufvec_size(c->content_types); i++) {
382 		/* Do not add "Content Type" fields to STOP or FINISH frames. */
383 		if (c->type == FSTRM_CONTROL_STOP ||
384 		    c->type == FSTRM_CONTROL_FINISH)
385 		{
386 			break;
387 		}
388 
389 		fs_buf c_type = fs_bufvec_value(c->content_types, i);
390 
391 		/* FSTRM_CONTROL_FIELD_CONTENT_TYPE: 32-bit BE integer. */
392 		len += sizeof(uint32_t);
393 
394 		/* Length of the "Content Type" string: 32-bit BE integer. */
395 		len += sizeof(uint32_t);
396 
397 		/* Enforce limit on "Content Type" payload length. */
398 		if (c_type.len > FSTRM_CONTROL_FIELD_CONTENT_TYPE_LENGTH_MAX)
399 			return fstrm_res_failure;
400 
401 		/* The "Content Type" payload. */
402 		len += c_type.len;
403 
404 		/* Only add one "Content Type" field to START frames. */
405 		if (c->type == FSTRM_CONTROL_START)
406 			break;
407 	}
408 
409 	/* Sanity check the overall length. */
410 	if (len > FSTRM_CONTROL_FRAME_LENGTH_MAX)
411 		return fstrm_res_failure;
412 
413 	*len_control_frame = len;
414 	return fstrm_res_success;
415 }
416 
417 fstrm_res
fstrm_control_encode(const struct fstrm_control * c,void * control_frame,size_t * len_control_frame,const uint32_t flags)418 fstrm_control_encode(const struct fstrm_control *c,
419 		     void *control_frame,
420 		     size_t *len_control_frame,
421 		     const uint32_t flags)
422 {
423 	fstrm_res res;
424 	size_t encoded_size;
425 
426 	/* Calculate the size of the control frame. */
427 	res = fstrm_control_encoded_size(c, &encoded_size, flags);
428 	if (res != fstrm_res_success)
429 		return res;
430 
431 	/*
432 	 * The caller must have provided a large enough buffer to serialize the
433 	 * control frame.
434 	 */
435 	if (*len_control_frame < encoded_size)
436 		return fstrm_res_failure;
437 
438 	/*
439 	 * Now actually serialize the control frame.
440 	 */
441 	size_t len = encoded_size;
442 	uint8_t *buf = control_frame;
443 
444 	if (flags & FSTRM_CONTROL_FLAG_WITH_HEADER) {
445 		/* Escape: 32-bit BE integer. Zero. */
446 		if (!fs_store_be32(&buf, &len, 0))
447 			return fstrm_res_failure;
448 
449 		/*
450 		 * Frame length: 32-bit BE integer.
451 		 *
452 		 * This does not include the length of the escape frame or the length
453 		 * of the frame length field itself, so subtract 2*4 bytes from the
454 		 * total length.
455 		 */
456 		if (!fs_store_be32(&buf, &len, encoded_size - 2 * sizeof(uint32_t)))
457 			return fstrm_res_failure;
458 	}
459 
460 	/* Control type: 32-bit BE integer. */
461 	if (!fs_store_be32(&buf, &len, c->type))
462 		return fstrm_res_failure;
463 
464 	/* "Content Type" fields. */
465 	for (size_t i = 0; i < fs_bufvec_size(c->content_types); i++) {
466 		/* Do not add "Content Type" fields to STOP or FINISH frames. */
467 		if (c->type == FSTRM_CONTROL_STOP ||
468 		    c->type == FSTRM_CONTROL_FINISH)
469 		{
470 			break;
471 		}
472 
473 		fs_buf c_type = fs_bufvec_value(c->content_types, i);
474 
475 		/* FSTRM_CONTROL_FIELD_CONTENT_TYPE: 32-bit BE integer. */
476 		if (!fs_store_be32(&buf, &len, FSTRM_CONTROL_FIELD_CONTENT_TYPE))
477 			return fstrm_res_failure;
478 
479 		/* Length of the "Content Type" payload: 32-bit BE integer. */
480 		if (!fs_store_be32(&buf, &len, c_type.len))
481 			return fstrm_res_failure;
482 
483 		/* The "Content Type" string itself. */
484 		if (!fs_store_bytes(&buf, &len, c_type.data, c_type.len))
485 			return fstrm_res_failure;
486 
487 		/* Only add one "Content Type" field to START frames. */
488 		if (c->type == FSTRM_CONTROL_START)
489 			break;
490 	}
491 
492 	*len_control_frame = encoded_size;
493 	return fstrm_res_success;
494 }
495