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