1 /*
2  * JavaScript Object Notation (JSON) parser (RFC7159)
3  * Copyright (c) 2017, Qualcomm Atheros, Inc.
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 
11 #include "common.h"
12 #include "base64.h"
13 #include "json.h"
14 
15 #define JSON_MAX_DEPTH 10
16 #define JSON_MAX_TOKENS 500
17 
18 
json_escape_string(char * txt,size_t maxlen,const char * data,size_t len)19 void json_escape_string(char *txt, size_t maxlen, const char *data, size_t len)
20 {
21 	char *end = txt + maxlen;
22 	size_t i;
23 
24 	for (i = 0; i < len; i++) {
25 		if (txt + 4 >= end)
26 			break;
27 
28 		switch (data[i]) {
29 		case '\"':
30 			*txt++ = '\\';
31 			*txt++ = '\"';
32 			break;
33 		case '\\':
34 			*txt++ = '\\';
35 			*txt++ = '\\';
36 			break;
37 		case '\n':
38 			*txt++ = '\\';
39 			*txt++ = 'n';
40 			break;
41 		case '\r':
42 			*txt++ = '\\';
43 			*txt++ = 'r';
44 			break;
45 		case '\t':
46 			*txt++ = '\\';
47 			*txt++ = 't';
48 			break;
49 		default:
50 			if (data[i] >= 32 && data[i] <= 126) {
51 				*txt++ = data[i];
52 			} else {
53 				txt += os_snprintf(txt, end - txt, "\\u%04x",
54 						   (unsigned char) data[i]);
55 			}
56 			break;
57 		}
58 	}
59 
60 	*txt = '\0';
61 }
62 
63 
json_parse_string(const char ** json_pos,const char * end)64 static char * json_parse_string(const char **json_pos, const char *end)
65 {
66 	const char *pos = *json_pos;
67 	char *str, *spos, *s_end;
68 	size_t max_len, buf_len;
69 	u8 bin[2];
70 
71 	pos++; /* skip starting quote */
72 
73 	max_len = end - pos + 1;
74 	buf_len = max_len > 10 ? 10 : max_len;
75 	str = os_malloc(buf_len);
76 	if (!str)
77 		return NULL;
78 	spos = str;
79 	s_end = str + buf_len;
80 
81 	for (; pos < end; pos++) {
82 		if (buf_len < max_len && s_end - spos < 3) {
83 			char *tmp;
84 			int idx;
85 
86 			idx = spos - str;
87 			buf_len *= 2;
88 			if (buf_len > max_len)
89 				buf_len = max_len;
90 			tmp = os_realloc(str, buf_len);
91 			if (!tmp)
92 				goto fail;
93 			str = tmp;
94 			spos = str + idx;
95 			s_end = str + buf_len;
96 		}
97 
98 		switch (*pos) {
99 		case '\"': /* end string */
100 			*spos = '\0';
101 			/* caller will move to the next position */
102 			*json_pos = pos;
103 			return str;
104 		case '\\':
105 			pos++;
106 			if (pos >= end) {
107 				wpa_printf(MSG_DEBUG,
108 					   "JSON: Truncated \\ escape");
109 				goto fail;
110 			}
111 			switch (*pos) {
112 			case '"':
113 			case '\\':
114 			case '/':
115 				*spos++ = *pos;
116 				break;
117 			case 'n':
118 				*spos++ = '\n';
119 				break;
120 			case 'r':
121 				*spos++ = '\r';
122 				break;
123 			case 't':
124 				*spos++ = '\t';
125 				break;
126 			case 'u':
127 				if (end - pos < 5 ||
128 				    hexstr2bin(pos + 1, bin, 2) < 0 ||
129 				    bin[1] == 0x00) {
130 					wpa_printf(MSG_DEBUG,
131 						   "JSON: Invalid \\u escape");
132 					goto fail;
133 				}
134 				if (bin[0] == 0x00) {
135 					*spos++ = bin[1];
136 				} else {
137 					*spos++ = bin[0];
138 					*spos++ = bin[1];
139 				}
140 				pos += 4;
141 				break;
142 			default:
143 				wpa_printf(MSG_DEBUG,
144 					   "JSON: Unknown escape '%c'", *pos);
145 				goto fail;
146 			}
147 			break;
148 		default:
149 			*spos++ = *pos;
150 			break;
151 		}
152 	}
153 
154 fail:
155 	os_free(str);
156 	return NULL;
157 }
158 
159 
json_parse_number(const char ** json_pos,const char * end,int * ret_val)160 static int json_parse_number(const char **json_pos, const char *end,
161 			     int *ret_val)
162 {
163 	const char *pos = *json_pos;
164 	size_t len;
165 	char *str;
166 
167 	for (; pos < end; pos++) {
168 		if (*pos != '-' && (*pos < '0' || *pos > '9')) {
169 			pos--;
170 			break;
171 		}
172 	}
173 	if (pos == end)
174 		pos--;
175 	if (pos < *json_pos)
176 		return -1;
177 	len = pos - *json_pos + 1;
178 	str = os_malloc(len + 1);
179 	if (!str)
180 		return -1;
181 	os_memcpy(str, *json_pos, len);
182 	str[len] = '\0';
183 
184 	*ret_val = atoi(str);
185 	os_free(str);
186 	*json_pos = pos;
187 	return 0;
188 }
189 
190 
json_check_tree_state(struct json_token * token)191 static int json_check_tree_state(struct json_token *token)
192 {
193 	if (!token)
194 		return 0;
195 	if (json_check_tree_state(token->child) < 0 ||
196 	    json_check_tree_state(token->sibling) < 0)
197 		return -1;
198 	if (token->state != JSON_COMPLETED) {
199 		wpa_printf(MSG_DEBUG,
200 			   "JSON: Unexpected token state %d (name=%s type=%d)",
201 			   token->state, token->name ? token->name : "N/A",
202 			   token->type);
203 		return -1;
204 	}
205 	return 0;
206 }
207 
208 
json_alloc_token(unsigned int * tokens)209 static struct json_token * json_alloc_token(unsigned int *tokens)
210 {
211 	(*tokens)++;
212 	if (*tokens > JSON_MAX_TOKENS) {
213 		wpa_printf(MSG_DEBUG, "JSON: Maximum token limit exceeded");
214 		return NULL;
215 	}
216 	return os_zalloc(sizeof(struct json_token));
217 }
218 
219 
json_parse(const char * data,size_t data_len)220 struct json_token * json_parse(const char *data, size_t data_len)
221 {
222 	struct json_token *root = NULL, *curr_token = NULL, *token = NULL;
223 	const char *pos, *end;
224 	char *str;
225 	int num;
226 	unsigned int depth = 0;
227 	unsigned int tokens = 0;
228 
229 	pos = data;
230 	end = data + data_len;
231 
232 	for (; pos < end; pos++) {
233 		switch (*pos) {
234 		case '[': /* start array */
235 		case '{': /* start object */
236 			if (!curr_token) {
237 				token = json_alloc_token(&tokens);
238 				if (!token)
239 					goto fail;
240 				if (!root)
241 					root = token;
242 			} else if (curr_token->state == JSON_WAITING_VALUE) {
243 				token = curr_token;
244 			} else if (curr_token->parent &&
245 				   curr_token->parent->type == JSON_ARRAY &&
246 				   curr_token->parent->state == JSON_STARTED &&
247 				   curr_token->state == JSON_EMPTY) {
248 				token = curr_token;
249 			} else {
250 				wpa_printf(MSG_DEBUG,
251 					   "JSON: Invalid state for start array/object");
252 				goto fail;
253 			}
254 			depth++;
255 			if (depth > JSON_MAX_DEPTH) {
256 				wpa_printf(MSG_DEBUG,
257 					   "JSON: Max depth exceeded");
258 				goto fail;
259 			}
260 			token->type = *pos == '[' ? JSON_ARRAY : JSON_OBJECT;
261 			token->state = JSON_STARTED;
262 			token->child = json_alloc_token(&tokens);
263 			if (!token->child)
264 				goto fail;
265 			curr_token = token->child;
266 			curr_token->parent = token;
267 			curr_token->state = JSON_EMPTY;
268 			break;
269 		case ']': /* end array */
270 		case '}': /* end object */
271 			if (!curr_token || !curr_token->parent ||
272 			    curr_token->parent->state != JSON_STARTED ||
273 			    depth == 0) {
274 				wpa_printf(MSG_DEBUG,
275 					   "JSON: Invalid state for end array/object");
276 				goto fail;
277 			}
278 			depth--;
279 			curr_token = curr_token->parent;
280 			if ((*pos == ']' &&
281 			     curr_token->type != JSON_ARRAY) ||
282 			    (*pos == '}' &&
283 			     curr_token->type != JSON_OBJECT)) {
284 				wpa_printf(MSG_DEBUG,
285 					   "JSON: Array/Object mismatch");
286 				goto fail;
287 			}
288 			if (curr_token->child->state == JSON_EMPTY &&
289 			    !curr_token->child->child &&
290 			    !curr_token->child->sibling) {
291 				/* Remove pending child token since the
292 				 * array/object was empty. */
293 				json_free(curr_token->child);
294 				curr_token->child = NULL;
295 			}
296 			curr_token->state = JSON_COMPLETED;
297 			break;
298 		case '\"': /* string */
299 			str = json_parse_string(&pos, end);
300 			if (!str)
301 				goto fail;
302 			if (!curr_token) {
303 				token = json_alloc_token(&tokens);
304 				if (!token) {
305 					os_free(str);
306 					goto fail;
307 				}
308 				token->type = JSON_STRING;
309 				token->string = str;
310 				token->state = JSON_COMPLETED;
311 			} else if (curr_token->parent &&
312 				   curr_token->parent->type == JSON_ARRAY &&
313 				   curr_token->parent->state == JSON_STARTED &&
314 				   curr_token->state == JSON_EMPTY) {
315 				curr_token->string = str;
316 				curr_token->state = JSON_COMPLETED;
317 				curr_token->type = JSON_STRING;
318 				wpa_printf(MSG_MSGDUMP,
319 					   "JSON: String value: '%s'",
320 					   curr_token->string);
321 			} else if (curr_token->state == JSON_EMPTY) {
322 				curr_token->type = JSON_VALUE;
323 				curr_token->name = str;
324 				curr_token->state = JSON_STARTED;
325 			} else if (curr_token->state == JSON_WAITING_VALUE) {
326 				curr_token->string = str;
327 				curr_token->state = JSON_COMPLETED;
328 				curr_token->type = JSON_STRING;
329 				wpa_printf(MSG_MSGDUMP,
330 					   "JSON: String value: '%s' = '%s'",
331 					   curr_token->name,
332 					   curr_token->string);
333 			} else {
334 				wpa_printf(MSG_DEBUG,
335 					   "JSON: Invalid state for a string");
336 				os_free(str);
337 				goto fail;
338 			}
339 			break;
340 		case ' ':
341 		case '\t':
342 		case '\r':
343 		case '\n':
344 			/* ignore whitespace */
345 			break;
346 		case ':': /* name/value separator */
347 			if (!curr_token || curr_token->state != JSON_STARTED)
348 				goto fail;
349 			curr_token->state = JSON_WAITING_VALUE;
350 			break;
351 		case ',': /* member separator */
352 			if (!curr_token)
353 				goto fail;
354 			curr_token->sibling = json_alloc_token(&tokens);
355 			if (!curr_token->sibling)
356 				goto fail;
357 			curr_token->sibling->parent = curr_token->parent;
358 			curr_token = curr_token->sibling;
359 			curr_token->state = JSON_EMPTY;
360 			break;
361 		case 't': /* true */
362 		case 'f': /* false */
363 		case 'n': /* null */
364 			if (!((end - pos >= 4 &&
365 			       os_strncmp(pos, "true", 4) == 0) ||
366 			      (end - pos >= 5 &&
367 			       os_strncmp(pos, "false", 5) == 0) ||
368 			      (end - pos >= 4 &&
369 			       os_strncmp(pos, "null", 4) == 0))) {
370 				wpa_printf(MSG_DEBUG,
371 					   "JSON: Invalid literal name");
372 				goto fail;
373 			}
374 			if (!curr_token) {
375 				token = json_alloc_token(&tokens);
376 				if (!token)
377 					goto fail;
378 				curr_token = token;
379 			} else if (curr_token->state == JSON_WAITING_VALUE) {
380 				wpa_printf(MSG_MSGDUMP,
381 					   "JSON: Literal name: '%s' = %c",
382 					   curr_token->name, *pos);
383 			} else if (curr_token->parent &&
384 				   curr_token->parent->type == JSON_ARRAY &&
385 				   curr_token->parent->state == JSON_STARTED &&
386 				   curr_token->state == JSON_EMPTY) {
387 				wpa_printf(MSG_MSGDUMP,
388 					   "JSON: Literal name: %c", *pos);
389 			} else {
390 				wpa_printf(MSG_DEBUG,
391 					   "JSON: Invalid state for a literal name");
392 				goto fail;
393 			}
394 			switch (*pos) {
395 			case 't':
396 				curr_token->type = JSON_BOOLEAN;
397 				curr_token->number = 1;
398 				pos += 3;
399 				break;
400 			case 'f':
401 				curr_token->type = JSON_BOOLEAN;
402 				curr_token->number = 0;
403 				pos += 4;
404 				break;
405 			case 'n':
406 				curr_token->type = JSON_NULL;
407 				pos += 3;
408 				break;
409 			}
410 			curr_token->state = JSON_COMPLETED;
411 			break;
412 		case '-':
413 		case '0':
414 		case '1':
415 		case '2':
416 		case '3':
417 		case '4':
418 		case '5':
419 		case '6':
420 		case '7':
421 		case '8':
422 		case '9':
423 			/* number */
424 			if (json_parse_number(&pos, end, &num) < 0)
425 				goto fail;
426 			if (!curr_token) {
427 				token = json_alloc_token(&tokens);
428 				if (!token)
429 					goto fail;
430 				token->type = JSON_NUMBER;
431 				token->number = num;
432 				token->state = JSON_COMPLETED;
433 			} else if (curr_token->state == JSON_WAITING_VALUE) {
434 				curr_token->number = num;
435 				curr_token->state = JSON_COMPLETED;
436 				curr_token->type = JSON_NUMBER;
437 				wpa_printf(MSG_MSGDUMP,
438 					   "JSON: Number value: '%s' = '%d'",
439 					   curr_token->name,
440 					   curr_token->number);
441 			} else if (curr_token->parent &&
442 				   curr_token->parent->type == JSON_ARRAY &&
443 				   curr_token->parent->state == JSON_STARTED &&
444 				   curr_token->state == JSON_EMPTY) {
445 				curr_token->number = num;
446 				curr_token->state = JSON_COMPLETED;
447 				curr_token->type = JSON_NUMBER;
448 				wpa_printf(MSG_MSGDUMP,
449 					   "JSON: Number value: %d",
450 					   curr_token->number);
451 			} else {
452 				wpa_printf(MSG_DEBUG,
453 					   "JSON: Invalid state for a number");
454 				goto fail;
455 			}
456 			break;
457 		default:
458 			wpa_printf(MSG_DEBUG,
459 				   "JSON: Unexpected JSON character: %c", *pos);
460 			goto fail;
461 		}
462 
463 		if (!root)
464 			root = token;
465 		if (!curr_token)
466 			curr_token = token;
467 	}
468 
469 	if (json_check_tree_state(root) < 0) {
470 		wpa_printf(MSG_DEBUG, "JSON: Incomplete token in the tree");
471 		goto fail;
472 	}
473 
474 	return root;
475 fail:
476 	wpa_printf(MSG_DEBUG, "JSON: Parsing failed");
477 	json_free(root);
478 	return NULL;
479 }
480 
481 
json_free(struct json_token * json)482 void json_free(struct json_token *json)
483 {
484 	if (!json)
485 		return;
486 	json_free(json->child);
487 	json_free(json->sibling);
488 	os_free(json->name);
489 	os_free(json->string);
490 	os_free(json);
491 }
492 
493 
json_get_member(struct json_token * json,const char * name)494 struct json_token * json_get_member(struct json_token *json, const char *name)
495 {
496 	struct json_token *token, *ret = NULL;
497 
498 	if (!json || json->type != JSON_OBJECT)
499 		return NULL;
500 	/* Return last matching entry */
501 	for (token = json->child; token; token = token->sibling) {
502 		if (token->name && os_strcmp(token->name, name) == 0)
503 			ret = token;
504 	}
505 	return ret;
506 }
507 
508 
json_get_member_base64url(struct json_token * json,const char * name)509 struct wpabuf * json_get_member_base64url(struct json_token *json,
510 					  const char *name)
511 {
512 	struct json_token *token;
513 	unsigned char *buf;
514 	size_t buflen;
515 	struct wpabuf *ret;
516 
517 	token = json_get_member(json, name);
518 	if (!token || token->type != JSON_STRING)
519 		return NULL;
520 	buf = base64_url_decode(token->string, os_strlen(token->string),
521 				&buflen);
522 	if (!buf)
523 		return NULL;
524 	ret = wpabuf_alloc_ext_data(buf, buflen);
525 	if (!ret)
526 		os_free(buf);
527 
528 	return ret;
529 }
530 
531 
json_get_member_base64(struct json_token * json,const char * name)532 struct wpabuf * json_get_member_base64(struct json_token *json,
533 				       const char *name)
534 {
535 	struct json_token *token;
536 	unsigned char *buf;
537 	size_t buflen;
538 	struct wpabuf *ret;
539 
540 	token = json_get_member(json, name);
541 	if (!token || token->type != JSON_STRING)
542 		return NULL;
543 	buf = base64_decode(token->string, os_strlen(token->string), &buflen);
544 	if (!buf)
545 		return NULL;
546 	ret = wpabuf_alloc_ext_data(buf, buflen);
547 	if (!ret)
548 		os_free(buf);
549 
550 	return ret;
551 }
552 
553 
json_type_str(enum json_type type)554 static const char * json_type_str(enum json_type type)
555 {
556 	switch (type) {
557 	case JSON_VALUE:
558 		return "VALUE";
559 	case JSON_OBJECT:
560 		return "OBJECT";
561 	case JSON_ARRAY:
562 		return "ARRAY";
563 	case JSON_STRING:
564 		return "STRING";
565 	case JSON_NUMBER:
566 		return "NUMBER";
567 	case JSON_BOOLEAN:
568 		return "BOOLEAN";
569 	case JSON_NULL:
570 		return "NULL";
571 	}
572 	return "??";
573 }
574 
575 
json_print_token(struct json_token * token,int depth,char * buf,size_t buflen)576 static void json_print_token(struct json_token *token, int depth,
577 			     char *buf, size_t buflen)
578 {
579 	size_t len;
580 	int ret;
581 
582 	if (!token)
583 		return;
584 	len = os_strlen(buf);
585 	ret = os_snprintf(buf + len, buflen - len, "[%d:%s:%s]",
586 			  depth, json_type_str(token->type),
587 			  token->name ? token->name : "");
588 	if (os_snprintf_error(buflen - len, ret)) {
589 		buf[len] = '\0';
590 		return;
591 	}
592 	json_print_token(token->child, depth + 1, buf, buflen);
593 	json_print_token(token->sibling, depth, buf, buflen);
594 }
595 
596 
json_print_tree(struct json_token * root,char * buf,size_t buflen)597 void json_print_tree(struct json_token *root, char *buf, size_t buflen)
598 {
599 	buf[0] = '\0';
600 	json_print_token(root, 1, buf, buflen);
601 }
602 
603 
json_add_int(struct wpabuf * json,const char * name,int val)604 void json_add_int(struct wpabuf *json, const char *name, int val)
605 {
606 	wpabuf_printf(json, "\"%s\":%d", name, val);
607 }
608 
609 
json_add_string(struct wpabuf * json,const char * name,const char * val)610 void json_add_string(struct wpabuf *json, const char *name, const char *val)
611 {
612 	wpabuf_printf(json, "\"%s\":\"%s\"", name, val);
613 }
614 
615 
json_add_string_escape(struct wpabuf * json,const char * name,const void * val,size_t len)616 int json_add_string_escape(struct wpabuf *json, const char *name,
617 			   const void *val, size_t len)
618 {
619 	char *tmp;
620 	size_t tmp_len = 6 * len + 1;
621 
622 	tmp = os_malloc(tmp_len);
623 	if (!tmp)
624 		return -1;
625 	json_escape_string(tmp, tmp_len, val, len);
626 	json_add_string(json, name, tmp);
627 	bin_clear_free(tmp, tmp_len);
628 	return 0;
629 }
630 
631 
json_add_base64url(struct wpabuf * json,const char * name,const void * val,size_t len)632 int json_add_base64url(struct wpabuf *json, const char *name, const void *val,
633 		       size_t len)
634 {
635 	char *b64;
636 
637 	b64 = base64_url_encode(val, len, NULL);
638 	if (!b64)
639 		return -1;
640 	json_add_string(json, name, b64);
641 	os_free(b64);
642 	return 0;
643 }
644 
645 
json_add_base64(struct wpabuf * json,const char * name,const void * val,size_t len)646 int json_add_base64(struct wpabuf *json, const char *name, const void *val,
647 		    size_t len)
648 {
649 	char *b64;
650 
651 	b64 = base64_encode_no_lf(val, len, NULL);
652 	if (!b64)
653 		return -1;
654 	json_add_string(json, name, b64);
655 	os_free(b64);
656 	return 0;
657 }
658 
659 
json_start_object(struct wpabuf * json,const char * name)660 void json_start_object(struct wpabuf *json, const char *name)
661 {
662 	if (name)
663 		wpabuf_printf(json, "\"%s\":", name);
664 	wpabuf_put_u8(json, '{');
665 }
666 
667 
json_end_object(struct wpabuf * json)668 void json_end_object(struct wpabuf *json)
669 {
670 	wpabuf_put_u8(json, '}');
671 }
672 
673 
json_start_array(struct wpabuf * json,const char * name)674 void json_start_array(struct wpabuf *json, const char *name)
675 {
676 	if (name)
677 		wpabuf_printf(json, "\"%s\":", name);
678 	wpabuf_put_u8(json, '[');
679 }
680 
681 
json_end_array(struct wpabuf * json)682 void json_end_array(struct wpabuf *json)
683 {
684 	wpabuf_put_u8(json, ']');
685 }
686 
687 
json_value_sep(struct wpabuf * json)688 void json_value_sep(struct wpabuf *json)
689 {
690 	wpabuf_put_u8(json, ',');
691 }
692