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_get_number_len(const char * json_pos,const char * end,bool * is_double)160 static size_t json_get_number_len(const char *json_pos, const char *end,
161 bool *is_double)
162 {
163 const char *pos = json_pos;
164 size_t len;
165
166 for (; pos < end; pos++) {
167 switch (*pos) {
168 case '.':
169 case 'e':
170 case 'E':
171 *is_double = true;
172 case '-':
173 case '0':
174 case '1':
175 case '2':
176 case '3':
177 case '4':
178 case '5':
179 case '6':
180 case '7':
181 case '8':
182 case '9':
183 continue;
184 default:
185 pos--;
186 break;
187 }
188 break;
189 }
190 if (pos == end)
191 pos--;
192 if (pos < json_pos)
193 return 0;
194 len = pos - json_pos + 1;
195
196 return len;
197 }
198
199
json_parse_double(const char ** json_pos,size_t len,double * ret_val)200 static int json_parse_double(const char **json_pos, size_t len, double *ret_val)
201 {
202 char *str;
203 char *endptr;
204
205 str = os_malloc(len + 1);
206 if (!str)
207 return -1;
208 os_memcpy(str, *json_pos, len);
209 str[len] = '\0';
210
211 *ret_val = strtod(str, &endptr);
212 if (endptr == str) {
213 os_free(str);
214 return -1;
215 }
216 os_free(str);
217 *json_pos += len - 1;
218 return 0;
219 }
220
221
json_parse_number(const char ** json_pos,size_t len,int * ret_val)222 static int json_parse_number(const char **json_pos, size_t len, int *ret_val)
223 {
224 char *str;
225
226 str = os_malloc(len + 1);
227 if (!str)
228 return -1;
229 os_memcpy(str, *json_pos, len);
230 str[len] = '\0';
231
232 *ret_val = atoi(str);
233 os_free(str);
234 *json_pos += len - 1;
235 return 0;
236 }
237
238
json_check_tree_state(struct json_token * token)239 static int json_check_tree_state(struct json_token *token)
240 {
241 if (!token)
242 return 0;
243 if (json_check_tree_state(token->child) < 0 ||
244 json_check_tree_state(token->sibling) < 0)
245 return -1;
246 if (token->state != JSON_COMPLETED) {
247 wpa_printf(MSG_DEBUG,
248 "JSON: Unexpected token state %d (name=%s type=%d)",
249 token->state, token->name ? token->name : "N/A",
250 token->type);
251 return -1;
252 }
253 return 0;
254 }
255
256
json_alloc_token(unsigned int * tokens)257 static struct json_token * json_alloc_token(unsigned int *tokens)
258 {
259 (*tokens)++;
260 if (*tokens > JSON_MAX_TOKENS) {
261 wpa_printf(MSG_DEBUG, "JSON: Maximum token limit exceeded");
262 return NULL;
263 }
264 return os_zalloc(sizeof(struct json_token));
265 }
266
267
json_parse(const char * data,size_t data_len)268 struct json_token * json_parse(const char *data, size_t data_len)
269 {
270 struct json_token *root = NULL, *curr_token = NULL, *token = NULL;
271 const char *pos, *end;
272 char *str;
273 int num;
274 double dnum;
275 bool is_double;
276 unsigned int depth = 0;
277 unsigned int tokens = 0;
278 size_t len;
279
280 pos = data;
281 end = data + data_len;
282
283 for (; pos < end; pos++) {
284 switch (*pos) {
285 case '[': /* start array */
286 case '{': /* start object */
287 if (!curr_token) {
288 token = json_alloc_token(&tokens);
289 if (!token)
290 goto fail;
291 if (!root)
292 root = token;
293 } else if (curr_token->state == JSON_WAITING_VALUE) {
294 token = curr_token;
295 } else if (curr_token->parent &&
296 curr_token->parent->type == JSON_ARRAY &&
297 curr_token->parent->state == JSON_STARTED &&
298 curr_token->state == JSON_EMPTY) {
299 token = curr_token;
300 } else {
301 wpa_printf(MSG_DEBUG,
302 "JSON: Invalid state for start array/object");
303 goto fail;
304 }
305 depth++;
306 if (depth > JSON_MAX_DEPTH) {
307 wpa_printf(MSG_DEBUG,
308 "JSON: Max depth exceeded");
309 goto fail;
310 }
311 token->type = *pos == '[' ? JSON_ARRAY : JSON_OBJECT;
312 token->state = JSON_STARTED;
313 token->child = json_alloc_token(&tokens);
314 if (!token->child)
315 goto fail;
316 curr_token = token->child;
317 curr_token->parent = token;
318 curr_token->state = JSON_EMPTY;
319 break;
320 case ']': /* end array */
321 case '}': /* end object */
322 if (!curr_token || !curr_token->parent ||
323 curr_token->parent->state != JSON_STARTED ||
324 depth == 0) {
325 wpa_printf(MSG_DEBUG,
326 "JSON: Invalid state for end array/object");
327 goto fail;
328 }
329 depth--;
330 curr_token = curr_token->parent;
331 if ((*pos == ']' &&
332 curr_token->type != JSON_ARRAY) ||
333 (*pos == '}' &&
334 curr_token->type != JSON_OBJECT)) {
335 wpa_printf(MSG_DEBUG,
336 "JSON: Array/Object mismatch");
337 goto fail;
338 }
339 if (curr_token->child->state == JSON_EMPTY &&
340 !curr_token->child->child &&
341 !curr_token->child->sibling) {
342 /* Remove pending child token since the
343 * array/object was empty. */
344 json_free(curr_token->child);
345 curr_token->child = NULL;
346 }
347 curr_token->state = JSON_COMPLETED;
348 break;
349 case '\"': /* string */
350 str = json_parse_string(&pos, end);
351 if (!str)
352 goto fail;
353 if (!curr_token) {
354 token = json_alloc_token(&tokens);
355 if (!token) {
356 os_free(str);
357 goto fail;
358 }
359 token->type = JSON_STRING;
360 token->string = str;
361 token->state = JSON_COMPLETED;
362 } else if (curr_token->parent &&
363 curr_token->parent->type == JSON_ARRAY &&
364 curr_token->parent->state == JSON_STARTED &&
365 curr_token->state == JSON_EMPTY) {
366 curr_token->string = str;
367 curr_token->state = JSON_COMPLETED;
368 curr_token->type = JSON_STRING;
369 wpa_printf(MSG_MSGDUMP,
370 "JSON: String value: '%s'",
371 curr_token->string);
372 } else if (curr_token->state == JSON_EMPTY) {
373 curr_token->type = JSON_VALUE;
374 curr_token->name = str;
375 curr_token->state = JSON_STARTED;
376 } else if (curr_token->state == JSON_WAITING_VALUE) {
377 curr_token->string = str;
378 curr_token->state = JSON_COMPLETED;
379 curr_token->type = JSON_STRING;
380 wpa_printf(MSG_MSGDUMP,
381 "JSON: String value: '%s' = '%s'",
382 curr_token->name,
383 curr_token->string);
384 } else {
385 wpa_printf(MSG_DEBUG,
386 "JSON: Invalid state for a string");
387 os_free(str);
388 goto fail;
389 }
390 break;
391 case ' ':
392 case '\t':
393 case '\r':
394 case '\n':
395 /* ignore whitespace */
396 break;
397 case ':': /* name/value separator */
398 if (!curr_token || curr_token->state != JSON_STARTED)
399 goto fail;
400 curr_token->state = JSON_WAITING_VALUE;
401 break;
402 case ',': /* member separator */
403 if (!curr_token)
404 goto fail;
405 curr_token->sibling = json_alloc_token(&tokens);
406 if (!curr_token->sibling)
407 goto fail;
408 curr_token->sibling->parent = curr_token->parent;
409 curr_token = curr_token->sibling;
410 curr_token->state = JSON_EMPTY;
411 break;
412 case 't': /* true */
413 case 'f': /* false */
414 case 'n': /* null */
415 if (!((end - pos >= 4 &&
416 os_strncmp(pos, "true", 4) == 0) ||
417 (end - pos >= 5 &&
418 os_strncmp(pos, "false", 5) == 0) ||
419 (end - pos >= 4 &&
420 os_strncmp(pos, "null", 4) == 0))) {
421 wpa_printf(MSG_DEBUG,
422 "JSON: Invalid literal name");
423 goto fail;
424 }
425 if (!curr_token) {
426 token = json_alloc_token(&tokens);
427 if (!token)
428 goto fail;
429 curr_token = token;
430 } else if (curr_token->state == JSON_WAITING_VALUE) {
431 wpa_printf(MSG_MSGDUMP,
432 "JSON: Literal name: '%s' = %c",
433 curr_token->name, *pos);
434 } else if (curr_token->parent &&
435 curr_token->parent->type == JSON_ARRAY &&
436 curr_token->parent->state == JSON_STARTED &&
437 curr_token->state == JSON_EMPTY) {
438 wpa_printf(MSG_MSGDUMP,
439 "JSON: Literal name: %c", *pos);
440 } else {
441 wpa_printf(MSG_DEBUG,
442 "JSON: Invalid state for a literal name");
443 goto fail;
444 }
445 switch (*pos) {
446 case 't':
447 curr_token->type = JSON_BOOLEAN;
448 curr_token->number = 1;
449 pos += 3;
450 break;
451 case 'f':
452 curr_token->type = JSON_BOOLEAN;
453 curr_token->number = 0;
454 pos += 4;
455 break;
456 case 'n':
457 curr_token->type = JSON_NULL;
458 pos += 3;
459 break;
460 }
461 curr_token->state = JSON_COMPLETED;
462 break;
463 case '-':
464 case '0':
465 case '1':
466 case '2':
467 case '3':
468 case '4':
469 case '5':
470 case '6':
471 case '7':
472 case '8':
473 case '9':
474 /* number */
475 is_double = false;
476 len = json_get_number_len(pos, end, &is_double);
477 if (!len)
478 goto fail;
479 if (is_double) {
480 if (json_parse_double(&pos, len, &dnum) < 0)
481 goto fail;
482 } else {
483 if (json_parse_number(&pos, len, &num) < 0)
484 goto fail;
485 }
486
487 if (!curr_token) {
488 token = json_alloc_token(&tokens);
489 if (!token)
490 goto fail;
491 if (is_double) {
492 token->dnumber = dnum;
493 token->type = JSON_DOUBLE;
494 } else {
495 token->number = num;
496 token->type = JSON_NUMBER;
497 }
498 token->state = JSON_COMPLETED;
499 } else if (curr_token->state == JSON_WAITING_VALUE) {
500 curr_token->state = JSON_COMPLETED;
501 if (is_double) {
502 curr_token->dnumber = dnum;
503 curr_token->type = JSON_DOUBLE;
504 wpa_printf(MSG_MSGDUMP,
505 "JSON: Double value: '%s' = '%f'",
506 curr_token->name,
507 curr_token->dnumber);
508 } else {
509 curr_token->number = num;
510 curr_token->type = JSON_NUMBER;
511 wpa_printf(MSG_MSGDUMP,
512 "JSON: Number value: '%s' = '%d'",
513 curr_token->name,
514 curr_token->number);
515 }
516 } else if (curr_token->parent &&
517 curr_token->parent->type == JSON_ARRAY &&
518 curr_token->parent->state == JSON_STARTED &&
519 curr_token->state == JSON_EMPTY) {
520 curr_token->state = JSON_COMPLETED;
521 if (is_double) {
522 curr_token->dnumber = dnum;
523 curr_token->type = JSON_DOUBLE;
524 wpa_printf(MSG_MSGDUMP,
525 "JSON: Double value: %f",
526 curr_token->dnumber);
527 } else {
528 curr_token->number = num;
529 curr_token->type = JSON_NUMBER;
530 wpa_printf(MSG_MSGDUMP,
531 "JSON: Number value: %d",
532 curr_token->number);
533 }
534 } else {
535 wpa_printf(MSG_DEBUG,
536 "JSON: Invalid state for a number");
537 goto fail;
538 }
539 break;
540 default:
541 wpa_printf(MSG_DEBUG,
542 "JSON: Unexpected JSON character: %c", *pos);
543 goto fail;
544 }
545
546 if (!root)
547 root = token;
548 if (!curr_token)
549 curr_token = token;
550 }
551
552 if (json_check_tree_state(root) < 0) {
553 wpa_printf(MSG_DEBUG, "JSON: Incomplete token in the tree");
554 goto fail;
555 }
556
557 return root;
558 fail:
559 wpa_printf(MSG_DEBUG, "JSON: Parsing failed");
560 json_free(root);
561 return NULL;
562 }
563
564
json_free(struct json_token * json)565 void json_free(struct json_token *json)
566 {
567 if (!json)
568 return;
569 json_free(json->child);
570 json_free(json->sibling);
571 os_free(json->name);
572 os_free(json->string);
573 os_free(json);
574 }
575
576
json_get_member(struct json_token * json,const char * name)577 struct json_token * json_get_member(struct json_token *json, const char *name)
578 {
579 struct json_token *token, *ret = NULL;
580
581 if (!json || json->type != JSON_OBJECT)
582 return NULL;
583 /* Return last matching entry */
584 for (token = json->child; token; token = token->sibling) {
585 if (token->name && os_strcmp(token->name, name) == 0)
586 ret = token;
587 }
588 return ret;
589 }
590
591
json_get_member_base64url(struct json_token * json,const char * name)592 struct wpabuf * json_get_member_base64url(struct json_token *json,
593 const char *name)
594 {
595 struct json_token *token;
596 unsigned char *buf;
597 size_t buflen;
598 struct wpabuf *ret;
599
600 token = json_get_member(json, name);
601 if (!token || token->type != JSON_STRING)
602 return NULL;
603 buf = base64_url_decode(token->string, os_strlen(token->string),
604 &buflen);
605 if (!buf)
606 return NULL;
607 ret = wpabuf_alloc_ext_data(buf, buflen);
608 if (!ret)
609 os_free(buf);
610
611 return ret;
612 }
613
614
json_get_member_base64(struct json_token * json,const char * name)615 struct wpabuf * json_get_member_base64(struct json_token *json,
616 const char *name)
617 {
618 struct json_token *token;
619 unsigned char *buf;
620 size_t buflen;
621 struct wpabuf *ret;
622
623 token = json_get_member(json, name);
624 if (!token || token->type != JSON_STRING)
625 return NULL;
626 buf = base64_decode(token->string, os_strlen(token->string), &buflen);
627 if (!buf)
628 return NULL;
629 ret = wpabuf_alloc_ext_data(buf, buflen);
630 if (!ret)
631 os_free(buf);
632
633 return ret;
634 }
635
636
json_type_str(enum json_type type)637 static const char * json_type_str(enum json_type type)
638 {
639 switch (type) {
640 case JSON_VALUE:
641 return "VALUE";
642 case JSON_OBJECT:
643 return "OBJECT";
644 case JSON_ARRAY:
645 return "ARRAY";
646 case JSON_STRING:
647 return "STRING";
648 case JSON_NUMBER:
649 return "NUMBER";
650 case JSON_DOUBLE:
651 return "DOUBLE";
652 case JSON_BOOLEAN:
653 return "BOOLEAN";
654 case JSON_NULL:
655 return "NULL";
656 }
657 return "??";
658 }
659
660
json_print_token(struct json_token * token,int depth,char * buf,size_t buflen)661 static void json_print_token(struct json_token *token, int depth,
662 char *buf, size_t buflen)
663 {
664 size_t len;
665 int ret;
666
667 if (!token)
668 return;
669 len = os_strlen(buf);
670 ret = os_snprintf(buf + len, buflen - len, "[%d:%s:%s]",
671 depth, json_type_str(token->type),
672 token->name ? token->name : "");
673 if (os_snprintf_error(buflen - len, ret)) {
674 buf[len] = '\0';
675 return;
676 }
677 json_print_token(token->child, depth + 1, buf, buflen);
678 json_print_token(token->sibling, depth, buf, buflen);
679 }
680
681
json_print_tree(struct json_token * root,char * buf,size_t buflen)682 void json_print_tree(struct json_token *root, char *buf, size_t buflen)
683 {
684 buf[0] = '\0';
685 json_print_token(root, 1, buf, buflen);
686 }
687
688
json_add_int(struct wpabuf * json,const char * name,int val)689 void json_add_int(struct wpabuf *json, const char *name, int val)
690 {
691 wpabuf_printf(json, "\"%s\":%d", name, val);
692 }
693
694
json_add_double(struct wpabuf * json,const char * name,double val)695 void json_add_double(struct wpabuf *json, const char *name, double val)
696 {
697 wpabuf_printf(json, "\"%s\":%f", name, val);
698 }
699
700
json_add_string(struct wpabuf * json,const char * name,const char * val)701 void json_add_string(struct wpabuf *json, const char *name, const char *val)
702 {
703 wpabuf_printf(json, "\"%s\":\"%s\"", name, val);
704 }
705
706
json_add_string_escape(struct wpabuf * json,const char * name,const void * val,size_t len)707 int json_add_string_escape(struct wpabuf *json, const char *name,
708 const void *val, size_t len)
709 {
710 char *tmp;
711 size_t tmp_len = 6 * len + 1;
712
713 tmp = os_malloc(tmp_len);
714 if (!tmp)
715 return -1;
716 json_escape_string(tmp, tmp_len, val, len);
717 json_add_string(json, name, tmp);
718 bin_clear_free(tmp, tmp_len);
719 return 0;
720 }
721
722
json_add_base64url(struct wpabuf * json,const char * name,const void * val,size_t len)723 int json_add_base64url(struct wpabuf *json, const char *name, const void *val,
724 size_t len)
725 {
726 char *b64;
727
728 b64 = base64_url_encode(val, len, NULL);
729 if (!b64)
730 return -1;
731 json_add_string(json, name, b64);
732 os_free(b64);
733 return 0;
734 }
735
736
json_add_base64(struct wpabuf * json,const char * name,const void * val,size_t len)737 int json_add_base64(struct wpabuf *json, const char *name, const void *val,
738 size_t len)
739 {
740 char *b64;
741
742 b64 = base64_encode_no_lf(val, len, NULL);
743 if (!b64)
744 return -1;
745 json_add_string(json, name, b64);
746 os_free(b64);
747 return 0;
748 }
749
750
json_start_object(struct wpabuf * json,const char * name)751 void json_start_object(struct wpabuf *json, const char *name)
752 {
753 if (name)
754 wpabuf_printf(json, "\"%s\":", name);
755 wpabuf_put_u8(json, '{');
756 }
757
758
json_end_object(struct wpabuf * json)759 void json_end_object(struct wpabuf *json)
760 {
761 wpabuf_put_u8(json, '}');
762 }
763
764
json_start_array(struct wpabuf * json,const char * name)765 void json_start_array(struct wpabuf *json, const char *name)
766 {
767 if (name)
768 wpabuf_printf(json, "\"%s\":", name);
769 wpabuf_put_u8(json, '[');
770 }
771
772
json_end_array(struct wpabuf * json)773 void json_end_array(struct wpabuf *json)
774 {
775 wpabuf_put_u8(json, ']');
776 }
777
778
json_value_sep(struct wpabuf * json)779 void json_value_sep(struct wpabuf *json)
780 {
781 wpabuf_put_u8(json, ',');
782 }
783