Changeset 1037 for pjproject/trunk/pjlib-util/src/pjlib-util/stun_msg.c
- Timestamp:
- Mar 3, 2007 2:16:36 AM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib-util/src/pjlib-util/stun_msg.c
r1030 r1037 22 22 #include <pjlib-util/hmac_sha1.h> 23 23 #include <pjlib-util/md5.h> 24 #include <pjlib-util/sha1.h>25 24 #include <pj/assert.h> 26 25 #include <pj/log.h> … … 89 88 }; 90 89 91 static pj_status_t decode_ generic_ip_addr_attr(pj_pool_t *pool,92 93 94 static pj_status_t encode_ generic_ip_addr_attr(const void *a, pj_uint8_t *buf,95 96 97 static pj_status_t decode_ generic_string_attr(pj_pool_t *pool,98 99 100 static pj_status_t encode_ generic_string_attr(const void *a, pj_uint8_t *buf,101 102 static pj_status_t decode_msg _integrity_attr(pj_pool_t *pool,103 104 105 static pj_status_t encode_msg _integrity_attr(const void *a, pj_uint8_t *buf,106 107 static pj_status_t decode_err or_code_attr(pj_pool_t *pool,108 109 110 static pj_status_t encode_err or_code_attr(const void *a, pj_uint8_t *buf,111 90 static pj_status_t decode_ip_addr_attr(pj_pool_t *pool, 91 const pj_uint8_t *buf, 92 void **p_attr); 93 static pj_status_t encode_ip_addr_attr(const void *a, pj_uint8_t *buf, 94 unsigned len, 95 unsigned *printed); 96 static pj_status_t decode_string_attr(pj_pool_t *pool, 97 const pj_uint8_t *buf, 98 void **p_attr); 99 static pj_status_t encode_string_attr(const void *a, pj_uint8_t *buf, 100 unsigned len, unsigned *printed); 101 static pj_status_t decode_msgint_attr(pj_pool_t *pool, 102 const pj_uint8_t *buf, 103 void **p_attr); 104 static pj_status_t encode_msgint_attr(const void *a, pj_uint8_t *buf, 105 unsigned len, unsigned *printed); 106 static pj_status_t decode_errcode_attr(pj_pool_t *pool, 107 const pj_uint8_t *buf, 108 void **p_attr); 109 static pj_status_t encode_errcode_attr(const void *a, pj_uint8_t *buf, 110 unsigned len, unsigned *printed); 112 111 static pj_status_t decode_unknown_attr(pj_pool_t *pool, 113 112 const pj_uint8_t *buf, … … 115 114 static pj_status_t encode_unknown_attr(const void *a, pj_uint8_t *buf, 116 115 unsigned len, unsigned *printed); 117 static pj_status_t decode_ generic_uint_attr(pj_pool_t *pool,118 119 120 static pj_status_t encode_ generic_uint_attr(const void *a, pj_uint8_t *buf,121 116 static pj_status_t decode_uint_attr(pj_pool_t *pool, 117 const pj_uint8_t *buf, 118 void **p_attr); 119 static pj_status_t encode_uint_attr(const void *a, pj_uint8_t *buf, 120 unsigned len, unsigned *printed); 122 121 static pj_status_t decode_binary_attr(pj_pool_t *pool, 123 122 const pj_uint8_t *buf, … … 143 142 /* PJ_STUN_ATTR_MAPPED_ADDR, */ 144 143 "MAPPED-ADDRESS", 145 &decode_ generic_ip_addr_attr,146 &encode_ generic_ip_addr_attr144 &decode_ip_addr_attr, 145 &encode_ip_addr_attr 147 146 }, 148 147 { 149 148 /* PJ_STUN_ATTR_RESPONSE_ADDR, */ 150 149 "RESPONSE-ADDRESS", 151 &decode_ generic_ip_addr_attr,152 &encode_ generic_ip_addr_attr150 &decode_ip_addr_attr, 151 &encode_ip_addr_attr 153 152 }, 154 153 { 155 154 /* PJ_STUN_ATTR_CHANGE_REQUEST, */ 156 155 "CHANGE-REQUEST", 157 &decode_ generic_uint_attr,158 &encode_ generic_uint_attr156 &decode_uint_attr, 157 &encode_uint_attr 159 158 }, 160 159 { 161 160 /* PJ_STUN_ATTR_SOURCE_ADDR, */ 162 161 "SOURCE-ADDRESS", 163 &decode_ generic_ip_addr_attr,164 &encode_ generic_ip_addr_attr162 &decode_ip_addr_attr, 163 &encode_ip_addr_attr 165 164 }, 166 165 { 167 166 /* PJ_STUN_ATTR_CHANGED_ADDR, */ 168 167 "CHANGED-ADDRESS", 169 &decode_ generic_ip_addr_attr,170 &encode_ generic_ip_addr_attr168 &decode_ip_addr_attr, 169 &encode_ip_addr_attr 171 170 }, 172 171 { 173 172 /* PJ_STUN_ATTR_USERNAME, */ 174 173 "USERNAME", 175 &decode_ generic_string_attr,176 &encode_ generic_string_attr174 &decode_string_attr, 175 &encode_string_attr 177 176 }, 178 177 { 179 178 /* PJ_STUN_ATTR_PASSWORD, */ 180 179 "PASSWORD", 181 &decode_ generic_string_attr,182 &encode_ generic_string_attr180 &decode_string_attr, 181 &encode_string_attr 183 182 }, 184 183 { 185 184 /* PJ_STUN_ATTR_MESSAGE_INTEGRITY, */ 186 185 "MESSAGE-INTEGRITY", 187 &decode_msg _integrity_attr,188 &encode_msg _integrity_attr186 &decode_msgint_attr, 187 &encode_msgint_attr 189 188 }, 190 189 { 191 190 /* PJ_STUN_ATTR_ERROR_CODE, */ 192 191 "ERROR-CODE", 193 &decode_err or_code_attr,194 &encode_err or_code_attr192 &decode_errcode_attr, 193 &encode_errcode_attr 195 194 }, 196 195 { … … 203 202 /* PJ_STUN_ATTR_REFLECTED_FROM, */ 204 203 "REFLECTED-FROM", 205 &decode_ generic_ip_addr_attr,206 &encode_ generic_ip_addr_attr204 &decode_ip_addr_attr, 205 &encode_ip_addr_attr 207 206 }, 208 207 { … … 215 214 /* PJ_STUN_ATTR_LIFETIME, */ 216 215 "LIFETIME", 217 &decode_ generic_uint_attr,218 &encode_ generic_uint_attr216 &decode_uint_attr, 217 &encode_uint_attr 219 218 }, 220 219 { … … 233 232 /* PJ_STUN_ATTR_BANDWIDTH, */ 234 233 "BANDWIDTH", 235 &decode_ generic_uint_attr,236 &encode_ generic_uint_attr234 &decode_uint_attr, 235 &encode_uint_attr 237 236 }, 238 237 { … … 245 244 /* PJ_STUN_ATTR_REMOTE_ADDRESS, */ 246 245 "REMOTE-ADDRESS", 247 &decode_ generic_ip_addr_attr,248 &encode_ generic_ip_addr_attr246 &decode_ip_addr_attr, 247 &encode_ip_addr_attr 249 248 }, 250 249 { … … 257 256 /* PJ_STUN_ATTR_REALM, */ 258 257 "REALM", 259 &decode_ generic_string_attr,260 &encode_ generic_string_attr258 &decode_string_attr, 259 &encode_string_attr 261 260 }, 262 261 { 263 262 /* PJ_STUN_ATTR_NONCE, */ 264 263 "NONCE", 265 &decode_ generic_string_attr,266 &encode_ generic_string_attr264 &decode_string_attr, 265 &encode_string_attr 267 266 }, 268 267 { 269 268 /* PJ_STUN_ATTR_RELAY_ADDRESS, */ 270 269 "RELAY-ADDRESS", 271 &decode_ generic_ip_addr_attr,272 &encode_ generic_ip_addr_attr270 &decode_ip_addr_attr, 271 &encode_ip_addr_attr 273 272 }, 274 273 { 275 274 /* PJ_STUN_ATTR_REQUESTED_ADDR_TYPE, */ 276 275 "REQUESTED-ADDRESS-TYPE", 277 &decode_ generic_uint_attr,278 &encode_ generic_uint_attr276 &decode_uint_attr, 277 &encode_uint_attr 279 278 }, 280 279 { 281 280 /* PJ_STUN_ATTR_REQUESTED_PORT_PROPS, */ 282 281 "REQUESTED-PORT-PROPS", 283 &decode_ generic_uint_attr,284 &encode_ generic_uint_attr282 &decode_uint_attr, 283 &encode_uint_attr 285 284 }, 286 285 { 287 286 /* PJ_STUN_ATTR_REQUESTED_TRANSPORT, */ 288 287 "REQUESTED-TRANSPORT", 289 &decode_ generic_uint_attr,290 &encode_ generic_uint_attr288 &decode_uint_attr, 289 &encode_uint_attr 291 290 }, 292 291 { … … 329 328 /* PJ_STUN_ATTR_XOR_MAPPED_ADDRESS, */ 330 329 "XOR-MAPPED-ADDRESS", 331 &decode_ generic_ip_addr_attr,332 &encode_ generic_ip_addr_attr330 &decode_ip_addr_attr, 331 &encode_ip_addr_attr 333 332 }, 334 333 { 335 334 /* PJ_STUN_ATTR_TIMER_VAL, */ 336 335 "TIMER-VAL", 337 &decode_ generic_uint_attr,338 &encode_ generic_uint_attr336 &decode_uint_attr, 337 &encode_uint_attr 339 338 }, 340 339 { 341 340 /* PJ_STUN_ATTR_REQUESTED_IP, */ 342 341 "REQUESTED-IP", 343 &decode_ generic_ip_addr_attr,344 &encode_ generic_ip_addr_attr342 &decode_ip_addr_attr, 343 &encode_ip_addr_attr 345 344 }, 346 345 { 347 346 /* PJ_STUN_ATTR_XOR_REFLECTED_FROM, */ 348 347 "XOR-REFLECTED-FROM", 349 &decode_ generic_ip_addr_attr,350 &encode_ generic_ip_addr_attr348 &decode_ip_addr_attr, 349 &encode_ip_addr_attr 351 350 }, 352 351 { 353 352 /* PJ_STUN_ATTR_PRIORITY, */ 354 353 "PRIORITY", 355 &decode_ generic_uint_attr,356 &encode_ generic_uint_attr354 &decode_uint_attr, 355 &encode_uint_attr 357 356 }, 358 357 { … … 365 364 /* PJ_STUN_ATTR_XOR_INTERNAL_ADDR, */ 366 365 "XOR-INTERNAL-ADDRESS", 367 &decode_ generic_ip_addr_attr,368 &encode_ generic_ip_addr_attr366 &decode_ip_addr_attr, 367 &encode_ip_addr_attr 369 368 }, 370 369 … … 383 382 /* PJ_STUN_ATTR_FINGERPRINT, */ 384 383 "FINGERPRINT", 385 &decode_ generic_uint_attr,386 &encode_ generic_uint_attr384 &decode_uint_attr, 385 &encode_uint_attr 387 386 }, 388 387 { 389 388 /* PJ_STUN_ATTR_SERVER, */ 390 389 "SERVER", 391 &decode_ generic_string_attr,392 &encode_ generic_string_attr390 &decode_string_attr, 391 &encode_string_attr 393 392 }, 394 393 { 395 394 /* PJ_STUN_ATTR_ALTERNATE_SERVER, */ 396 395 "ALTERNATE-SERVER", 397 &decode_ generic_ip_addr_attr,398 &encode_ generic_ip_addr_attr396 &decode_ip_addr_attr, 397 &encode_ip_addr_attr 399 398 }, 400 399 { 401 400 /* PJ_STUN_ATTR_REFRESH_INTERVAL, */ 402 401 "REFRESH-INTERVAL", 403 &decode_ generic_uint_attr,404 &encode_ generic_uint_attr402 &decode_uint_attr, 403 &encode_uint_attr 405 404 }, 406 405 }; … … 515 514 */ 516 515 PJ_DEF(pj_status_t) 517 pj_stun_ generic_ip_addr_attr_create(pj_pool_t *pool,518 519 520 521 522 pj_stun_generic_ip_addr_attr **p_attr)523 { 524 pj_stun_ generic_ip_addr_attr *attr;516 pj_stun_ip_addr_attr_create(pj_pool_t *pool, 517 int attr_type, 518 pj_bool_t xor_ed, 519 const pj_sockaddr_t *addr, 520 unsigned addr_len, 521 pj_stun_ip_addr_attr **p_attr) 522 { 523 pj_stun_ip_addr_attr *attr; 525 524 526 525 PJ_ASSERT_RETURN(pool && addr_len && addr && p_attr, PJ_EINVAL); … … 528 527 addr_len == sizeof(pj_sockaddr_in6), PJ_EINVAL); 529 528 530 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_ generic_ip_addr_attr);529 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_ip_addr_attr); 531 530 INIT_ATTR(attr, attr_type, STUN_GENERIC_IP_ADDR_LEN); 532 531 … … 556 555 */ 557 556 PJ_DEF(pj_status_t) 558 pj_stun_msg_add_ generic_ip_addr_attr(pj_pool_t *pool,559 560 561 562 563 564 { 565 pj_stun_ generic_ip_addr_attr *attr;557 pj_stun_msg_add_ip_addr_attr(pj_pool_t *pool, 558 pj_stun_msg *msg, 559 int attr_type, 560 pj_bool_t xor_ed, 561 const pj_sockaddr_t *addr, 562 unsigned addr_len) 563 { 564 pj_stun_ip_addr_attr *attr; 566 565 pj_status_t status; 567 566 568 status = pj_stun_ generic_ip_addr_attr_create(pool, attr_type, xor_ed,567 status = pj_stun_ip_addr_attr_create(pool, attr_type, xor_ed, 569 568 addr, addr_len, &attr); 570 569 if (status != PJ_SUCCESS) … … 574 573 } 575 574 576 static pj_status_t decode_ generic_ip_addr_attr(pj_pool_t *pool,577 578 579 { 580 pj_stun_ generic_ip_addr_attr *attr;575 static pj_status_t decode_ip_addr_attr(pj_pool_t *pool, 576 const pj_uint8_t *buf, 577 void **p_attr) 578 { 579 pj_stun_ip_addr_attr *attr; 581 580 pj_uint32_t val; 582 581 583 582 /* Create the attribute */ 584 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_ generic_ip_addr_attr);583 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_ip_addr_attr); 585 584 pj_memcpy(attr, buf, ATTR_HDR_LEN); 586 585 … … 612 611 613 612 614 static pj_status_t encode_ generic_ip_addr_attr(const void *a, pj_uint8_t *buf,615 613 static pj_status_t encode_ip_addr_attr(const void *a, pj_uint8_t *buf, 614 unsigned len, unsigned *printed) 616 615 { 617 616 enum { … … 619 618 }; 620 619 pj_uint8_t *start_buf = buf; 621 const pj_stun_ generic_ip_addr_attr *ca =622 (const pj_stun_ generic_ip_addr_attr *)a;623 pj_stun_ generic_ip_addr_attr *attr;620 const pj_stun_ip_addr_attr *ca = 621 (const pj_stun_ip_addr_attr *)a; 622 pj_stun_ip_addr_attr *attr; 624 623 625 624 if (len < ATTR_LEN) … … 628 627 /* Copy and convert headers to network byte order */ 629 628 pj_memcpy(buf, a, ATTR_HDR_LEN); 630 attr = (pj_stun_ generic_ip_addr_attr*) buf;629 attr = (pj_stun_ip_addr_attr*) buf; 631 630 attr->hdr.type = pj_htons(attr->hdr.type); 632 631 attr->hdr.length = pj_htons((pj_uint16_t)STUN_GENERIC_IP_ADDR_LEN); … … 666 665 */ 667 666 PJ_DEF(pj_status_t) 668 pj_stun_ generic_string_attr_create(pj_pool_t *pool,669 670 671 pj_stun_generic_string_attr **p_attr)672 { 673 pj_stun_ generic_string_attr *attr;667 pj_stun_string_attr_create(pj_pool_t *pool, 668 int attr_type, 669 const pj_str_t *value, 670 pj_stun_string_attr **p_attr) 671 { 672 pj_stun_string_attr *attr; 674 673 675 674 PJ_ASSERT_RETURN(pool && value && p_attr, PJ_EINVAL); 676 675 677 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_ generic_string_attr);676 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_string_attr); 678 677 INIT_ATTR(attr, attr_type, value->slen); 679 678 pj_strdup(pool, &attr->value, value); … … 689 688 */ 690 689 PJ_DEF(pj_status_t) 691 pj_stun_msg_add_ generic_string_attr(pj_pool_t *pool,692 693 694 695 { 696 pj_stun_ generic_string_attr *attr;690 pj_stun_msg_add_string_attr(pj_pool_t *pool, 691 pj_stun_msg *msg, 692 int attr_type, 693 const pj_str_t *value) 694 { 695 pj_stun_string_attr *attr; 697 696 pj_status_t status; 698 697 699 status = pj_stun_ generic_string_attr_create(pool, attr_type, value,698 status = pj_stun_string_attr_create(pool, attr_type, value, 700 699 &attr); 701 700 if (status != PJ_SUCCESS) … … 706 705 707 706 708 static pj_status_t decode_ generic_string_attr(pj_pool_t *pool,709 710 711 { 712 pj_stun_ generic_string_attr *attr;707 static pj_status_t decode_string_attr(pj_pool_t *pool, 708 const pj_uint8_t *buf, 709 void **p_attr) 710 { 711 pj_stun_string_attr *attr; 713 712 pj_str_t value; 714 713 715 714 /* Create the attribute */ 716 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_ generic_string_attr);715 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_string_attr); 717 716 718 717 /* Copy the header */ … … 738 737 739 738 740 static pj_status_t encode_ generic_string_attr(const void *a, pj_uint8_t *buf,741 742 { 743 const pj_stun_ generic_string_attr *ca =744 (const pj_stun_ generic_string_attr*)a;739 static pj_status_t encode_string_attr(const void *a, pj_uint8_t *buf, 740 unsigned len, unsigned *printed) 741 { 742 const pj_stun_string_attr *ca = 743 (const pj_stun_string_attr*)a; 745 744 pj_stun_attr_hdr *attr; 746 745 … … 857 856 */ 858 857 PJ_DEF(pj_status_t) 859 pj_stun_ generic_uint_attr_create(pj_pool_t *pool,860 861 862 pj_stun_generic_uint_attr **p_attr)863 { 864 pj_stun_ generic_uint_attr *attr;858 pj_stun_uint_attr_create(pj_pool_t *pool, 859 int attr_type, 860 pj_uint32_t value, 861 pj_stun_uint_attr **p_attr) 862 { 863 pj_stun_uint_attr *attr; 865 864 866 865 PJ_ASSERT_RETURN(pool && p_attr, PJ_EINVAL); 867 866 868 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_ generic_uint_attr);867 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_uint_attr); 869 868 INIT_ATTR(attr, attr_type, STUN_UINT_LEN); 870 869 attr->value = value; … … 877 876 /* Create and add STUN generic 32bit value attribute to the message. */ 878 877 PJ_DEF(pj_status_t) 879 pj_stun_msg_add_ generic_uint_attr(pj_pool_t *pool,880 881 882 883 { 884 pj_stun_ generic_uint_attr *attr;878 pj_stun_msg_add_uint_attr(pj_pool_t *pool, 879 pj_stun_msg *msg, 880 int attr_type, 881 pj_uint32_t value) 882 { 883 pj_stun_uint_attr *attr; 885 884 pj_status_t status; 886 885 887 status = pj_stun_ generic_uint_attr_create(pool, attr_type, value, &attr);886 status = pj_stun_uint_attr_create(pool, attr_type, value, &attr); 888 887 if (status != PJ_SUCCESS) 889 888 return status; … … 892 891 } 893 892 894 static pj_status_t decode_ generic_uint_attr(pj_pool_t *pool,895 896 893 static pj_status_t decode_uint_attr(pj_pool_t *pool, 894 const pj_uint8_t *buf, 895 void **p_attr) 897 896 { 898 897 enum … … 900 899 ATTR_LEN = STUN_UINT_LEN + ATTR_HDR_LEN 901 900 }; 902 pj_stun_ generic_uint_attr *attr;901 pj_stun_uint_attr *attr; 903 902 904 903 /* Check that the struct address is valid */ 905 pj_assert(sizeof(pj_stun_ generic_uint_attr) == ATTR_LEN);904 pj_assert(sizeof(pj_stun_uint_attr) == ATTR_LEN); 906 905 907 906 /* Create the attribute */ 908 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_ generic_uint_attr);907 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_uint_attr); 909 908 pj_memcpy(attr, buf, ATTR_LEN); 910 909 … … 925 924 926 925 927 static pj_status_t encode_ generic_uint_attr(const void *a, pj_uint8_t *buf,928 926 static pj_status_t encode_uint_attr(const void *a, pj_uint8_t *buf, 927 unsigned len, unsigned *printed) 929 928 { 930 929 enum … … 932 931 ATTR_LEN = STUN_UINT_LEN + ATTR_HDR_LEN 933 932 }; 934 pj_stun_ generic_uint_attr *attr;933 pj_stun_uint_attr *attr; 935 934 936 935 if (len < ATTR_LEN) … … 939 938 /* Copy and convert attribute to network byte order */ 940 939 pj_memcpy(buf, a, ATTR_LEN); 941 attr = (pj_stun_ generic_uint_attr*) buf;940 attr = (pj_stun_uint_attr*) buf; 942 941 attr->hdr.type = pj_htons(attr->hdr.type); 943 942 pj_assert(attr->hdr.length == STUN_UINT_LEN); … … 962 961 */ 963 962 PJ_DEF(pj_status_t) 964 pj_stun_msg _integrity_attr_create(pj_pool_t *pool,965 pj_stun_msg_integrity_attr **p_attr)966 { 967 pj_stun_msg _integrity_attr *attr;963 pj_stun_msgint_attr_create(pj_pool_t *pool, 964 pj_stun_msgint_attr **p_attr) 965 { 966 pj_stun_msgint_attr *attr; 968 967 969 968 PJ_ASSERT_RETURN(pool && p_attr, PJ_EINVAL); 970 969 971 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_msg _integrity_attr);970 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_msgint_attr); 972 971 INIT_ATTR(attr, PJ_STUN_ATTR_MESSAGE_INTEGRITY, STUN_MSG_INTEGRITY_LEN); 973 972 … … 978 977 979 978 980 static pj_status_t decode_msg_integrity_attr(pj_pool_t *pool, 981 const pj_uint8_t *buf, 982 void **p_attr) 979 PJ_DEF(pj_status_t) pj_stun_msg_add_msgint_attr(pj_pool_t *pool, 980 pj_stun_msg *msg) 981 { 982 pj_stun_msgint_attr *attr; 983 pj_status_t status; 984 985 status = pj_stun_msgint_attr_create(pool, &attr); 986 if (status != PJ_SUCCESS) 987 return status; 988 989 return pj_stun_msg_add_attr(msg, &attr->hdr); 990 } 991 992 static pj_status_t decode_msgint_attr(pj_pool_t *pool, 993 const pj_uint8_t *buf, 994 void **p_attr) 983 995 { 984 996 enum … … 986 998 ATTR_LEN = STUN_MSG_INTEGRITY_LEN + ATTR_HDR_LEN 987 999 }; 988 pj_stun_msg _integrity_attr *attr;1000 pj_stun_msgint_attr *attr; 989 1001 990 1002 /* Check that struct size is valid */ 991 pj_assert(sizeof(pj_stun_msg _integrity_attr)==ATTR_LEN);1003 pj_assert(sizeof(pj_stun_msgint_attr)==ATTR_LEN); 992 1004 993 1005 /* Create attribute */ 994 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_msg _integrity_attr);995 pj_memcpy(attr, buf, sizeof(pj_stun_msg _integrity_attr));1006 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_msgint_attr); 1007 pj_memcpy(attr, buf, sizeof(pj_stun_msgint_attr)); 996 1008 attr->hdr.type = pj_ntohs(attr->hdr.type); 997 1009 attr->hdr.length = pj_ntohs(attr->hdr.length); … … 1007 1019 1008 1020 1009 static pj_status_t encode_msg _integrity_attr(const void *a, pj_uint8_t *buf,1010 1021 static pj_status_t encode_msgint_attr(const void *a, pj_uint8_t *buf, 1022 unsigned len, unsigned *printed) 1011 1023 { 1012 1024 enum … … 1014 1026 ATTR_LEN = STUN_MSG_INTEGRITY_LEN + ATTR_HDR_LEN 1015 1027 }; 1016 pj_stun_msg _integrity_attr *attr;1028 pj_stun_msgint_attr *attr; 1017 1029 1018 1030 if (len < ATTR_LEN) … … 1021 1033 /* Copy and convert attribute to network byte order */ 1022 1034 pj_memcpy(buf, a, ATTR_LEN); 1023 attr = (pj_stun_msg _integrity_attr*) buf;1035 attr = (pj_stun_msgint_attr*) buf; 1024 1036 attr->hdr.type = pj_htons(attr->hdr.type); 1025 1037 pj_assert(attr->hdr.length == STUN_MSG_INTEGRITY_LEN); … … 1041 1053 */ 1042 1054 PJ_DEF(pj_status_t) 1043 pj_stun_err or_code_attr_create(pj_pool_t *pool,1044 1045 1046 pj_stun_error_code_attr **p_attr)1047 { 1048 pj_stun_err or_code_attr *attr;1055 pj_stun_errcode_attr_create(pj_pool_t *pool, 1056 int err_code, 1057 const pj_str_t *err_reason, 1058 pj_stun_errcode_attr **p_attr) 1059 { 1060 pj_stun_errcode_attr *attr; 1049 1061 char err_buf[80]; 1050 1062 pj_str_t str; … … 1062 1074 } 1063 1075 1064 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_err or_code_attr);1076 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_errcode_attr); 1065 1077 INIT_ATTR(attr, PJ_STUN_ATTR_ERROR_CODE, 4+err_reason->slen); 1066 1078 attr->err_class = (pj_uint8_t)(err_code / 100); … … 1074 1086 1075 1087 1076 static pj_status_t decode_error_code_attr(pj_pool_t *pool, 1077 const pj_uint8_t *buf, 1078 void **p_attr) 1079 { 1080 pj_stun_error_code_attr *attr; 1088 PJ_DEF(pj_status_t) pj_stun_msg_add_errcode_attr(pj_pool_t *pool, 1089 pj_stun_msg *msg, 1090 int err_code, 1091 const pj_str_t *err_reason) 1092 { 1093 pj_stun_errcode_attr *err_attr; 1094 pj_status_t status; 1095 1096 status = pj_stun_errcode_attr_create(pool, err_code, err_reason, 1097 &err_attr); 1098 if (status != PJ_SUCCESS) 1099 return status; 1100 1101 return pj_stun_msg_add_attr(msg, &err_attr->hdr); 1102 } 1103 1104 static pj_status_t decode_errcode_attr(pj_pool_t *pool, 1105 const pj_uint8_t *buf, 1106 void **p_attr) 1107 { 1108 pj_stun_errcode_attr *attr; 1081 1109 pj_str_t value; 1082 1110 1083 1111 /* Create the attribute */ 1084 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_err or_code_attr);1112 attr = PJ_POOL_ZALLOC_TYPE(pool, pj_stun_errcode_attr); 1085 1113 1086 1114 /* Copy the header */ … … 1105 1133 1106 1134 1107 static pj_status_t encode_err or_code_attr(const void *a, pj_uint8_t *buf,1108 1109 { 1110 const pj_stun_err or_code_attr *ca =1111 (const pj_stun_err or_code_attr*)a;1112 pj_stun_err or_code_attr *attr;1135 static pj_status_t encode_errcode_attr(const void *a, pj_uint8_t *buf, 1136 unsigned len, unsigned *printed) 1137 { 1138 const pj_stun_errcode_attr *ca = 1139 (const pj_stun_errcode_attr*)a; 1140 pj_stun_errcode_attr *attr; 1113 1141 1114 1142 if (len < ATTR_HDR_LEN + 4 + (unsigned)ca->reason.slen) … … 1119 1147 1120 1148 /* Update length */ 1121 attr = (pj_stun_err or_code_attr*) buf;1149 attr = (pj_stun_errcode_attr*) buf; 1122 1150 attr->hdr.length = (pj_uint16_t)(4 + ca->reason.slen); 1123 1151 … … 1508 1536 unsigned msg_type = req_msg->hdr.type; 1509 1537 pj_stun_msg *response; 1510 pj_stun_error_code_attr *err_attr;1511 1538 pj_status_t status; 1512 1539 … … 1530 1557 /* Add error code attribute */ 1531 1558 if (err_code) { 1532 status = pj_stun_ error_code_attr_create(pool, err_code, err_msg,1533 &err_attr);1559 status = pj_stun_msg_add_errcode_attr(pool, response, 1560 err_code, err_msg); 1534 1561 if (status != PJ_SUCCESS) { 1535 1562 return status; 1536 1563 } 1537 1538 pj_stun_msg_add_attr(response, &err_attr->hdr);1539 1564 } 1540 1565 … … 1703 1728 NULL, p_response); 1704 1729 } 1705 return PJ _STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_BAD_REQUEST);1730 return PJLIB_UTIL_ESTUNDUPATTR; 1706 1731 } 1707 1732 has_msg_int = PJ_TRUE; … … 1717 1742 NULL, p_response); 1718 1743 } 1719 return PJ _STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_BAD_REQUEST);1744 return PJLIB_UTIL_ESTUNDUPATTR; 1720 1745 } 1721 1746 has_fingerprint = PJ_TRUE; … … 1731 1756 NULL, p_response); 1732 1757 } 1733 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_BAD_REQUEST); 1758 return has_fingerprint ? PJLIB_UTIL_ESTUNFINGERPOS : 1759 PJLIB_UTIL_ESTUNMSGINTPOS; 1734 1760 } 1735 1761 } … … 1767 1793 * MD5 digest of username, realm, and password. 1768 1794 */ 1769 static voidcalc_md5_key(pj_uint8_t digest[16],1770 const pj_str_t *realm,1771 const pj_str_t *username,1772 const pj_str_t *passwd)1795 void pj_stun_calc_md5_key(pj_uint8_t digest[16], 1796 const pj_str_t *realm, 1797 const pj_str_t *username, 1798 const pj_str_t *passwd) 1773 1799 { 1774 1800 /* The 16-byte key for MESSAGE-INTEGRITY HMAC is formed by taking … … 1828 1854 pj_stun_realm_attr *arealm = NULL; 1829 1855 pj_stun_username_attr *auname = NULL; 1830 pj_stun_msg _integrity_attr *amsg_integrity= NULL;1856 pj_stun_msgint_attr *amsgint = NULL; 1831 1857 pj_stun_fingerprint_attr *afingerprint = NULL; 1832 1858 unsigned printed; … … 1860 1886 1861 1887 if (attr_hdr->type == PJ_STUN_ATTR_MESSAGE_INTEGRITY) { 1862 pj_assert(amsg _integrity== NULL);1863 amsg _integrity = (pj_stun_msg_integrity_attr*) attr_hdr;1888 pj_assert(amsgint == NULL); 1889 amsgint = (pj_stun_msgint_attr*) attr_hdr; 1864 1890 1865 1891 /* Stop when encountering MESSAGE-INTEGRITY */ … … 1902 1928 if (attr_hdr->type == PJ_STUN_ATTR_MESSAGE_INTEGRITY) { 1903 1929 /* There mustn't be MESSAGE-INTEGRITY before */ 1904 PJ_ASSERT_RETURN(amsg _integrity== NULL,1930 PJ_ASSERT_RETURN(amsgint == NULL, 1905 1931 PJLIB_UTIL_ESTUNMSGINTPOS); 1906 amsg _integrity = (pj_stun_msg_integrity_attr*) attr_hdr;1932 amsgint = (pj_stun_msgint_attr*) attr_hdr; 1907 1933 1908 1934 } else if (attr_hdr->type == PJ_STUN_ATTR_FINGERPRINT) { … … 1915 1941 * Note that length is not including the 20 bytes header. 1916 1942 */ 1917 if (amsg _integrity&& afingerprint) {1943 if (amsgint && afingerprint) { 1918 1944 msg->hdr.length = (pj_uint16_t)((buf - start) - 20 + 24 + 8); 1919 } else if (amsg _integrity) {1945 } else if (amsgint) { 1920 1946 msg->hdr.length = (pj_uint16_t)((buf - start) - 20 + 24); 1921 1947 } else if (afingerprint) { … … 1930 1956 1931 1957 /* Calculate message integrity, if present */ 1932 if (amsg _integrity!= NULL) {1958 if (amsgint != NULL) { 1933 1959 1934 1960 pj_uint8_t md5_key_buf[16]; … … 1969 1995 1970 1996 } else { 1971 calc_md5_key(md5_key_buf, &arealm->value, &auname->value,1972 password);1997 pj_stun_calc_md5_key(md5_key_buf, &arealm->value, 1998 &auname->value, password); 1973 1999 key.ptr = (char*) md5_key_buf; 1974 2000 key.slen = 16; … … 1978 2004 pj_hmac_sha1((pj_uint8_t*)buf, buf-start, 1979 2005 (pj_uint8_t*)key.ptr, key.slen, 1980 amsg _integrity->hmac);2006 amsgint->hmac); 1981 2007 1982 2008 /* Put this attribute in the message */ 1983 status = encode_msg _integrity_attr(amsg_integrity, buf, buf_size,1984 2009 status = encode_msgint_attr(amsgint, buf, buf_size, 2010 &printed); 1985 2011 if (status != PJ_SUCCESS) 1986 2012 return status; … … 1996 2022 1997 2023 /* Put this attribute in the message */ 1998 status = encode_ generic_uint_attr(afingerprint, buf, buf_size,2024 status = encode_uint_attr(afingerprint, buf, buf_size, 1999 2025 &printed); 2000 2026 if (status != PJ_SUCCESS) … … 2025 2051 for (; index < msg->attr_count; ++index) { 2026 2052 if (msg->attr[index]->type == attr_type) 2027 return (pj_stun_attr_hdr*) &msg->attr[index];2053 return (pj_stun_attr_hdr*) msg->attr[index]; 2028 2054 } 2029 2055 … … 2031 2057 } 2032 2058 2033 2034 /**************************************************************************/2035 /*2036 * Authentication2037 */2038 2039 2040 /* Send 401 response */2041 static pj_status_t create_challenge(pj_pool_t *pool,2042 const pj_stun_msg *msg,2043 int err_code,2044 const pj_str_t *err_msg,2045 const pj_str_t *realm,2046 const pj_str_t *nonce,2047 pj_stun_msg **p_response)2048 {2049 pj_stun_msg *response;2050 pj_status_t rc;2051 2052 rc = pj_stun_msg_create_response(pool, msg,2053 err_code, err_msg, &response);2054 if (rc != PJ_SUCCESS)2055 return rc;2056 2057 2058 if (realm && realm->slen) {2059 rc = pj_stun_msg_add_generic_string_attr(pool, response,2060 PJ_STUN_ATTR_REALM,2061 realm);2062 if (rc != PJ_SUCCESS)2063 return rc;2064 }2065 2066 if (nonce && nonce->slen) {2067 rc = pj_stun_msg_add_generic_string_attr(pool, response,2068 PJ_STUN_ATTR_NONCE,2069 nonce);2070 if (rc != PJ_SUCCESS)2071 return rc;2072 }2073 2074 *p_response = response;2075 2076 return PJ_SUCCESS;2077 }2078 2079 /* Verify credential */2080 PJ_DEF(pj_status_t) pj_stun_verify_credential( const pj_uint8_t *pkt,2081 unsigned pkt_len,2082 const pj_stun_msg *msg,2083 pj_stun_auth_policy *pol,2084 pj_pool_t *pool,2085 pj_stun_msg **p_response)2086 {2087 pj_str_t realm, nonce, password;2088 const pj_stun_msg_integrity_attr *amsgi;2089 unsigned amsgi_pos;2090 const pj_stun_username_attr *auser;2091 pj_bool_t username_ok;2092 const pj_stun_realm_attr *arealm;2093 const pj_stun_realm_attr *anonce;2094 pj_uint8_t digest[PJ_SHA1_DIGEST_SIZE];2095 pj_uint8_t md5_digest[16];2096 pj_str_t key;2097 pj_status_t status;2098 2099 /* msg and policy MUST be specified */2100 PJ_ASSERT_RETURN(pkt && pkt_len && msg && pol, PJ_EINVAL);2101 2102 /* If p_response is specified, pool MUST be specified. */2103 PJ_ASSERT_RETURN(!p_response || pool, PJ_EINVAL);2104 2105 if (p_response)2106 *p_response = NULL;2107 2108 if (!PJ_STUN_IS_REQUEST(msg->hdr.type))2109 p_response = NULL;2110 2111 /* Get realm and nonce */2112 realm.slen = nonce.slen = 0;2113 if (pol->type == PJ_STUN_POLICY_STATIC_SHORT_TERM) {2114 realm.slen = 0;2115 nonce = pol->data.static_short_term.nonce;2116 } else if (pol->type == PJ_STUN_POLICY_STATIC_LONG_TERM) {2117 realm = pol->data.static_long_term.realm;2118 nonce = pol->data.static_long_term.nonce;2119 } else if (pol->type == PJ_STUN_POLICY_DYNAMIC) {2120 status = pol->data.dynamic.get_auth(pol->user_data, pool,2121 &realm, &nonce);2122 if (status != PJ_SUCCESS)2123 return status;2124 } else {2125 pj_assert(!"Unexpected");2126 return PJ_EBUG;2127 }2128 2129 /* First check that MESSAGE-INTEGRITY is present */2130 amsgi = (const pj_stun_msg_integrity_attr*)2131 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_MESSAGE_INTEGRITY, 0);2132 if (amsgi == NULL) {2133 if (p_response) {2134 create_challenge(pool, msg, PJ_STUN_STATUS_UNAUTHORIZED, NULL,2135 &realm, &nonce, p_response);2136 }2137 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_UNAUTHORIZED);2138 }2139 2140 /* Next check that USERNAME is present */2141 auser = (const pj_stun_username_attr*)2142 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_USERNAME, 0);2143 if (auser == NULL) {2144 if (p_response) {2145 create_challenge(pool, msg, PJ_STUN_STATUS_MISSING_USERNAME, NULL,2146 &realm, &nonce, p_response);2147 }2148 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_MISSING_USERNAME);2149 }2150 2151 /* Get REALM, if any */2152 arealm = (const pj_stun_realm_attr*)2153 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REALM, 0);2154 2155 /* Check if username match */2156 if (pol->type == PJ_STUN_POLICY_STATIC_SHORT_TERM) {2157 username_ok = !pj_strcmp(&auser->value,2158 &pol->data.static_short_term.username);2159 password = pol->data.static_short_term.password;2160 } else if (pol->type == PJ_STUN_POLICY_STATIC_LONG_TERM) {2161 username_ok = !pj_strcmp(&auser->value,2162 &pol->data.static_long_term.username);2163 password = pol->data.static_long_term.password;2164 } else if (pol->type == PJ_STUN_POLICY_DYNAMIC) {2165 pj_status_t rc;2166 rc = pol->data.dynamic.get_password(pol->user_data,2167 (arealm?&arealm->value:NULL),2168 &auser->value, pool,2169 &password);2170 username_ok = (rc == PJ_SUCCESS);2171 } else {2172 username_ok = PJ_TRUE;2173 password.slen = 0;2174 }2175 2176 if (!username_ok) {2177 /* Username mismatch */2178 if (p_response) {2179 create_challenge(pool, msg, PJ_STUN_STATUS_UNKNOWN_USERNAME, NULL,2180 &realm, &nonce, p_response);2181 }2182 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_UNKNOWN_USERNAME);2183 }2184 2185 2186 /* Get NONCE attribute */2187 anonce = (pj_stun_nonce_attr*)2188 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_NONCE, 0);2189 2190 /* Check for long term/short term requirements. */2191 if (realm.slen != 0 && arealm == NULL) {2192 /* Long term credential is required and REALM is not present */2193 if (p_response) {2194 create_challenge(pool, msg, PJ_STUN_STATUS_MISSING_REALM, NULL,2195 &realm, &nonce, p_response);2196 }2197 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_MISSING_REALM);2198 2199 } else if (realm.slen != 0 && arealm != NULL) {2200 /* We want long term, and REALM is present */2201 2202 /* NONCE must be present. */2203 if (anonce == NULL) {2204 if (p_response) {2205 create_challenge(pool, msg, PJ_STUN_STATUS_MISSING_NONCE,2206 NULL, &realm, &nonce, p_response);2207 }2208 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_MISSING_NONCE);2209 }2210 2211 /* Verify REALM matches */2212 if (pj_stricmp(&arealm->value, &realm)) {2213 /* REALM doesn't match */2214 if (p_response) {2215 create_challenge(pool, msg, PJ_STUN_STATUS_MISSING_REALM,2216 NULL, &realm, &nonce, p_response);2217 }2218 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_MISSING_REALM);2219 }2220 2221 /* Valid case, will validate the message integrity later */2222 2223 } else if (realm.slen == 0 && arealm != NULL) {2224 /* We want to use short term credential, but client uses long2225 * term credential. The draft doesn't mention anything about2226 * switching between long term and short term.2227 */2228 2229 /* For now just accept the credential, anyway it will probably2230 * cause wrong message integrity value later.2231 */2232 } else if (realm.slen==0 && arealm == NULL) {2233 /* Short term authentication is wanted, and one is supplied */2234 2235 /* Application MAY request NONCE to be supplied */2236 if (nonce.slen != 0) {2237 if (p_response) {2238 create_challenge(pool, msg, PJ_STUN_STATUS_MISSING_NONCE,2239 NULL, &realm, &nonce, p_response);2240 }2241 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_MISSING_NONCE);2242 }2243 }2244 2245 /* If NONCE is present, validate it */2246 if (anonce) {2247 pj_bool_t ok;2248 2249 if (pol->type == PJ_STUN_POLICY_DYNAMIC) {2250 ok = pol->data.dynamic.verify_nonce(pol->user_data,2251 (arealm?&arealm->value:NULL),2252 &auser->value,2253 &anonce->value);2254 } else {2255 if (nonce.slen) {2256 ok = !pj_strcmp(&anonce->value, &nonce);2257 } else {2258 ok = PJ_TRUE;2259 }2260 }2261 2262 if (!ok) {2263 if (p_response) {2264 create_challenge(pool, msg, PJ_STUN_STATUS_STALE_NONCE,2265 NULL, &realm, &nonce, p_response);2266 }2267 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_STALE_NONCE);2268 }2269 }2270 2271 /* Get the position of MESSAGE-INTEGRITY in the packet */2272 amsgi_pos = 20+msg->hdr.length-22;2273 if (GET_VAL16(pkt, amsgi_pos) == PJ_STUN_ATTR_MESSAGE_INTEGRITY) {2274 /* Found MESSAGE-INTEGRITY as the last attribute */2275 } else {2276 amsgi_pos = 0;2277 }2278 2279 if (amsgi_pos==0) {2280 amsgi_pos = 20+msg->hdr.length-8-22;2281 if (GET_VAL16(pkt, amsgi_pos) == PJ_STUN_ATTR_MESSAGE_INTEGRITY) {2282 /* Found MESSAGE-INTEGRITY before FINGERPRINT */2283 } else {2284 amsgi_pos = 0;2285 }2286 }2287 2288 if (amsgi_pos==0) {2289 pj_assert(!"Unable to find MESSAGE-INTEGRITY in the message!");2290 return PJ_EBUG;2291 }2292 2293 /* Determine which key to use */2294 if (realm.slen) {2295 calc_md5_key(md5_digest, &realm, &auser->value, &password);2296 key.ptr = (char*)md5_digest;2297 key.slen = 16;2298 } else {2299 key = password;2300 }2301 2302 /* Now calculate HMAC of the message */2303 pj_hmac_sha1(pkt, amsgi_pos, (pj_uint8_t*)key.ptr, key.slen, digest);2304 2305 /* Compare HMACs */2306 if (pj_memcmp(amsgi->hmac, digest, 20)) {2307 /* HMAC value mismatch */2308 if (p_response) {2309 create_challenge(pool, msg, PJ_STUN_STATUS_INTEGRITY_CHECK_FAILURE,2310 NULL, &realm, &nonce, p_response);2311 }2312 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_INTEGRITY_CHECK_FAILURE);2313 }2314 2315 /* Everything looks okay! */2316 return PJ_SUCCESS;2317 }2318 2319
Note: See TracChangeset
for help on using the changeset viewer.