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