Ignore:
Timestamp:
May 15, 2007 10:42:56 AM (17 years ago)
Author:
bennylp
Message:

Fixed several STUN bugs: USERNAME, REALM etc are not allowed in the response, retransmission timer calculation bug, etc.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjnath/src/pjnath/stun_session.c

    r1239 r1275  
    212212} 
    213213 
    214 static pj_str_t *get_passwd(pj_stun_session *sess, pj_pool_t *pool, 
    215                             const pj_stun_msg *msg) 
     214static pj_status_t get_key(pj_stun_session *sess, pj_pool_t *pool, 
     215                           const pj_stun_msg *msg, pj_str_t *auth_key) 
    216216{ 
    217217    if (sess->cred == NULL) { 
    218         return NULL; 
     218        auth_key->slen = 0; 
     219        return PJ_SUCCESS; 
    219220    } else if (sess->cred->type == PJ_STUN_AUTH_CRED_STATIC) { 
    220         return &sess->cred->data.static_cred.data; 
     221        pj_stun_create_key(pool, auth_key,  
     222                           &sess->cred->data.static_cred.realm, 
     223                           &sess->cred->data.static_cred.username, 
     224                           &sess->cred->data.static_cred.data); 
     225        return PJ_SUCCESS; 
    221226    } else if (sess->cred->type == PJ_STUN_AUTH_CRED_DYNAMIC) { 
    222227        pj_str_t realm, username, nonce; 
     
    232237                                                       &nonce, &data_type, 
    233238                                                       password); 
    234         return password; 
     239        if (status != PJ_SUCCESS) 
     240            return status; 
     241 
     242        pj_stun_create_key(pool, auth_key,  
     243                           &realm, &username, password); 
     244 
     245        return PJ_SUCCESS; 
    235246 
    236247    } else { 
    237         return NULL; 
     248        pj_assert(!"Unknown credential type"); 
     249        return PJ_EBUG; 
    238250    } 
    239251} 
     
    244256{ 
    245257    pj_status_t status = 0; 
     258    pj_bool_t need_auth; 
    246259    pj_str_t realm, username, nonce, password; 
    247260    int data_type = 0; 
     
    250263 
    251264    /* The server SHOULD include a SERVER attribute in all responses */ 
    252     if (sess->srv_name.slen && (PJ_STUN_IS_SUCCESS_RESPONSE(msg->hdr.type) || 
    253                                 PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)))  
    254     { 
     265    if (sess->srv_name.slen && PJ_STUN_IS_RESPONSE(msg->hdr.type)) { 
    255266        pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SERVER, 
    256267                                    &sess->srv_name); 
    257268    } 
    258269 
    259     /* From draft-ietf-behave-rfc3489bis-05.txt 
    260      * Section 8.3.1.  Formulating the Request Message 
    261      * 
    262      * Note: only put MESSAGE-INTEGRITY in non error response. 
    263      */ 
     270    need_auth = PJ_STUN_IS_REQUEST(msg->hdr.type) || 
     271                PJ_STUN_IS_SUCCESS_RESPONSE(msg->hdr.type); 
     272 
    264273    if (sess->cred && sess->cred->type == PJ_STUN_AUTH_CRED_STATIC && 
    265         !PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type))  
     274        need_auth) 
    266275    { 
    267276        realm = sess->cred->data.static_cred.realm; 
     
    272281 
    273282    } else if (sess->cred && sess->cred->type == PJ_STUN_AUTH_CRED_DYNAMIC && 
    274                !PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type))  
     283               need_auth)  
    275284    { 
    276285        void *user_data = sess->cred->data.dyn_cred.user_data; 
     
    285294 
    286295 
    287     /* Create and add USERNAME attribute */ 
    288     if (username.slen) { 
     296    /* Create and add USERNAME attribute for */ 
     297    if (username.slen && PJ_STUN_IS_REQUEST(msg->hdr.type)) { 
    289298        status = pj_stun_msg_add_string_attr(pool, msg, 
    290299                                             PJ_STUN_ATTR_USERNAME, 
     
    294303 
    295304    /* Add REALM only when long term credential is used */ 
    296     if (realm.slen) { 
     305    if (realm.slen &&  PJ_STUN_IS_REQUEST(msg->hdr.type)) { 
    297306        status = pj_stun_msg_add_string_attr(pool, msg, 
    298307                                            PJ_STUN_ATTR_REALM, 
     
    302311 
    303312    /* Add NONCE when desired */ 
    304     if (nonce.slen) { 
     313    if (nonce.slen &&  
     314        (PJ_STUN_IS_REQUEST(msg->hdr.type) || 
     315         PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)))  
     316    { 
    305317        status = pj_stun_msg_add_string_attr(pool, msg, 
    306318                                            PJ_STUN_ATTR_NONCE, 
     
    309321 
    310322    /* Add MESSAGE-INTEGRITY attribute */ 
    311     if (username.slen) { 
     323    if (username.slen && need_auth) { 
    312324        status = pj_stun_msg_add_msgint_attr(pool, msg); 
    313325        PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 
     
    509521 * Create a STUN response message. 
    510522 */ 
    511 PJ_DEF(pj_status_t) pj_stun_session_create_response( pj_stun_session *sess, 
    512                                                      const pj_stun_msg *req, 
    513                                                      unsigned err_code, 
    514                                                      const pj_str_t *err_msg, 
    515                                                      pj_stun_tx_data **p_tdata) 
     523PJ_DEF(pj_status_t) pj_stun_session_create_res( pj_stun_session *sess, 
     524                                                const pj_stun_msg *req, 
     525                                                unsigned err_code, 
     526                                                const pj_str_t *err_msg, 
     527                                                pj_stun_tx_data **p_tdata) 
    516528{ 
    517529    pj_status_t status; 
     
    598610    } 
    599611 
     612    status = get_key(sess, tdata->pool, tdata->msg, &tdata->auth_key); 
     613    if (status != PJ_SUCCESS) { 
     614        pj_stun_msg_destroy_tdata(sess, tdata); 
     615        pj_mutex_unlock(sess->mutex); 
     616        LOG_ERR_(sess, "Error getting creadential's key", status); 
     617        return status; 
     618    } 
     619 
    600620    /* Encode message */ 
    601621    status = pj_stun_msg_encode(tdata->msg, (pj_uint8_t*)tdata->pkt,  
    602622                                tdata->max_len, 0,  
    603                                 get_passwd(sess, tdata->pool, tdata->msg), 
     623                                &tdata->auth_key, 
    604624                                &tdata->pkt_size); 
    605625    if (status != PJ_SUCCESS) { 
     
    738758static pj_status_t send_response(pj_stun_session *sess,  
    739759                                 pj_pool_t *pool, pj_stun_msg *response, 
     760                                 const pj_str_t *auth_key, 
    740761                                 pj_bool_t retransmission, 
    741762                                 const pj_sockaddr_t *addr, unsigned addr_len) 
     
    758779    /* Encode */ 
    759780    status = pj_stun_msg_encode(response, out_pkt, out_max_len, 0,  
    760                                 get_passwd(sess, pool, response), 
    761                                 &out_len); 
     781                                auth_key, &out_len); 
    762782    if (status != PJ_SUCCESS) { 
    763783        LOG_ERR_(sess, "Error encoding message", status); 
     
    775795 
    776796/* Authenticate incoming message */ 
    777 static pj_status_t authenticate_msg(pj_stun_session *sess, 
     797static pj_status_t authenticate_req(pj_stun_session *sess, 
    778798                                    const pj_uint8_t *pkt, 
    779799                                    unsigned pkt_len, 
     
    789809        return PJ_SUCCESS; 
    790810 
    791     status = pj_stun_verify_credential(pkt, pkt_len, msg, sess->cred, 
    792                                        tmp_pool, &response); 
     811    status = pj_stun_authenticate_request(pkt, pkt_len, msg, sess->cred, 
     812                                          tmp_pool, &response); 
    793813    if (status != PJ_SUCCESS && response != NULL) { 
    794814        PJ_LOG(5,(SNAME(sess), "Message authentication failed")); 
    795         send_response(sess, tmp_pool, response, PJ_FALSE,  
     815        send_response(sess, tmp_pool, response, NULL, PJ_FALSE,  
    796816                      src_addr, src_addr_len); 
    797817    } 
     
    803823/* Handle incoming response */ 
    804824static pj_status_t on_incoming_response(pj_stun_session *sess, 
     825                                        unsigned options, 
     826                                        const pj_uint8_t *pkt, 
     827                                        unsigned pkt_len, 
    805828                                        pj_stun_msg *msg, 
    806829                                        const pj_sockaddr_t *src_addr, 
     
    816839                  "Transaction not found, response silently discarded")); 
    817840        return PJ_SUCCESS; 
     841    } 
     842 
     843    /* Authenticate the message, unless PJ_STUN_NO_AUTHENTICATE 
     844     * is specified in the option. 
     845     */ 
     846    if ((options & PJ_STUN_NO_AUTHENTICATE) == 0) { 
     847        status = pj_stun_authenticate_response(pkt, pkt_len, msg, &tdata->auth_key); 
     848        if (status != PJ_SUCCESS) { 
     849            PJ_LOG(5,(SNAME(sess),  
     850                      "Response authentication failed")); 
     851            return status; 
     852        } 
    818853    } 
    819854 
     
    867902                 "Request retransmission, sending cached response")); 
    868903 
    869         send_response(sess, tmp_pool, t->msg, PJ_TRUE,  
     904        send_response(sess, tmp_pool, t->msg, &t->auth_key, PJ_TRUE,  
    870905                      src_addr, src_addr_len); 
    871906        return PJ_SUCCESS; 
     
    877912/* Handle incoming request */ 
    878913static pj_status_t on_incoming_request(pj_stun_session *sess, 
     914                                       unsigned options, 
    879915                                       pj_pool_t *tmp_pool, 
    880916                                       const pj_uint8_t *in_pkt, 
     
    886922    pj_status_t status; 
    887923 
     924    /* Authenticate the message, unless PJ_STUN_NO_AUTHENTICATE 
     925     * is specified in the option. 
     926     */ 
     927    if ((options & PJ_STUN_NO_AUTHENTICATE) == 0) { 
     928        status = authenticate_req(sess, (const pj_uint8_t*) in_pkt, in_pkt_len, 
     929                                  msg, tmp_pool, src_addr, src_addr_len); 
     930        if (status != PJ_SUCCESS) { 
     931            return status; 
     932        } 
     933    } 
     934 
    888935    /* Distribute to handler, or respond with Bad Request */ 
    889936    if (sess->cb.on_rx_request) { 
     
    898945        if (status == PJ_SUCCESS && response) { 
    899946            status = send_response(sess, tmp_pool, response,  
    900                                    PJ_FALSE, src_addr, src_addr_len); 
     947                                   NULL, PJ_FALSE, src_addr, src_addr_len); 
    901948        } 
    902949    } 
     
    9531000        LOG_ERR_(sess, "STUN msg_decode() error", status); 
    9541001        if (response) { 
    955             send_response(sess, tmp_pool, response,  
     1002            send_response(sess, tmp_pool, response, NULL, 
    9561003                          PJ_FALSE, src_addr, src_addr_len); 
    9571004        } 
     
    9781025    } 
    9791026 
    980     /* Authenticate the message, unless PJ_STUN_NO_AUTHENTICATE 
    981      * is specified in the option. 
    982      */ 
    983     if ((options & PJ_STUN_NO_AUTHENTICATE) == 0) { 
    984         status = authenticate_msg(sess, (const pj_uint8_t*) packet, pkt_size,  
    985                                   msg, tmp_pool, src_addr, src_addr_len); 
    986         if (status != PJ_SUCCESS) { 
    987             goto on_return; 
    988         } 
    989     } 
    990  
    9911027    /* Handle message */ 
    9921028    if (PJ_STUN_IS_SUCCESS_RESPONSE(msg->hdr.type) || 
    9931029        PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) 
    9941030    { 
    995         status = on_incoming_response(sess, msg, src_addr, src_addr_len); 
     1031        status = on_incoming_response(sess, options,  
     1032                                      (const pj_uint8_t*) packet, pkt_size,  
     1033                                      msg, src_addr, src_addr_len); 
    9961034 
    9971035    } else if (PJ_STUN_IS_REQUEST(msg->hdr.type)) { 
    9981036 
    999         status = on_incoming_request(sess, tmp_pool,  
     1037        status = on_incoming_request(sess, options, tmp_pool,  
    10001038                                     (const pj_uint8_t*) packet, pkt_size,  
    10011039                                     msg, src_addr, src_addr_len); 
Note: See TracChangeset for help on using the changeset viewer.