From 240fa9cd6f0ede43211b799f4706df92c62a5be9 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Tue, 15 May 2007 10:42:56 +0000 Subject: Fixed several STUN bugs: USERNAME, REALM etc are not allowed in the response, retransmission timer calculation bug, etc. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1275 74dad513-b988-da41-8d7b-12977e46ad98 --- pjnath/include/pjnath/config.h | 16 ++++++++-- pjnath/include/pjnath/stun_auth.h | 50 +++++++++++++++++------------- pjnath/include/pjnath/stun_config.h | 2 +- pjnath/include/pjnath/stun_msg.h | 60 ++++++++++++++++++++++++++---------- pjnath/include/pjnath/stun_session.h | 12 +++++--- 5 files changed, 93 insertions(+), 47 deletions(-) (limited to 'pjnath/include') diff --git a/pjnath/include/pjnath/config.h b/pjnath/include/pjnath/config.h index f7cb3009..3b24b944 100644 --- a/pjnath/include/pjnath/config.h +++ b/pjnath/include/pjnath/config.h @@ -88,12 +88,22 @@ /** - * Maximum number of STUN retransmission count. + * Maximum number of STUN transmission count. * * Default: 7 (as per RFC 3489-bis) */ -#ifndef PJ_STUN_MAX_RETRANSMIT_COUNT -# define PJ_STUN_MAX_RETRANSMIT_COUNT 7 +#ifndef PJ_STUN_MAX_TRANSMIT_COUNT +# define PJ_STUN_MAX_TRANSMIT_COUNT 7 +#endif + + +/** + * Duration to keep response in the cache, in msec. + * + * Default: 10000 (as per RFC 3489-bis) + */ +#ifndef PJ_STUN_RES_CACHE_DURATION +# define PJ_STUN_RES_CACHE_DURATION 10000 #endif diff --git a/pjnath/include/pjnath/stun_auth.h b/pjnath/include/pjnath/stun_auth.h index 539c8867..2bf190d8 100644 --- a/pjnath/include/pjnath/stun_auth.h +++ b/pjnath/include/pjnath/stun_auth.h @@ -262,7 +262,7 @@ PJ_DECL(void) pj_stun_auth_cred_dup(pj_pool_t *pool, /** - * Verify credential in the STUN message. Note that before calling this + * Verify credential in the STUN request. Note that before calling this * function, application must have checked that the message contains * PJ_STUN_ATTR_MESSAGE_INTEGRITY attribute by calling pj_stun_msg_find_attr() * function, because this function will reject the message with 401 error @@ -286,35 +286,41 @@ PJ_DECL(void) pj_stun_auth_cred_dup(pj_pool_t *pool, * NULL, an appropriate response will be returned in * \a p_response. */ -PJ_DECL(pj_status_t) pj_stun_verify_credential(const pj_uint8_t *pkt, - unsigned pkt_len, - const pj_stun_msg *msg, - pj_stun_auth_cred *cred, - pj_pool_t *pool, - pj_stun_msg **p_response); - - +PJ_DECL(pj_status_t) pj_stun_authenticate_request(const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_stun_msg *msg, + pj_stun_auth_cred *cred, + pj_pool_t *pool, + pj_stun_msg **p_response); /** - * @} + * Verify credential in the STUN response. Note that before calling this + * function, application must have checked that the message contains + * PJ_STUN_ATTR_MESSAGE_INTEGRITY attribute by calling pj_stun_msg_find_attr() + * function, because otherwise this function will report authentication + * failure. + * + * @param pkt The original packet which has been parsed into + * the message. This packet MUST NOT have been modified + * after the parsing. + * @param pkt_len The length of the packet. + * @param msg The parsed message to be verified. + * @param key Authentication key to calculate MESSAGE-INTEGRITY + * value. Application can create this key by using + * #pj_stun_create_key() function. + * + * @return PJ_SUCCESS if credential is verified successfully. */ +PJ_DECL(pj_status_t) pj_stun_authenticate_response(const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_stun_msg *msg, + const pj_str_t *key); /** - * Calculate HMAC-SHA1 key for long term credential, by getting - * MD5 digest of username, realm, and password. - * - * @param digest The buffer for the digest. - * @param realm The realm of the credential, if long term credential - * is to be used. - * @param username The username. - * @param passwd The clear text password. + * @} */ -void pj_stun_calc_md5_key(pj_uint8_t digest[16], - const pj_str_t *realm, - const pj_str_t *username, - const pj_str_t *passwd); PJ_END_DECL diff --git a/pjnath/include/pjnath/stun_config.h b/pjnath/include/pjnath/stun_config.h index d0914267..6a487be8 100644 --- a/pjnath/include/pjnath/stun_config.h +++ b/pjnath/include/pjnath/stun_config.h @@ -98,7 +98,7 @@ PJ_INLINE(void) pj_stun_config_init(pj_stun_config *cfg, cfg->ioqueue = ioqueue; cfg->timer_heap = timer_heap; cfg->rto_msec = PJ_STUN_RTO_VALUE; - cfg->res_cache_msec = 10000; + cfg->res_cache_msec = PJ_STUN_RES_CACHE_DURATION; } diff --git a/pjnath/include/pjnath/stun_msg.h b/pjnath/include/pjnath/stun_msg.h index 7234884b..5f04ba59 100644 --- a/pjnath/include/pjnath/stun_msg.h +++ b/pjnath/include/pjnath/stun_msg.h @@ -132,13 +132,11 @@ enum pj_stun_msg_class_e */ #define PJ_STUN_IS_REQUEST(msg_type) (((msg_type) & 0x0110) == 0x0000) - /** - * Determine if the message type is a response. + * Determine if the message type is a successful response. */ #define PJ_STUN_IS_SUCCESS_RESPONSE(msg_type) (((msg_type) & 0x0110) == 0x0100) - /** * The response bit in the message type. */ @@ -149,12 +147,15 @@ enum pj_stun_msg_class_e */ #define PJ_STUN_IS_ERROR_RESPONSE(msg_type) (((msg_type) & 0x0110) == 0x0110) - /** * The error response bit in the message type. */ #define PJ_STUN_ERROR_RESPONSE_BIT (0x0110) +/** + * Determine if the message type is a response. + */ +#define PJ_STUN_IS_RESPONSE(msg_type) (((msg_type) & 0x0100) == 0x0100) /** * Determine if the message type is an indication message. @@ -1148,17 +1149,20 @@ PJ_DECL(pj_status_t) pj_stun_msg_add_attr(pj_stun_msg *msg, * Print the STUN message structure to a packet buffer, ready to be * sent to remote destination. This function will take care about * calculating the MESSAGE-INTEGRITY digest as well as FINGERPRINT - * value. + * value, if these attributes are present in the message. * - * If MESSAGE-INTEGRITY attribute is present, the function assumes - * that application wants to include credential (short or long term) - * in the message, and this function will calculate the HMAC digest - * from the message using the supplied password in the parameter. - * If REALM attribute is present, the HMAC digest is calculated as - * long term credential, otherwise as short term credential. + * If application wants to apply credential to the message, it MUST + * include a blank MESSAGE-INTEGRITY attribute in the message, as the + * last attribute or the attribute before FINGERPRINT. This function will + * calculate the HMAC digest from the message using the supplied key in + * the parameter. The key should be set to the password if short term + * credential is used, or calculated from the MD5 hash of the realm, + * username, and password using #pj_stun_create_key() if long term + * credential is used. * * If FINGERPRINT attribute is present, this function will calculate - * the FINGERPRINT CRC attribute for the message. + * the FINGERPRINT CRC attribute for the message. The FINGERPRINT MUST + * be added as the last attribute of the message. * * @param msg The STUN message to be printed. Upon return, * some fields in the header (such as message @@ -1166,9 +1170,9 @@ PJ_DECL(pj_status_t) pj_stun_msg_add_attr(pj_stun_msg *msg, * @param pkt_buf The buffer to be filled with the packet. * @param buf_size Size of the buffer. * @param options Options, which currently must be zero. - * @param password Password to be used when credential is to be - * included. This parameter MUST be specified when - * the message contains MESSAGE-INTEGRITY attribute. + * @param key Authentication key to calculate MESSAGE-INTEGRITY + * value. Application can create this key by using + * #pj_stun_create_key() function. * @param p_msg_len Upon return, it will be filed with the size of * the packet in bytes, or negative value on error. * @@ -1178,9 +1182,33 @@ PJ_DECL(pj_status_t) pj_stun_msg_encode(pj_stun_msg *msg, pj_uint8_t *pkt_buf, unsigned buf_size, unsigned options, - const pj_str_t *password, + const pj_str_t *key, unsigned *p_msg_len); + +/** + * Create authentication key to be used for encoding the message with + * MESSAGE-INTEGRITY. If short term credential is used (i.e. the realm + * argument is NULL or empty), the key will be copied from the password. + * If long term credential is used, the key will be calculated from the + * MD5 hash of the realm, username, and password. + * + * @param pool Pool to allocate memory for the key. + * @param key String to receive the key. + * @param realm The realm of the credential, if long term credential + * is to be used. If short term credential is wanted, + * application can put NULL or empty string here. + * @param username The username. + * @param passwd The clear text password. + */ +PJ_DECL(void) pj_stun_create_key(pj_pool_t *pool, + pj_str_t *key, + const pj_str_t *realm, + const pj_str_t *username, + const pj_str_t *passwd); + + + /** * Check that the PDU is potentially a valid STUN message. This function * is useful when application needs to multiplex STUN packets with other diff --git a/pjnath/include/pjnath/stun_session.h b/pjnath/include/pjnath/stun_session.h index dfbf61c0..8a399a42 100644 --- a/pjnath/include/pjnath/stun_session.h +++ b/pjnath/include/pjnath/stun_session.h @@ -161,6 +161,8 @@ struct pj_stun_tx_data pj_uint32_t msg_magic; /**< Message magic. */ pj_uint8_t msg_key[12]; /**< Message/transaction key. */ + pj_str_t auth_key; /**< Auth key. */ + void *pkt; /**< The STUN packet. */ unsigned max_len; /**< Length of packet buffer. */ unsigned pkt_size; /**< The actual length of STUN pkt. */ @@ -305,11 +307,11 @@ PJ_DECL(pj_status_t) pj_stun_session_create_ind(pj_stun_session *sess, * * @return PJ_SUCCESS on success, or the appropriate error code. */ -PJ_DECL(pj_status_t) pj_stun_session_create_response(pj_stun_session *sess, - const pj_stun_msg *req, - unsigned err_code, - const pj_str_t *err_msg, - pj_stun_tx_data **p_tdata); +PJ_DECL(pj_status_t) pj_stun_session_create_res(pj_stun_session *sess, + const pj_stun_msg *req, + unsigned err_code, + const pj_str_t *err_msg, + pj_stun_tx_data **p_tdata); /** -- cgit v1.2.3