Changeset 1877


Ignore:
Timestamp:
Mar 19, 2008 11:00:30 PM (16 years ago)
Author:
bennylp
Message:

Related to ticket #485: huge changeset to update STUN relating to managing authentication. See the ticket for the details

Location:
pjproject/trunk/pjnath
Files:
1 added
18 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjnath/build/Makefile

    r1815 r1877  
    3939# 
    4040export PJNATH_TEST_SRCDIR = ../src/pjnath-test 
    41 export PJNATH_TEST_OBJS += ice_test.o stun.o test.o 
     41export PJNATH_TEST_OBJS += ice_test.o stun.o sess_auth.o test.o 
    4242export PJNATH_TEST_CFLAGS += $(_CFLAGS) 
    4343export PJNATH_TEST_LDFLAGS += $(_LDFLAGS) 
  • pjproject/trunk/pjnath/build/pjnath_test.dsp

    r1106 r1877  
    9696# Begin Source File 
    9797 
     98SOURCE="..\src\pjnath-test\sess_auth.c" 
     99# End Source File 
     100# Begin Source File 
     101 
    98102SOURCE="..\src\pjnath-test\stun.c" 
    99103# End Source File 
  • pjproject/trunk/pjnath/include/pjnath/stun_auth.h

    r1869 r1877  
    4040 
    4141/** 
     42 * Type of authentication. 
     43 */ 
     44typedef 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/** 
    4265 * Type of authentication data in the credential. 
    4366 */ 
     
    6083 
    6184} pj_stun_auth_cred_type; 
     85 
     86 
     87/** 
     88 * Type of encoding applied to the password stored in the credential. 
     89 */ 
     90typedef 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; 
    62105 
    63106 
     
    90133             * If not-empty, it indicates that this is a long term credential. 
    91134             */ 
    92             pj_str_t      realm; 
     135            pj_str_t            realm; 
    93136 
    94137            /**  
    95138             * The username of the credential. 
    96139             */ 
    97             pj_str_t      username; 
     140            pj_str_t            username; 
    98141 
    99142            /** 
    100143             * 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; 
    105146 
    106147            /**  
     
    109150             * plaintext password. 
    110151             */ 
    111             pj_str_t      data; 
     152            pj_str_t            data; 
    112153 
    113154            /**  
    114155             * Optional NONCE. 
    115156             */ 
    116             pj_str_t      nonce; 
     157            pj_str_t            nonce; 
    117158 
    118159        } static_cred; 
     
    157198 
    158199            /** 
    159              * Get the credential to be put in outgoing message. 
     200             * Get the credential to be put in outgoing request. 
    160201             * 
    161202             * @param msg       The outgoing message where the credential is 
     
    187228                                    pj_str_t *username, 
    188229                                    pj_str_t *nonce, 
    189                                     int *data_type, 
     230                                    pj_stun_passwd_type *data_type, 
    190231                                    pj_str_t *data); 
    191232 
     
    218259                                        const pj_str_t *username, 
    219260                                        pj_pool_t *pool, 
    220                                         int *data_type, 
     261                                        pj_stun_passwd_type *data_type, 
    221262                                        pj_str_t *data); 
    222263 
     
    251292 
    252293/** 
     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 */ 
     298typedef 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/** 
    253328 * Duplicate authentication credential. 
    254329 * 
     
    261336                                      const pj_stun_auth_cred *src); 
    262337 
     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 */ 
     345PJ_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 */ 
     366PJ_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); 
    263372 
    264373/** 
     
    278387 * @param pool          If response is to be created, then memory will 
    279388 *                      be allocated from this pool. 
    280  * @param auth_key      Optional pointer to receive authentication key to 
    281  *                      calculate MESSAGE-INTEGRITY of the response, if 
    282  *                      the 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. 
    283392 * @param p_response    Optional pointer to receive the response message 
    284393 *                      then the credential in the request fails to 
     
    295404                                                  pj_stun_auth_cred *cred, 
    296405                                                  pj_pool_t *pool, 
    297                                                   pj_str_t *auth_key, 
     406                                                  pj_stun_req_cred_info *info, 
    298407                                                  pj_stun_msg **p_response); 
    299408 
  • pjproject/trunk/pjnath/include/pjnath/stun_msg.h

    r1852 r1877  
    12261226 
    12271227/** 
     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 */ 
     1235PJ_DECL(pj_stun_msg*) pj_stun_msg_clone(pj_pool_t *pool, 
     1236                                        const pj_stun_msg *msg); 
     1237 
     1238/** 
    12281239 * Create STUN response message.  
    12291240 * 
     
    13001311                                        const pj_str_t *key, 
    13011312                                        unsigned *p_msg_len); 
    1302  
    1303  
    1304 /** 
    1305  * Create authentication key to be used for encoding the message with 
    1306  * MESSAGE-INTEGRITY. If short term credential is used (i.e. the realm 
    1307  * 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 the 
    1309  * 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 credential 
    1314  *                      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  
    13261313 
    13271314/** 
     
    14181405 
    14191406/** 
     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 */ 
     1414PJ_DECL(pj_stun_attr_hdr*) pj_stun_attr_clone(pj_pool_t *pool, 
     1415                                              const pj_stun_attr_hdr *attr); 
     1416 
     1417 
     1418/** 
    14201419 * Create a generic STUN IP address attribute. The \a addr_len and 
    14211420 * \a addr parameters specify whether the address is IPv4 or IPv4 
  • pjproject/trunk/pjnath/include/pjnath/stun_session.h

    r1862 r1877  
    4646/** Forward declaration for pj_stun_tx_data */ 
    4747typedef struct pj_stun_tx_data pj_stun_tx_data; 
     48 
     49/** Forward declaration for pj_stun_rx_data */ 
     50typedef struct pj_stun_rx_data pj_stun_rx_data; 
    4851 
    4952/** Forward declaration for pj_stun_session */ 
     
    8689     * @param pkt           Pointer to the original STUN packet. 
    8790     * @param pkt_len       Length of the STUN packet. 
    88      * @param msg           The parsed STUN request. 
     91     * @param rdata         Data containing incoming request message. 
    8992     * @param src_addr      Source address of the packet. 
    9093     * @param src_addr_len  Length of the source address. 
     
    97100                                 const pj_uint8_t *pkt, 
    98101                                 unsigned pkt_len, 
    99                                  const pj_stun_msg *msg, 
     102                                 const pj_stun_rx_data *rdata, 
    100103                                 const pj_sockaddr_t *src_addr, 
    101104                                 unsigned src_addr_len); 
     
    145148 
    146149/** 
     150 * This structure describes incoming request message. 
     151 */ 
     152struct 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/** 
    147169 * This structure describe the outgoing STUN transmit data to carry the 
    148170 * message to be sent. 
     
    162184    pj_uint8_t           msg_key[12];   /**< Message/transaction key.       */ 
    163185 
    164     pj_str_t             auth_key;      /**< Auth key.                      */ 
     186    pj_stun_req_cred_info auth_info;    /**< Credential info                */ 
    165187 
    166188    void                *pkt;           /**< The STUN packet.               */ 
     
    260282 * 
    261283 * @param sess      The STUN session instance. 
     284 * @param auth_type Type of authentication. 
    262285 * @param cred      The credential to be used by this session. If NULL 
    263286 *                  is specified, authentication will be disabled. 
     
    265288 * @return          PJ_SUCCESS on success, or the appropriate error code. 
    266289 */ 
    267 PJ_DECL(void) pj_stun_session_set_credential(pj_stun_session *sess, 
    268                                              const pj_stun_auth_cred *cred); 
     290PJ_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); 
    269293 
    270294/** 
     
    329353 */ 
    330354PJ_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, 
    332356                                                unsigned err_code, 
    333357                                                const pj_str_t *err_msg, 
     
    363387 * 
    364388 * @param sess      The STUN session instance. 
    365  * @param req       The STUN request message to be responded. 
     389 * @param rdata     The STUN request message to be responded. 
    366390 * @param err_code  Error code to be set in the response, if error response 
    367391 *                  is to be created, according to pj_stun_status enumeration. 
     
    383407 */ 
    384408PJ_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, 
    386410                                             unsigned code,  
    387411                                             const char *err_msg, 
  • pjproject/trunk/pjnath/src/pjnath-test/stun.c

    r1869 r1877  
    270270 
    271271        /* 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); 
    273273        status = pj_stun_msg_encode(msg, buf, sizeof(buf), 0, &key, &len); 
    274274        if (status != PJ_SUCCESS) { 
     
    406406{ 
    407407    /* 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 (Missing 
    419      * Username). 
    420      */ 
    421  
    422     /* If long term credential is wanted and REALM is not present, server  
    423      * 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 and 
    432      * 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 has 
    440      * 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  
    457408    return 0; 
    458409} 
     
    615566 
    616567            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)); 
    618569            pj_stun_msg_encode(msg, buf, sizeof(buf), 0, &key, &len); 
    619570 
     
    752703        goto on_return; 
    753704 
    754     rc = auth_test(); 
    755     if (rc != 0) 
    756         goto on_return; 
    757  
    758705    rc = fingerprint_test_vector(); 
    759706    if (rc != 0) 
  • pjproject/trunk/pjnath/src/pjnath-test/test.c

    r1439 r1877  
    6969#if INCLUDE_STUN_TEST 
    7070    DO_TEST(stun_test()); 
     71    DO_TEST(sess_auth_test()); 
    7172#endif 
    7273 
  • pjproject/trunk/pjnath/src/pjnath-test/test.h

    r1439 r1877  
    2424#define INCLUDE_ICE_TEST            1 
    2525 
    26 extern int stun_test(void); 
    27 extern int ice_test(void); 
    28 extern int test_main(void); 
     26int stun_test(void); 
     27int sess_auth_test(void); 
     28int ice_test(void); 
     29int test_main(void); 
    2930 
    3031extern void app_perror(const char *title, pj_status_t rc); 
  • pjproject/trunk/pjnath/src/pjnath/ice_session.c

    r1731 r1877  
    121121                                      const pj_uint8_t *pkt, 
    122122                                      unsigned pkt_len, 
    123                                       const pj_stun_msg *msg, 
     123                                      const pj_stun_rx_data *rdata, 
    124124                                      const pj_sockaddr_t *src_addr, 
    125125                                      unsigned src_addr_len); 
     
    148148                                      pj_str_t *username, 
    149149                                      pj_str_t *nonce, 
    150                                       int *data_type, 
     150                                      pj_stun_passwd_type *data_type, 
    151151                                      pj_str_t *data); 
    152152static pj_status_t stun_auth_get_password(const pj_stun_msg *msg, 
     
    155155                                          const pj_str_t *username, 
    156156                                          pj_pool_t *pool, 
    157                                           int *data_type, 
     157                                          pj_stun_passwd_type *data_type, 
    158158                                          pj_str_t *data); 
    159159 
     
    233233    auth_cred.data.dyn_cred.get_password = &stun_auth_get_password; 
    234234    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); 
    236237 
    237238    return PJ_SUCCESS; 
     
    447448                                      pj_str_t *username, 
    448449                                      pj_str_t *nonce, 
    449                                       int *data_type, 
     450                                      pj_stun_passwd_type *data_type, 
    450451                                      pj_str_t *data) 
    451452{ 
     
    462463         */ 
    463464        *username = ice->rx_uname; 
    464         *data_type = 0; 
     465        *data_type = PJ_STUN_PASSWD_PLAIN; 
    465466        *data = ice->rx_pass; 
    466467    } 
    467468    else { 
    468469        *username = ice->tx_uname; 
    469         *data_type = 0; 
     470        *data_type = PJ_STUN_PASSWD_PLAIN; 
    470471        *data = ice->tx_pass; 
    471472    } 
     
    480481                                          const pj_str_t *username, 
    481482                                          pj_pool_t *pool, 
    482                                           int *data_type, 
     483                                          pj_stun_passwd_type *data_type, 
    483484                                          pj_str_t *data) 
    484485{ 
     
    497498        if (pj_strcmp(username, &ice->tx_uname) != 0) 
    498499            return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNAUTHORIZED); 
    499         *data_type = 0; 
     500        *data_type = PJ_STUN_PASSWD_PLAIN; 
    500501        *data = ice->tx_pass; 
    501502 
     
    522523            return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNAUTHORIZED); 
    523524 
    524         *data_type = 0; 
     525        *data_type = PJ_STUN_PASSWD_PLAIN; 
    525526        *data = ice->rx_pass; 
    526527 
     
    19041905                                      const pj_uint8_t *pkt, 
    19051906                                      unsigned pkt_len, 
    1906                                       const pj_stun_msg *msg, 
     1907                                      const pj_stun_rx_data *rdata, 
    19071908                                      const pj_sockaddr_t *src_addr, 
    19081909                                      unsigned src_addr_len) 
    19091910{ 
    19101911    stun_data *sd; 
     1912    const pj_stun_msg *msg = rdata->msg; 
    19111913    pj_ice_sess *ice; 
    19121914    pj_stun_priority_attr *prio_attr; 
     
    19221924    /* Reject any requests except Binding request */ 
    19231925    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,  
    19251927                                            PJ_STUN_SC_BAD_REQUEST, 
    19261928                                            NULL, &tdata); 
     
    19931995        } else { 
    19941996            /* Generate 487 response */ 
    1995             status = pj_stun_session_create_res(sess, msg,  
     1997            status = pj_stun_session_create_res(sess, rdata,  
    19961998                                                PJ_STUN_SC_ROLE_CONFLICT, 
    19971999                                                NULL, &tdata); 
     
    20092011        if (pj_cmp_timestamp(&ice->tie_breaker, &role_attr->value) < 0) { 
    20102012            /* Generate 487 response */ 
    2011             status = pj_stun_session_create_res(sess, msg,  
     2013            status = pj_stun_session_create_res(sess, rdata,  
    20122014                                                PJ_STUN_SC_ROLE_CONFLICT, 
    20132015                                                NULL, &tdata); 
     
    20292031     * First send response to this request  
    20302032     */ 
    2031     status = pj_stun_session_create_res(sess, msg, 0, NULL, &tdata); 
     2033    status = pj_stun_session_create_res(sess, rdata, 0, NULL, &tdata); 
    20322034    if (status != PJ_SUCCESS) { 
    20332035        pj_mutex_unlock(ice->mutex); 
  • pjproject/trunk/pjnath/src/pjnath/stun_auth.c

    r1869 r1877  
    2020#include <pjnath/errno.h> 
    2121#include <pjlib-util/hmac_sha1.h> 
     22#include <pjlib-util/md5.h> 
    2223#include <pjlib-util/sha1.h> 
    2324#include <pj/assert.h> 
    2425#include <pj/log.h> 
     26#include <pj/pool.h> 
    2527#include <pj/string.h> 
    2628 
     
    5456 
    5557 
     58/* 
     59 * Duplicate request credential. 
     60 */ 
     61PJ_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 */ 
     75static 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 */ 
     127PJ_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 
    56151PJ_INLINE(pj_uint16_t) GET_VAL16(const pj_uint8_t *pdu, unsigned pos) 
    57152{ 
     
    87182        return rc; 
    88183 
    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) { 
    91186        rc = pj_stun_msg_add_string_attr(pool, response, 
    92187                                         PJ_STUN_ATTR_REALM,  
     
    102197    } 
    103198 
    104     if (nonce && nonce->slen) { 
     199    if (err_code!=400 && nonce && nonce->slen) { 
    105200        rc = pj_stun_msg_add_string_attr(pool, response, 
    106201                                         PJ_STUN_ATTR_NONCE,  
     
    122217                                                 pj_stun_auth_cred *cred, 
    123218                                                 pj_pool_t *pool, 
    124                                                  pj_str_t *auth_key, 
     219                                                 pj_stun_req_cred_info *p_info, 
    125220                                                 pj_stun_msg **p_response) 
    126221{ 
    127     pj_str_t realm, nonce, password; 
     222    pj_stun_req_cred_info tmp_info; 
    128223    const pj_stun_msgint_attr *amsgi; 
    129224    unsigned i, amsgi_pos; 
    130225    pj_bool_t has_attr_beyond_mi; 
    131226    const pj_stun_username_attr *auser; 
    132     pj_bool_t username_ok; 
    133227    const pj_stun_realm_attr *arealm; 
    134228    const pj_stun_realm_attr *anonce; 
    135229    pj_hmac_sha1_context ctx; 
    136230    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; 
    138233    pj_status_t status; 
    139234 
     
    150245        p_response = NULL; 
    151246 
     247    if (p_info == NULL) 
     248        p_info = &tmp_info; 
     249 
     250    pj_bzero(p_info, sizeof(pj_stun_req_cred_info)); 
     251 
    152252    /* Get realm and nonce from credential */ 
    153     realm.slen = nonce.slen = 0; 
     253    p_info->realm.slen = p_info->nonce.slen = 0; 
    154254    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; 
    157257    } else if (cred->type == PJ_STUN_AUTH_CRED_DYNAMIC) { 
    158258        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); 
    160261        if (status != PJ_SUCCESS) 
    161262            return status; 
    162263    } else { 
    163         pj_assert(!"Unexpected"); 
     264        pj_assert(!"Invalid credential type"); 
    164265        return PJ_EBUG; 
    165266    } 
     
    185286           The rule has been changed from rfc3489bis-06 
    186287        */ 
    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; 
    195291    } 
    196292 
     
    203299           The rule has been changed from rfc3489bis-06 
    204300        */ 
    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; 
    211304    } 
    212305 
     
    215308             pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REALM, 0); 
    216309 
     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 
    217319    /* Check if username match */ 
    218320    if (cred->type == PJ_STUN_AUTH_CRED_STATIC) { 
     321        pj_bool_t username_ok; 
    219322        username_ok = !pj_strcmp(&auser->value,  
    220323                                 &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        } 
    222338    } 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; 
    224341        pj_status_t rc; 
     342 
    225343        rc = cred->data.dyn_cred.get_password(msg,  
    226344                                              cred->data.dyn_cred.user_data, 
     
    228346                                              &auser->value, pool, 
    229347                                              &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        } 
    231357    } 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 
    247362 
    248363 
     
    252367 
    253368    /* Check for long term/short term requirements. */ 
    254     if (realm.slen != 0 && arealm == NULL) { 
     369    if (p_info->realm.slen != 0 && arealm == NULL) { 
    255370        /* 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) { 
    264376        /* We want long term, and REALM is present */ 
    265377 
    266378        /* 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; 
    273383        } 
    274384 
    275385        /* Verify REALM matches */ 
    276         if (pj_stricmp(&arealm->value, &realm)) { 
     386        if (pj_stricmp(&arealm->value, &p_info->realm)) { 
    277387            /* 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; 
    283391        } 
    284392 
    285393        /* Valid case, will validate the message integrity later */ 
    286394 
    287     } else if (realm.slen == 0 && arealm != NULL) { 
     395    } else if (p_info->realm.slen == 0 && arealm != NULL) { 
    288396        /* We want to use short term credential, but client uses long 
    289397         * term credential. The draft doesn't mention anything about 
     
    294402         * cause wrong message integrity value later. 
    295403         */ 
    296     } else if (realm.slen==0 && arealm == NULL) { 
     404    } else if (p_info->realm.slen==0 && arealm == NULL) { 
    297405        /* Short term authentication is wanted, and one is supplied */ 
    298406 
    299407        /* 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; 
    306412        } 
    307413    } 
     
    322428            ok = PJ_TRUE; 
    323429        } 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); 
    326432            } else { 
    327433                ok = PJ_TRUE; 
     
    330436 
    331437        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    } 
    346442 
    347443    /* 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); 
    349446 
    350447#if PJ_STUN_OLD_STYLE_MI_FINGERPRINT 
     
    383480        /* HMAC value mismatch */ 
    384481        /* 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; 
    390485    } 
    391486 
    392487    /* Everything looks okay! */ 
    393488    return PJ_SUCCESS; 
     489 
     490on_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); 
    394496} 
    395497 
     
    426528    case PJ_STUN_SC_BAD_REQUEST:            /* 400 (Bad Request)            */ 
    427529    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: 
    433534        return PJ_FALSE; 
    434535    default: 
  • pjproject/trunk/pjnath/src/pjnath/stun_msg.c

    r1852 r1877  
    2121#include <pjlib-util/crc32.h> 
    2222#include <pjlib-util/hmac_sha1.h> 
    23 #include <pjlib-util/md5.h> 
    2423#include <pj/assert.h> 
    2524#include <pj/log.h> 
     
    9190    pj_status_t (*encode_attr)(const void *a, pj_uint8_t *buf,  
    9291                               unsigned len, unsigned *printed); 
     92    void*       (*clone_attr)(pj_pool_t *pool, const void *src); 
    9393}; 
    9494 
     
    102102                                       unsigned len,  
    103103                                       unsigned *printed); 
     104static void*       clone_sockaddr_attr(pj_pool_t *pool, const void *src); 
    104105static pj_status_t decode_string_attr(pj_pool_t *pool,  
    105106                                      const pj_uint8_t *buf,  
     
    107108static pj_status_t encode_string_attr(const void *a, pj_uint8_t *buf,  
    108109                                      unsigned len, unsigned *printed); 
     110static void*       clone_string_attr(pj_pool_t *pool, const void *src); 
    109111static pj_status_t decode_msgint_attr(pj_pool_t *pool,  
    110112                                      const pj_uint8_t *buf, 
     
    112114static pj_status_t encode_msgint_attr(const void *a, pj_uint8_t *buf,  
    113115                                      unsigned len, unsigned *printed); 
     116static void*       clone_msgint_attr(pj_pool_t *pool, const void *src); 
    114117static pj_status_t decode_errcode_attr(pj_pool_t *pool,  
    115118                                       const pj_uint8_t *buf, 
     
    117120static pj_status_t encode_errcode_attr(const void *a, pj_uint8_t *buf,  
    118121                                       unsigned len, unsigned *printed); 
     122static void*       clone_errcode_attr(pj_pool_t *pool, const void *src); 
    119123static pj_status_t decode_unknown_attr(pj_pool_t *pool,  
    120124                                       const pj_uint8_t *buf,  
     
    122126static pj_status_t encode_unknown_attr(const void *a, pj_uint8_t *buf,  
    123127                                       unsigned len, unsigned *printed); 
     128static void*       clone_unknown_attr(pj_pool_t *pool, const void *src); 
    124129static pj_status_t decode_uint_attr(pj_pool_t *pool,  
    125130                                    const pj_uint8_t *buf,  
     
    127132static pj_status_t encode_uint_attr(const void *a, pj_uint8_t *buf,  
    128133                                    unsigned len, unsigned *printed); 
     134static void*       clone_uint_attr(pj_pool_t *pool, const void *src); 
    129135static pj_status_t decode_uint64_attr(pj_pool_t *pool,  
    130136                                      const pj_uint8_t *buf,  
     
    132138static pj_status_t encode_uint64_attr(const void *a, pj_uint8_t *buf,  
    133139                                      unsigned len, unsigned *printed); 
     140static void*       clone_uint64_attr(pj_pool_t *pool, const void *src); 
    134141static pj_status_t decode_binary_attr(pj_pool_t *pool,  
    135142                                      const pj_uint8_t *buf, 
     
    137144static pj_status_t encode_binary_attr(const void *a, pj_uint8_t *buf,  
    138145                                      unsigned len, unsigned *printed); 
     146static void*       clone_binary_attr(pj_pool_t *pool, const void *src); 
    139147static pj_status_t decode_empty_attr(pj_pool_t *pool,  
    140148                                     const pj_uint8_t *buf,  
     
    142150static pj_status_t encode_empty_attr(const void *a, pj_uint8_t *buf,  
    143151                                     unsigned len, unsigned *printed); 
    144  
     152static void*       clone_empty_attr(pj_pool_t *pool, const void *src); 
    145153 
    146154static struct attr_desc mandatory_attr_desc[] =  
     
    148156    { 
    149157        /* type zero */ 
     158        NULL, 
    150159        NULL, 
    151160        NULL, 
     
    156165        "MAPPED-ADDRESS", 
    157166        &decode_sockaddr_attr, 
    158         &encode_sockaddr_attr 
     167        &encode_sockaddr_attr, 
     168        &clone_sockaddr_attr 
    159169    }, 
    160170    { 
     
    162172        "RESPONSE-ADDRESS", 
    163173        &decode_sockaddr_attr, 
    164         &encode_sockaddr_attr 
     174        &encode_sockaddr_attr, 
     175        &clone_sockaddr_attr 
    165176    }, 
    166177    { 
     
    168179        "CHANGE-REQUEST", 
    169180        &decode_uint_attr, 
    170         &encode_uint_attr 
     181        &encode_uint_attr, 
     182        &clone_uint_attr 
    171183    }, 
    172184    { 
     
    174186        "SOURCE-ADDRESS", 
    175187        &decode_sockaddr_attr, 
    176         &encode_sockaddr_attr 
     188        &encode_sockaddr_attr, 
     189        &clone_sockaddr_attr 
    177190    }, 
    178191    { 
     
    180193        "CHANGED-ADDRESS", 
    181194        &decode_sockaddr_attr, 
    182         &encode_sockaddr_attr 
     195        &encode_sockaddr_attr, 
     196        &clone_sockaddr_attr 
    183197    }, 
    184198    { 
     
    186200        "USERNAME", 
    187201        &decode_string_attr, 
    188         &encode_string_attr 
     202        &encode_string_attr, 
     203        &clone_string_attr 
    189204    }, 
    190205    { 
     
    192207        "PASSWORD", 
    193208        &decode_string_attr, 
    194         &encode_string_attr 
     209        &encode_string_attr, 
     210        &clone_string_attr 
    195211    }, 
    196212    { 
     
    198214        "MESSAGE-INTEGRITY", 
    199215        &decode_msgint_attr, 
    200         &encode_msgint_attr 
     216        &encode_msgint_attr, 
     217        &clone_msgint_attr 
    201218    }, 
    202219    { 
     
    204221        "ERROR-CODE", 
    205222        &decode_errcode_attr, 
    206         &encode_errcode_attr 
     223        &encode_errcode_attr, 
     224        &clone_errcode_attr 
    207225    }, 
    208226    { 
     
    210228        "UNKNOWN-ATTRIBUTES", 
    211229        &decode_unknown_attr, 
    212         &encode_unknown_attr 
     230        &encode_unknown_attr, 
     231        &clone_unknown_attr 
    213232    }, 
    214233    { 
     
    216235        "REFLECTED-FROM", 
    217236        &decode_sockaddr_attr, 
    218         &encode_sockaddr_attr 
     237        &encode_sockaddr_attr, 
     238        &clone_sockaddr_attr 
    219239    }, 
    220240    { 
     
    222242        "CHANNEL-NUMBER", 
    223243        &decode_uint_attr, 
    224         &encode_uint_attr 
     244        &encode_uint_attr, 
     245        &clone_uint_attr 
    225246    }, 
    226247    { 
     
    228249        "LIFETIME", 
    229250        &decode_uint_attr, 
    230         &encode_uint_attr 
     251        &encode_uint_attr, 
     252        &clone_uint_attr 
    231253    }, 
    232254    { 
    233255        /* ID 0x000E is not assigned */ 
     256        NULL, 
    234257        NULL, 
    235258        NULL, 
     
    240263        "MAGIC-COOKIE", 
    241264        &decode_uint_attr, 
    242         &encode_uint_attr 
     265        &encode_uint_attr, 
     266        &clone_uint_attr 
    243267    }, 
    244268    { 
     
    246270        "BANDWIDTH", 
    247271        &decode_uint_attr, 
    248         &encode_uint_attr 
     272        &encode_uint_attr, 
     273        &clone_uint_attr 
    249274    }, 
    250275    { 
    251276        /* ID 0x0011 is not assigned */ 
     277        NULL, 
    252278        NULL, 
    253279        NULL, 
     
    258284        "PEER-ADDRESS", 
    259285        &decode_xored_sockaddr_attr, 
    260         &encode_sockaddr_attr 
     286        &encode_sockaddr_attr, 
     287        &clone_sockaddr_attr 
    261288    }, 
    262289    { 
     
    264291        "DATA", 
    265292        &decode_binary_attr, 
    266         &encode_binary_attr 
     293        &encode_binary_attr, 
     294        &clone_binary_attr 
    267295    }, 
    268296    { 
     
    270298        "REALM", 
    271299        &decode_string_attr, 
    272         &encode_string_attr 
     300        &encode_string_attr, 
     301        &clone_string_attr 
    273302    }, 
    274303    { 
     
    276305        "NONCE", 
    277306        &decode_string_attr, 
    278         &encode_string_attr 
     307        &encode_string_attr, 
     308        &clone_string_attr 
    279309    }, 
    280310    { 
     
    282312        "RELAY-ADDRESS", 
    283313        &decode_xored_sockaddr_attr, 
    284         &encode_sockaddr_attr 
     314        &encode_sockaddr_attr, 
     315        &clone_sockaddr_attr 
    285316    }, 
    286317    { 
     
    288319        "REQUESTED-ADDRESS-TYPE", 
    289320        &decode_uint_attr, 
    290         &encode_uint_attr 
     321        &encode_uint_attr, 
     322        &clone_uint_attr 
    291323    }, 
    292324    { 
     
    294326        "REQUESTED-PROPS", 
    295327        &decode_uint_attr, 
    296         &encode_uint_attr 
     328        &encode_uint_attr, 
     329        &clone_uint_attr 
    297330    }, 
    298331    { 
     
    300333        "REQUESTED-TRANSPORT", 
    301334        &decode_uint_attr, 
    302         &encode_uint_attr 
     335        &encode_uint_attr, 
     336        &clone_uint_attr 
    303337    }, 
    304338    { 
     
    306340        NULL, 
    307341        NULL, 
     342        NULL, 
    308343        NULL 
    309344    }, 
     
    312347        NULL, 
    313348        NULL, 
     349        NULL, 
    314350        NULL 
    315351    }, 
     
    318354        NULL, 
    319355        NULL, 
     356        NULL, 
    320357        NULL 
    321358    }, 
     
    324361        NULL, 
    325362        NULL, 
     363        NULL, 
    326364        NULL 
    327365    }, 
     
    330368        NULL, 
    331369        NULL, 
     370        NULL, 
    332371        NULL 
    333372    }, 
    334373    { 
    335374        /* ID 0x001F is not assigned */ 
     375        NULL, 
    336376        NULL, 
    337377        NULL, 
     
    342382        "XOR-MAPPED-ADDRESS", 
    343383        &decode_xored_sockaddr_attr, 
    344         &encode_sockaddr_attr 
     384        &encode_sockaddr_attr, 
     385        &clone_sockaddr_attr 
    345386    }, 
    346387    { 
     
    348389        "TIMER-VAL", 
    349390        &decode_uint_attr, 
    350         &encode_uint_attr 
     391        &encode_uint_attr, 
     392        &clone_uint_attr 
    351393    }, 
    352394    { 
     
    354396        "RESERVATION-TOKEN", 
    355397        &decode_uint64_attr, 
    356         &encode_uint64_attr 
     398        &encode_uint64_attr, 
     399        &clone_uint64_attr 
    357400    }, 
    358401    { 
     
    360403        "XOR-REFLECTED-FROM", 
    361404        &decode_xored_sockaddr_attr, 
    362         &encode_sockaddr_attr 
     405        &encode_sockaddr_attr, 
     406        &clone_sockaddr_attr 
    363407    }, 
    364408    { 
     
    366410        "PRIORITY", 
    367411        &decode_uint_attr, 
    368         &encode_uint_attr 
     412        &encode_uint_attr, 
     413        &clone_uint_attr 
    369414    }, 
    370415    { 
     
    372417        "USE-CANDIDATE", 
    373418        &decode_empty_attr, 
    374         &encode_empty_attr 
     419        &encode_empty_attr, 
     420        &clone_empty_attr 
    375421    }, 
    376422    { 
     
    378424        "XOR-INTERNAL-ADDRESS", 
    379425        &decode_xored_sockaddr_attr, 
    380         &encode_sockaddr_attr 
     426        &encode_sockaddr_attr, 
     427        &clone_sockaddr_attr 
    381428    }, 
    382429 
     
    386433        NULL, 
    387434        NULL, 
     435        NULL, 
    388436        NULL 
    389437    } 
     
    394442    { 
    395443        /* ID 0x8021 is not assigned */ 
     444        NULL, 
    396445        NULL, 
    397446        NULL, 
     
    402451        "SERVER", 
    403452        &decode_string_attr, 
    404         &encode_string_attr 
     453        &encode_string_attr, 
     454        &clone_string_attr 
    405455    }, 
    406456    { 
     
    408458        "ALTERNATE-SERVER", 
    409459        &decode_sockaddr_attr, 
    410         &encode_sockaddr_attr 
     460        &encode_sockaddr_attr, 
     461        &clone_sockaddr_attr 
    411462    }, 
    412463    { 
     
    414465        "REFRESH-INTERVAL", 
    415466        &decode_uint_attr, 
    416         &encode_uint_attr 
     467        &encode_uint_attr, 
     468        &clone_uint_attr 
    417469    }, 
    418470    { 
     
    420472        NULL, 
    421473        NULL, 
     474        NULL, 
    422475        NULL 
    423476    }, 
     
    426479        NULL, 
    427480        NULL, 
     481        NULL, 
    428482        NULL 
    429483    }, 
    430484    { 
    431485        /* CACHE-TIMEOUT, 0x8027 */ 
     486        NULL, 
    432487        NULL, 
    433488        NULL, 
     
    438493        "FINGERPRINT", 
    439494        &decode_uint_attr, 
    440         &encode_uint_attr 
     495        &encode_uint_attr, 
     496        &clone_uint_attr 
    441497    }, 
    442498    { 
     
    444500        "ICE-CONTROLLED", 
    445501        &decode_uint64_attr, 
    446         &encode_uint64_attr 
     502        &encode_uint64_attr, 
     503        &clone_uint64_attr 
    447504    }, 
    448505    { 
     
    450507        "ICE-CONTROLLING", 
    451508        &decode_uint64_attr, 
    452         &encode_uint64_attr 
     509        &encode_uint64_attr, 
     510        &clone_uint64_attr 
    453511    } 
    454512}; 
     
    827885 
    828886 
     887static 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 
    829894////////////////////////////////////////////////////////////////////////////// 
    830895/* 
     
    9351000 
    9361001 
     1002static 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 
    9371013////////////////////////////////////////////////////////////////////////////// 
    9381014/* 
     
    10181094} 
    10191095 
     1096 
     1097static 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} 
    10201105 
    10211106////////////////////////////////////////////////////////////////////////////// 
     
    11041189} 
    11051190 
     1191 
     1192static 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 
    11061201////////////////////////////////////////////////////////////////////////////// 
    11071202 
     
    11901285 
    11911286 
     1287static 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 
    11921297////////////////////////////////////////////////////////////////////////////// 
    11931298/* 
     
    12701375 
    12711376    return PJ_SUCCESS; 
     1377} 
     1378 
     1379 
     1380static 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; 
    12721387} 
    12731388 
     
    13821497} 
    13831498 
     1499 
     1500static 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 
    13841511////////////////////////////////////////////////////////////////////////////// 
    13851512/* 
     
    15001627 
    15011628 
     1629static 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 
    15021638////////////////////////////////////////////////////////////////////////////// 
    15031639/* 
     
    15971733} 
    15981734 
     1735 
     1736static 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} 
    15991750 
    16001751////////////////////////////////////////////////////////////////////////////// 
     
    16381789 
    16391790    return PJ_SUCCESS; 
     1791} 
     1792 
     1793 
     1794/* 
     1795 * Clone a STUN message with all of its attributes. 
     1796 */ 
     1797PJ_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; 
    16401816} 
    16411817 
     
    19822158} 
    19832159 
    1984 /* Calculate HMAC-SHA1 key for long term credential, by getting 
    1985  * 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 taking 
    1993      * the MD5 hash of the result of concatenating the following five 
    1994      * fields: (1) The username, with any quotes and trailing nulls 
    1995      * removed, (2) A single colon, (3) The realm, with any quotes and 
    1996      * trailing nulls removed, (4) A single colon, and (5) The  
    1997      * 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_QUOTE 
    2023  
    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 with 
    2037  * 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  
    20572160/* 
    20582161static char *print_binary(const pj_uint8_t *data, unsigned data_len) 
     
    22082311         * the last attribute before FINGERPRINT. 
    22092312         */ 
    2210         if (i < msg->attr_count-2) { 
     2313        if (msg->attr_count>1 && i < msg->attr_count-2) { 
    22112314            /* Should not happen for message generated by us */ 
    22122315            pj_assert(PJ_FALSE); 
     
    22992402} 
    23002403 
     2404 
     2405/* 
     2406 * Clone a STUN attribute. 
     2407 */ 
     2408PJ_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  
    1818 */ 
    1919#include <pjnath/stun_session.h> 
     20#include <pjnath/errno.h> 
    2021#include <pjlib.h> 
    2122 
     
    3031 
    3132    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 
    3341    pj_str_t             srv_name; 
    3442 
     
    126134} 
    127135 
    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  
    161136static void stun_tsx_on_destroy(pj_stun_client_tsx *tsx) 
    162137{ 
     
    216191} 
    217192 
    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  
    257193static pj_status_t apply_msg_options(pj_stun_session *sess, 
    258194                                     pj_pool_t *pool, 
     195                                     const pj_stun_req_cred_info *auth_info, 
    259196                                     pj_stun_msg *msg) 
    260197{ 
    261198    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; 
    267200 
    268201    /* The server SHOULD include a SERVER attribute in all responses */ 
     
    272205    } 
    273206 
    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 */ 
    300217    if (username.slen && PJ_STUN_IS_REQUEST(msg->hdr.type)) { 
    301218        status = pj_stun_msg_add_string_attr(pool, msg, 
     
    324241 
    325242    /* Add MESSAGE-INTEGRITY attribute */ 
    326     if (username.slen && need_auth) { 
     243    if (username.slen && auth_key.slen) { 
    327244        status = pj_stun_msg_add_msgint_attr(pool, msg); 
    328245        PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 
     
    340257} 
    341258 
     259static 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} 
    342358 
    343359static void stun_tsx_on_complete(pj_stun_client_tsx *tsx, 
     
    347363                                 unsigned src_addr_len) 
    348364{ 
     365    pj_stun_session *sess; 
     366    pj_bool_t notify_user = PJ_TRUE; 
    349367    pj_stun_tx_data *tdata; 
    350368 
    351369    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, &notify_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); 
    357380    } 
    358381} 
     
    489512} 
    490513 
    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); 
     514PJ_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; 
    495521    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); 
    499523    } 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 
     532static 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} 
    504572 
    505573PJ_DEF(pj_status_t) pj_stun_session_create_req(pj_stun_session *sess, 
     
    514582    PJ_ASSERT_RETURN(sess && p_tdata, PJ_EINVAL); 
    515583 
    516     status = create_request_tdata(sess, method, magic, tsx_id, &tdata); 
     584    status = create_tdata(sess, &tdata); 
    517585    if (status != PJ_SUCCESS) 
    518586        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    } 
    519633 
    520634    *p_tdata = tdata; 
     
    552666 */ 
    553667PJ_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, 
    555669                                                unsigned err_code, 
    556670                                                const pj_str_t *err_msg, 
     
    565679 
    566680    /* Create STUN response message */ 
    567     status = pj_stun_msg_create_response(tdata->pool, req, 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); 
    569683    if (status != PJ_SUCCESS) { 
    570684        pj_pool_release(tdata->pool); 
     
    573687 
    574688    /* 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); 
    578696 
    579697    *p_tdata = tdata; 
     
    587705                        unsigned pkt_size, const pj_sockaddr_t *addr) 
    588706{ 
    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]; 
    593708     
    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); 
    604710 
    605711    PJ_LOG(5,(SNAME(sess),  
    606               "TX %d bytes STUN message to %s:%d:\n" 
     712              "TX %d bytes STUN message to %s:\n" 
    607713              "--- begin STUN message ---\n" 
    608714              "%s" 
    609715              "--- 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))); 
    612719 
    613720} 
     
    632739 
    633740    /* 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); 
    635743    if (status != PJ_SUCCESS) { 
    636744        pj_stun_msg_destroy_tdata(sess, tdata); 
     
    640748    } 
    641749 
    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  
    650750    /* Encode message */ 
    651751    status = pj_stun_msg_encode(tdata->msg, (pj_uint8_t*)tdata->pkt,  
    652752                                tdata->max_len, 0,  
    653                                 &tdata->auth_key, 
     753                                &tdata->auth_info.auth_key, 
    654754                                &tdata->pkt_size); 
    655755    if (status != PJ_SUCCESS) { 
     
    743843 */ 
    744844PJ_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, 
    746846                                             unsigned code,  
    747847                                             const char *errmsg, 
     
    754854    pj_stun_tx_data *tdata; 
    755855 
    756     status = pj_stun_session_create_res(sess, req, code,  
     856    status = pj_stun_session_create_res(sess, rdata, code,  
    757857                                        (errmsg?pj_cstr(&reason,errmsg):NULL),  
    758858                                        &tdata); 
     
    814914static pj_status_t send_response(pj_stun_session *sess,  
    815915                                 pj_pool_t *pool, pj_stun_msg *response, 
    816                                  const pj_str_t *auth_key, 
     916                                 const pj_stun_req_cred_info *auth_info, 
    817917                                 pj_bool_t retransmission, 
    818918                                 const pj_sockaddr_t *addr, unsigned addr_len) 
     
    824924    /* Apply options */ 
    825925    if (!retransmission) { 
    826         status = apply_msg_options(sess, pool, response); 
     926        status = apply_msg_options(sess, pool, auth_info, response); 
    827927        if (status != PJ_SUCCESS) 
    828928            return status; 
     
    835935    /* Encode */ 
    836936    status = pj_stun_msg_encode(response, out_pkt, out_max_len, 0,  
    837                                 auth_key, &out_len); 
     937                                &auth_info->auth_key, &out_len); 
    838938    if (status != PJ_SUCCESS) { 
    839939        LOG_ERR_(sess, "Error encoding message", status); 
     
    854954                                    const pj_uint8_t *pkt, 
    855955                                    unsigned pkt_len, 
    856                                     const pj_stun_msg *msg, 
     956                                    pj_stun_rx_data *rdata, 
    857957                                    pj_pool_t *tmp_pool, 
    858958                                    const pj_sockaddr_t *src_addr, 
     
    860960{ 
    861961    pj_stun_msg *response; 
    862     pj_str_t auth_key; 
    863962    pj_status_t status; 
    864963 
    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    { 
    866967        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); 
    870973    if (status != PJ_SUCCESS && response != NULL) { 
    871974        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,  
    873976                      src_addr, src_addr_len); 
    874977    } 
     
    8981001    } 
    8991002 
     1003    if (sess->auth_type == PJ_STUN_AUTH_NONE) 
     1004        options |= PJ_STUN_NO_AUTHENTICATE; 
     1005 
    9001006    /* Authenticate the message, unless PJ_STUN_NO_AUTHENTICATE 
    9011007     * is specified in the option. 
    9021008     */ 
    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)) 
    9051012    { 
    9061013        status = pj_stun_authenticate_response(pkt, pkt_len, msg,  
    907                                                &tdata->auth_key); 
     1014                                               &tdata->auth_info.auth_key); 
    9081015        if (status != PJ_SUCCESS) { 
    9091016            PJ_LOG(5,(SNAME(sess),  
     
    9631070                 "Request retransmission, sending cached response")); 
    9641071 
    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,  
    9661073                      src_addr, src_addr_len); 
    9671074        return PJ_SUCCESS; 
     
    9771084                                       const pj_uint8_t *in_pkt, 
    9781085                                       unsigned in_pkt_len, 
    979                                        const pj_stun_msg *msg, 
     1086                                       pj_stun_msg *msg, 
    9801087                                       const pj_sockaddr_t *src_addr, 
    9811088                                       unsigned src_addr_len) 
    9821089{ 
     1090    pj_stun_rx_data rdata; 
    9831091    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; 
    9841099 
    9851100    /* Authenticate the message, unless PJ_STUN_NO_AUTHENTICATE 
     
    9881103    if ((options & PJ_STUN_NO_AUTHENTICATE) == 0) { 
    9891104        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); 
    9911106        if (status != PJ_SUCCESS) { 
    9921107            return status; 
     
    9961111    /* Distribute to handler, or respond with Bad Request */ 
    9971112    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, 
    9991114                                           src_addr, src_addr_len); 
    10001115    } else { 
     1116        pj_str_t err_text; 
    10011117        pj_stun_msg *response; 
    10021118 
     1119        err_text = pj_str("Callback is not set to handle request"); 
    10031120        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); 
    10061123        if (status == PJ_SUCCESS && response) { 
    10071124            status = send_response(sess, tmp_pool, response,  
  • pjproject/trunk/pjnath/src/pjnath/turn_session.c

    r1869 r1877  
    522522    pj_lock_acquire(sess->lock); 
    523523 
    524     pj_stun_session_set_credential(sess->stun, cred); 
     524    pj_stun_session_set_credential(sess->stun, PJ_STUN_AUTH_LONG_TERM, cred); 
    525525 
    526526    pj_lock_release(sess->lock); 
  • pjproject/trunk/pjnath/src/pjturn-srv/allocation.c

    r1854 r1877  
    7373                                      const pj_uint8_t *pkt, 
    7474                                      unsigned pkt_len, 
    75                                       const pj_stun_msg *msg, 
     75                                      const pj_stun_rx_data *rdata, 
    7676                                      const pj_sockaddr_t *src_addr, 
    7777                                      unsigned src_addr_len); 
     
    9898static pj_status_t parse_allocate_req(alloc_request *cfg, 
    9999                                      pj_stun_session *sess, 
    100                                       const pj_stun_msg *req, 
     100                                      const pj_stun_rx_data *rdata, 
    101101                                      const pj_sockaddr_t *src_addr, 
    102102                                      unsigned src_addr_len) 
    103103{ 
     104    const pj_stun_msg *req = rdata->msg; 
    104105    pj_stun_bandwidth_attr *attr_bw; 
    105106    pj_stun_req_transport_attr *attr_req_tp; 
     
    121122    /* Check if we can satisfy the bandwidth */ 
    122123    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, 
    124126                                "Invalid bandwidth", PJ_TRUE, 
    125127                                src_addr, src_addr_len); 
     
    131133                  pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_TRANSPORT, 0); 
    132134    if (attr_req_tp == NULL) { 
    133         pj_stun_session_respond(sess, req, PJ_STUN_SC_BAD_REQUEST, 
     135        pj_stun_session_respond(sess, rdata, PJ_STUN_SC_BAD_REQUEST, 
    134136                                "Missing REQUESTED-TRANSPORT attribute",  
    135137                                PJ_TRUE, src_addr, src_addr_len); 
     
    141143    /* Can only support UDP for now */ 
    142144    if (cfg->tp_type != PJ_TURN_TP_UDP) { 
    143         pj_stun_session_respond(sess, req, PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO, 
     145        pj_stun_session_respond(sess, rdata, PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO, 
    144146                                NULL, PJ_TRUE, src_addr, src_addr_len); 
    145147        return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO); 
     
    152154    if (attr_res_token) { 
    153155        /* We don't support RESERVATION-TOKEN for now */ 
    154         pj_stun_session_respond(sess, req,  
     156        pj_stun_session_respond(sess, rdata,  
    155157                                PJ_STUN_SC_BAD_REQUEST, 
    156158                                "RESERVATION-TOKEN is not supported", PJ_TRUE,  
     
    164166    if (attr_rpp) { 
    165167        /* We don't support REQUESTED-PROPS for now */ 
    166         pj_stun_session_respond(sess, req,  
     168        pj_stun_session_respond(sess, rdata,  
    167169                                PJ_STUN_SC_BAD_REQUEST, 
    168170                                "REQUESTED-PROPS is not supported", PJ_TRUE,  
     
    177179        cfg->lifetime = attr_lifetime->value; 
    178180        if (cfg->lifetime < MIN_LIFETIME) { 
    179             pj_stun_session_respond(sess, req, PJ_STUN_SC_BAD_REQUEST, 
     181            pj_stun_session_respond(sess, rdata, PJ_STUN_SC_BAD_REQUEST, 
    180182                                    "LIFETIME too short", PJ_TRUE,  
    181183                                    src_addr, src_addr_len); 
     
    195197static pj_status_t send_allocate_response(pj_turn_allocation *alloc, 
    196198                                          pj_stun_session *srv_sess, 
    197                                           const pj_stun_msg *msg) 
     199                                          const pj_stun_rx_data *rdata) 
    198200{ 
    199201    pj_stun_tx_data *tdata; 
     
    201203 
    202204    /* 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); 
    204206    if (status != PJ_SUCCESS) 
    205207        return status; 
     
    285287                                              const pj_sockaddr_t *src_addr, 
    286288                                              unsigned src_addr_len, 
    287                                               const pj_stun_msg *msg, 
     289                                              const pj_stun_rx_data *rdata, 
    288290                                              pj_stun_session *srv_sess, 
    289291                                              pj_turn_allocation **p_alloc) 
    290292{ 
    291293    pj_turn_srv *srv = listener->server; 
     294    const pj_stun_msg *msg = rdata->msg; 
    292295    pj_pool_t *pool; 
    293296    alloc_request req; 
     
    298301 
    299302    /* 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); 
    301304    if (status != PJ_SUCCESS) 
    302305        return status; 
     
    355358 
    356359    /* 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); 
    358362 
    359363    /* Create the relay resource */ 
     
    367371 
    368372    /* Respond to ALLOCATE request */ 
    369     status = send_allocate_response(alloc, srv_sess, msg); 
     373    status = send_allocate_response(alloc, srv_sess, rdata); 
    370374    if (status != PJ_SUCCESS) 
    371375        goto on_error; 
     
    384388    /* Send reply to the ALLOCATE request */ 
    385389    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,  
    387391                            PJ_TRUE, src_addr, src_addr_len); 
    388392 
     
    710714/* Create and send error response */ 
    711715static void send_reply_err(pj_turn_allocation *alloc, 
    712                            const pj_stun_msg *req, 
     716                           const pj_stun_rx_data *rdata, 
    713717                           pj_bool_t cache,  
    714718                           int code, const char *errmsg) 
     
    716720    pj_status_t status; 
    717721 
    718     status = pj_stun_session_respond(alloc->sess, req, code, errmsg, cache, 
     722    status = pj_stun_session_respond(alloc->sess, rdata, code, errmsg, cache, 
    719723                                     &alloc->hkey.clt_addr, 
    720724                                     pj_sockaddr_get_len(&alloc->hkey.clt_addr.addr)); 
     
    727731/* Create and send successful response */ 
    728732static void send_reply_ok(pj_turn_allocation *alloc, 
    729                           const pj_stun_msg *req) 
     733                          const pj_stun_rx_data *rdata) 
    730734{ 
    731735    pj_status_t status; 
     
    733737    pj_stun_tx_data *tdata; 
    734738 
    735     status = pj_stun_session_create_res(alloc->sess, req, 0, NULL, &tdata); 
     739    status = pj_stun_session_create_res(alloc->sess, rdata, 0, NULL, &tdata); 
    736740    if (status != PJ_SUCCESS) { 
    737741        alloc_err(alloc, "Error creating STUN success response", status); 
     
    10731077                                      const pj_uint8_t *pkt, 
    10741078                                      unsigned pkt_len, 
    1075                                       const pj_stun_msg *msg, 
     1079                                      const pj_stun_rx_data *rdata, 
    10761080                                      const pj_sockaddr_t *src_addr, 
    10771081                                      unsigned src_addr_len) 
    10781082{ 
     1083    const pj_stun_msg *msg = rdata->msg; 
    10791084    pj_turn_allocation *alloc; 
    10801085 
     
    10891094    if (alloc->relay.lifetime == 0) { 
    10901095        /* Reject with 437 if we're shutting down */ 
    1091         send_reply_err(alloc, msg, PJ_TRUE,  
     1096        send_reply_err(alloc, rdata, PJ_TRUE,  
    10921097                       PJ_STUN_SC_ALLOCATION_MISMATCH, NULL); 
    10931098        return PJ_SUCCESS; 
     
    11161121 
    11171122            /* Respond first */ 
    1118             send_reply_ok(alloc, msg); 
     1123            send_reply_ok(alloc, rdata); 
    11191124 
    11201125            /* Shutdown allocation */ 
     
    11421147 
    11431148            /* Send reply */ 
    1144             send_reply_ok(alloc, msg); 
     1149            send_reply_ok(alloc, rdata); 
    11451150        } 
    11461151 
     
    11591164 
    11601165        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); 
    11621168            return PJ_SUCCESS; 
    11631169        } 
     
    11721178            if (pj_sockaddr_cmp(&p1->hkey.peer_addr, &peer_attr->sockaddr)) { 
    11731179                /* Address mismatch. Send 400 */ 
    1174                 send_reply_err(alloc, msg, PJ_TRUE,  
     1180                send_reply_err(alloc, rdata, PJ_TRUE,  
    11751181                               PJ_STUN_SC_BAD_REQUEST,  
    11761182                               "Peer address mismatch"); 
     
    11911197                                       pj_sockaddr_get_len(&peer_attr->sockaddr)); 
    11921198        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,  
    11941200                           "Peer address already assigned a channel number"); 
    11951201            return PJ_SUCCESS; 
     
    12111217 
    12121218        /* Reply */ 
    1213         send_reply_ok(alloc, msg); 
     1219        send_reply_ok(alloc, rdata); 
    12141220 
    12151221        return PJ_SUCCESS; 
     
    12181224 
    12191225        /* 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); 
    12211228 
    12221229    } else { 
    12231230 
    12241231        /* 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); 
    12261233 
    12271234    } 
  • pjproject/trunk/pjnath/src/pjturn-srv/auth.c

    r1869 r1877  
    5656{ 
    5757    /* 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; 
    8158} 
    8259 
  • pjproject/trunk/pjnath/src/pjturn-srv/auth.h

    r1869 r1877  
    6262 
    6363/** 
    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 /** 
    7664 * This function is called to get the password for the specified username. 
    7765 * This function is also used to check whether the username is valid. 
  • pjproject/trunk/pjnath/src/pjturn-srv/server.c

    r1869 r1877  
    4141                                      const pj_uint8_t *pkt, 
    4242                                      unsigned pkt_len, 
    43                                       const pj_stun_msg *msg, 
     43                                      const pj_stun_rx_data *rdata, 
    4444                                      const pj_sockaddr_t *src_addr, 
    4545                                      unsigned src_addr_len); 
     
    148148    srv->core.cred.data.dyn_cred.user_data = srv; 
    149149    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; 
    151150    srv->core.cred.data.dyn_cred.get_password = &pj_turn_get_password; 
    152151    srv->core.cred.data.dyn_cred.verify_nonce = &pj_turn_verify_nonce; 
     
    369368 
    370369    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); 
    372372 
    373373    srv->core.stun_sess[index] = sess; 
     
    484484 
    485485/* 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, 
     486static pj_status_t stun_respond(pj_stun_session *sess,  
     487                                const pj_stun_rx_data *rdata, 
    489488                                unsigned code,  
    490489                                const char *errmsg, 
     
    498497 
    499498    /* Create response */ 
    500     status = pj_stun_session_create_res(sess, req, code,  
     499    status = pj_stun_session_create_res(sess, rdata, code,  
    501500                                        (errmsg?pj_cstr(&reason,errmsg):NULL), 
    502501                                        &tdata); 
     
    504503        return status; 
    505504 
    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  
    511505    /* Send the response */ 
    512506    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 for 
    518  * 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; 
    605507} 
    606508 
     
    613515                                      const pj_uint8_t *pkt, 
    614516                                      unsigned pkt_len, 
    615                                       const pj_stun_msg *msg, 
     517                                      const pj_stun_rx_data *rdata, 
    616518                                      const pj_sockaddr_t *src_addr, 
    617519                                      unsigned src_addr_len) 
    618520{ 
    619521    pj_turn_listener *listener; 
     522    const pj_stun_msg *msg = rdata->msg; 
    620523    pj_turn_srv *srv; 
    621524    pj_turn_allocation *alloc; 
     
    630533    /* Respond any requests other than ALLOCATE with 437 response */ 
    631534    if (msg->hdr.type != PJ_STUN_ALLOCATE_REQUEST) { 
    632         stun_respond(srv, sess, msg, PJ_STUN_SC_ALLOCATION_MISMATCH, 
     535        stun_respond(sess, rdata, PJ_STUN_SC_ALLOCATION_MISMATCH, 
    633536                     NULL, PJ_FALSE, src_addr, src_addr_len); 
    634537        return PJ_SUCCESS; 
     
    639542     */ 
    640543    status = pj_turn_allocation_create(listener, src_addr, src_addr_len, 
    641                                        msg, sess, &alloc); 
     544                                       rdata, sess, &alloc); 
    642545    if (status != PJ_SUCCESS) { 
    643546        /* STUN response has been sent, no need to reply here */ 
  • pjproject/trunk/pjnath/src/pjturn-srv/turn.h

    r1854 r1877  
    205205                                              const pj_sockaddr_t *src_addr, 
    206206                                              unsigned src_addr_len, 
    207                                               const pj_stun_msg *msg, 
     207                                              const pj_stun_rx_data *rdata, 
    208208                                              pj_stun_session *srv_sess, 
    209209                                              pj_turn_allocation **p_alloc); 
     
    460460 
    461461 
    462 /** 
    463  * Store the credential to put placed for the specified message for 
    464  * 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  
    483462#endif  /* __PJ_TURN_SRV_TURN_H__ */ 
    484463 
Note: See TracChangeset for help on using the changeset viewer.