- Timestamp:
- May 15, 2007 10:42:56 AM (18 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjnath/include/pjnath/config.h
r1153 r1275 89 89 90 90 /** 91 * Maximum number of STUN retransmission count.91 * Maximum number of STUN transmission count. 92 92 * 93 93 * Default: 7 (as per RFC 3489-bis) 94 94 */ 95 #ifndef PJ_STUN_MAX_RETRANSMIT_COUNT 96 # define PJ_STUN_MAX_RETRANSMIT_COUNT 7 95 #ifndef PJ_STUN_MAX_TRANSMIT_COUNT 96 # define PJ_STUN_MAX_TRANSMIT_COUNT 7 97 #endif 98 99 100 /** 101 * Duration to keep response in the cache, in msec. 102 * 103 * Default: 10000 (as per RFC 3489-bis) 104 */ 105 #ifndef PJ_STUN_RES_CACHE_DURATION 106 # define PJ_STUN_RES_CACHE_DURATION 10000 97 107 #endif 98 108 -
pjproject/trunk/pjnath/include/pjnath/stun_auth.h
r1126 r1275 263 263 264 264 /** 265 * Verify credential in the STUN message. Note that before calling this265 * Verify credential in the STUN request. Note that before calling this 266 266 * function, application must have checked that the message contains 267 267 * PJ_STUN_ATTR_MESSAGE_INTEGRITY attribute by calling pj_stun_msg_find_attr() … … 287 287 * \a p_response. 288 288 */ 289 PJ_DECL(pj_status_t) pj_stun_verify_credential(const pj_uint8_t *pkt, 290 unsigned pkt_len, 291 const pj_stun_msg *msg, 292 pj_stun_auth_cred *cred, 293 pj_pool_t *pool, 294 pj_stun_msg **p_response); 295 296 289 PJ_DECL(pj_status_t) pj_stun_authenticate_request(const pj_uint8_t *pkt, 290 unsigned pkt_len, 291 const pj_stun_msg *msg, 292 pj_stun_auth_cred *cred, 293 pj_pool_t *pool, 294 pj_stun_msg **p_response); 295 296 297 /** 298 * Verify credential in the STUN response. Note that before calling this 299 * function, application must have checked that the message contains 300 * PJ_STUN_ATTR_MESSAGE_INTEGRITY attribute by calling pj_stun_msg_find_attr() 301 * function, because otherwise this function will report authentication 302 * failure. 303 * 304 * @param pkt The original packet which has been parsed into 305 * the message. This packet MUST NOT have been modified 306 * after the parsing. 307 * @param pkt_len The length of the packet. 308 * @param msg The parsed message to be verified. 309 * @param key Authentication key to calculate MESSAGE-INTEGRITY 310 * value. Application can create this key by using 311 * #pj_stun_create_key() function. 312 * 313 * @return PJ_SUCCESS if credential is verified successfully. 314 */ 315 PJ_DECL(pj_status_t) pj_stun_authenticate_response(const pj_uint8_t *pkt, 316 unsigned pkt_len, 317 const pj_stun_msg *msg, 318 const pj_str_t *key); 297 319 298 320 … … 302 324 303 325 304 /**305 * Calculate HMAC-SHA1 key for long term credential, by getting306 * MD5 digest of username, realm, and password.307 *308 * @param digest The buffer for the digest.309 * @param realm The realm of the credential, if long term credential310 * is to be used.311 * @param username The username.312 * @param passwd The clear text password.313 */314 void pj_stun_calc_md5_key(pj_uint8_t digest[16],315 const pj_str_t *realm,316 const pj_str_t *username,317 const pj_str_t *passwd);318 319 320 326 PJ_END_DECL 321 327 -
pjproject/trunk/pjnath/include/pjnath/stun_config.h
r1091 r1275 99 99 cfg->timer_heap = timer_heap; 100 100 cfg->rto_msec = PJ_STUN_RTO_VALUE; 101 cfg->res_cache_msec = 10000;101 cfg->res_cache_msec = PJ_STUN_RES_CACHE_DURATION; 102 102 } 103 103 -
pjproject/trunk/pjnath/include/pjnath/stun_msg.h
r1154 r1275 133 133 #define PJ_STUN_IS_REQUEST(msg_type) (((msg_type) & 0x0110) == 0x0000) 134 134 135 /** 136 * Determine if the message type is a successful response. 137 */ 138 #define PJ_STUN_IS_SUCCESS_RESPONSE(msg_type) (((msg_type) & 0x0110) == 0x0100) 139 140 /** 141 * The response bit in the message type. 142 */ 143 #define PJ_STUN_RESPONSE_BIT (0x0100) 144 145 /** 146 * Determine if the message type is an error response. 147 */ 148 #define PJ_STUN_IS_ERROR_RESPONSE(msg_type) (((msg_type) & 0x0110) == 0x0110) 149 150 /** 151 * The error response bit in the message type. 152 */ 153 #define PJ_STUN_ERROR_RESPONSE_BIT (0x0110) 135 154 136 155 /** 137 156 * Determine if the message type is a response. 138 157 */ 139 #define PJ_STUN_IS_SUCCESS_RESPONSE(msg_type) (((msg_type) & 0x0110) == 0x0100) 140 141 142 /** 143 * The response bit in the message type. 144 */ 145 #define PJ_STUN_RESPONSE_BIT (0x0100) 146 147 /** 148 * Determine if the message type is an error response. 149 */ 150 #define PJ_STUN_IS_ERROR_RESPONSE(msg_type) (((msg_type) & 0x0110) == 0x0110) 151 152 153 /** 154 * The error response bit in the message type. 155 */ 156 #define PJ_STUN_ERROR_RESPONSE_BIT (0x0110) 157 158 #define PJ_STUN_IS_RESPONSE(msg_type) (((msg_type) & 0x0100) == 0x0100) 158 159 159 160 /** … … 1149 1150 * sent to remote destination. This function will take care about 1150 1151 * calculating the MESSAGE-INTEGRITY digest as well as FINGERPRINT 1151 * value. 1152 * 1153 * If MESSAGE-INTEGRITY attribute is present, the function assumes 1154 * that application wants to include credential (short or long term) 1155 * in the message, and this function will calculate the HMAC digest 1156 * from the message using the supplied password in the parameter. 1157 * If REALM attribute is present, the HMAC digest is calculated as 1158 * long term credential, otherwise as short term credential. 1152 * value, if these attributes are present in the message. 1153 * 1154 * If application wants to apply credential to the message, it MUST 1155 * include a blank MESSAGE-INTEGRITY attribute in the message, as the 1156 * last attribute or the attribute before FINGERPRINT. This function will 1157 * calculate the HMAC digest from the message using the supplied key in 1158 * the parameter. The key should be set to the password if short term 1159 * credential is used, or calculated from the MD5 hash of the realm, 1160 * username, and password using #pj_stun_create_key() if long term 1161 * credential is used. 1159 1162 * 1160 1163 * If FINGERPRINT attribute is present, this function will calculate 1161 * the FINGERPRINT CRC attribute for the message. 1164 * the FINGERPRINT CRC attribute for the message. The FINGERPRINT MUST 1165 * be added as the last attribute of the message. 1162 1166 * 1163 1167 * @param msg The STUN message to be printed. Upon return, … … 1167 1171 * @param buf_size Size of the buffer. 1168 1172 * @param options Options, which currently must be zero. 1169 * @param password Password to be used when credential is to be1170 * included. This parameter MUST be specified when1171 * the message contains MESSAGE-INTEGRITY attribute.1173 * @param key Authentication key to calculate MESSAGE-INTEGRITY 1174 * value. Application can create this key by using 1175 * #pj_stun_create_key() function. 1172 1176 * @param p_msg_len Upon return, it will be filed with the size of 1173 1177 * the packet in bytes, or negative value on error. … … 1179 1183 unsigned buf_size, 1180 1184 unsigned options, 1181 const pj_str_t * password,1185 const pj_str_t *key, 1182 1186 unsigned *p_msg_len); 1187 1188 1189 /** 1190 * Create authentication key to be used for encoding the message with 1191 * MESSAGE-INTEGRITY. If short term credential is used (i.e. the realm 1192 * argument is NULL or empty), the key will be copied from the password. 1193 * If long term credential is used, the key will be calculated from the 1194 * MD5 hash of the realm, username, and password. 1195 * 1196 * @param pool Pool to allocate memory for the key. 1197 * @param key String to receive the key. 1198 * @param realm The realm of the credential, if long term credential 1199 * is to be used. If short term credential is wanted, 1200 * application can put NULL or empty string here. 1201 * @param username The username. 1202 * @param passwd The clear text password. 1203 */ 1204 PJ_DECL(void) pj_stun_create_key(pj_pool_t *pool, 1205 pj_str_t *key, 1206 const pj_str_t *realm, 1207 const pj_str_t *username, 1208 const pj_str_t *passwd); 1209 1210 1183 1211 1184 1212 /** -
pjproject/trunk/pjnath/include/pjnath/stun_session.h
r1152 r1275 162 162 pj_uint8_t msg_key[12]; /**< Message/transaction key. */ 163 163 164 pj_str_t auth_key; /**< Auth key. */ 165 164 166 void *pkt; /**< The STUN packet. */ 165 167 unsigned max_len; /**< Length of packet buffer. */ … … 306 308 * @return PJ_SUCCESS on success, or the appropriate error code. 307 309 */ 308 PJ_DECL(pj_status_t) pj_stun_session_create_res ponse(pj_stun_session *sess,309 310 311 312 310 PJ_DECL(pj_status_t) pj_stun_session_create_res(pj_stun_session *sess, 311 const pj_stun_msg *req, 312 unsigned err_code, 313 const pj_str_t *err_msg, 314 pj_stun_tx_data **p_tdata); 313 315 314 316 -
pjproject/trunk/pjnath/src/pjnath/ice_session.c
r1239 r1275 1870 1870 /* Reject any requests except Binding request */ 1871 1871 if (msg->hdr.type != PJ_STUN_BINDING_REQUEST) { 1872 status = pj_stun_session_create_res ponse(sess, msg,1873 1874 1872 status = pj_stun_session_create_res(sess, msg, 1873 PJ_STUN_SC_BAD_REQUEST, 1874 NULL, &tdata); 1875 1875 if (status != PJ_SUCCESS) 1876 1876 return status; … … 1928 1928 } else { 1929 1929 /* Generate 487 response */ 1930 status = pj_stun_session_create_res ponse(sess, msg,1931 1932 1930 status = pj_stun_session_create_res(sess, msg, 1931 PJ_STUN_SC_ROLE_CONFLICT, 1932 NULL, &tdata); 1933 1933 if (status == PJ_SUCCESS) { 1934 1934 pj_stun_session_send_msg(sess, PJ_TRUE, … … 1944 1944 if (pj_cmp_timestamp(&ice->tie_breaker, &role_attr->value) < 0) { 1945 1945 /* Generate 487 response */ 1946 status = pj_stun_session_create_res ponse(sess, msg,1947 1948 1946 status = pj_stun_session_create_res(sess, msg, 1947 PJ_STUN_SC_ROLE_CONFLICT, 1948 NULL, &tdata); 1949 1949 if (status == PJ_SUCCESS) { 1950 1950 pj_stun_session_send_msg(sess, PJ_TRUE, … … 1977 1977 * First send response to this request 1978 1978 */ 1979 status = pj_stun_session_create_res ponse(sess, msg, 0, NULL, &tdata);1979 status = pj_stun_session_create_res(sess, msg, 0, NULL, &tdata); 1980 1980 if (status != PJ_SUCCESS) { 1981 1981 pj_mutex_unlock(ice->mutex); -
pjproject/trunk/pjnath/src/pjnath/stun_auth.c
r1265 r1275 105 105 106 106 107 /* Verify credential */108 PJ_DEF(pj_status_t) pj_stun_ verify_credential(const pj_uint8_t *pkt,109 unsigned pkt_len,110 const pj_stun_msg *msg,111 pj_stun_auth_cred *cred,112 pj_pool_t *pool,113 pj_stun_msg **p_response)107 /* Verify credential in the request */ 108 PJ_DEF(pj_status_t) pj_stun_authenticate_request(const pj_uint8_t *pkt, 109 unsigned pkt_len, 110 const pj_stun_msg *msg, 111 pj_stun_auth_cred *cred, 112 pj_pool_t *pool, 113 pj_stun_msg **p_response) 114 114 { 115 115 pj_str_t realm, nonce, password; … … 122 122 pj_hmac_sha1_context ctx; 123 123 pj_uint8_t digest[PJ_SHA1_DIGEST_SIZE]; 124 pj_uint8_t md5_digest[16];125 124 pj_str_t key; 126 125 pj_status_t status; … … 225 224 226 225 /* NONCE must be present. */ 227 if (anonce == NULL ) {226 if (anonce == NULL && nonce.slen) { 228 227 if (p_response) { 229 228 create_challenge(pool, msg, PJ_STUN_SC_MISSING_NONCE, … … 320 319 } 321 320 322 /* Determine which key to use */ 323 if (realm.slen) { 324 pj_stun_calc_md5_key(md5_digest, &realm, &auser->value, &password); 325 key.ptr = (char*)md5_digest; 326 key.slen = 16; 327 } else { 328 key = password; 329 } 321 /* Calculate key */ 322 pj_stun_create_key(pool, &key, &realm, &auser->value, &password); 330 323 331 324 /* Now calculate HMAC of the message, adding zero padding if necessary … … 334 327 pj_hmac_sha1_init(&ctx, (pj_uint8_t*)key.ptr, key.slen); 335 328 pj_hmac_sha1_update(&ctx, pkt, amsgi_pos); 336 if (amsgi_pos & 0x3F) {329 if (amsgi_pos & 63) { 337 330 pj_uint8_t zeroes[64]; 338 331 pj_bzero(zeroes, sizeof(zeroes)); 339 pj_hmac_sha1_update(&ctx, zeroes, 64-(amsgi_pos & 0x3F));332 pj_hmac_sha1_update(&ctx, zeroes, 64-(amsgi_pos & 63)); 340 333 } 341 334 pj_hmac_sha1_final(&ctx, digest); … … 356 349 357 350 351 /* Authenticate MESSAGE-INTEGRITY in the response */ 352 PJ_DEF(pj_status_t) pj_stun_authenticate_response(const pj_uint8_t *pkt, 353 unsigned pkt_len, 354 const pj_stun_msg *msg, 355 const pj_str_t *key) 356 { 357 const pj_stun_msgint_attr *amsgi; 358 unsigned amsgi_pos; 359 pj_hmac_sha1_context ctx; 360 pj_uint8_t digest[PJ_SHA1_DIGEST_SIZE]; 361 362 PJ_ASSERT_RETURN(pkt && pkt_len && msg && key, PJ_EINVAL); 363 364 /* First check that MESSAGE-INTEGRITY is present */ 365 amsgi = (const pj_stun_msgint_attr*) 366 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_MESSAGE_INTEGRITY, 0); 367 if (amsgi == NULL) { 368 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_INTEGRITY_CHECK_FAILURE); 369 } 370 371 372 /* Check that message length is valid */ 373 if (msg->hdr.length < 24) { 374 return PJNATH_EINSTUNMSGLEN; 375 } 376 377 /* Get the position of MESSAGE-INTEGRITY in the packet */ 378 amsgi_pos = 20+msg->hdr.length-24; 379 if (GET_VAL16(pkt, amsgi_pos) == PJ_STUN_ATTR_MESSAGE_INTEGRITY) { 380 /* Found MESSAGE-INTEGRITY as the last attribute */ 381 } else { 382 amsgi_pos = 0; 383 } 384 385 if (amsgi_pos==0) { 386 /* Check that message length is valid */ 387 if (msg->hdr.length < 32) { 388 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_INTEGRITY_CHECK_FAILURE); 389 } 390 391 amsgi_pos = 20+msg->hdr.length-8-24; 392 if (GET_VAL16(pkt, amsgi_pos) == PJ_STUN_ATTR_MESSAGE_INTEGRITY) { 393 /* Found MESSAGE-INTEGRITY before FINGERPRINT */ 394 } else { 395 amsgi_pos = 0; 396 } 397 } 398 399 if (amsgi_pos==0) { 400 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_INTEGRITY_CHECK_FAILURE); 401 } 402 403 /* Now calculate HMAC of the message, adding zero padding if necessary 404 * to make the input 64 bytes aligned. 405 */ 406 pj_hmac_sha1_init(&ctx, (pj_uint8_t*)key->ptr, key->slen); 407 pj_hmac_sha1_update(&ctx, pkt, amsgi_pos); 408 if (amsgi_pos & 0x3F) { 409 pj_uint8_t zeroes[64]; 410 pj_bzero(zeroes, sizeof(zeroes)); 411 pj_hmac_sha1_update(&ctx, zeroes, 64-(amsgi_pos & 0x3F)); 412 } 413 pj_hmac_sha1_final(&ctx, digest); 414 415 /* Compare HMACs */ 416 if (pj_memcmp(amsgi->hmac, digest, 20)) { 417 /* HMAC value mismatch */ 418 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_INTEGRITY_CHECK_FAILURE); 419 } 420 421 /* Everything looks okay! */ 422 return PJ_SUCCESS; 423 } 424 -
pjproject/trunk/pjnath/src/pjnath/stun_msg.c
r1266 r1275 18 18 */ 19 19 #include <pjnath/stun_msg.h> 20 #include <pjnath/stun_auth.h>21 20 #include <pjnath/errno.h> 22 21 #include <pjlib-util/crc32.h> … … 1949 1948 * MD5 digest of username, realm, and password. 1950 1949 */ 1951 void pj_stun_calc_md5_key(pj_uint8_t digest[16],1952 1953 1954 1950 static void calc_md5_key(pj_uint8_t digest[16], 1951 const pj_str_t *realm, 1952 const pj_str_t *username, 1953 const pj_str_t *passwd) 1955 1954 { 1956 1955 /* The 16-byte key for MESSAGE-INTEGRITY HMAC is formed by taking … … 1967 1966 1968 1967 #define REMOVE_QUOTE(s) if (s.slen && *s.ptr=='"') \ 1969 s.ptr++, s.slen--; \1970 if (s.slen && s.ptr[s.slen-1]=='"') \1971 s.slen--;1968 s.ptr++, s.slen--; \ 1969 if (s.slen && s.ptr[s.slen-1]=='"') \ 1970 s.slen--; 1972 1971 1973 1972 /* Add username */ … … 1998 1997 1999 1998 /* 1999 * Create authentication key to be used for encoding the message with 2000 * MESSAGE-INTEGRITY. 2001 */ 2002 PJ_DEF(void) pj_stun_create_key(pj_pool_t *pool, 2003 pj_str_t *key, 2004 const pj_str_t *realm, 2005 const pj_str_t *username, 2006 const pj_str_t *passwd) 2007 { 2008 PJ_ASSERT_ON_FAIL(pool && key && username && passwd, return); 2009 2010 if (realm && realm->slen) { 2011 key->ptr = (char*) pj_pool_alloc(pool, 16); 2012 calc_md5_key((pj_uint8_t*)key->ptr, realm, username, passwd); 2013 key->slen = 16; 2014 } else { 2015 pj_strdup(pool, key, passwd); 2016 } 2017 } 2018 2019 2020 /* 2000 2021 static char *print_binary(const pj_uint8_t *data, unsigned data_len) 2001 2022 { … … 2029 2050 pj_uint8_t *buf, unsigned buf_size, 2030 2051 unsigned options, 2031 const pj_str_t * password,2052 const pj_str_t *key, 2032 2053 unsigned *p_msg_len) 2033 2054 { 2034 pj_stun_msg_hdr *hdr;2035 2055 pj_uint8_t *start = buf; 2036 pj_stun_realm_attr *arealm = NULL;2037 pj_stun_username_attr *auname = NULL;2038 2056 pj_stun_msgint_attr *amsgint = NULL; 2039 2057 pj_stun_fingerprint_attr *afingerprint = NULL; 2040 unsigned printed = 0 ;2058 unsigned printed = 0, body_len; 2041 2059 pj_status_t status; 2042 2060 unsigned i; … … 2053 2071 if (buf_size < sizeof(pj_stun_msg_hdr)) 2054 2072 return PJ_ETOOSMALL; 2055 pj_memcpy(buf, &msg->hdr, sizeof(pj_stun_msg_hdr));2056 hdr = (pj_stun_msg_hdr*) buf;2057 hdr->magic = pj_htonl(hdr->magic);2058 hdr->type = pj_htons(hdr->type);2059 /* We'll fill in the length later */2073 2074 PUTVAL16H(buf, 0, msg->hdr.type); 2075 PUTVAL16H(buf, 2, 0); /* length will be calculated later */ 2076 PUTVAL32H(buf, 4, msg->hdr.magic); 2077 pj_memcpy(buf+8, msg->hdr.tsx_id, sizeof(msg->hdr.tsx_id)); 2060 2078 2061 2079 buf += sizeof(pj_stun_msg_hdr); 2062 2080 buf_size -= sizeof(pj_stun_msg_hdr); 2063 2081 2064 /* Print each attribute */2082 /* Encode each attribute to the message */ 2065 2083 for (i=0; i<msg->attr_count; ++i) { 2066 2084 const struct attr_desc *adesc; … … 2073 2091 /* Stop when encountering MESSAGE-INTEGRITY */ 2074 2092 break; 2075 2076 } else if (attr_hdr->type == PJ_STUN_ATTR_USERNAME) {2077 pj_assert(auname == NULL);2078 auname = (pj_stun_username_attr*) attr_hdr;2079 2080 } else if (attr_hdr->type == PJ_STUN_ATTR_REALM) {2081 pj_assert(arealm == NULL);2082 arealm = (pj_stun_realm_attr*) attr_hdr;2083 2093 2084 2094 } else if (attr_hdr->type == PJ_STUN_ATTR_FINGERPRINT) { … … 2124 2134 */ 2125 2135 if (amsgint && afingerprint) { 2126 msg->hdr.length= (pj_uint16_t)((buf - start) - 20 + 24 + 8);2136 body_len = (pj_uint16_t)((buf - start) - 20 + 24 + 8); 2127 2137 } else if (amsgint) { 2128 msg->hdr.length= (pj_uint16_t)((buf - start) - 20 + 24);2138 body_len = (pj_uint16_t)((buf - start) - 20 + 24); 2129 2139 } else if (afingerprint) { 2130 msg->hdr.length= (pj_uint16_t)((buf - start) - 20 + 8);2140 body_len = (pj_uint16_t)((buf - start) - 20 + 8); 2131 2141 } else { 2132 msg->hdr.length= (pj_uint16_t)((buf - start) - 20);2142 body_len = (pj_uint16_t)((buf - start) - 20); 2133 2143 } 2134 2144 2135 2145 /* hdr->length = pj_htons(length); */ 2136 start[2] = (pj_uint8_t)((msg->hdr.length >> 8) & 0x00FF); 2137 start[3] = (pj_uint8_t)(msg->hdr.length & 0x00FF); 2146 PUTVAL16H(start, 2, (pj_uint16_t)body_len); 2138 2147 2139 2148 /* Calculate message integrity, if present */ 2140 2149 if (amsgint != NULL) { 2141 2142 pj_uint8_t md5_key_buf[16];2143 2150 pj_hmac_sha1_context ctx; 2144 pj_str_t key; 2151 2152 /* Key MUST be specified */ 2153 PJ_ASSERT_RETURN(key, PJ_EINVALIDOP); 2145 2154 2146 2155 /* MESSAGE-INTEGRITY must be the last attribute in the message, or … … 2162 2171 } 2163 2172 2164 /* Must have USERNAME attribute */2165 if (auname == NULL) {2166 /* Should not happen for message generated by us */2167 pj_assert(PJ_FALSE);2168 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_MISSING_USERNAME);2169 }2170 2171 /* Password must be specified */2172 PJ_ASSERT_RETURN(password, PJ_EINVAL);2173 2174 /* Get the key to sign the message */2175 if (arealm == NULL ) {2176 /* For short term credential, the key is the password */2177 key = *password;2178 2179 } else {2180 pj_stun_calc_md5_key(md5_key_buf, &arealm->value,2181 &auname->value, password);2182 key.ptr = (char*) md5_key_buf;2183 key.slen = 16;2184 }2185 2186 2173 /* Calculate HMAC-SHA1 digest, add zero padding to input 2187 2174 * if necessary to make the input 64 bytes aligned. 2188 2175 */ 2189 pj_hmac_sha1_init(&ctx, (pj_uint8_t*)key .ptr, key.slen);2176 pj_hmac_sha1_init(&ctx, (pj_uint8_t*)key->ptr, key->slen); 2190 2177 pj_hmac_sha1_update(&ctx, (pj_uint8_t*)start, buf-start); 2191 2178 if ((buf-start) & 0x3F) { … … 2221 2208 } 2222 2209 2223 /* Done */ 2210 /* Update message length. */ 2211 msg->hdr.length = (pj_uint16_t) ((buf - start) - 20); 2212 2213 /* Return the length */ 2224 2214 if (p_msg_len) 2225 2215 *p_msg_len = (buf - start); -
pjproject/trunk/pjnath/src/pjnath/stun_session.c
r1239 r1275 212 212 } 213 213 214 static pj_st r_t *get_passwd(pj_stun_session *sess, pj_pool_t *pool,215 const pj_stun_msg *msg)214 static pj_status_t get_key(pj_stun_session *sess, pj_pool_t *pool, 215 const pj_stun_msg *msg, pj_str_t *auth_key) 216 216 { 217 217 if (sess->cred == NULL) { 218 return NULL; 218 auth_key->slen = 0; 219 return PJ_SUCCESS; 219 220 } else if (sess->cred->type == PJ_STUN_AUTH_CRED_STATIC) { 220 return &sess->cred->data.static_cred.data; 221 pj_stun_create_key(pool, auth_key, 222 &sess->cred->data.static_cred.realm, 223 &sess->cred->data.static_cred.username, 224 &sess->cred->data.static_cred.data); 225 return PJ_SUCCESS; 221 226 } else if (sess->cred->type == PJ_STUN_AUTH_CRED_DYNAMIC) { 222 227 pj_str_t realm, username, nonce; … … 232 237 &nonce, &data_type, 233 238 password); 234 return password; 239 if (status != PJ_SUCCESS) 240 return status; 241 242 pj_stun_create_key(pool, auth_key, 243 &realm, &username, password); 244 245 return PJ_SUCCESS; 235 246 236 247 } else { 237 return NULL; 248 pj_assert(!"Unknown credential type"); 249 return PJ_EBUG; 238 250 } 239 251 } … … 244 256 { 245 257 pj_status_t status = 0; 258 pj_bool_t need_auth; 246 259 pj_str_t realm, username, nonce, password; 247 260 int data_type = 0; … … 250 263 251 264 /* The server SHOULD include a SERVER attribute in all responses */ 252 if (sess->srv_name.slen && (PJ_STUN_IS_SUCCESS_RESPONSE(msg->hdr.type) || 253 PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type))) 254 { 265 if (sess->srv_name.slen && PJ_STUN_IS_RESPONSE(msg->hdr.type)) { 255 266 pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SERVER, 256 267 &sess->srv_name); 257 268 } 258 269 259 /* From draft-ietf-behave-rfc3489bis-05.txt 260 * Section 8.3.1. Formulating the Request Message 261 * 262 * Note: only put MESSAGE-INTEGRITY in non error response. 263 */ 270 need_auth = PJ_STUN_IS_REQUEST(msg->hdr.type) || 271 PJ_STUN_IS_SUCCESS_RESPONSE(msg->hdr.type); 272 264 273 if (sess->cred && sess->cred->type == PJ_STUN_AUTH_CRED_STATIC && 265 !PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type))274 need_auth) 266 275 { 267 276 realm = sess->cred->data.static_cred.realm; … … 272 281 273 282 } else if (sess->cred && sess->cred->type == PJ_STUN_AUTH_CRED_DYNAMIC && 274 !PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type))283 need_auth) 275 284 { 276 285 void *user_data = sess->cred->data.dyn_cred.user_data; … … 285 294 286 295 287 /* Create and add USERNAME attribute */288 if (username.slen ) {296 /* Create and add USERNAME attribute for */ 297 if (username.slen && PJ_STUN_IS_REQUEST(msg->hdr.type)) { 289 298 status = pj_stun_msg_add_string_attr(pool, msg, 290 299 PJ_STUN_ATTR_USERNAME, … … 294 303 295 304 /* Add REALM only when long term credential is used */ 296 if (realm.slen ) {305 if (realm.slen && PJ_STUN_IS_REQUEST(msg->hdr.type)) { 297 306 status = pj_stun_msg_add_string_attr(pool, msg, 298 307 PJ_STUN_ATTR_REALM, … … 302 311 303 312 /* Add NONCE when desired */ 304 if (nonce.slen) { 313 if (nonce.slen && 314 (PJ_STUN_IS_REQUEST(msg->hdr.type) || 315 PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type))) 316 { 305 317 status = pj_stun_msg_add_string_attr(pool, msg, 306 318 PJ_STUN_ATTR_NONCE, … … 309 321 310 322 /* Add MESSAGE-INTEGRITY attribute */ 311 if (username.slen ) {323 if (username.slen && need_auth) { 312 324 status = pj_stun_msg_add_msgint_attr(pool, msg); 313 325 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); … … 509 521 * Create a STUN response message. 510 522 */ 511 PJ_DEF(pj_status_t) pj_stun_session_create_res ponse( pj_stun_session *sess,512 513 514 515 523 PJ_DEF(pj_status_t) pj_stun_session_create_res( pj_stun_session *sess, 524 const pj_stun_msg *req, 525 unsigned err_code, 526 const pj_str_t *err_msg, 527 pj_stun_tx_data **p_tdata) 516 528 { 517 529 pj_status_t status; … … 598 610 } 599 611 612 status = get_key(sess, tdata->pool, tdata->msg, &tdata->auth_key); 613 if (status != PJ_SUCCESS) { 614 pj_stun_msg_destroy_tdata(sess, tdata); 615 pj_mutex_unlock(sess->mutex); 616 LOG_ERR_(sess, "Error getting creadential's key", status); 617 return status; 618 } 619 600 620 /* Encode message */ 601 621 status = pj_stun_msg_encode(tdata->msg, (pj_uint8_t*)tdata->pkt, 602 622 tdata->max_len, 0, 603 get_passwd(sess, tdata->pool, tdata->msg),623 &tdata->auth_key, 604 624 &tdata->pkt_size); 605 625 if (status != PJ_SUCCESS) { … … 738 758 static pj_status_t send_response(pj_stun_session *sess, 739 759 pj_pool_t *pool, pj_stun_msg *response, 760 const pj_str_t *auth_key, 740 761 pj_bool_t retransmission, 741 762 const pj_sockaddr_t *addr, unsigned addr_len) … … 758 779 /* Encode */ 759 780 status = pj_stun_msg_encode(response, out_pkt, out_max_len, 0, 760 get_passwd(sess, pool, response), 761 &out_len); 781 auth_key, &out_len); 762 782 if (status != PJ_SUCCESS) { 763 783 LOG_ERR_(sess, "Error encoding message", status); … … 775 795 776 796 /* Authenticate incoming message */ 777 static pj_status_t authenticate_ msg(pj_stun_session *sess,797 static pj_status_t authenticate_req(pj_stun_session *sess, 778 798 const pj_uint8_t *pkt, 779 799 unsigned pkt_len, … … 789 809 return PJ_SUCCESS; 790 810 791 status = pj_stun_ verify_credential(pkt, pkt_len, msg, sess->cred,792 tmp_pool, &response);811 status = pj_stun_authenticate_request(pkt, pkt_len, msg, sess->cred, 812 tmp_pool, &response); 793 813 if (status != PJ_SUCCESS && response != NULL) { 794 814 PJ_LOG(5,(SNAME(sess), "Message authentication failed")); 795 send_response(sess, tmp_pool, response, PJ_FALSE,815 send_response(sess, tmp_pool, response, NULL, PJ_FALSE, 796 816 src_addr, src_addr_len); 797 817 } … … 803 823 /* Handle incoming response */ 804 824 static pj_status_t on_incoming_response(pj_stun_session *sess, 825 unsigned options, 826 const pj_uint8_t *pkt, 827 unsigned pkt_len, 805 828 pj_stun_msg *msg, 806 829 const pj_sockaddr_t *src_addr, … … 816 839 "Transaction not found, response silently discarded")); 817 840 return PJ_SUCCESS; 841 } 842 843 /* Authenticate the message, unless PJ_STUN_NO_AUTHENTICATE 844 * is specified in the option. 845 */ 846 if ((options & PJ_STUN_NO_AUTHENTICATE) == 0) { 847 status = pj_stun_authenticate_response(pkt, pkt_len, msg, &tdata->auth_key); 848 if (status != PJ_SUCCESS) { 849 PJ_LOG(5,(SNAME(sess), 850 "Response authentication failed")); 851 return status; 852 } 818 853 } 819 854 … … 867 902 "Request retransmission, sending cached response")); 868 903 869 send_response(sess, tmp_pool, t->msg, PJ_TRUE,904 send_response(sess, tmp_pool, t->msg, &t->auth_key, PJ_TRUE, 870 905 src_addr, src_addr_len); 871 906 return PJ_SUCCESS; … … 877 912 /* Handle incoming request */ 878 913 static pj_status_t on_incoming_request(pj_stun_session *sess, 914 unsigned options, 879 915 pj_pool_t *tmp_pool, 880 916 const pj_uint8_t *in_pkt, … … 886 922 pj_status_t status; 887 923 924 /* Authenticate the message, unless PJ_STUN_NO_AUTHENTICATE 925 * is specified in the option. 926 */ 927 if ((options & PJ_STUN_NO_AUTHENTICATE) == 0) { 928 status = authenticate_req(sess, (const pj_uint8_t*) in_pkt, in_pkt_len, 929 msg, tmp_pool, src_addr, src_addr_len); 930 if (status != PJ_SUCCESS) { 931 return status; 932 } 933 } 934 888 935 /* Distribute to handler, or respond with Bad Request */ 889 936 if (sess->cb.on_rx_request) { … … 898 945 if (status == PJ_SUCCESS && response) { 899 946 status = send_response(sess, tmp_pool, response, 900 PJ_FALSE, src_addr, src_addr_len);947 NULL, PJ_FALSE, src_addr, src_addr_len); 901 948 } 902 949 } … … 953 1000 LOG_ERR_(sess, "STUN msg_decode() error", status); 954 1001 if (response) { 955 send_response(sess, tmp_pool, response, 1002 send_response(sess, tmp_pool, response, NULL, 956 1003 PJ_FALSE, src_addr, src_addr_len); 957 1004 } … … 978 1025 } 979 1026 980 /* Authenticate the message, unless PJ_STUN_NO_AUTHENTICATE981 * is specified in the option.982 */983 if ((options & PJ_STUN_NO_AUTHENTICATE) == 0) {984 status = authenticate_msg(sess, (const pj_uint8_t*) packet, pkt_size,985 msg, tmp_pool, src_addr, src_addr_len);986 if (status != PJ_SUCCESS) {987 goto on_return;988 }989 }990 991 1027 /* Handle message */ 992 1028 if (PJ_STUN_IS_SUCCESS_RESPONSE(msg->hdr.type) || 993 1029 PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) 994 1030 { 995 status = on_incoming_response(sess, msg, src_addr, src_addr_len); 1031 status = on_incoming_response(sess, options, 1032 (const pj_uint8_t*) packet, pkt_size, 1033 msg, src_addr, src_addr_len); 996 1034 997 1035 } else if (PJ_STUN_IS_REQUEST(msg->hdr.type)) { 998 1036 999 status = on_incoming_request(sess, tmp_pool,1037 status = on_incoming_request(sess, options, tmp_pool, 1000 1038 (const pj_uint8_t*) packet, pkt_size, 1001 1039 msg, src_addr, src_addr_len); -
pjproject/trunk/pjnath/src/pjnath/stun_transaction.c
r1152 r1275 189 189 tsx->retransmit_time.msec = tsx->cfg->rto_msec; 190 190 191 } else if (tsx->transmit_count < PJ_STUN_MAX_ RETRANSMIT_COUNT-1) {191 } else if (tsx->transmit_count < PJ_STUN_MAX_TRANSMIT_COUNT-1) { 192 192 unsigned msec; 193 193 194 194 msec = PJ_TIME_VAL_MSEC(tsx->retransmit_time); 195 msec = (msec << 1) + 100;195 msec <<= 1; 196 196 tsx->retransmit_time.sec = msec / 1000; 197 197 tsx->retransmit_time.msec = msec % 1000; … … 217 217 218 218 219 tsx->transmit_count++; 220 221 PJ_LOG(5,(tsx->obj_name, "STUN sending message (transmit count=%d)", 222 tsx->transmit_count)); 223 219 224 /* Send message */ 220 225 status = tsx->cb.on_send_msg(tsx, tsx->last_pkt, tsx->last_pkt_size); … … 229 234 } 230 235 231 tsx->transmit_count++;232 233 PJ_LOG(5,(tsx->obj_name, "STUN sending message (transmit count=%d)",234 tsx->transmit_count));235 236 return status; 236 237 } … … 269 270 PJ_UNUSED_ARG(timer_heap); 270 271 271 if (tsx->transmit_count >= PJ_STUN_MAX_ RETRANSMIT_COUNT) {272 if (tsx->transmit_count >= PJ_STUN_MAX_TRANSMIT_COUNT) { 272 273 /* Retransmission count exceeded. Transaction has failed */ 273 274 tsx->retransmit_timer.id = 0; -
pjproject/trunk/pjnath/src/pjstun-client/client_main.c
r1266 r1275 108 108 { 109 109 pj_stun_relay_addr_attr *ar; 110 pj_stun_lifetime_attr *al; 111 112 al = (pj_stun_lifetime_attr*) 113 pj_stun_msg_find_attr(response, 114 PJ_STUN_ATTR_LIFETIME, 0); 115 if (!al) { 116 PJ_LOG(1,(THIS_FILE, "Error: LIFETIME attribute not present")); 117 return; 118 } 110 119 111 120 ar = (pj_stun_relay_addr_attr*) … … 120 129 } else { 121 130 pj_memset(&g.relay_addr, 0, sizeof(g.relay_addr)); 131 } 132 133 if (al->value == 0) { 134 PJ_LOG(3,(THIS_FILE, "Relay deallocated")); 122 135 } 123 136 } … … 633 646 g.data = g.data_buf; 634 647 635 while((c=pj_getopt_long(argc,argv, "r:u:p: hF", long_options, &opt_id))!=-1) {648 while((c=pj_getopt_long(argc,argv, "r:u:p:N:hF", long_options, &opt_id))!=-1) { 636 649 switch (c) { 637 650 case 'r': -
pjproject/trunk/pjnath/src/pjstun-srv-test/bind_usage.c
r1091 r1275 158 158 159 159 /* Create response */ 160 status = pj_stun_session_create_res ponse(sess, msg, 0, NULL, &tdata);160 status = pj_stun_session_create_res(sess, msg, 0, NULL, &tdata); 161 161 if (status != PJ_SUCCESS) 162 162 return status; -
pjproject/trunk/pjnath/src/pjstun-srv-test/main.c
r1054 r1275 79 79 pj_caching_pool cp; 80 80 pj_stun_server *srv; 81 pj_stun_usage *turn; 81 82 pj_status_t status; 82 83 83 while((c=pj_getopt_long(argc,argv, "r:u:p: hF", long_options, &opt_id))!=-1) {84 while((c=pj_getopt_long(argc,argv, "r:u:p:N:hF", long_options, &opt_id))!=-1) { 84 85 switch (c) { 85 86 case 'r': … … 132 133 133 134 status = pj_stun_turn_usage_create(srv, PJ_SOCK_DGRAM, NULL, 134 3478, NULL);135 3478, &turn); 135 136 if (status != PJ_SUCCESS) { 136 137 pj_stun_perror(THIS_FILE, "Unable to create bind usage", status); 137 138 return 1; 139 } 140 141 if (o.user_name && o.password) { 142 pj_stun_auth_cred cred; 143 pj_bzero(&cred, sizeof(cred)); 144 cred.type = PJ_STUN_AUTH_CRED_STATIC; 145 cred.data.static_cred.realm = pj_str(o.realm); 146 cred.data.static_cred.username = pj_str(o.user_name); 147 cred.data.static_cred.data_type = 0; 148 cred.data.static_cred.data = pj_str(o.password); 149 cred.data.static_cred.nonce = pj_str(o.nonce); 150 pj_stun_turn_usage_set_credential(turn, &cred); 138 151 } 139 152 -
pjproject/trunk/pjnath/src/pjstun-srv-test/server.h
r1091 r1275 125 125 pj_stun_usage **p_bu); 126 126 127 PJ_DECL(pj_status_t) pj_stun_turn_usage_set_credential(pj_stun_usage *turn, 128 const pj_stun_auth_cred *cred); 127 129 128 130 pj_status_t pj_stun_server_register_usage(pj_stun_server *srv, -
pjproject/trunk/pjnath/src/pjstun-srv-test/turn_usage.c
r1266 r1275 79 79 pj_stun_session *default_session; 80 80 pj_hash_table_t *client_htable; 81 pj_stun_auth_cred *cred; 81 82 82 83 unsigned max_bw_kbps; … … 222 223 } 223 224 225 return PJ_SUCCESS; 226 } 227 228 229 PJ_DEF(pj_status_t) pj_stun_turn_usage_set_credential(pj_stun_usage *turn, 230 const pj_stun_auth_cred *c) 231 { 232 struct turn_usage *tu; 233 tu = (struct turn_usage*) pj_stun_usage_get_user_data(turn); 234 235 tu->cred = PJ_POOL_ZALLOC_T(tu->pool, pj_stun_auth_cred); 236 pj_stun_auth_cred_dup(tu->pool, tu->cred, c); 237 pj_stun_session_set_credential(tu->default_session, tu->cred); 224 238 return PJ_SUCCESS; 225 239 } … … 442 456 } else if (msg->hdr.type != PJ_STUN_ALLOCATE_REQUEST) { 443 457 if (PJ_STUN_IS_REQUEST(msg->hdr.type)) { 444 status = pj_stun_session_create_res ponse(sess, msg,445 446 458 status = pj_stun_session_create_res(sess, msg, 459 PJ_STUN_SC_NO_BINDING, 460 NULL, &tdata); 447 461 if (status==PJ_SUCCESS) { 448 462 status = pj_stun_session_send_msg(sess, PJ_FALSE, … … 631 645 } 632 646 647 if (tu->cred) 648 pj_stun_session_set_credential(client->session, tu->cred); 649 633 650 sd = PJ_POOL_ZALLOC_T(pool, struct session_data); 634 651 sd->tu = tu; … … 864 881 pj_cstr(&err_msg, custom_msg), p_err_msg = &err_msg; 865 882 866 status = pj_stun_session_create_res ponse(client->session, msg,867 868 883 status = pj_stun_session_create_res(client->session, msg, 884 err_code, p_err_msg, 885 &response); 869 886 if (status == PJ_SUCCESS) 870 887 status = pj_stun_session_send_msg(client->session, PJ_TRUE, … … 1015 1032 1016 1033 /* Done successfully, create and send success response */ 1017 status = pj_stun_session_create_res ponse(client->session, msg,1018 1034 status = pj_stun_session_create_res(client->session, msg, 1035 0, NULL, &response); 1019 1036 if (status != PJ_SUCCESS) { 1020 1037 return status; … … 1063 1080 1064 1081 /* Create response */ 1065 status = pj_stun_session_create_res ponse(session, msg, 0, NULL,1066 1082 status = pj_stun_session_create_res(session, msg, 0, NULL, 1083 &tdata); 1067 1084 if (status != PJ_SUCCESS) 1068 1085 return status; -
pjproject/trunk/third_party/build/Makefile
r1202 r1275 1 DIRS = resample 2 1 3 include ../../build.mak 2 4 include $(PJDIR)/build/common.mak -
pjproject/trunk/third_party/build/os-auto.mak.in
r1202 r1275 1 DIRS = resample2 1 3 2 ifneq (@ac_no_gsm_codec@,1)
Note: See TracChangeset
for help on using the changeset viewer.