Changeset 1037 for pjproject/trunk/pjlib-util/src/pjlib-util/stun_session.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_session.c
r1034 r1037 28 28 void *user_data; 29 29 30 /* Long term credential */ 31 pj_str_t l_realm; 32 pj_str_t l_username; 33 pj_str_t l_password; 34 35 /* Short term credential */ 36 pj_str_t s_username; 37 pj_str_t s_password; 30 pj_bool_t use_fingerprint; 31 pj_stun_auth_cred *cred; 32 pj_str_t srv_name; 38 33 39 34 pj_stun_tx_data pending_request_list; … … 214 209 } 215 210 211 static pj_str_t *get_passwd(pj_stun_session *sess) 212 { 213 if (sess->cred == NULL) 214 return NULL; 215 else if (sess->cred->type == PJ_STUN_AUTH_CRED_STATIC) 216 return &sess->cred->data.static_cred.data; 217 else 218 return NULL; 219 } 220 216 221 static pj_status_t apply_msg_options(pj_stun_session *sess, 217 222 pj_pool_t *pool, 218 unsigned options, 219 pj_stun_msg *msg, 220 pj_str_t **p_passwd) 221 { 222 pj_status_t status; 223 pj_stun_msg *msg) 224 { 225 pj_status_t status = 0; 226 227 /* The server SHOULD include a SERVER attribute in all responses */ 228 if (PJ_STUN_IS_RESPONSE(msg->hdr.type) || 229 PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) 230 { 231 pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SERVER, 232 &sess->srv_name); 233 } 223 234 224 235 /* From draft-ietf-behave-rfc3489bis-05.txt 225 236 * Section 8.3.1. Formulating the Request Message 237 * 238 * Note: only put MESSAGE-INTEGRITY in non error response. 226 239 */ 227 if (options & PJ_STUN_USE_LONG_TERM_CRED) { 228 pj_stun_generic_string_attr *auname; 229 pj_stun_msg_integrity_attr *amsgi; 230 pj_stun_generic_string_attr *arealm; 231 232 *p_passwd = &sess->l_password; 240 if (sess->cred && sess->cred->type == PJ_STUN_AUTH_CRED_STATIC && 241 !PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) 242 { 243 const pj_str_t *username; 233 244 234 245 /* Create and add USERNAME attribute */ 235 status = pj_stun_generic_string_attr_create(pool,236 PJ_STUN_ATTR_USERNAME,237 &sess->l_username,238 &auname);246 username = &sess->cred->data.static_cred.username; 247 status = pj_stun_msg_add_string_attr(pool, msg, 248 PJ_STUN_ATTR_USERNAME, 249 username); 239 250 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 240 251 241 status = pj_stun_msg_add_attr(msg, &auname->hdr); 252 /* Add REALM only when long term credential is used */ 253 if (sess->cred->data.static_cred.realm.slen) { 254 const pj_str_t *realm = &sess->cred->data.static_cred.realm; 255 status = pj_stun_msg_add_string_attr(pool, msg, 256 PJ_STUN_ATTR_REALM, 257 realm); 258 } 259 260 /* Add MESSAGE-INTEGRITY attribute */ 261 status = pj_stun_msg_add_msgint_attr(pool, msg); 242 262 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 243 263 244 /* Add REALM only when long term credential is used */ 245 status = pj_stun_generic_string_attr_create(pool, 246 PJ_STUN_ATTR_REALM, 247 &sess->l_realm, 248 &arealm); 249 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 250 251 status = pj_stun_msg_add_attr(msg, &arealm->hdr); 252 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 253 254 /* Add MESSAGE-INTEGRITY attribute */ 255 status = pj_stun_msg_integrity_attr_create(pool, &amsgi); 256 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 257 258 status = pj_stun_msg_add_attr(msg, &amsgi->hdr); 259 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 260 261 } else if (options & PJ_STUN_USE_SHORT_TERM_CRED) { 262 pj_stun_generic_string_attr *auname; 263 pj_stun_msg_integrity_attr *amsgi; 264 265 *p_passwd = &sess->s_password; 266 267 /* Create and add USERNAME attribute */ 268 status = pj_stun_generic_string_attr_create(pool, 269 PJ_STUN_ATTR_USERNAME, 270 &sess->s_username, 271 &auname); 272 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 273 274 status = pj_stun_msg_add_attr(msg, &auname->hdr); 275 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 276 277 /* Add MESSAGE-INTEGRITY attribute */ 278 status = pj_stun_msg_integrity_attr_create(pool, &amsgi); 279 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 280 281 status = pj_stun_msg_add_attr(msg, &amsgi->hdr); 282 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 283 284 } else { 285 *p_passwd = NULL; 286 } 264 } 287 265 288 266 /* Add FINGERPRINT attribute if necessary */ 289 if (options & PJ_STUN_USE_FINGERPRINT) { 290 pj_stun_fingerprint_attr *af; 291 292 status = pj_stun_generic_uint_attr_create(pool, 293 PJ_STUN_ATTR_FINGERPRINT, 294 0, &af); 295 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 296 297 status = pj_stun_msg_add_attr(msg, &af->hdr); 267 if (sess->use_fingerprint) { 268 status = pj_stun_msg_add_uint_attr(pool, msg, 269 PJ_STUN_ATTR_FINGERPRINT, 0); 298 270 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 299 271 } … … 334 306 const char *name, 335 307 const pj_stun_session_cb *cb, 308 pj_bool_t fingerprint, 336 309 pj_stun_session **p_sess) 337 310 { … … 352 325 sess->pool = pool; 353 326 pj_memcpy(&sess->cb, cb, sizeof(*cb)); 327 sess->use_fingerprint = fingerprint; 328 329 sess->srv_name.ptr = pj_pool_alloc(pool, 32); 330 sess->srv_name.slen = pj_ansi_snprintf(sess->srv_name.ptr, 32, 331 "pj_stun-%s", PJ_VERSION); 354 332 355 333 pj_list_init(&sess->pending_request_list); … … 394 372 } 395 373 396 PJ_DEF(pj_status_t) 397 pj_stun_session_set_long_term_credential(pj_stun_session *sess, 398 const pj_str_t *realm, 399 const pj_str_t *user, 400 const pj_str_t *passwd) 401 { 402 pj_str_t nil = { NULL, 0 }; 403 404 PJ_ASSERT_RETURN(sess, PJ_EINVAL); 405 406 pj_mutex_lock(sess->mutex); 407 pj_strdup_with_null(sess->pool, &sess->l_realm, realm ? realm : &nil); 408 pj_strdup_with_null(sess->pool, &sess->l_username, user ? user : &nil); 409 pj_strdup_with_null(sess->pool, &sess->l_password, passwd ? passwd : &nil); 410 pj_mutex_unlock(sess->mutex); 411 412 return PJ_SUCCESS; 413 } 414 415 416 PJ_DEF(pj_status_t) 417 pj_stun_session_set_short_term_credential(pj_stun_session *sess, 418 const pj_str_t *user, 419 const pj_str_t *passwd) 420 { 421 pj_str_t nil = { NULL, 0 }; 422 423 PJ_ASSERT_RETURN(sess, PJ_EINVAL); 424 425 pj_mutex_lock(sess->mutex); 426 pj_strdup_with_null(sess->pool, &sess->s_username, user ? user : &nil); 427 pj_strdup_with_null(sess->pool, &sess->s_password, passwd ? passwd : &nil); 428 pj_mutex_unlock(sess->mutex); 429 430 return PJ_SUCCESS; 374 PJ_DEF(pj_status_t) pj_stun_session_set_server_name(pj_stun_session *sess, 375 const pj_str_t *srv_name) 376 { 377 PJ_ASSERT_RETURN(sess && srv_name, PJ_EINVAL); 378 pj_strdup(sess->pool, &sess->srv_name, srv_name); 379 return PJ_SUCCESS; 380 } 381 382 PJ_DEF(void) pj_stun_session_set_credential(pj_stun_session *sess, 383 const pj_stun_auth_cred *cred) 384 { 385 PJ_ASSERT_ON_FAIL(sess, return); 386 if (cred) { 387 if (!sess->cred) 388 sess->cred = pj_pool_alloc(sess->pool, sizeof(pj_stun_auth_cred)); 389 pj_stun_auth_cred_dup(sess->pool, sess->cred, cred); 390 } else { 391 sess->cred = NULL; 392 } 431 393 } 432 394 … … 570 532 571 533 PJ_DEF(pj_status_t) pj_stun_session_send_msg( pj_stun_session *sess, 572 unsigned options,534 pj_bool_t cache_res, 573 535 const pj_sockaddr_t *server, 574 536 unsigned addr_len, 575 537 pj_stun_tx_data *tdata) 576 538 { 577 pj_str_t *password;578 539 pj_status_t status; 579 540 580 541 PJ_ASSERT_RETURN(sess && addr_len && server && tdata, PJ_EINVAL); 581 582 tdata->options = options;583 542 584 543 /* Allocate packet */ … … 590 549 591 550 /* Apply options */ 592 status = apply_msg_options(sess, tdata->pool, options, 593 tdata->msg, &password); 551 status = apply_msg_options(sess, tdata->pool, tdata->msg); 594 552 if (status != PJ_SUCCESS) { 595 553 pj_stun_msg_destroy_tdata(sess, tdata); … … 601 559 /* Encode message */ 602 560 status = pj_stun_msg_encode(tdata->msg, tdata->pkt, tdata->max_len, 603 0, password, &tdata->pkt_size);561 0, get_passwd(sess), &tdata->pkt_size); 604 562 if (status != PJ_SUCCESS) { 605 563 pj_stun_msg_destroy_tdata(sess, tdata); … … 641 599 642 600 } else { 643 if ( (options & PJ_STUN_CACHE_RESPONSE)&&601 if (cache_res && 644 602 (PJ_STUN_IS_RESPONSE(tdata->msg->hdr.type) || 645 603 PJ_STUN_IS_ERROR_RESPONSE(tdata->msg->hdr.type))) … … 688 646 689 647 648 /* Send response */ 649 static pj_status_t send_response(pj_stun_session *sess, 650 pj_pool_t *pool, pj_stun_msg *response, 651 pj_bool_t retransmission, 652 const pj_sockaddr_t *addr, unsigned addr_len) 653 { 654 pj_uint8_t *out_pkt; 655 unsigned out_max_len, out_len; 656 pj_status_t status; 657 658 /* Alloc packet buffer */ 659 out_max_len = PJ_STUN_MAX_PKT_LEN; 660 out_pkt = pj_pool_alloc(pool, out_max_len); 661 662 /* Apply options */ 663 if (!retransmission) { 664 apply_msg_options(sess, pool, response); 665 } 666 667 /* Encode */ 668 status = pj_stun_msg_encode(response, out_pkt, out_max_len, 0, 669 get_passwd(sess), &out_len); 670 if (status != PJ_SUCCESS) { 671 LOG_ERR_(sess, "Error encoding message", status); 672 return status; 673 } 674 675 /* Print log */ 676 dump_tx_msg(sess, response, out_len, addr); 677 678 /* Send packet */ 679 status = sess->cb.on_send_msg(sess, out_pkt, out_len, addr, addr_len); 680 681 return status; 682 } 683 684 /* Authenticate incoming message */ 685 static pj_status_t authenticate_msg(pj_stun_session *sess, 686 const pj_uint8_t *pkt, 687 unsigned pkt_len, 688 const pj_stun_msg *msg, 689 pj_pool_t *tmp_pool, 690 const pj_sockaddr_t *src_addr, 691 unsigned src_addr_len) 692 { 693 pj_stun_msg *response; 694 pj_status_t status; 695 696 if (PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type) || sess->cred == NULL) 697 return PJ_SUCCESS; 698 699 status = pj_stun_verify_credential(pkt, pkt_len, msg, sess->cred, 700 tmp_pool, &response); 701 if (status != PJ_SUCCESS && response != NULL) { 702 send_response(sess, tmp_pool, response, PJ_FALSE, 703 src_addr, src_addr_len); 704 } 705 706 return status; 707 } 708 709 690 710 /* Handle incoming response */ 691 711 static pj_status_t on_incoming_response(pj_stun_session *sess, … … 724 744 725 745 726 /* Send response */ 727 static pj_status_t send_response(pj_stun_session *sess, unsigned options, 728 pj_pool_t *pool, pj_stun_msg *response, 729 const pj_sockaddr_t *addr, unsigned addr_len) 730 { 731 pj_uint8_t *out_pkt; 732 unsigned out_max_len, out_len; 733 pj_str_t *passwd; 734 pj_status_t status; 735 736 /* Alloc packet buffer */ 737 out_max_len = PJ_STUN_MAX_PKT_LEN; 738 out_pkt = pj_pool_alloc(pool, out_max_len); 739 740 /* Apply options */ 741 apply_msg_options(sess, pool, options, response, &passwd); 742 743 /* Encode */ 744 status = pj_stun_msg_encode(response, out_pkt, out_max_len, 0, 745 passwd, &out_len); 746 if (status != PJ_SUCCESS) { 747 LOG_ERR_(sess, "Error encoding message", status); 748 return status; 749 } 750 751 /* Print log */ 752 dump_tx_msg(sess, response, out_len, addr); 753 754 /* Send packet */ 755 status = sess->cb.on_send_msg(sess, out_pkt, out_len, addr, addr_len); 756 757 return status; 758 } 759 760 /* Handle incoming request */ 761 static pj_status_t on_incoming_request(pj_stun_session *sess, 762 pj_pool_t *tmp_pool, 763 const pj_uint8_t *in_pkt, 764 unsigned in_pkt_len, 765 const pj_stun_msg *msg, 766 const pj_sockaddr_t *src_addr, 767 unsigned src_addr_len) 746 /* For requests, check if we cache the response */ 747 static pj_status_t check_cached_response(pj_stun_session *sess, 748 pj_pool_t *tmp_pool, 749 const pj_stun_msg *msg, 750 const pj_sockaddr_t *src_addr, 751 unsigned src_addr_len) 768 752 { 769 753 pj_stun_tx_data *t; 770 pj_status_t status;771 754 772 755 /* First lookup response in response cache */ … … 784 767 if (t != &sess->cached_response_list) { 785 768 /* Found response in the cache */ 786 unsigned options;787 769 788 770 PJ_LOG(5,(SNAME(sess), 789 771 "Request retransmission, sending cached response")); 790 772 791 options = t->options; 792 options &= ~PJ_STUN_CACHE_RESPONSE; 793 pj_stun_session_send_msg(sess, options, src_addr, src_addr_len, t); 773 send_response(sess, tmp_pool, t->msg, PJ_TRUE, 774 src_addr, src_addr_len); 794 775 return PJ_SUCCESS; 795 776 } 777 778 return PJ_ENOTFOUND; 779 } 780 781 /* Handle incoming request */ 782 static pj_status_t on_incoming_request(pj_stun_session *sess, 783 pj_pool_t *tmp_pool, 784 const pj_uint8_t *in_pkt, 785 unsigned in_pkt_len, 786 const pj_stun_msg *msg, 787 const pj_sockaddr_t *src_addr, 788 unsigned src_addr_len) 789 { 790 pj_status_t status; 796 791 797 792 /* Distribute to handler, or respond with Bad Request */ … … 800 795 src_addr, src_addr_len); 801 796 } else { 802 pj_stun_msg *response = NULL;797 pj_stun_msg *response; 803 798 804 799 status = pj_stun_msg_create_response(tmp_pool, msg, … … 806 801 &response); 807 802 if (status == PJ_SUCCESS && response) { 808 status = send_response(sess, 0,tmp_pool, response,809 src_addr, src_addr_len);803 status = send_response(sess, tmp_pool, response, 804 PJ_FALSE, src_addr, src_addr_len); 810 805 } 811 806 } … … 862 857 LOG_ERR_(sess, "STUN msg_decode() error", status); 863 858 if (response) { 864 send_response(sess, 0,tmp_pool, response,865 src_addr, src_addr_len);859 send_response(sess, tmp_pool, response, 860 PJ_FALSE, src_addr, src_addr_len); 866 861 } 867 862 pj_pool_release(tmp_pool); … … 880 875 pj_mutex_lock(sess->mutex); 881 876 877 /* For requests, check if we have cached response */ 878 status = check_cached_response(sess, tmp_pool, msg, 879 src_addr, src_addr_len); 880 if (status == PJ_SUCCESS) { 881 goto on_return; 882 } 883 884 /* Authenticate the message */ 885 status = authenticate_msg(sess, packet, pkt_size, msg, tmp_pool, 886 src_addr, src_addr_len); 887 if (status != PJ_SUCCESS) 888 goto on_return; 889 890 /* Handle message */ 882 891 if (PJ_STUN_IS_RESPONSE(msg->hdr.type) || 883 892 PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) … … 900 909 } 901 910 911 on_return: 902 912 pj_mutex_unlock(sess->mutex); 903 913
Note: See TracChangeset
for help on using the changeset viewer.