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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 759 void json_end_object(struct wpabuf *json) 760 { 761 wpabuf_put_u8(json, '}'); 762 } 763 764 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 773 void json_end_array(struct wpabuf *json) 774 { 775 wpabuf_put_u8(json, ']'); 776 } 777 778 779 void json_value_sep(struct wpabuf *json) 780 { 781 wpabuf_put_u8(json, ','); 782 } 783