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