- Timestamp:
- Mar 19, 2008 11:00:30 PM (17 years ago)
- Location:
- pjproject/trunk/pjnath
- Files:
-
- 1 added
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjnath/build/Makefile
r1815 r1877 39 39 # 40 40 export PJNATH_TEST_SRCDIR = ../src/pjnath-test 41 export PJNATH_TEST_OBJS += ice_test.o stun.o test.o41 export PJNATH_TEST_OBJS += ice_test.o stun.o sess_auth.o test.o 42 42 export PJNATH_TEST_CFLAGS += $(_CFLAGS) 43 43 export PJNATH_TEST_LDFLAGS += $(_LDFLAGS) -
pjproject/trunk/pjnath/build/pjnath_test.dsp
r1106 r1877 96 96 # Begin Source File 97 97 98 SOURCE="..\src\pjnath-test\sess_auth.c" 99 # End Source File 100 # Begin Source File 101 98 102 SOURCE="..\src\pjnath-test\stun.c" 99 103 # End Source File -
pjproject/trunk/pjnath/include/pjnath/stun_auth.h
r1869 r1877 40 40 41 41 /** 42 * Type of authentication. 43 */ 44 typedef enum pj_stun_auth_type 45 { 46 /** 47 * No authentication. 48 */ 49 PJ_STUN_AUTH_NONE = 0, 50 51 /** 52 * Authentication using short term credential. 53 */ 54 PJ_STUN_AUTH_SHORT_TERM = 1, 55 56 /** 57 * Authentication using long term credential. 58 */ 59 PJ_STUN_AUTH_LONG_TERM = 2 60 61 } pj_stun_auth_type; 62 63 64 /** 42 65 * Type of authentication data in the credential. 43 66 */ … … 60 83 61 84 } pj_stun_auth_cred_type; 85 86 87 /** 88 * Type of encoding applied to the password stored in the credential. 89 */ 90 typedef enum pj_stun_passwd_type 91 { 92 /** 93 * Plain text password. 94 */ 95 PJ_STUN_PASSWD_PLAIN = 0, 96 97 /** 98 * Hashed password, valid for long term credential only. The hash value 99 * of the password is calculated as MD5(USERNAME ":" REALM ":" PASSWD) 100 * with all quotes removed from the username and realm values. 101 */ 102 PJ_STUN_PASSWD_HASHED = 1 103 104 } pj_stun_passwd_type; 62 105 63 106 … … 90 133 * If not-empty, it indicates that this is a long term credential. 91 134 */ 92 pj_str_t 135 pj_str_t realm; 93 136 94 137 /** 95 138 * The username of the credential. 96 139 */ 97 pj_str_t 140 pj_str_t username; 98 141 99 142 /** 100 143 * Data type to indicate the type of password in the \a data field. 101 * Value zero indicates that the data contains a plaintext 102 * password. 103 */ 104 int data_type; 144 */ 145 pj_stun_passwd_type data_type; 105 146 106 147 /** … … 109 150 * plaintext password. 110 151 */ 111 pj_str_t 152 pj_str_t data; 112 153 113 154 /** 114 155 * Optional NONCE. 115 156 */ 116 pj_str_t 157 pj_str_t nonce; 117 158 118 159 } static_cred; … … 157 198 158 199 /** 159 * Get the credential to be put in outgoing message.200 * Get the credential to be put in outgoing request. 160 201 * 161 202 * @param msg The outgoing message where the credential is … … 187 228 pj_str_t *username, 188 229 pj_str_t *nonce, 189 int*data_type,230 pj_stun_passwd_type *data_type, 190 231 pj_str_t *data); 191 232 … … 218 259 const pj_str_t *username, 219 260 pj_pool_t *pool, 220 int*data_type,261 pj_stun_passwd_type *data_type, 221 262 pj_str_t *data); 222 263 … … 251 292 252 293 /** 294 * This structure contains the credential information that is found and 295 * used to authenticate incoming requests. Application may use this 296 * information when generating authentication for the outgoing response. 297 */ 298 typedef struct pj_stun_req_cred_info 299 { 300 /** 301 * The REALM value found in the incoming request. If short term 302 * credential is used, the value will be empty. 303 */ 304 pj_str_t realm; 305 306 /** 307 * The USERNAME value found in the incoming request. 308 */ 309 pj_str_t username; 310 311 /** 312 * Optional NONCE. 313 */ 314 pj_str_t nonce; 315 316 /** 317 * Authentication key that was used to authenticate the incoming 318 * request. This key is created with #pj_stun_create_key(), and 319 * it can be used to encode the credential of the outgoing 320 * response. 321 */ 322 pj_str_t auth_key; 323 324 } pj_stun_req_cred_info; 325 326 327 /** 253 328 * Duplicate authentication credential. 254 329 * … … 261 336 const pj_stun_auth_cred *src); 262 337 338 /** 339 * Duplicate request credential. 340 * 341 * @param pool Pool to be used to allocate memory. 342 * @param dst Destination credential. 343 * @param src Source credential. 344 */ 345 PJ_DECL(void) pj_stun_req_cred_info_dup(pj_pool_t *pool, 346 pj_stun_req_cred_info *dst, 347 const pj_stun_req_cred_info *src); 348 349 350 /** 351 * Create authentication key to be used for encoding the message with 352 * MESSAGE-INTEGRITY. If short term credential is used (i.e. the realm 353 * argument is NULL or empty), the key will be copied from the password. 354 * If long term credential is used, the key will be calculated from the 355 * MD5 hash of the realm, username, and password. 356 * 357 * @param pool Pool to allocate memory for the key. 358 * @param key String to receive the key. 359 * @param realm The realm of the credential, if long term credential 360 * is to be used. If short term credential is wanted, 361 * application can put NULL or empty string here. 362 * @param username The username. 363 * @param data_type Password encoding. 364 * @param data The password. 365 */ 366 PJ_DECL(void) pj_stun_create_key(pj_pool_t *pool, 367 pj_str_t *key, 368 const pj_str_t *realm, 369 const pj_str_t *username, 370 pj_stun_passwd_type data_type, 371 const pj_str_t *data); 263 372 264 373 /** … … 278 387 * @param pool If response is to be created, then memory will 279 388 * be allocated from this pool. 280 * @param auth_key Optional pointer to receive authentication key to281 * calculate MESSAGE-INTEGRITY of the response, if282 * t he response needs to be authenticated.389 * @param info Optional pointer to receive authentication information 390 * found in the request and the credential that is used 391 * to authenticate the request. 283 392 * @param p_response Optional pointer to receive the response message 284 393 * then the credential in the request fails to … … 295 404 pj_stun_auth_cred *cred, 296 405 pj_pool_t *pool, 297 pj_st r_t *auth_key,406 pj_stun_req_cred_info *info, 298 407 pj_stun_msg **p_response); 299 408 -
pjproject/trunk/pjnath/include/pjnath/stun_msg.h
r1852 r1877 1226 1226 1227 1227 /** 1228 * Clone a STUN message with all of its attributes. 1229 * 1230 * @param pool Pool to allocate memory for the new message. 1231 * @param msg The message to be cloned. 1232 * 1233 * @return The duplicate message. 1234 */ 1235 PJ_DECL(pj_stun_msg*) pj_stun_msg_clone(pj_pool_t *pool, 1236 const pj_stun_msg *msg); 1237 1238 /** 1228 1239 * Create STUN response message. 1229 1240 * … … 1300 1311 const pj_str_t *key, 1301 1312 unsigned *p_msg_len); 1302 1303 1304 /**1305 * Create authentication key to be used for encoding the message with1306 * MESSAGE-INTEGRITY. If short term credential is used (i.e. the realm1307 * argument is NULL or empty), the key will be copied from the password.1308 * If long term credential is used, the key will be calculated from the1309 * MD5 hash of the realm, username, and password.1310 *1311 * @param pool Pool to allocate memory for the key.1312 * @param key String to receive the key.1313 * @param realm The realm of the credential, if long term credential1314 * is to be used. If short term credential is wanted,1315 * application can put NULL or empty string here.1316 * @param username The username.1317 * @param passwd The clear text password.1318 */1319 PJ_DECL(void) pj_stun_create_key(pj_pool_t *pool,1320 pj_str_t *key,1321 const pj_str_t *realm,1322 const pj_str_t *username,1323 const pj_str_t *passwd);1324 1325 1326 1313 1327 1314 /** … … 1418 1405 1419 1406 /** 1407 * Clone a STUN attribute. 1408 * 1409 * @param pool Pool to allocate memory. 1410 * @param attr Attribute to clone. 1411 * 1412 * @return Duplicate attribute. 1413 */ 1414 PJ_DECL(pj_stun_attr_hdr*) pj_stun_attr_clone(pj_pool_t *pool, 1415 const pj_stun_attr_hdr *attr); 1416 1417 1418 /** 1420 1419 * Create a generic STUN IP address attribute. The \a addr_len and 1421 1420 * \a addr parameters specify whether the address is IPv4 or IPv4 -
pjproject/trunk/pjnath/include/pjnath/stun_session.h
r1862 r1877 46 46 /** Forward declaration for pj_stun_tx_data */ 47 47 typedef struct pj_stun_tx_data pj_stun_tx_data; 48 49 /** Forward declaration for pj_stun_rx_data */ 50 typedef struct pj_stun_rx_data pj_stun_rx_data; 48 51 49 52 /** Forward declaration for pj_stun_session */ … … 86 89 * @param pkt Pointer to the original STUN packet. 87 90 * @param pkt_len Length of the STUN packet. 88 * @param msg The parsed STUN request.91 * @param rdata Data containing incoming request message. 89 92 * @param src_addr Source address of the packet. 90 93 * @param src_addr_len Length of the source address. … … 97 100 const pj_uint8_t *pkt, 98 101 unsigned pkt_len, 99 const pj_stun_ msg *msg,102 const pj_stun_rx_data *rdata, 100 103 const pj_sockaddr_t *src_addr, 101 104 unsigned src_addr_len); … … 145 148 146 149 /** 150 * This structure describes incoming request message. 151 */ 152 struct pj_stun_rx_data 153 { 154 /** 155 * The parsed request message. 156 */ 157 pj_stun_msg *msg; 158 159 /** 160 * Credential information that is found and used to authenticate 161 * incoming request. Application may use this information when 162 * generating authentication for the outgoing response. 163 */ 164 pj_stun_req_cred_info info; 165 }; 166 167 168 /** 147 169 * This structure describe the outgoing STUN transmit data to carry the 148 170 * message to be sent. … … 162 184 pj_uint8_t msg_key[12]; /**< Message/transaction key. */ 163 185 164 pj_st r_t auth_key; /**< Auth key.*/186 pj_stun_req_cred_info auth_info; /**< Credential info */ 165 187 166 188 void *pkt; /**< The STUN packet. */ … … 260 282 * 261 283 * @param sess The STUN session instance. 284 * @param auth_type Type of authentication. 262 285 * @param cred The credential to be used by this session. If NULL 263 286 * is specified, authentication will be disabled. … … 265 288 * @return PJ_SUCCESS on success, or the appropriate error code. 266 289 */ 267 PJ_DECL(void) pj_stun_session_set_credential(pj_stun_session *sess, 268 const pj_stun_auth_cred *cred); 290 PJ_DECL(pj_status_t) pj_stun_session_set_credential(pj_stun_session *sess, 291 pj_stun_auth_type auth_type, 292 const pj_stun_auth_cred *cred); 269 293 270 294 /** … … 329 353 */ 330 354 PJ_DECL(pj_status_t) pj_stun_session_create_res(pj_stun_session *sess, 331 const pj_stun_ msg *req,355 const pj_stun_rx_data *rdata, 332 356 unsigned err_code, 333 357 const pj_str_t *err_msg, … … 363 387 * 364 388 * @param sess The STUN session instance. 365 * @param r eqThe STUN request message to be responded.389 * @param rdata The STUN request message to be responded. 366 390 * @param err_code Error code to be set in the response, if error response 367 391 * is to be created, according to pj_stun_status enumeration. … … 383 407 */ 384 408 PJ_DECL(pj_status_t) pj_stun_session_respond(pj_stun_session *sess, 385 const pj_stun_ msg *req,409 const pj_stun_rx_data *rdata, 386 410 unsigned code, 387 411 const char *err_msg, -
pjproject/trunk/pjnath/src/pjnath-test/stun.c
r1869 r1877 270 270 271 271 /* Try to encode message */ 272 pj_stun_create_key(pool, &key, NULL, &USERNAME, &PASSWORD);272 pj_stun_create_key(pool, &key, NULL, &USERNAME, PJ_STUN_PASSWD_PLAIN, &PASSWORD); 273 273 status = pj_stun_msg_encode(msg, buf, sizeof(buf), 0, &key, &len); 274 274 if (status != PJ_SUCCESS) { … … 406 406 { 407 407 /* Decode all attribute types */ 408 return 0;409 }410 411 static int auth_test(void)412 {413 /* REALM and USERNAME is present, but MESSAGE-INTEGRITY is not present.414 * For short term, must with reply 401 without REALM.415 * For long term, must reply with 401 with REALM.416 */417 418 /* USERNAME is not present, server must respond with 432 (Missing419 * Username).420 */421 422 /* If long term credential is wanted and REALM is not present, server423 * must respond with 434 (Missing Realm)424 */425 426 /* If REALM doesn't match, server must respond with 434 (Missing Realm)427 * too, containing REALM and NONCE attribute.428 */429 430 /* When long term authentication is wanted and NONCE is NOT present,431 * server must respond with 435 (Missing Nonce), containing REALM and432 * NONCE attribute.433 */434 435 /* Simulate 438 (Stale Nonce) */436 437 /* Simulate 436 (Unknown Username) */438 439 /* When server wants to use short term credential, but request has440 * REALM, reject with .... ???441 */442 443 /* Invalid HMAC */444 445 /* Valid static short term, without NONCE */446 447 /* Valid static short term, WITH NONCE */448 449 /* Valid static long term (with NONCE */450 451 /* Valid dynamic short term (without NONCE) */452 453 /* Valid dynamic short term (with NONCE) */454 455 /* Valid dynamic long term (with NONCE) */456 457 408 return 0; 458 409 } … … 615 566 616 567 pj_stun_create_key(pool, &key, NULL, pj_cstr(&s1, v->username), 617 pj_cstr(&s2, v->password));568 PJ_STUN_PASSWD_PLAIN, pj_cstr(&s2, v->password)); 618 569 pj_stun_msg_encode(msg, buf, sizeof(buf), 0, &key, &len); 619 570 … … 752 703 goto on_return; 753 704 754 rc = auth_test();755 if (rc != 0)756 goto on_return;757 758 705 rc = fingerprint_test_vector(); 759 706 if (rc != 0) -
pjproject/trunk/pjnath/src/pjnath-test/test.c
r1439 r1877 69 69 #if INCLUDE_STUN_TEST 70 70 DO_TEST(stun_test()); 71 DO_TEST(sess_auth_test()); 71 72 #endif 72 73 -
pjproject/trunk/pjnath/src/pjnath-test/test.h
r1439 r1877 24 24 #define INCLUDE_ICE_TEST 1 25 25 26 extern int stun_test(void); 27 extern int ice_test(void); 28 extern int test_main(void); 26 int stun_test(void); 27 int sess_auth_test(void); 28 int ice_test(void); 29 int test_main(void); 29 30 30 31 extern void app_perror(const char *title, pj_status_t rc); -
pjproject/trunk/pjnath/src/pjnath/ice_session.c
r1731 r1877 121 121 const pj_uint8_t *pkt, 122 122 unsigned pkt_len, 123 const pj_stun_ msg *msg,123 const pj_stun_rx_data *rdata, 124 124 const pj_sockaddr_t *src_addr, 125 125 unsigned src_addr_len); … … 148 148 pj_str_t *username, 149 149 pj_str_t *nonce, 150 int*data_type,150 pj_stun_passwd_type *data_type, 151 151 pj_str_t *data); 152 152 static pj_status_t stun_auth_get_password(const pj_stun_msg *msg, … … 155 155 const pj_str_t *username, 156 156 pj_pool_t *pool, 157 int*data_type,157 pj_stun_passwd_type *data_type, 158 158 pj_str_t *data); 159 159 … … 233 233 auth_cred.data.dyn_cred.get_password = &stun_auth_get_password; 234 234 auth_cred.data.dyn_cred.user_data = comp->stun_sess; 235 pj_stun_session_set_credential(comp->stun_sess, &auth_cred); 235 pj_stun_session_set_credential(comp->stun_sess, PJ_STUN_AUTH_SHORT_TERM, 236 &auth_cred); 236 237 237 238 return PJ_SUCCESS; … … 447 448 pj_str_t *username, 448 449 pj_str_t *nonce, 449 int*data_type,450 pj_stun_passwd_type *data_type, 450 451 pj_str_t *data) 451 452 { … … 462 463 */ 463 464 *username = ice->rx_uname; 464 *data_type = 0;465 *data_type = PJ_STUN_PASSWD_PLAIN; 465 466 *data = ice->rx_pass; 466 467 } 467 468 else { 468 469 *username = ice->tx_uname; 469 *data_type = 0;470 *data_type = PJ_STUN_PASSWD_PLAIN; 470 471 *data = ice->tx_pass; 471 472 } … … 480 481 const pj_str_t *username, 481 482 pj_pool_t *pool, 482 int*data_type,483 pj_stun_passwd_type *data_type, 483 484 pj_str_t *data) 484 485 { … … 497 498 if (pj_strcmp(username, &ice->tx_uname) != 0) 498 499 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNAUTHORIZED); 499 *data_type = 0;500 *data_type = PJ_STUN_PASSWD_PLAIN; 500 501 *data = ice->tx_pass; 501 502 … … 522 523 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNAUTHORIZED); 523 524 524 *data_type = 0;525 *data_type = PJ_STUN_PASSWD_PLAIN; 525 526 *data = ice->rx_pass; 526 527 … … 1904 1905 const pj_uint8_t *pkt, 1905 1906 unsigned pkt_len, 1906 const pj_stun_ msg *msg,1907 const pj_stun_rx_data *rdata, 1907 1908 const pj_sockaddr_t *src_addr, 1908 1909 unsigned src_addr_len) 1909 1910 { 1910 1911 stun_data *sd; 1912 const pj_stun_msg *msg = rdata->msg; 1911 1913 pj_ice_sess *ice; 1912 1914 pj_stun_priority_attr *prio_attr; … … 1922 1924 /* Reject any requests except Binding request */ 1923 1925 if (msg->hdr.type != PJ_STUN_BINDING_REQUEST) { 1924 status = pj_stun_session_create_res(sess, msg,1926 status = pj_stun_session_create_res(sess, rdata, 1925 1927 PJ_STUN_SC_BAD_REQUEST, 1926 1928 NULL, &tdata); … … 1993 1995 } else { 1994 1996 /* Generate 487 response */ 1995 status = pj_stun_session_create_res(sess, msg,1997 status = pj_stun_session_create_res(sess, rdata, 1996 1998 PJ_STUN_SC_ROLE_CONFLICT, 1997 1999 NULL, &tdata); … … 2009 2011 if (pj_cmp_timestamp(&ice->tie_breaker, &role_attr->value) < 0) { 2010 2012 /* Generate 487 response */ 2011 status = pj_stun_session_create_res(sess, msg,2013 status = pj_stun_session_create_res(sess, rdata, 2012 2014 PJ_STUN_SC_ROLE_CONFLICT, 2013 2015 NULL, &tdata); … … 2029 2031 * First send response to this request 2030 2032 */ 2031 status = pj_stun_session_create_res(sess, msg, 0, NULL, &tdata);2033 status = pj_stun_session_create_res(sess, rdata, 0, NULL, &tdata); 2032 2034 if (status != PJ_SUCCESS) { 2033 2035 pj_mutex_unlock(ice->mutex); -
pjproject/trunk/pjnath/src/pjnath/stun_auth.c
r1869 r1877 20 20 #include <pjnath/errno.h> 21 21 #include <pjlib-util/hmac_sha1.h> 22 #include <pjlib-util/md5.h> 22 23 #include <pjlib-util/sha1.h> 23 24 #include <pj/assert.h> 24 25 #include <pj/log.h> 26 #include <pj/pool.h> 25 27 #include <pj/string.h> 26 28 … … 54 56 55 57 58 /* 59 * Duplicate request credential. 60 */ 61 PJ_DEF(void) pj_stun_req_cred_info_dup( pj_pool_t *pool, 62 pj_stun_req_cred_info *dst, 63 const pj_stun_req_cred_info *src) 64 { 65 pj_strdup(pool, &dst->realm, &src->realm); 66 pj_strdup(pool, &dst->username, &src->username); 67 pj_strdup(pool, &dst->nonce, &src->nonce); 68 pj_strdup(pool, &dst->auth_key, &src->auth_key); 69 } 70 71 72 /* Calculate HMAC-SHA1 key for long term credential, by getting 73 * MD5 digest of username, realm, and password. 74 */ 75 static void calc_md5_key(pj_uint8_t digest[16], 76 const pj_str_t *realm, 77 const pj_str_t *username, 78 const pj_str_t *passwd) 79 { 80 /* The 16-byte key for MESSAGE-INTEGRITY HMAC is formed by taking 81 * the MD5 hash of the result of concatenating the following five 82 * fields: (1) The username, with any quotes and trailing nulls 83 * removed, (2) A single colon, (3) The realm, with any quotes and 84 * trailing nulls removed, (4) A single colon, and (5) The 85 * password, with any trailing nulls removed. 86 */ 87 pj_md5_context ctx; 88 pj_str_t s; 89 90 pj_md5_init(&ctx); 91 92 #define REMOVE_QUOTE(s) if (s.slen && *s.ptr=='"') \ 93 s.ptr++, s.slen--; \ 94 if (s.slen && s.ptr[s.slen-1]=='"') \ 95 s.slen--; 96 97 /* Add username */ 98 s = *username; 99 REMOVE_QUOTE(s); 100 pj_md5_update(&ctx, (pj_uint8_t*)s.ptr, s.slen); 101 102 /* Add single colon */ 103 pj_md5_update(&ctx, (pj_uint8_t*)":", 1); 104 105 /* Add realm */ 106 s = *realm; 107 REMOVE_QUOTE(s); 108 pj_md5_update(&ctx, (pj_uint8_t*)s.ptr, s.slen); 109 110 #undef REMOVE_QUOTE 111 112 /* Another colon */ 113 pj_md5_update(&ctx, (pj_uint8_t*)":", 1); 114 115 /* Add password */ 116 pj_md5_update(&ctx, (pj_uint8_t*)passwd->ptr, passwd->slen); 117 118 /* Done */ 119 pj_md5_final(&ctx, digest); 120 } 121 122 123 /* 124 * Create authentication key to be used for encoding the message with 125 * MESSAGE-INTEGRITY. 126 */ 127 PJ_DEF(void) pj_stun_create_key(pj_pool_t *pool, 128 pj_str_t *key, 129 const pj_str_t *realm, 130 const pj_str_t *username, 131 pj_stun_passwd_type data_type, 132 const pj_str_t *data) 133 { 134 PJ_ASSERT_ON_FAIL(pool && key && username && data, return); 135 136 if (realm && realm->slen) { 137 if (data_type == PJ_STUN_PASSWD_PLAIN) { 138 key->ptr = (char*) pj_pool_alloc(pool, 16); 139 calc_md5_key((pj_uint8_t*)key->ptr, realm, username, data); 140 key->slen = 16; 141 } else { 142 pj_strdup(pool, key, data); 143 } 144 } else { 145 pj_assert(data_type == PJ_STUN_PASSWD_PLAIN); 146 pj_strdup(pool, key, data); 147 } 148 } 149 150 56 151 PJ_INLINE(pj_uint16_t) GET_VAL16(const pj_uint8_t *pdu, unsigned pos) 57 152 { … … 87 182 return rc; 88 183 89 90 if ( realm && realm->slen) {184 /* SHOULD NOT add REALM, NONCE, USERNAME, and M-I on 400 response */ 185 if (err_code!=400 && realm && realm->slen) { 91 186 rc = pj_stun_msg_add_string_attr(pool, response, 92 187 PJ_STUN_ATTR_REALM, … … 102 197 } 103 198 104 if ( nonce && nonce->slen) {199 if (err_code!=400 && nonce && nonce->slen) { 105 200 rc = pj_stun_msg_add_string_attr(pool, response, 106 201 PJ_STUN_ATTR_NONCE, … … 122 217 pj_stun_auth_cred *cred, 123 218 pj_pool_t *pool, 124 pj_st r_t *auth_key,219 pj_stun_req_cred_info *p_info, 125 220 pj_stun_msg **p_response) 126 221 { 127 pj_st r_t realm, nonce, password;222 pj_stun_req_cred_info tmp_info; 128 223 const pj_stun_msgint_attr *amsgi; 129 224 unsigned i, amsgi_pos; 130 225 pj_bool_t has_attr_beyond_mi; 131 226 const pj_stun_username_attr *auser; 132 pj_bool_t username_ok;133 227 const pj_stun_realm_attr *arealm; 134 228 const pj_stun_realm_attr *anonce; 135 229 pj_hmac_sha1_context ctx; 136 230 pj_uint8_t digest[PJ_SHA1_DIGEST_SIZE]; 137 pj_str_t key; 231 pj_stun_status err_code; 232 const char *err_text = NULL; 138 233 pj_status_t status; 139 234 … … 150 245 p_response = NULL; 151 246 247 if (p_info == NULL) 248 p_info = &tmp_info; 249 250 pj_bzero(p_info, sizeof(pj_stun_req_cred_info)); 251 152 252 /* Get realm and nonce from credential */ 153 realm.slen =nonce.slen = 0;253 p_info->realm.slen = p_info->nonce.slen = 0; 154 254 if (cred->type == PJ_STUN_AUTH_CRED_STATIC) { 155 realm = cred->data.static_cred.realm;156 nonce = cred->data.static_cred.nonce;255 p_info->realm = cred->data.static_cred.realm; 256 p_info->nonce = cred->data.static_cred.nonce; 157 257 } else if (cred->type == PJ_STUN_AUTH_CRED_DYNAMIC) { 158 258 status = cred->data.dyn_cred.get_auth(cred->data.dyn_cred.user_data, 159 pool, &realm, &nonce); 259 pool, &p_info->realm, 260 &p_info->nonce); 160 261 if (status != PJ_SUCCESS) 161 262 return status; 162 263 } else { 163 pj_assert(!" Unexpected");264 pj_assert(!"Invalid credential type"); 164 265 return PJ_EBUG; 165 266 } … … 185 286 The rule has been changed from rfc3489bis-06 186 287 */ 187 int code; 188 189 code = realm.slen ? PJ_STUN_SC_UNAUTHORIZED : PJ_STUN_SC_BAD_REQUEST; 190 if (p_response) { 191 create_challenge(pool, msg, code, NULL, 192 &realm, &nonce, p_response); 193 } 194 return PJ_STATUS_FROM_STUN_CODE(code); 288 err_code = p_info->realm.slen ? PJ_STUN_SC_UNAUTHORIZED : 289 PJ_STUN_SC_BAD_REQUEST; 290 goto on_auth_failed; 195 291 } 196 292 … … 203 299 The rule has been changed from rfc3489bis-06 204 300 */ 205 int code = PJ_STUN_SC_BAD_REQUEST; 206 if (p_response) { 207 create_challenge(pool, msg, code, "Missing USERNAME", 208 &realm, &nonce, p_response); 209 } 210 return PJ_STATUS_FROM_STUN_CODE(code); 301 err_code = PJ_STUN_SC_BAD_REQUEST; 302 err_text = "Missing USERNAME"; 303 goto on_auth_failed; 211 304 } 212 305 … … 215 308 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REALM, 0); 216 309 310 /* Reject with 400 if we have long term credential and the request 311 * is missing REALM attribute. 312 */ 313 if (p_info->realm.slen && arealm==NULL) { 314 err_code = PJ_STUN_SC_BAD_REQUEST; 315 err_text = "Missing REALM"; 316 goto on_auth_failed; 317 } 318 217 319 /* Check if username match */ 218 320 if (cred->type == PJ_STUN_AUTH_CRED_STATIC) { 321 pj_bool_t username_ok; 219 322 username_ok = !pj_strcmp(&auser->value, 220 323 &cred->data.static_cred.username); 221 password = cred->data.static_cred.data; 324 if (username_ok) { 325 pj_strdup(pool, &p_info->username, 326 &cred->data.static_cred.username); 327 pj_stun_create_key(pool, &p_info->auth_key, &p_info->realm, 328 &auser->value, cred->data.static_cred.data_type, 329 &cred->data.static_cred.data); 330 } else { 331 /* Username mismatch */ 332 /* According to rfc3489bis-10 Sec 10.1.2/10.2.2, we should 333 * return 401 334 */ 335 err_code = PJ_STUN_SC_UNAUTHORIZED; 336 goto on_auth_failed; 337 } 222 338 } else if (cred->type == PJ_STUN_AUTH_CRED_DYNAMIC) { 223 int data_type = 0; 339 pj_stun_passwd_type data_type = PJ_STUN_PASSWD_PLAIN; 340 pj_str_t password; 224 341 pj_status_t rc; 342 225 343 rc = cred->data.dyn_cred.get_password(msg, 226 344 cred->data.dyn_cred.user_data, … … 228 346 &auser->value, pool, 229 347 &data_type, &password); 230 username_ok = (rc == PJ_SUCCESS); 348 if (rc == PJ_SUCCESS) { 349 pj_strdup(pool, &p_info->username, &auser->value); 350 pj_stun_create_key(pool, &p_info->auth_key, 351 (arealm?&arealm->value:NULL), &auser->value, 352 data_type, &password); 353 } else { 354 err_code = PJ_STUN_SC_UNAUTHORIZED; 355 goto on_auth_failed; 356 } 231 357 } else { 232 username_ok = PJ_TRUE; 233 password.slen = 0; 234 } 235 236 if (!username_ok) { 237 /* Username mismatch */ 238 /* According to rfc3489bis-10 Sec 10.1.2/10.2.2, we should 239 * return 401 240 */ 241 if (p_response) { 242 create_challenge(pool, msg, PJ_STUN_SC_UNAUTHORIZED, NULL, 243 &realm, &nonce, p_response); 244 } 245 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNAUTHORIZED); 246 } 358 pj_assert(!"Invalid credential type"); 359 return PJ_EBUG; 360 } 361 247 362 248 363 … … 252 367 253 368 /* Check for long term/short term requirements. */ 254 if ( realm.slen != 0 && arealm == NULL) {369 if (p_info->realm.slen != 0 && arealm == NULL) { 255 370 /* Long term credential is required and REALM is not present */ 256 if (p_response) { 257 create_challenge(pool, msg, PJ_STUN_SC_BAD_REQUEST, 258 "Missing REALM", 259 &realm, &nonce, p_response); 260 } 261 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); 262 263 } else if (realm.slen != 0 && arealm != NULL) { 371 err_code = PJ_STUN_SC_BAD_REQUEST; 372 err_text = "Missing REALM"; 373 goto on_auth_failed; 374 375 } else if (p_info->realm.slen != 0 && arealm != NULL) { 264 376 /* We want long term, and REALM is present */ 265 377 266 378 /* NONCE must be present. */ 267 if (anonce == NULL && nonce.slen) { 268 if (p_response) { 269 create_challenge(pool, msg, PJ_STUN_SC_BAD_REQUEST, 270 "Missing NONCE", &realm, &nonce, p_response); 271 } 272 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); 379 if (anonce == NULL && p_info->nonce.slen) { 380 err_code = PJ_STUN_SC_BAD_REQUEST; 381 err_text = "Missing NONCE"; 382 goto on_auth_failed; 273 383 } 274 384 275 385 /* Verify REALM matches */ 276 if (pj_stricmp(&arealm->value, & realm)) {386 if (pj_stricmp(&arealm->value, &p_info->realm)) { 277 387 /* REALM doesn't match */ 278 if (p_response) { 279 create_challenge(pool, msg, PJ_STUN_SC_UNAUTHORIZED, 280 "Invalid REALM", &realm, &nonce, p_response); 281 } 282 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNAUTHORIZED); 388 err_code = PJ_STUN_SC_UNAUTHORIZED; 389 err_text = "Invalid REALM"; 390 goto on_auth_failed; 283 391 } 284 392 285 393 /* Valid case, will validate the message integrity later */ 286 394 287 } else if ( realm.slen == 0 && arealm != NULL) {395 } else if (p_info->realm.slen == 0 && arealm != NULL) { 288 396 /* We want to use short term credential, but client uses long 289 397 * term credential. The draft doesn't mention anything about … … 294 402 * cause wrong message integrity value later. 295 403 */ 296 } else if ( realm.slen==0 && arealm == NULL) {404 } else if (p_info->realm.slen==0 && arealm == NULL) { 297 405 /* Short term authentication is wanted, and one is supplied */ 298 406 299 407 /* Application MAY request NONCE to be supplied */ 300 if (nonce.slen != 0) { 301 if (p_response) { 302 create_challenge(pool, msg, PJ_STUN_SC_UNAUTHORIZED, 303 "NONCE required", &realm, &nonce, p_response); 304 } 305 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNAUTHORIZED); 408 if (p_info->nonce.slen != 0) { 409 err_code = PJ_STUN_SC_UNAUTHORIZED; 410 err_text = "NONCE required"; 411 goto on_auth_failed; 306 412 } 307 413 } … … 322 428 ok = PJ_TRUE; 323 429 } else { 324 if ( nonce.slen) {325 ok = !pj_strcmp(&anonce->value, & nonce);430 if (p_info->nonce.slen) { 431 ok = !pj_strcmp(&anonce->value, &p_info->nonce); 326 432 } else { 327 433 ok = PJ_TRUE; … … 330 436 331 437 if (!ok) { 332 if (p_response) { 333 create_challenge(pool, msg, PJ_STUN_SC_STALE_NONCE, 334 NULL, &realm, &nonce, p_response); 335 } 336 if (auth_key) { 337 pj_stun_create_key(pool, auth_key, &realm, 338 &auser->value, &password); 339 } 340 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_STALE_NONCE); 341 } 342 } 343 344 /* Calculate key */ 345 pj_stun_create_key(pool, &key, &realm, &auser->value, &password); 438 err_code = PJ_STUN_SC_STALE_NONCE; 439 goto on_auth_failed; 440 } 441 } 346 442 347 443 /* Now calculate HMAC of the message. */ 348 pj_hmac_sha1_init(&ctx, (pj_uint8_t*)key.ptr, key.slen); 444 pj_hmac_sha1_init(&ctx, (pj_uint8_t*)p_info->auth_key.ptr, 445 p_info->auth_key.slen); 349 446 350 447 #if PJ_STUN_OLD_STYLE_MI_FINGERPRINT … … 383 480 /* HMAC value mismatch */ 384 481 /* According to rfc3489bis-10 Sec 10.1.2 we should return 401 */ 385 if (p_response) { 386 create_challenge(pool, msg, PJ_STUN_SC_UNAUTHORIZED, 387 NULL, &realm, &nonce, p_response); 388 } 389 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNAUTHORIZED); 482 err_code = PJ_STUN_SC_UNAUTHORIZED; 483 err_text = "MESSAGE-INTEGRITY mismatch"; 484 goto on_auth_failed; 390 485 } 391 486 392 487 /* Everything looks okay! */ 393 488 return PJ_SUCCESS; 489 490 on_auth_failed: 491 if (p_response) { 492 create_challenge(pool, msg, err_code, err_text, 493 &p_info->realm, &p_info->nonce, p_response); 494 } 495 return PJ_STATUS_FROM_STUN_CODE(err_code); 394 496 } 395 497 … … 426 528 case PJ_STUN_SC_BAD_REQUEST: /* 400 (Bad Request) */ 427 529 case PJ_STUN_SC_UNAUTHORIZED: /* 401 (Unauthorized) */ 428 //case PJ_STUN_SC_STALE_CREDENTIALS: /* 430 (Stale Credential) */ 429 //case PJ_STUN_SC_MISSING_USERNAME: /* 432 (Missing Username) */ 430 //case PJ_STUN_SC_MISSING_REALM: /* 434 (Missing Realm) */ 431 //case PJ_STUN_SC_UNKNOWN_USERNAME: /* 436 (Unknown Username) */ 432 //case PJ_STUN_SC_INTEGRITY_CHECK_FAILURE:/* 431 (Integrity Check Fail) */ 530 531 /* Due to the way this response is generated here, we can't really 532 * authenticate 420 (Unknown Attribute) response */ 533 case PJ_STUN_SC_UNKNOWN_ATTRIBUTE: 433 534 return PJ_FALSE; 434 535 default: -
pjproject/trunk/pjnath/src/pjnath/stun_msg.c
r1852 r1877 21 21 #include <pjlib-util/crc32.h> 22 22 #include <pjlib-util/hmac_sha1.h> 23 #include <pjlib-util/md5.h>24 23 #include <pj/assert.h> 25 24 #include <pj/log.h> … … 91 90 pj_status_t (*encode_attr)(const void *a, pj_uint8_t *buf, 92 91 unsigned len, unsigned *printed); 92 void* (*clone_attr)(pj_pool_t *pool, const void *src); 93 93 }; 94 94 … … 102 102 unsigned len, 103 103 unsigned *printed); 104 static void* clone_sockaddr_attr(pj_pool_t *pool, const void *src); 104 105 static pj_status_t decode_string_attr(pj_pool_t *pool, 105 106 const pj_uint8_t *buf, … … 107 108 static pj_status_t encode_string_attr(const void *a, pj_uint8_t *buf, 108 109 unsigned len, unsigned *printed); 110 static void* clone_string_attr(pj_pool_t *pool, const void *src); 109 111 static pj_status_t decode_msgint_attr(pj_pool_t *pool, 110 112 const pj_uint8_t *buf, … … 112 114 static pj_status_t encode_msgint_attr(const void *a, pj_uint8_t *buf, 113 115 unsigned len, unsigned *printed); 116 static void* clone_msgint_attr(pj_pool_t *pool, const void *src); 114 117 static pj_status_t decode_errcode_attr(pj_pool_t *pool, 115 118 const pj_uint8_t *buf, … … 117 120 static pj_status_t encode_errcode_attr(const void *a, pj_uint8_t *buf, 118 121 unsigned len, unsigned *printed); 122 static void* clone_errcode_attr(pj_pool_t *pool, const void *src); 119 123 static pj_status_t decode_unknown_attr(pj_pool_t *pool, 120 124 const pj_uint8_t *buf, … … 122 126 static pj_status_t encode_unknown_attr(const void *a, pj_uint8_t *buf, 123 127 unsigned len, unsigned *printed); 128 static void* clone_unknown_attr(pj_pool_t *pool, const void *src); 124 129 static pj_status_t decode_uint_attr(pj_pool_t *pool, 125 130 const pj_uint8_t *buf, … … 127 132 static pj_status_t encode_uint_attr(const void *a, pj_uint8_t *buf, 128 133 unsigned len, unsigned *printed); 134 static void* clone_uint_attr(pj_pool_t *pool, const void *src); 129 135 static pj_status_t decode_uint64_attr(pj_pool_t *pool, 130 136 const pj_uint8_t *buf, … … 132 138 static pj_status_t encode_uint64_attr(const void *a, pj_uint8_t *buf, 133 139 unsigned len, unsigned *printed); 140 static void* clone_uint64_attr(pj_pool_t *pool, const void *src); 134 141 static pj_status_t decode_binary_attr(pj_pool_t *pool, 135 142 const pj_uint8_t *buf, … … 137 144 static pj_status_t encode_binary_attr(const void *a, pj_uint8_t *buf, 138 145 unsigned len, unsigned *printed); 146 static void* clone_binary_attr(pj_pool_t *pool, const void *src); 139 147 static pj_status_t decode_empty_attr(pj_pool_t *pool, 140 148 const pj_uint8_t *buf, … … 142 150 static pj_status_t encode_empty_attr(const void *a, pj_uint8_t *buf, 143 151 unsigned len, unsigned *printed); 144 152 static void* clone_empty_attr(pj_pool_t *pool, const void *src); 145 153 146 154 static struct attr_desc mandatory_attr_desc[] = … … 148 156 { 149 157 /* type zero */ 158 NULL, 150 159 NULL, 151 160 NULL, … … 156 165 "MAPPED-ADDRESS", 157 166 &decode_sockaddr_attr, 158 &encode_sockaddr_attr 167 &encode_sockaddr_attr, 168 &clone_sockaddr_attr 159 169 }, 160 170 { … … 162 172 "RESPONSE-ADDRESS", 163 173 &decode_sockaddr_attr, 164 &encode_sockaddr_attr 174 &encode_sockaddr_attr, 175 &clone_sockaddr_attr 165 176 }, 166 177 { … … 168 179 "CHANGE-REQUEST", 169 180 &decode_uint_attr, 170 &encode_uint_attr 181 &encode_uint_attr, 182 &clone_uint_attr 171 183 }, 172 184 { … … 174 186 "SOURCE-ADDRESS", 175 187 &decode_sockaddr_attr, 176 &encode_sockaddr_attr 188 &encode_sockaddr_attr, 189 &clone_sockaddr_attr 177 190 }, 178 191 { … … 180 193 "CHANGED-ADDRESS", 181 194 &decode_sockaddr_attr, 182 &encode_sockaddr_attr 195 &encode_sockaddr_attr, 196 &clone_sockaddr_attr 183 197 }, 184 198 { … … 186 200 "USERNAME", 187 201 &decode_string_attr, 188 &encode_string_attr 202 &encode_string_attr, 203 &clone_string_attr 189 204 }, 190 205 { … … 192 207 "PASSWORD", 193 208 &decode_string_attr, 194 &encode_string_attr 209 &encode_string_attr, 210 &clone_string_attr 195 211 }, 196 212 { … … 198 214 "MESSAGE-INTEGRITY", 199 215 &decode_msgint_attr, 200 &encode_msgint_attr 216 &encode_msgint_attr, 217 &clone_msgint_attr 201 218 }, 202 219 { … … 204 221 "ERROR-CODE", 205 222 &decode_errcode_attr, 206 &encode_errcode_attr 223 &encode_errcode_attr, 224 &clone_errcode_attr 207 225 }, 208 226 { … … 210 228 "UNKNOWN-ATTRIBUTES", 211 229 &decode_unknown_attr, 212 &encode_unknown_attr 230 &encode_unknown_attr, 231 &clone_unknown_attr 213 232 }, 214 233 { … … 216 235 "REFLECTED-FROM", 217 236 &decode_sockaddr_attr, 218 &encode_sockaddr_attr 237 &encode_sockaddr_attr, 238 &clone_sockaddr_attr 219 239 }, 220 240 { … … 222 242 "CHANNEL-NUMBER", 223 243 &decode_uint_attr, 224 &encode_uint_attr 244 &encode_uint_attr, 245 &clone_uint_attr 225 246 }, 226 247 { … … 228 249 "LIFETIME", 229 250 &decode_uint_attr, 230 &encode_uint_attr 251 &encode_uint_attr, 252 &clone_uint_attr 231 253 }, 232 254 { 233 255 /* ID 0x000E is not assigned */ 256 NULL, 234 257 NULL, 235 258 NULL, … … 240 263 "MAGIC-COOKIE", 241 264 &decode_uint_attr, 242 &encode_uint_attr 265 &encode_uint_attr, 266 &clone_uint_attr 243 267 }, 244 268 { … … 246 270 "BANDWIDTH", 247 271 &decode_uint_attr, 248 &encode_uint_attr 272 &encode_uint_attr, 273 &clone_uint_attr 249 274 }, 250 275 { 251 276 /* ID 0x0011 is not assigned */ 277 NULL, 252 278 NULL, 253 279 NULL, … … 258 284 "PEER-ADDRESS", 259 285 &decode_xored_sockaddr_attr, 260 &encode_sockaddr_attr 286 &encode_sockaddr_attr, 287 &clone_sockaddr_attr 261 288 }, 262 289 { … … 264 291 "DATA", 265 292 &decode_binary_attr, 266 &encode_binary_attr 293 &encode_binary_attr, 294 &clone_binary_attr 267 295 }, 268 296 { … … 270 298 "REALM", 271 299 &decode_string_attr, 272 &encode_string_attr 300 &encode_string_attr, 301 &clone_string_attr 273 302 }, 274 303 { … … 276 305 "NONCE", 277 306 &decode_string_attr, 278 &encode_string_attr 307 &encode_string_attr, 308 &clone_string_attr 279 309 }, 280 310 { … … 282 312 "RELAY-ADDRESS", 283 313 &decode_xored_sockaddr_attr, 284 &encode_sockaddr_attr 314 &encode_sockaddr_attr, 315 &clone_sockaddr_attr 285 316 }, 286 317 { … … 288 319 "REQUESTED-ADDRESS-TYPE", 289 320 &decode_uint_attr, 290 &encode_uint_attr 321 &encode_uint_attr, 322 &clone_uint_attr 291 323 }, 292 324 { … … 294 326 "REQUESTED-PROPS", 295 327 &decode_uint_attr, 296 &encode_uint_attr 328 &encode_uint_attr, 329 &clone_uint_attr 297 330 }, 298 331 { … … 300 333 "REQUESTED-TRANSPORT", 301 334 &decode_uint_attr, 302 &encode_uint_attr 335 &encode_uint_attr, 336 &clone_uint_attr 303 337 }, 304 338 { … … 306 340 NULL, 307 341 NULL, 342 NULL, 308 343 NULL 309 344 }, … … 312 347 NULL, 313 348 NULL, 349 NULL, 314 350 NULL 315 351 }, … … 318 354 NULL, 319 355 NULL, 356 NULL, 320 357 NULL 321 358 }, … … 324 361 NULL, 325 362 NULL, 363 NULL, 326 364 NULL 327 365 }, … … 330 368 NULL, 331 369 NULL, 370 NULL, 332 371 NULL 333 372 }, 334 373 { 335 374 /* ID 0x001F is not assigned */ 375 NULL, 336 376 NULL, 337 377 NULL, … … 342 382 "XOR-MAPPED-ADDRESS", 343 383 &decode_xored_sockaddr_attr, 344 &encode_sockaddr_attr 384 &encode_sockaddr_attr, 385 &clone_sockaddr_attr 345 386 }, 346 387 { … … 348 389 "TIMER-VAL", 349 390 &decode_uint_attr, 350 &encode_uint_attr 391 &encode_uint_attr, 392 &clone_uint_attr 351 393 }, 352 394 { … … 354 396 "RESERVATION-TOKEN", 355 397 &decode_uint64_attr, 356 &encode_uint64_attr 398 &encode_uint64_attr, 399 &clone_uint64_attr 357 400 }, 358 401 { … … 360 403 "XOR-REFLECTED-FROM", 361 404 &decode_xored_sockaddr_attr, 362 &encode_sockaddr_attr 405 &encode_sockaddr_attr, 406 &clone_sockaddr_attr 363 407 }, 364 408 { … … 366 410 "PRIORITY", 367 411 &decode_uint_attr, 368 &encode_uint_attr 412 &encode_uint_attr, 413 &clone_uint_attr 369 414 }, 370 415 { … … 372 417 "USE-CANDIDATE", 373 418 &decode_empty_attr, 374 &encode_empty_attr 419 &encode_empty_attr, 420 &clone_empty_attr 375 421 }, 376 422 { … … 378 424 "XOR-INTERNAL-ADDRESS", 379 425 &decode_xored_sockaddr_attr, 380 &encode_sockaddr_attr 426 &encode_sockaddr_attr, 427 &clone_sockaddr_attr 381 428 }, 382 429 … … 386 433 NULL, 387 434 NULL, 435 NULL, 388 436 NULL 389 437 } … … 394 442 { 395 443 /* ID 0x8021 is not assigned */ 444 NULL, 396 445 NULL, 397 446 NULL, … … 402 451 "SERVER", 403 452 &decode_string_attr, 404 &encode_string_attr 453 &encode_string_attr, 454 &clone_string_attr 405 455 }, 406 456 { … … 408 458 "ALTERNATE-SERVER", 409 459 &decode_sockaddr_attr, 410 &encode_sockaddr_attr 460 &encode_sockaddr_attr, 461 &clone_sockaddr_attr 411 462 }, 412 463 { … … 414 465 "REFRESH-INTERVAL", 415 466 &decode_uint_attr, 416 &encode_uint_attr 467 &encode_uint_attr, 468 &clone_uint_attr 417 469 }, 418 470 { … … 420 472 NULL, 421 473 NULL, 474 NULL, 422 475 NULL 423 476 }, … … 426 479 NULL, 427 480 NULL, 481 NULL, 428 482 NULL 429 483 }, 430 484 { 431 485 /* CACHE-TIMEOUT, 0x8027 */ 486 NULL, 432 487 NULL, 433 488 NULL, … … 438 493 "FINGERPRINT", 439 494 &decode_uint_attr, 440 &encode_uint_attr 495 &encode_uint_attr, 496 &clone_uint_attr 441 497 }, 442 498 { … … 444 500 "ICE-CONTROLLED", 445 501 &decode_uint64_attr, 446 &encode_uint64_attr 502 &encode_uint64_attr, 503 &clone_uint64_attr 447 504 }, 448 505 { … … 450 507 "ICE-CONTROLLING", 451 508 &decode_uint64_attr, 452 &encode_uint64_attr 509 &encode_uint64_attr, 510 &clone_uint64_attr 453 511 } 454 512 }; … … 827 885 828 886 887 static void* clone_sockaddr_attr(pj_pool_t *pool, const void *src) 888 { 889 pj_stun_sockaddr_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_sockaddr_attr); 890 pj_memcpy(dst, src, sizeof(pj_stun_sockaddr_attr)); 891 return (void*)dst; 892 } 893 829 894 ////////////////////////////////////////////////////////////////////////////// 830 895 /* … … 935 1000 936 1001 1002 static void* clone_string_attr(pj_pool_t *pool, const void *src) 1003 { 1004 const pj_stun_string_attr *asrc = (const pj_stun_string_attr*)src; 1005 pj_stun_string_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_string_attr); 1006 1007 pj_memcpy(dst, src, sizeof(pj_stun_attr_hdr)); 1008 pj_strdup(pool, &dst->value, &asrc->value); 1009 1010 return (void*)dst; 1011 } 1012 937 1013 ////////////////////////////////////////////////////////////////////////////// 938 1014 /* … … 1018 1094 } 1019 1095 1096 1097 static void* clone_empty_attr(pj_pool_t *pool, const void *src) 1098 { 1099 pj_stun_empty_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_empty_attr); 1100 1101 pj_memcpy(dst, src, sizeof(pj_stun_empty_attr)); 1102 1103 return (void*) dst; 1104 } 1020 1105 1021 1106 ////////////////////////////////////////////////////////////////////////////// … … 1104 1189 } 1105 1190 1191 1192 static void* clone_uint_attr(pj_pool_t *pool, const void *src) 1193 { 1194 pj_stun_uint_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_uint_attr); 1195 1196 pj_memcpy(dst, src, sizeof(pj_stun_uint_attr)); 1197 1198 return (void*)dst; 1199 } 1200 1106 1201 ////////////////////////////////////////////////////////////////////////////// 1107 1202 … … 1190 1285 1191 1286 1287 static void* clone_uint64_attr(pj_pool_t *pool, const void *src) 1288 { 1289 pj_stun_uint64_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_uint64_attr); 1290 1291 pj_memcpy(dst, src, sizeof(pj_stun_uint64_attr)); 1292 1293 return (void*)dst; 1294 } 1295 1296 1192 1297 ////////////////////////////////////////////////////////////////////////////// 1193 1298 /* … … 1270 1375 1271 1376 return PJ_SUCCESS; 1377 } 1378 1379 1380 static void* clone_msgint_attr(pj_pool_t *pool, const void *src) 1381 { 1382 pj_stun_msgint_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_msgint_attr); 1383 1384 pj_memcpy(dst, src, sizeof(pj_stun_msgint_attr)); 1385 1386 return (void*) dst; 1272 1387 } 1273 1388 … … 1382 1497 } 1383 1498 1499 1500 static void* clone_errcode_attr(pj_pool_t *pool, const void *src) 1501 { 1502 const pj_stun_errcode_attr *asrc = (const pj_stun_errcode_attr*)src; 1503 pj_stun_errcode_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_errcode_attr); 1504 1505 pj_memcpy(dst, src, sizeof(pj_stun_errcode_attr)); 1506 pj_strdup(pool, &dst->reason, &asrc->reason); 1507 1508 return (void*)dst; 1509 } 1510 1384 1511 ////////////////////////////////////////////////////////////////////////////// 1385 1512 /* … … 1500 1627 1501 1628 1629 static void* clone_unknown_attr(pj_pool_t *pool, const void *src) 1630 { 1631 pj_stun_unknown_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_unknown_attr); 1632 1633 pj_memcpy(dst, src, sizeof(pj_stun_unknown_attr)); 1634 1635 return (void*)dst; 1636 } 1637 1502 1638 ////////////////////////////////////////////////////////////////////////////// 1503 1639 /* … … 1597 1733 } 1598 1734 1735 1736 static void* clone_binary_attr(pj_pool_t *pool, const void *src) 1737 { 1738 const pj_stun_binary_attr *asrc = (const pj_stun_binary_attr*)src; 1739 pj_stun_binary_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_binary_attr); 1740 1741 pj_memcpy(dst, src, sizeof(pj_stun_binary_attr)); 1742 1743 if (asrc->length) { 1744 dst->data = (pj_uint8_t*) pj_pool_alloc(pool, asrc->length); 1745 pj_memcpy(dst->data, asrc->data, asrc->length); 1746 } 1747 1748 return (void*)dst; 1749 } 1599 1750 1600 1751 ////////////////////////////////////////////////////////////////////////////// … … 1638 1789 1639 1790 return PJ_SUCCESS; 1791 } 1792 1793 1794 /* 1795 * Clone a STUN message with all of its attributes. 1796 */ 1797 PJ_DEF(pj_stun_msg*) pj_stun_msg_clone( pj_pool_t *pool, 1798 const pj_stun_msg *src) 1799 { 1800 pj_stun_msg *dst; 1801 unsigned i; 1802 1803 PJ_ASSERT_RETURN(pool && src, NULL); 1804 1805 dst = PJ_POOL_ZALLOC_T(pool, pj_stun_msg); 1806 pj_memcpy(dst, src, sizeof(pj_stun_msg)); 1807 1808 /* Duplicate the attributes */ 1809 for (i=0, dst->attr_count=0; i<src->attr_count; ++i) { 1810 dst->attr[dst->attr_count] = pj_stun_attr_clone(pool, src->attr[i]); 1811 if (dst->attr[dst->attr_count]) 1812 ++dst->attr_count; 1813 } 1814 1815 return dst; 1640 1816 } 1641 1817 … … 1982 2158 } 1983 2159 1984 /* Calculate HMAC-SHA1 key for long term credential, by getting1985 * MD5 digest of username, realm, and password.1986 */1987 static void calc_md5_key(pj_uint8_t digest[16],1988 const pj_str_t *realm,1989 const pj_str_t *username,1990 const pj_str_t *passwd)1991 {1992 /* The 16-byte key for MESSAGE-INTEGRITY HMAC is formed by taking1993 * the MD5 hash of the result of concatenating the following five1994 * fields: (1) The username, with any quotes and trailing nulls1995 * removed, (2) A single colon, (3) The realm, with any quotes and1996 * trailing nulls removed, (4) A single colon, and (5) The1997 * password, with any trailing nulls removed.1998 */1999 pj_md5_context ctx;2000 pj_str_t s;2001 2002 pj_md5_init(&ctx);2003 2004 #define REMOVE_QUOTE(s) if (s.slen && *s.ptr=='"') \2005 s.ptr++, s.slen--; \2006 if (s.slen && s.ptr[s.slen-1]=='"') \2007 s.slen--;2008 2009 /* Add username */2010 s = *username;2011 REMOVE_QUOTE(s);2012 pj_md5_update(&ctx, (pj_uint8_t*)s.ptr, s.slen);2013 2014 /* Add single colon */2015 pj_md5_update(&ctx, (pj_uint8_t*)":", 1);2016 2017 /* Add realm */2018 s = *realm;2019 REMOVE_QUOTE(s);2020 pj_md5_update(&ctx, (pj_uint8_t*)s.ptr, s.slen);2021 2022 #undef REMOVE_QUOTE2023 2024 /* Another colon */2025 pj_md5_update(&ctx, (pj_uint8_t*)":", 1);2026 2027 /* Add password */2028 pj_md5_update(&ctx, (pj_uint8_t*)passwd->ptr, passwd->slen);2029 2030 /* Done */2031 pj_md5_final(&ctx, digest);2032 }2033 2034 2035 /*2036 * Create authentication key to be used for encoding the message with2037 * MESSAGE-INTEGRITY.2038 */2039 PJ_DEF(void) pj_stun_create_key(pj_pool_t *pool,2040 pj_str_t *key,2041 const pj_str_t *realm,2042 const pj_str_t *username,2043 const pj_str_t *passwd)2044 {2045 PJ_ASSERT_ON_FAIL(pool && key && username && passwd, return);2046 2047 if (realm && realm->slen) {2048 key->ptr = (char*) pj_pool_alloc(pool, 16);2049 calc_md5_key((pj_uint8_t*)key->ptr, realm, username, passwd);2050 key->slen = 16;2051 } else {2052 pj_strdup(pool, key, passwd);2053 }2054 }2055 2056 2057 2160 /* 2058 2161 static char *print_binary(const pj_uint8_t *data, unsigned data_len) … … 2208 2311 * the last attribute before FINGERPRINT. 2209 2312 */ 2210 if ( i < msg->attr_count-2) {2313 if (msg->attr_count>1 && i < msg->attr_count-2) { 2211 2314 /* Should not happen for message generated by us */ 2212 2315 pj_assert(PJ_FALSE); … … 2299 2402 } 2300 2403 2404 2405 /* 2406 * Clone a STUN attribute. 2407 */ 2408 PJ_DEF(pj_stun_attr_hdr*) pj_stun_attr_clone( pj_pool_t *pool, 2409 const pj_stun_attr_hdr *attr) 2410 { 2411 const struct attr_desc *adesc; 2412 2413 /* Get the attribute descriptor */ 2414 adesc = find_attr_desc(attr->type); 2415 PJ_ASSERT_RETURN(adesc != NULL, NULL); 2416 2417 return (pj_stun_attr_hdr*) (*adesc->clone_attr)(pool, attr); 2418 } 2419 2420 -
pjproject/trunk/pjnath/src/pjnath/stun_session.c
r1869 r1877 18 18 */ 19 19 #include <pjnath/stun_session.h> 20 #include <pjnath/errno.h> 20 21 #include <pjlib.h> 21 22 … … 30 31 31 32 pj_bool_t use_fingerprint; 32 pj_stun_auth_cred *cred; 33 34 char dump_buf[1000]; 35 36 pj_stun_auth_type auth_type; 37 pj_stun_auth_cred cred; 38 int auth_retry; 39 pj_str_t next_nonce; 40 33 41 pj_str_t srv_name; 34 42 … … 126 134 } 127 135 128 static pj_status_t create_request_tdata(pj_stun_session *sess,129 unsigned msg_type,130 pj_uint32_t magic,131 const pj_uint8_t tsx_id[12],132 pj_stun_tx_data **p_tdata)133 {134 pj_status_t status;135 pj_stun_tx_data *tdata;136 137 status = create_tdata(sess, &tdata);138 if (status != PJ_SUCCESS)139 return status;140 141 /* Create STUN message */142 status = pj_stun_msg_create(tdata->pool, msg_type, magic,143 tsx_id, &tdata->msg);144 if (status != PJ_SUCCESS) {145 pj_pool_release(tdata->pool);146 return status;147 }148 149 /* copy the request's transaction ID as the transaction key. */150 pj_assert(sizeof(tdata->msg_key)==sizeof(tdata->msg->hdr.tsx_id));151 tdata->msg_magic = tdata->msg->hdr.magic;152 pj_memcpy(tdata->msg_key, tdata->msg->hdr.tsx_id,153 sizeof(tdata->msg->hdr.tsx_id));154 155 *p_tdata = tdata;156 157 return PJ_SUCCESS;158 }159 160 161 136 static void stun_tsx_on_destroy(pj_stun_client_tsx *tsx) 162 137 { … … 216 191 } 217 192 218 static pj_status_t get_key(pj_stun_session *sess, pj_pool_t *pool,219 const pj_stun_msg *msg, pj_str_t *auth_key)220 {221 if (sess->cred == NULL) {222 auth_key->slen = 0;223 return PJ_SUCCESS;224 } else if (sess->cred->type == PJ_STUN_AUTH_CRED_STATIC) {225 pj_stun_create_key(pool, auth_key,226 &sess->cred->data.static_cred.realm,227 &sess->cred->data.static_cred.username,228 &sess->cred->data.static_cred.data);229 return PJ_SUCCESS;230 } else if (sess->cred->type == PJ_STUN_AUTH_CRED_DYNAMIC) {231 pj_str_t realm, username, nonce;232 pj_str_t *password;233 void *user_data = sess->cred->data.dyn_cred.user_data;234 int data_type = 0;235 pj_status_t status;236 237 realm.slen = username.slen = nonce.slen = 0;238 password = PJ_POOL_ZALLOC_T(pool, pj_str_t);239 status = (*sess->cred->data.dyn_cred.get_cred)(msg, user_data, pool,240 &realm, &username,241 &nonce, &data_type,242 password);243 if (status != PJ_SUCCESS)244 return status;245 246 pj_stun_create_key(pool, auth_key,247 &realm, &username, password);248 249 return PJ_SUCCESS;250 251 } else {252 pj_assert(!"Unknown credential type");253 return PJ_EBUG;254 }255 }256 257 193 static pj_status_t apply_msg_options(pj_stun_session *sess, 258 194 pj_pool_t *pool, 195 const pj_stun_req_cred_info *auth_info, 259 196 pj_stun_msg *msg) 260 197 { 261 198 pj_status_t status = 0; 262 pj_bool_t need_auth; 263 pj_str_t realm, username, nonce, password; 264 int data_type = 0; 265 266 realm.slen = username.slen = nonce.slen = password.slen = 0; 199 pj_str_t realm, username, nonce, auth_key; 267 200 268 201 /* The server SHOULD include a SERVER attribute in all responses */ … … 272 205 } 273 206 274 need_auth = pj_stun_auth_valid_for_msg(msg); 275 276 if (sess->cred && sess->cred->type == PJ_STUN_AUTH_CRED_STATIC && 277 need_auth) 278 { 279 realm = sess->cred->data.static_cred.realm; 280 username = sess->cred->data.static_cred.username; 281 data_type = sess->cred->data.static_cred.data_type; 282 password = sess->cred->data.static_cred.data; 283 nonce = sess->cred->data.static_cred.nonce; 284 285 } else if (sess->cred && sess->cred->type == PJ_STUN_AUTH_CRED_DYNAMIC && 286 need_auth) 287 { 288 void *user_data = sess->cred->data.dyn_cred.user_data; 289 290 status = (*sess->cred->data.dyn_cred.get_cred)(msg, user_data, pool, 291 &realm, &username, 292 &nonce, &data_type, 293 &password); 294 if (status != PJ_SUCCESS) 295 return status; 296 } 297 298 299 /* Create and add USERNAME attribute for */ 207 if (pj_stun_auth_valid_for_msg(msg) && auth_info) { 208 realm = auth_info->realm; 209 username = auth_info->username; 210 nonce = auth_info->nonce; 211 auth_key = auth_info->auth_key; 212 } else { 213 realm.slen = username.slen = nonce.slen = auth_key.slen = 0; 214 } 215 216 /* Create and add USERNAME attribute if needed */ 300 217 if (username.slen && PJ_STUN_IS_REQUEST(msg->hdr.type)) { 301 218 status = pj_stun_msg_add_string_attr(pool, msg, … … 324 241 325 242 /* Add MESSAGE-INTEGRITY attribute */ 326 if (username.slen && need_auth) {243 if (username.slen && auth_key.slen) { 327 244 status = pj_stun_msg_add_msgint_attr(pool, msg); 328 245 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); … … 340 257 } 341 258 259 static pj_status_t handle_auth_challenge(pj_stun_session *sess, 260 const pj_stun_tx_data *request, 261 const pj_stun_msg *response, 262 const pj_sockaddr_t *src_addr, 263 unsigned src_addr_len, 264 pj_bool_t *notify_user) 265 { 266 const pj_stun_errcode_attr *ea; 267 268 *notify_user = PJ_TRUE; 269 270 if (sess->auth_type != PJ_STUN_AUTH_LONG_TERM) 271 return PJ_SUCCESS; 272 273 if (!PJ_STUN_IS_ERROR_RESPONSE(response->hdr.type)) 274 return PJ_SUCCESS; 275 276 ea = (const pj_stun_errcode_attr*) 277 pj_stun_msg_find_attr(response, PJ_STUN_ATTR_ERROR_CODE, 0); 278 if (!ea) { 279 PJ_LOG(4,(SNAME(sess), "Invalid error response: no ERROR-CODE" 280 " attribute")); 281 *notify_user = PJ_FALSE; 282 return PJNATH_EINSTUNMSG; 283 } 284 285 if (ea->err_code == PJ_STUN_SC_UNAUTHORIZED || 286 ea->err_code == PJ_STUN_SC_STALE_NONCE) 287 { 288 const pj_stun_nonce_attr *anonce; 289 pj_stun_tx_data *tdata; 290 unsigned i; 291 pj_status_t status; 292 293 anonce = (const pj_stun_nonce_attr*) 294 pj_stun_msg_find_attr(response, PJ_STUN_ATTR_NONCE, 0); 295 if (!anonce) { 296 PJ_LOG(4,(SNAME(sess), "Invalid response: missing NONCE")); 297 *notify_user = PJ_FALSE; 298 return PJNATH_EINSTUNMSG; 299 } 300 301 /* Bail out if we've supplied the correct nonce */ 302 if (pj_strcmp(&anonce->value, &sess->next_nonce)==0) { 303 return PJ_SUCCESS; 304 } 305 306 /* Bail out if we've tried too many */ 307 if (++sess->auth_retry > 3) { 308 PJ_LOG(4,(SNAME(sess), "Error: authentication failed (too " 309 "many retries)")); 310 return PJ_STATUS_FROM_STUN_CODE(401); 311 } 312 313 /* Save next_nonce */ 314 pj_strdup(sess->pool, &sess->next_nonce, &anonce->value); 315 316 /* Create new request */ 317 status = pj_stun_session_create_req(sess, request->msg->hdr.type, 318 request->msg->hdr.magic, 319 NULL, &tdata); 320 if (status != PJ_SUCCESS) 321 return status; 322 323 /* Duplicate all the attributes in the old request, except 324 * USERNAME, REALM, M-I, and NONCE 325 */ 326 for (i=0; i<request->msg->attr_count; ++i) { 327 const pj_stun_attr_hdr *asrc = request->msg->attr[i]; 328 329 if (asrc->type == PJ_STUN_ATTR_USERNAME || 330 asrc->type == PJ_STUN_ATTR_REALM || 331 asrc->type == PJ_STUN_ATTR_MESSAGE_INTEGRITY || 332 asrc->type == PJ_STUN_ATTR_NONCE) 333 { 334 continue; 335 } 336 337 tdata->msg->attr[tdata->msg->attr_count++] = 338 pj_stun_attr_clone(tdata->pool, asrc); 339 } 340 341 /* Will retry the request with authentication, no need to 342 * notify user. 343 */ 344 *notify_user = PJ_FALSE; 345 346 PJ_LOG(4,(SNAME(sess), "Retrying request with new authentication")); 347 348 /* Retry the request */ 349 status = pj_stun_session_send_msg(sess, PJ_TRUE, src_addr, 350 src_addr_len, tdata); 351 352 } else { 353 sess->auth_retry = 0; 354 } 355 356 return PJ_SUCCESS; 357 } 342 358 343 359 static void stun_tsx_on_complete(pj_stun_client_tsx *tsx, … … 347 363 unsigned src_addr_len) 348 364 { 365 pj_stun_session *sess; 366 pj_bool_t notify_user = PJ_TRUE; 349 367 pj_stun_tx_data *tdata; 350 368 351 369 tdata = (pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx); 352 353 if (tdata->sess->cb.on_request_complete) { 354 (*tdata->sess->cb.on_request_complete)(tdata->sess, status, tdata, 355 response, 356 src_addr, src_addr_len); 370 sess = tdata->sess; 371 372 /* Handle authentication challenge */ 373 handle_auth_challenge(sess, tdata, response, src_addr, 374 src_addr_len, ¬ify_user); 375 376 if (notify_user && sess->cb.on_request_complete) { 377 (*sess->cb.on_request_complete)(sess, status, tdata, 378 response, 379 src_addr, src_addr_len); 357 380 } 358 381 } … … 489 512 } 490 513 491 PJ_DEF(void) pj_stun_session_set_credential(pj_stun_session *sess, 492 const pj_stun_auth_cred *cred) 493 { 494 PJ_ASSERT_ON_FAIL(sess, return); 514 PJ_DEF(pj_status_t) pj_stun_session_set_credential(pj_stun_session *sess, 515 pj_stun_auth_type auth_type, 516 const pj_stun_auth_cred *cred) 517 { 518 PJ_ASSERT_RETURN(sess, PJ_EINVAL); 519 520 sess->auth_type = auth_type; 495 521 if (cred) { 496 if (!sess->cred) 497 sess->cred = PJ_POOL_ALLOC_T(sess->pool, pj_stun_auth_cred); 498 pj_stun_auth_cred_dup(sess->pool, sess->cred, cred); 522 pj_stun_auth_cred_dup(sess->pool, &sess->cred, cred); 499 523 } else { 500 sess->cred = NULL; 501 } 502 } 503 524 sess->auth_type = PJ_STUN_AUTH_NONE; 525 pj_bzero(&sess->cred, sizeof(sess->cred)); 526 } 527 528 return PJ_SUCCESS; 529 } 530 531 532 static pj_status_t get_auth(pj_stun_session *sess, 533 pj_stun_tx_data *tdata) 534 { 535 if (sess->cred.type == PJ_STUN_AUTH_CRED_STATIC) { 536 tdata->auth_info.realm = sess->cred.data.static_cred.realm; 537 tdata->auth_info.username = sess->cred.data.static_cred.username; 538 tdata->auth_info.nonce = sess->cred.data.static_cred.nonce; 539 540 pj_stun_create_key(tdata->pool, &tdata->auth_info.auth_key, 541 &tdata->auth_info.realm, 542 &tdata->auth_info.username, 543 sess->cred.data.static_cred.data_type, 544 &sess->cred.data.static_cred.data); 545 546 } else if (sess->cred.type == PJ_STUN_AUTH_CRED_DYNAMIC) { 547 pj_str_t password; 548 void *user_data = sess->cred.data.dyn_cred.user_data; 549 pj_stun_passwd_type data_type = PJ_STUN_PASSWD_PLAIN; 550 pj_status_t rc; 551 552 rc = (*sess->cred.data.dyn_cred.get_cred)(tdata->msg, user_data, 553 tdata->pool, 554 &tdata->auth_info.realm, 555 &tdata->auth_info.username, 556 &tdata->auth_info.nonce, 557 &data_type, &password); 558 if (rc != PJ_SUCCESS) 559 return rc; 560 561 pj_stun_create_key(tdata->pool, &tdata->auth_info.auth_key, 562 &tdata->auth_info.realm, &tdata->auth_info.username, 563 data_type, &password); 564 565 } else { 566 pj_assert(!"Unknown credential type"); 567 return PJ_EBUG; 568 } 569 570 return PJ_SUCCESS; 571 } 504 572 505 573 PJ_DEF(pj_status_t) pj_stun_session_create_req(pj_stun_session *sess, … … 514 582 PJ_ASSERT_RETURN(sess && p_tdata, PJ_EINVAL); 515 583 516 status = create_ request_tdata(sess, method, magic, tsx_id, &tdata);584 status = create_tdata(sess, &tdata); 517 585 if (status != PJ_SUCCESS) 518 586 return status; 587 588 /* Create STUN message */ 589 status = pj_stun_msg_create(tdata->pool, method, magic, 590 tsx_id, &tdata->msg); 591 if (status != PJ_SUCCESS) { 592 pj_pool_release(tdata->pool); 593 return status; 594 } 595 596 /* copy the request's transaction ID as the transaction key. */ 597 pj_assert(sizeof(tdata->msg_key)==sizeof(tdata->msg->hdr.tsx_id)); 598 tdata->msg_magic = tdata->msg->hdr.magic; 599 pj_memcpy(tdata->msg_key, tdata->msg->hdr.tsx_id, 600 sizeof(tdata->msg->hdr.tsx_id)); 601 602 603 /* Get authentication information for the request */ 604 if (sess->auth_type == PJ_STUN_AUTH_NONE) { 605 /* No authentication */ 606 607 } else if (sess->auth_type == PJ_STUN_AUTH_SHORT_TERM) { 608 /* MUST put authentication in request */ 609 status = get_auth(sess, tdata); 610 if (status != PJ_SUCCESS) { 611 pj_pool_release(tdata->pool); 612 return status; 613 } 614 615 } else if (sess->auth_type == PJ_STUN_AUTH_LONG_TERM) { 616 /* Only put authentication information if we've received 617 * response from server. 618 */ 619 if (sess->next_nonce.slen != 0) { 620 status = get_auth(sess, tdata); 621 if (status != PJ_SUCCESS) { 622 pj_pool_release(tdata->pool); 623 return status; 624 } 625 tdata->auth_info.nonce = sess->next_nonce; 626 } 627 628 } else { 629 pj_assert(!"Invalid authentication type"); 630 pj_pool_release(tdata->pool); 631 return PJ_EBUG; 632 } 519 633 520 634 *p_tdata = tdata; … … 552 666 */ 553 667 PJ_DEF(pj_status_t) pj_stun_session_create_res( pj_stun_session *sess, 554 const pj_stun_ msg *req,668 const pj_stun_rx_data *rdata, 555 669 unsigned err_code, 556 670 const pj_str_t *err_msg, … … 565 679 566 680 /* Create STUN response message */ 567 status = pj_stun_msg_create_response(tdata->pool, r eq, err_code, err_msg,568 &tdata->msg);681 status = pj_stun_msg_create_response(tdata->pool, rdata->msg, 682 err_code, err_msg, &tdata->msg); 569 683 if (status != PJ_SUCCESS) { 570 684 pj_pool_release(tdata->pool); … … 573 687 574 688 /* copy the request's transaction ID as the transaction key. */ 575 pj_assert(sizeof(tdata->msg_key)==sizeof(req->hdr.tsx_id)); 576 tdata->msg_magic = req->hdr.magic; 577 pj_memcpy(tdata->msg_key, req->hdr.tsx_id, sizeof(req->hdr.tsx_id)); 689 pj_assert(sizeof(tdata->msg_key)==sizeof(rdata->msg->hdr.tsx_id)); 690 tdata->msg_magic = rdata->msg->hdr.magic; 691 pj_memcpy(tdata->msg_key, rdata->msg->hdr.tsx_id, 692 sizeof(rdata->msg->hdr.tsx_id)); 693 694 /* copy the credential found in the request */ 695 pj_stun_req_cred_info_dup(tdata->pool, &tdata->auth_info, &rdata->info); 578 696 579 697 *p_tdata = tdata; … … 587 705 unsigned pkt_size, const pj_sockaddr_t *addr) 588 706 { 589 const char *dst_name; 590 int dst_port; 591 const pj_sockaddr *dst = (const pj_sockaddr*)addr; 592 char buf[800]; 707 char dst_name[80]; 593 708 594 if (dst->addr.sa_family == pj_AF_INET()) { 595 dst_name = pj_inet_ntoa(dst->ipv4.sin_addr); 596 dst_port = pj_ntohs(dst->ipv4.sin_port); 597 } else if (dst->addr.sa_family == pj_AF_INET6()) { 598 dst_name = "IPv6"; 599 dst_port = pj_ntohs(dst->ipv6.sin6_port); 600 } else { 601 LOG_ERR_(sess, "Invalid address family", PJ_EINVAL); 602 return; 603 } 709 pj_sockaddr_print(addr, dst_name, sizeof(dst_name), 3); 604 710 605 711 PJ_LOG(5,(SNAME(sess), 606 "TX %d bytes STUN message to %s: %d:\n"712 "TX %d bytes STUN message to %s:\n" 607 713 "--- begin STUN message ---\n" 608 714 "%s" 609 715 "--- end of STUN message ---\n", 610 pkt_size, dst_name, dst_port, 611 pj_stun_msg_dump(msg, buf, sizeof(buf), NULL))); 716 pkt_size, dst_name, 717 pj_stun_msg_dump(msg, sess->dump_buf, sizeof(sess->dump_buf), 718 NULL))); 612 719 613 720 } … … 632 739 633 740 /* Apply options */ 634 status = apply_msg_options(sess, tdata->pool, tdata->msg); 741 status = apply_msg_options(sess, tdata->pool, &tdata->auth_info, 742 tdata->msg); 635 743 if (status != PJ_SUCCESS) { 636 744 pj_stun_msg_destroy_tdata(sess, tdata); … … 640 748 } 641 749 642 status = get_key(sess, tdata->pool, tdata->msg, &tdata->auth_key);643 if (status != PJ_SUCCESS) {644 pj_stun_msg_destroy_tdata(sess, tdata);645 pj_lock_release(sess->lock);646 LOG_ERR_(sess, "Error getting creadential's key", status);647 return status;648 }649 650 750 /* Encode message */ 651 751 status = pj_stun_msg_encode(tdata->msg, (pj_uint8_t*)tdata->pkt, 652 752 tdata->max_len, 0, 653 &tdata->auth_ key,753 &tdata->auth_info.auth_key, 654 754 &tdata->pkt_size); 655 755 if (status != PJ_SUCCESS) { … … 743 843 */ 744 844 PJ_DEF(pj_status_t) pj_stun_session_respond( pj_stun_session *sess, 745 const pj_stun_ msg *req,845 const pj_stun_rx_data *rdata, 746 846 unsigned code, 747 847 const char *errmsg, … … 754 854 pj_stun_tx_data *tdata; 755 855 756 status = pj_stun_session_create_res(sess, r eq, code,856 status = pj_stun_session_create_res(sess, rdata, code, 757 857 (errmsg?pj_cstr(&reason,errmsg):NULL), 758 858 &tdata); … … 814 914 static pj_status_t send_response(pj_stun_session *sess, 815 915 pj_pool_t *pool, pj_stun_msg *response, 816 const pj_st r_t *auth_key,916 const pj_stun_req_cred_info *auth_info, 817 917 pj_bool_t retransmission, 818 918 const pj_sockaddr_t *addr, unsigned addr_len) … … 824 924 /* Apply options */ 825 925 if (!retransmission) { 826 status = apply_msg_options(sess, pool, response);926 status = apply_msg_options(sess, pool, auth_info, response); 827 927 if (status != PJ_SUCCESS) 828 928 return status; … … 835 935 /* Encode */ 836 936 status = pj_stun_msg_encode(response, out_pkt, out_max_len, 0, 837 auth_key, &out_len);937 &auth_info->auth_key, &out_len); 838 938 if (status != PJ_SUCCESS) { 839 939 LOG_ERR_(sess, "Error encoding message", status); … … 854 954 const pj_uint8_t *pkt, 855 955 unsigned pkt_len, 856 const pj_stun_msg *msg,956 pj_stun_rx_data *rdata, 857 957 pj_pool_t *tmp_pool, 858 958 const pj_sockaddr_t *src_addr, … … 860 960 { 861 961 pj_stun_msg *response; 862 pj_str_t auth_key;863 962 pj_status_t status; 864 963 865 if (PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type) || sess->cred == NULL) 964 if (PJ_STUN_IS_ERROR_RESPONSE(rdata->msg->hdr.type) || 965 sess->auth_type == PJ_STUN_AUTH_NONE) 966 { 866 967 return PJ_SUCCESS; 867 868 status = pj_stun_authenticate_request(pkt, pkt_len, msg, sess->cred, 869 tmp_pool, &auth_key, &response); 968 } 969 970 status = pj_stun_authenticate_request(pkt, pkt_len, rdata->msg, 971 &sess->cred, tmp_pool, &rdata->info, 972 &response); 870 973 if (status != PJ_SUCCESS && response != NULL) { 871 974 PJ_LOG(5,(SNAME(sess), "Message authentication failed")); 872 send_response(sess, tmp_pool, response, & auth_key, PJ_FALSE,975 send_response(sess, tmp_pool, response, &rdata->info, PJ_FALSE, 873 976 src_addr, src_addr_len); 874 977 } … … 898 1001 } 899 1002 1003 if (sess->auth_type == PJ_STUN_AUTH_NONE) 1004 options |= PJ_STUN_NO_AUTHENTICATE; 1005 900 1006 /* Authenticate the message, unless PJ_STUN_NO_AUTHENTICATE 901 1007 * is specified in the option. 902 1008 */ 903 if ((options & PJ_STUN_NO_AUTHENTICATE) == 0 && tdata->auth_key.slen != 0 904 && pj_stun_auth_valid_for_msg(msg)) 1009 if ((options & PJ_STUN_NO_AUTHENTICATE) == 0 && 1010 tdata->auth_info.auth_key.slen != 0 && 1011 pj_stun_auth_valid_for_msg(msg)) 905 1012 { 906 1013 status = pj_stun_authenticate_response(pkt, pkt_len, msg, 907 &tdata->auth_ key);1014 &tdata->auth_info.auth_key); 908 1015 if (status != PJ_SUCCESS) { 909 1016 PJ_LOG(5,(SNAME(sess), … … 963 1070 "Request retransmission, sending cached response")); 964 1071 965 send_response(sess, tmp_pool, t->msg, &t->auth_ key, PJ_TRUE,1072 send_response(sess, tmp_pool, t->msg, &t->auth_info, PJ_TRUE, 966 1073 src_addr, src_addr_len); 967 1074 return PJ_SUCCESS; … … 977 1084 const pj_uint8_t *in_pkt, 978 1085 unsigned in_pkt_len, 979 constpj_stun_msg *msg,1086 pj_stun_msg *msg, 980 1087 const pj_sockaddr_t *src_addr, 981 1088 unsigned src_addr_len) 982 1089 { 1090 pj_stun_rx_data rdata; 983 1091 pj_status_t status; 1092 1093 /* Init rdata */ 1094 rdata.msg = msg; 1095 pj_bzero(&rdata.info, sizeof(rdata.info)); 1096 1097 if (sess->auth_type == PJ_STUN_AUTH_NONE) 1098 options |= PJ_STUN_NO_AUTHENTICATE; 984 1099 985 1100 /* Authenticate the message, unless PJ_STUN_NO_AUTHENTICATE … … 988 1103 if ((options & PJ_STUN_NO_AUTHENTICATE) == 0) { 989 1104 status = authenticate_req(sess, (const pj_uint8_t*) in_pkt, in_pkt_len, 990 msg, tmp_pool, src_addr, src_addr_len);1105 &rdata, tmp_pool, src_addr, src_addr_len); 991 1106 if (status != PJ_SUCCESS) { 992 1107 return status; … … 996 1111 /* Distribute to handler, or respond with Bad Request */ 997 1112 if (sess->cb.on_rx_request) { 998 status = (*sess->cb.on_rx_request)(sess, in_pkt, in_pkt_len, msg,1113 status = (*sess->cb.on_rx_request)(sess, in_pkt, in_pkt_len, &rdata, 999 1114 src_addr, src_addr_len); 1000 1115 } else { 1116 pj_str_t err_text; 1001 1117 pj_stun_msg *response; 1002 1118 1119 err_text = pj_str("Callback is not set to handle request"); 1003 1120 status = pj_stun_msg_create_response(tmp_pool, msg, 1004 PJ_STUN_SC_BAD_REQUEST, NULL,1005 & response);1121 PJ_STUN_SC_BAD_REQUEST, 1122 &err_text, &response); 1006 1123 if (status == PJ_SUCCESS && response) { 1007 1124 status = send_response(sess, tmp_pool, response, -
pjproject/trunk/pjnath/src/pjnath/turn_session.c
r1869 r1877 522 522 pj_lock_acquire(sess->lock); 523 523 524 pj_stun_session_set_credential(sess->stun, cred);524 pj_stun_session_set_credential(sess->stun, PJ_STUN_AUTH_LONG_TERM, cred); 525 525 526 526 pj_lock_release(sess->lock); -
pjproject/trunk/pjnath/src/pjturn-srv/allocation.c
r1854 r1877 73 73 const pj_uint8_t *pkt, 74 74 unsigned pkt_len, 75 const pj_stun_ msg *msg,75 const pj_stun_rx_data *rdata, 76 76 const pj_sockaddr_t *src_addr, 77 77 unsigned src_addr_len); … … 98 98 static pj_status_t parse_allocate_req(alloc_request *cfg, 99 99 pj_stun_session *sess, 100 const pj_stun_ msg *req,100 const pj_stun_rx_data *rdata, 101 101 const pj_sockaddr_t *src_addr, 102 102 unsigned src_addr_len) 103 103 { 104 const pj_stun_msg *req = rdata->msg; 104 105 pj_stun_bandwidth_attr *attr_bw; 105 106 pj_stun_req_transport_attr *attr_req_tp; … … 121 122 /* Check if we can satisfy the bandwidth */ 122 123 if (cfg->bandwidth > MAX_CLIENT_BANDWIDTH) { 123 pj_stun_session_respond(sess, req, PJ_STUN_SC_ALLOCATION_QUOTA_REACHED, 124 pj_stun_session_respond(sess, rdata, 125 PJ_STUN_SC_ALLOCATION_QUOTA_REACHED, 124 126 "Invalid bandwidth", PJ_TRUE, 125 127 src_addr, src_addr_len); … … 131 133 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_TRANSPORT, 0); 132 134 if (attr_req_tp == NULL) { 133 pj_stun_session_respond(sess, r eq, PJ_STUN_SC_BAD_REQUEST,135 pj_stun_session_respond(sess, rdata, PJ_STUN_SC_BAD_REQUEST, 134 136 "Missing REQUESTED-TRANSPORT attribute", 135 137 PJ_TRUE, src_addr, src_addr_len); … … 141 143 /* Can only support UDP for now */ 142 144 if (cfg->tp_type != PJ_TURN_TP_UDP) { 143 pj_stun_session_respond(sess, r eq, PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO,145 pj_stun_session_respond(sess, rdata, PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO, 144 146 NULL, PJ_TRUE, src_addr, src_addr_len); 145 147 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO); … … 152 154 if (attr_res_token) { 153 155 /* We don't support RESERVATION-TOKEN for now */ 154 pj_stun_session_respond(sess, r eq,156 pj_stun_session_respond(sess, rdata, 155 157 PJ_STUN_SC_BAD_REQUEST, 156 158 "RESERVATION-TOKEN is not supported", PJ_TRUE, … … 164 166 if (attr_rpp) { 165 167 /* We don't support REQUESTED-PROPS for now */ 166 pj_stun_session_respond(sess, r eq,168 pj_stun_session_respond(sess, rdata, 167 169 PJ_STUN_SC_BAD_REQUEST, 168 170 "REQUESTED-PROPS is not supported", PJ_TRUE, … … 177 179 cfg->lifetime = attr_lifetime->value; 178 180 if (cfg->lifetime < MIN_LIFETIME) { 179 pj_stun_session_respond(sess, r eq, PJ_STUN_SC_BAD_REQUEST,181 pj_stun_session_respond(sess, rdata, PJ_STUN_SC_BAD_REQUEST, 180 182 "LIFETIME too short", PJ_TRUE, 181 183 src_addr, src_addr_len); … … 195 197 static pj_status_t send_allocate_response(pj_turn_allocation *alloc, 196 198 pj_stun_session *srv_sess, 197 const pj_stun_ msg *msg)199 const pj_stun_rx_data *rdata) 198 200 { 199 201 pj_stun_tx_data *tdata; … … 201 203 202 204 /* Respond the original ALLOCATE request */ 203 status = pj_stun_session_create_res(srv_sess, msg, 0, NULL, &tdata);205 status = pj_stun_session_create_res(srv_sess, rdata, 0, NULL, &tdata); 204 206 if (status != PJ_SUCCESS) 205 207 return status; … … 285 287 const pj_sockaddr_t *src_addr, 286 288 unsigned src_addr_len, 287 const pj_stun_ msg *msg,289 const pj_stun_rx_data *rdata, 288 290 pj_stun_session *srv_sess, 289 291 pj_turn_allocation **p_alloc) 290 292 { 291 293 pj_turn_srv *srv = listener->server; 294 const pj_stun_msg *msg = rdata->msg; 292 295 pj_pool_t *pool; 293 296 alloc_request req; … … 298 301 299 302 /* Parse ALLOCATE request */ 300 status = parse_allocate_req(&req, srv_sess, msg, src_addr, src_addr_len);303 status = parse_allocate_req(&req, srv_sess, rdata, src_addr, src_addr_len); 301 304 if (status != PJ_SUCCESS) 302 305 return status; … … 355 358 356 359 /* Attach authentication credential to STUN session */ 357 pj_stun_session_set_credential(alloc->sess, &alloc->cred); 360 pj_stun_session_set_credential(alloc->sess, PJ_STUN_AUTH_LONG_TERM, 361 &alloc->cred); 358 362 359 363 /* Create the relay resource */ … … 367 371 368 372 /* Respond to ALLOCATE request */ 369 status = send_allocate_response(alloc, srv_sess, msg);373 status = send_allocate_response(alloc, srv_sess, rdata); 370 374 if (status != PJ_SUCCESS) 371 375 goto on_error; … … 384 388 /* Send reply to the ALLOCATE request */ 385 389 pj_strerror(status, str_tmp, sizeof(str_tmp)); 386 pj_stun_session_respond(srv_sess, msg, PJ_STUN_SC_BAD_REQUEST, str_tmp,390 pj_stun_session_respond(srv_sess, rdata, PJ_STUN_SC_BAD_REQUEST, str_tmp, 387 391 PJ_TRUE, src_addr, src_addr_len); 388 392 … … 710 714 /* Create and send error response */ 711 715 static void send_reply_err(pj_turn_allocation *alloc, 712 const pj_stun_ msg *req,716 const pj_stun_rx_data *rdata, 713 717 pj_bool_t cache, 714 718 int code, const char *errmsg) … … 716 720 pj_status_t status; 717 721 718 status = pj_stun_session_respond(alloc->sess, r eq, code, errmsg, cache,722 status = pj_stun_session_respond(alloc->sess, rdata, code, errmsg, cache, 719 723 &alloc->hkey.clt_addr, 720 724 pj_sockaddr_get_len(&alloc->hkey.clt_addr.addr)); … … 727 731 /* Create and send successful response */ 728 732 static void send_reply_ok(pj_turn_allocation *alloc, 729 const pj_stun_ msg *req)733 const pj_stun_rx_data *rdata) 730 734 { 731 735 pj_status_t status; … … 733 737 pj_stun_tx_data *tdata; 734 738 735 status = pj_stun_session_create_res(alloc->sess, r eq, 0, NULL, &tdata);739 status = pj_stun_session_create_res(alloc->sess, rdata, 0, NULL, &tdata); 736 740 if (status != PJ_SUCCESS) { 737 741 alloc_err(alloc, "Error creating STUN success response", status); … … 1073 1077 const pj_uint8_t *pkt, 1074 1078 unsigned pkt_len, 1075 const pj_stun_ msg *msg,1079 const pj_stun_rx_data *rdata, 1076 1080 const pj_sockaddr_t *src_addr, 1077 1081 unsigned src_addr_len) 1078 1082 { 1083 const pj_stun_msg *msg = rdata->msg; 1079 1084 pj_turn_allocation *alloc; 1080 1085 … … 1089 1094 if (alloc->relay.lifetime == 0) { 1090 1095 /* Reject with 437 if we're shutting down */ 1091 send_reply_err(alloc, msg, PJ_TRUE,1096 send_reply_err(alloc, rdata, PJ_TRUE, 1092 1097 PJ_STUN_SC_ALLOCATION_MISMATCH, NULL); 1093 1098 return PJ_SUCCESS; … … 1116 1121 1117 1122 /* Respond first */ 1118 send_reply_ok(alloc, msg);1123 send_reply_ok(alloc, rdata); 1119 1124 1120 1125 /* Shutdown allocation */ … … 1142 1147 1143 1148 /* Send reply */ 1144 send_reply_ok(alloc, msg);1149 send_reply_ok(alloc, rdata); 1145 1150 } 1146 1151 … … 1159 1164 1160 1165 if (!ch_attr || !peer_attr) { 1161 send_reply_err(alloc, msg, PJ_TRUE, PJ_STUN_SC_BAD_REQUEST, NULL); 1166 send_reply_err(alloc, rdata, PJ_TRUE, 1167 PJ_STUN_SC_BAD_REQUEST, NULL); 1162 1168 return PJ_SUCCESS; 1163 1169 } … … 1172 1178 if (pj_sockaddr_cmp(&p1->hkey.peer_addr, &peer_attr->sockaddr)) { 1173 1179 /* Address mismatch. Send 400 */ 1174 send_reply_err(alloc, msg, PJ_TRUE,1180 send_reply_err(alloc, rdata, PJ_TRUE, 1175 1181 PJ_STUN_SC_BAD_REQUEST, 1176 1182 "Peer address mismatch"); … … 1191 1197 pj_sockaddr_get_len(&peer_attr->sockaddr)); 1192 1198 if (p2 && p2->channel != PJ_TURN_INVALID_CHANNEL) { 1193 send_reply_err(alloc, msg, PJ_TRUE, PJ_STUN_SC_BAD_REQUEST,1199 send_reply_err(alloc, rdata, PJ_TRUE, PJ_STUN_SC_BAD_REQUEST, 1194 1200 "Peer address already assigned a channel number"); 1195 1201 return PJ_SUCCESS; … … 1211 1217 1212 1218 /* Reply */ 1213 send_reply_ok(alloc, msg);1219 send_reply_ok(alloc, rdata); 1214 1220 1215 1221 return PJ_SUCCESS; … … 1218 1224 1219 1225 /* Respond with 437 (section 6.3 turn-07) */ 1220 send_reply_err(alloc, msg, PJ_TRUE, PJ_STUN_SC_ALLOCATION_MISMATCH, NULL); 1226 send_reply_err(alloc, rdata, PJ_TRUE, PJ_STUN_SC_ALLOCATION_MISMATCH, 1227 NULL); 1221 1228 1222 1229 } else { 1223 1230 1224 1231 /* Respond with Bad Request? */ 1225 send_reply_err(alloc, msg, PJ_TRUE, PJ_STUN_SC_BAD_REQUEST, NULL);1232 send_reply_err(alloc, rdata, PJ_TRUE, PJ_STUN_SC_BAD_REQUEST, NULL); 1226 1233 1227 1234 } -
pjproject/trunk/pjnath/src/pjturn-srv/auth.c
r1869 r1877 56 56 { 57 57 /* Nothing to do */ 58 }59 60 61 PJ_DEF(pj_status_t) pj_turn_get_cred( const pj_stun_msg *msg,62 void *user_data,63 pj_pool_t *pool,64 pj_str_t *realm,65 pj_str_t *username,66 pj_str_t *nonce,67 int *data_type,68 pj_str_t *data)69 {70 PJ_UNUSED_ARG(msg);71 PJ_UNUSED_ARG(pool);72 PJ_UNUSED_ARG(user_data);73 74 *realm = pj_str(g_realm);75 *username = pj_str(g_cred[0].username);76 *nonce = pj_str(THE_NONCE);77 *data_type = 0;78 *data = pj_str(g_cred[0].passwd);79 80 return PJ_SUCCESS;81 58 } 82 59 -
pjproject/trunk/pjnath/src/pjturn-srv/auth.h
r1869 r1877 62 62 63 63 /** 64 * Get credential.65 */66 PJ_DECL(pj_status_t) pj_turn_get_cred(const pj_stun_msg *msg,67 void *user_data,68 pj_pool_t *pool,69 pj_str_t *realm,70 pj_str_t *username,71 pj_str_t *nonce,72 int *data_type,73 pj_str_t *data);74 75 /**76 64 * This function is called to get the password for the specified username. 77 65 * This function is also used to check whether the username is valid. -
pjproject/trunk/pjnath/src/pjturn-srv/server.c
r1869 r1877 41 41 const pj_uint8_t *pkt, 42 42 unsigned pkt_len, 43 const pj_stun_ msg *msg,43 const pj_stun_rx_data *rdata, 44 44 const pj_sockaddr_t *src_addr, 45 45 unsigned src_addr_len); … … 148 148 srv->core.cred.data.dyn_cred.user_data = srv; 149 149 srv->core.cred.data.dyn_cred.get_auth = &pj_turn_get_auth; 150 srv->core.cred.data.dyn_cred.get_cred = &pj_turn_get_cred;151 150 srv->core.cred.data.dyn_cred.get_password = &pj_turn_get_password; 152 151 srv->core.cred.data.dyn_cred.verify_nonce = &pj_turn_verify_nonce; … … 369 368 370 369 pj_stun_session_set_user_data(sess, lis); 371 pj_stun_session_set_credential(sess, &srv->core.cred); 370 pj_stun_session_set_credential(sess, PJ_STUN_AUTH_LONG_TERM, 371 &srv->core.cred); 372 372 373 373 srv->core.stun_sess[index] = sess; … … 484 484 485 485 /* Respond to STUN request */ 486 static pj_status_t stun_respond(pj_turn_srv *srv, 487 pj_stun_session *sess, 488 const pj_stun_msg *req, 486 static pj_status_t stun_respond(pj_stun_session *sess, 487 const pj_stun_rx_data *rdata, 489 488 unsigned code, 490 489 const char *errmsg, … … 498 497 499 498 /* Create response */ 500 status = pj_stun_session_create_res(sess, r eq, code,499 status = pj_stun_session_create_res(sess, rdata, code, 501 500 (errmsg?pj_cstr(&reason,errmsg):NULL), 502 501 &tdata); … … 504 503 return status; 505 504 506 /* Store the credential for future lookup. */507 if (pj_stun_auth_valid_for_msg(tdata->msg)) {508 pj_turn_srv_put_cred(srv, req, tdata);509 }510 511 505 /* Send the response */ 512 506 return pj_stun_session_send_msg(sess, cache, dst_addr, addr_len, tdata); 513 }514 515 516 /*517 * Store the credential to put placed for the specified message for518 * future retrieval.519 */520 PJ_DEF(pj_status_t) pj_turn_srv_put_cred(pj_turn_srv *srv,521 const pj_stun_msg *req,522 pj_stun_tx_data *response)523 {524 pj_stun_username_attr *user;525 pj_stun_realm_attr *realm;526 pj_stun_nonce_attr *nonce;527 struct saved_cred *saved_cred;528 pj_status_t status;529 530 realm = (pj_stun_realm_attr*)531 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REALM, 0);532 PJ_ASSERT_RETURN(realm != NULL, PJ_EBUG);533 534 user = (pj_stun_username_attr*)535 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_USERNAME, 0);536 PJ_ASSERT_RETURN(user != NULL, PJ_EBUG);537 538 nonce = (pj_stun_nonce_attr*)539 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_NONCE, 0);540 PJ_ASSERT_RETURN(nonce != NULL, PJ_EBUG);541 542 saved_cred = PJ_POOL_ALLOC_T(response->pool, struct saved_cred);543 544 /* Lookup the password */545 status = pj_turn_get_password(response->msg, NULL, &realm->value,546 &user->value, response->pool,547 &saved_cred->data_type,548 &saved_cred->data);549 if (status != PJ_SUCCESS)550 return status;551 552 /* Store credential */553 pj_strdup(response->pool, &saved_cred->username, &user->value);554 pj_strdup(response->pool, &saved_cred->realm, &realm->value);555 pj_strdup(response->pool, &saved_cred->nonce, &nonce->value);556 557 pj_thread_local_set(srv->core.tls_key, response->msg);558 pj_thread_local_set(srv->core.tls_data, saved_cred);559 560 return PJ_SUCCESS;561 }562 563 564 /**565 * Retrieve previously stored credential for the specified message.566 */567 PJ_DEF(pj_status_t) pj_turn_srv_get_cred(const pj_stun_msg *msg,568 void *user_data,569 pj_pool_t *pool,570 pj_str_t *realm,571 pj_str_t *username,572 pj_str_t *nonce,573 int *data_type,574 pj_str_t *data)575 {576 pj_turn_srv *srv;577 const pj_stun_msg *saved_msg;578 struct saved_cred *saved_cred;579 580 PJ_UNUSED_ARG(pool);581 582 srv = (pj_turn_srv*)user_data;583 584 /* Lookup stored message and make sure it's for the same message */585 saved_msg = (const pj_stun_msg*)586 pj_thread_local_get(srv->core.tls_key);587 PJ_ASSERT_RETURN(saved_msg==msg, PJ_ENOTFOUND);588 589 /* Lookup saved credential */590 saved_cred = (struct saved_cred*)591 pj_thread_local_get(srv->core.tls_data);592 PJ_ASSERT_RETURN(saved_cred != NULL, PJ_ENOTFOUND);593 594 595 *realm = saved_cred->realm;596 *username = saved_cred->username;597 *nonce = saved_cred->nonce;598 *data_type = saved_cred->data_type;599 *data = saved_cred->data;600 601 602 /* Don't clear saved_cred as this may be called more than once */603 604 return PJ_SUCCESS;605 507 } 606 508 … … 613 515 const pj_uint8_t *pkt, 614 516 unsigned pkt_len, 615 const pj_stun_ msg *msg,517 const pj_stun_rx_data *rdata, 616 518 const pj_sockaddr_t *src_addr, 617 519 unsigned src_addr_len) 618 520 { 619 521 pj_turn_listener *listener; 522 const pj_stun_msg *msg = rdata->msg; 620 523 pj_turn_srv *srv; 621 524 pj_turn_allocation *alloc; … … 630 533 /* Respond any requests other than ALLOCATE with 437 response */ 631 534 if (msg->hdr.type != PJ_STUN_ALLOCATE_REQUEST) { 632 stun_respond(s rv, sess, msg, PJ_STUN_SC_ALLOCATION_MISMATCH,535 stun_respond(sess, rdata, PJ_STUN_SC_ALLOCATION_MISMATCH, 633 536 NULL, PJ_FALSE, src_addr, src_addr_len); 634 537 return PJ_SUCCESS; … … 639 542 */ 640 543 status = pj_turn_allocation_create(listener, src_addr, src_addr_len, 641 msg, sess, &alloc);544 rdata, sess, &alloc); 642 545 if (status != PJ_SUCCESS) { 643 546 /* STUN response has been sent, no need to reply here */ -
pjproject/trunk/pjnath/src/pjturn-srv/turn.h
r1854 r1877 205 205 const pj_sockaddr_t *src_addr, 206 206 unsigned src_addr_len, 207 const pj_stun_ msg *msg,207 const pj_stun_rx_data *rdata, 208 208 pj_stun_session *srv_sess, 209 209 pj_turn_allocation **p_alloc); … … 460 460 461 461 462 /**463 * Store the credential to put placed for the specified message for464 * future retrieval.465 */466 PJ_DECL(pj_status_t) pj_turn_srv_put_cred(pj_turn_srv *srv,467 const pj_stun_msg *request,468 pj_stun_tx_data *response);469 470 /**471 * Retrieve previously stored credential for the specified message.472 */473 PJ_DECL(pj_status_t) pj_turn_srv_get_cred(const pj_stun_msg *msg,474 void *user_data,475 pj_pool_t *pool,476 pj_str_t *realm,477 pj_str_t *username,478 pj_str_t *nonce,479 int *data_type,480 pj_str_t *data);481 482 483 462 #endif /* __PJ_TURN_SRV_TURN_H__ */ 484 463
Note: See TracChangeset
for help on using the changeset viewer.