Changeset 4899


Ignore:
Timestamp:
Aug 21, 2014 5:58:36 AM (10 years ago)
Author:
nanang
Message:

Close #1735: Implemented secure dialog check of "sips" scheme in Contact/Record?-Route header in incoming INVITE/UPDATE requests & responses.

Location:
pjproject/trunk/pjsip
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/include/pjsip/sip_config.h

    r4802 r4899  
    146146        pj_bool_t resolve_hostname_to_get_interface; 
    147147 
     148        /** 
     149         * Disable security check on incoming messages in a secure dialog. 
     150         * A secure dialog is created when the request that creates the dialog 
     151         * uses "sips" scheme in its request URI. Contact URI should use "sips" 
     152         * scheme and the top-most Record-Route URI, if any, should use either 
     153         * "sips" scheme or "transport=tls" param. See also 
     154         * https://trac.pjsip.org/repos/ticket/1735. 
     155         * 
     156         * Default is PJ_FALSE. 
     157         */ 
     158        pj_bool_t disable_secure_dlg_check; 
     159 
    148160    } endpt; 
    149161 
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c

    r4831 r4899  
    116116                                         pj_bool_t end_sess_on_failure); 
    117117 
     118static pj_bool_t inv_check_secure_dlg(pjsip_inv_session *inv, 
     119                                      pjsip_event *e); 
     120 
    118121static void (*inv_state_handler[])( pjsip_inv_session *inv, pjsip_event *e) =  
    119122{ 
     
    991994        status = PJSIP_ERRNO_FROM_SIP_STATUS(code); 
    992995        goto on_return; 
     996    } 
     997 
     998    /* Ticket #1735: Check Contact/Record-Route header in a secure dialog. */ 
     999    if (pjsip_cfg()->endpt.disable_secure_dlg_check == PJ_FALSE && 
     1000        msg && c_hdr && c_hdr->uri) 
     1001    { 
     1002        /* Check Contact header */ 
     1003        if (!PJSIP_URI_SCHEME_IS_SIPS(c_hdr->uri)) 
     1004            status = PJSIP_ESESSIONINSECURE; 
     1005 
     1006        /* Check top Record-Route header */ 
     1007        if (status == PJ_SUCCESS) { 
     1008            pjsip_rr_hdr *r = (pjsip_rr_hdr*) 
     1009                              pjsip_msg_find_hdr(msg, PJSIP_H_RECORD_ROUTE, 
     1010                                                 NULL); 
     1011            if (r && !PJSIP_URI_SCHEME_IS_SIPS(&r->name_addr)) { 
     1012                /* Not "sips", check if it is "sip" and has param 
     1013                 * "transport=tls". 
     1014                 */ 
     1015                if (PJSIP_URI_SCHEME_IS_SIP(&r->name_addr)) { 
     1016                    pjsip_sip_uri *sip_uri = (pjsip_sip_uri*) 
     1017                                     pjsip_uri_get_uri(r->name_addr.uri); 
     1018                    if (pj_stricmp2(&sip_uri->transport_param, "tls")!=0) 
     1019                        status = PJSIP_ESESSIONINSECURE; 
     1020                } else { 
     1021                    /* Not "sips" nor "sip", treat it as insecure? */ 
     1022                    status = PJSIP_ESESSIONINSECURE; 
     1023                } 
     1024            } 
     1025        } 
     1026 
     1027        if (status != PJ_SUCCESS) { 
     1028            pjsip_warning_hdr *w; 
     1029            pj_str_t warn_text = pj_str("SIPS Required"); 
     1030            w = pjsip_warning_hdr_create(tmp_pool, 381, 
     1031                                         pjsip_endpt_name(endpt), 
     1032                                         &warn_text); 
     1033            if (w) { 
     1034                pj_list_push_back(&res_hdr_list, w); 
     1035            } 
     1036            code = PJSIP_SC_TEMPORARILY_UNAVAILABLE; 
     1037            goto on_return; 
     1038        } 
    9931039    } 
    9941040 
     
    32253271 */ 
    32263272static void inv_respond_incoming_update(pjsip_inv_session *inv, 
    3227                                         pjsip_rx_data *rdata) 
     3273                                        pjsip_event *e) 
    32283274{ 
    32293275    pjmedia_sdp_neg_state neg_state; 
    32303276    pj_status_t status; 
    32313277    pjsip_tx_data *tdata = NULL; 
     3278    pjsip_rx_data *rdata; 
    32323279    pjsip_status_code st_code; 
     3280 
     3281    pj_assert(e->type == PJSIP_EVENT_TSX_STATE && 
     3282              e->body.tsx_state.type == PJSIP_EVENT_RX_MSG); 
     3283    rdata = e->body.tsx_state.src.rdata; 
     3284 
     3285    /* Check routing URI scheme for secure dialog */ 
     3286    if (!inv_check_secure_dlg(inv, e)) 
     3287        return; 
    32333288 
    32343289    /* Invoke Session Timers module */ 
     
    33863441    { 
    33873442        pjsip_rx_data *rdata = e->body.tsx_state.src.rdata; 
    3388         status = handle_timer_response(inv, rdata, PJ_FALSE); 
    3389  
    3390         if (rdata->msg_info.msg->body) { 
    3391             /* Only process remote SDP if we have sent local offer */ 
    3392             if (inv->neg && pjmedia_sdp_neg_get_state(inv->neg) ==  
    3393                                         PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) 
    3394             { 
    3395                 status = inv_check_sdp_in_incoming_msg(inv, tsx, rdata); 
    3396             } else { 
    3397                 PJ_LOG(5,(THIS_FILE, "Ignored message body in %s as no local " 
    3398                                      "offer was sent", 
    3399                                      pjsip_rx_data_get_info(rdata))); 
     3443 
     3444        /* Check routing URI scheme for secure dialog */ 
     3445        if (inv_check_secure_dlg(inv, e)) { 
     3446 
     3447            status = handle_timer_response(inv, rdata, PJ_FALSE); 
     3448 
     3449            if (rdata->msg_info.msg->body) { 
     3450                /* Only process remote SDP if we have sent local offer */ 
     3451                if (inv->neg && pjmedia_sdp_neg_get_state(inv->neg) ==  
     3452                                            PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) 
     3453                { 
     3454                    status = inv_check_sdp_in_incoming_msg(inv, tsx, rdata); 
     3455                } else { 
     3456                    PJ_LOG(5,(THIS_FILE, "Ignored message body in %s as no " 
     3457                                         "local offer was sent", 
     3458                                         pjsip_rx_data_get_info(rdata))); 
     3459                } 
    34003460            } 
    34013461        } 
    3402         handled = PJ_TRUE; 
     3462 
     3463        handled = PJ_TRUE; 
    34033464    } 
    34043465 
     
    35153576    } 
    35163577} 
     3578 
     3579 
     3580/* Ticket #1735: If this is a secure dialog, make sure that any incoming 
     3581 * initial/subsequent INVITE/UPDATE request or the 2xx response to INVITE/ 
     3582 * UPDATE specifies secure Contact and Record-Route headers. 
     3583 */ 
     3584static pj_bool_t inv_check_secure_dlg(pjsip_inv_session *inv, 
     3585                                      pjsip_event *e) 
     3586{ 
     3587    pjsip_transaction *tsx = e->body.tsx_state.tsx; 
     3588    pjsip_dialog *dlg = pjsip_tsx_get_dlg(tsx); 
     3589 
     3590    if (pjsip_cfg()->endpt.disable_secure_dlg_check == PJ_FALSE && 
     3591        dlg->secure && e->body.tsx_state.type==PJSIP_EVENT_RX_MSG && 
     3592        (tsx->role==PJSIP_ROLE_UAC && tsx->status_code/100 == 2 || 
     3593         tsx->role==PJSIP_ROLE_UAS && tsx->state == PJSIP_TSX_STATE_TRYING) && 
     3594        (tsx->method.id==PJSIP_INVITE_METHOD ||  
     3595         pjsip_method_cmp(&tsx->method, &pjsip_update_method)==0)) 
     3596    { 
     3597        const pjsip_msg *msg = e->body.tsx_state.src.rdata->msg_info.msg; 
     3598        pj_status_t status = PJ_SUCCESS; 
     3599        pjsip_contact_hdr *c; 
     3600 
     3601        /* Check Contact header */ 
     3602        c = (pjsip_contact_hdr*) 
     3603            pjsip_msg_find_hdr(msg,PJSIP_H_CONTACT, NULL); 
     3604        if (!(c && c->uri && PJSIP_URI_SCHEME_IS_SIPS(c->uri))) 
     3605            status = PJSIP_ESESSIONINSECURE; 
     3606 
     3607        /* Check top Record-Route header */ 
     3608        if (status == PJ_SUCCESS) { 
     3609            pjsip_rr_hdr *r = (pjsip_rr_hdr*) 
     3610                              pjsip_msg_find_hdr(msg, PJSIP_H_RECORD_ROUTE, 
     3611                                                 NULL); 
     3612            if (r && !PJSIP_URI_SCHEME_IS_SIPS(&r->name_addr)) { 
     3613                /* Not "sips", check if it is "sip" and has param 
     3614                 * "transport=tls". 
     3615                 */ 
     3616                if (PJSIP_URI_SCHEME_IS_SIP(&r->name_addr)) { 
     3617                    pjsip_sip_uri *sip_uri = (pjsip_sip_uri*) 
     3618                                     pjsip_uri_get_uri(r->name_addr.uri); 
     3619                    if (pj_stricmp2(&sip_uri->transport_param, "tls")!=0) 
     3620                        status = PJSIP_ESESSIONINSECURE; 
     3621                } else { 
     3622                    /* Not "sips" nor "sip", treat it as insecure? */ 
     3623                    status = PJSIP_ESESSIONINSECURE; 
     3624                } 
     3625            } 
     3626        } 
     3627 
     3628        if (status == PJSIP_ESESSIONINSECURE) { 
     3629            /* Found non-SIPS scheme in Contact/Record-Route header */ 
     3630 
     3631            pj_str_t warn_text = pj_str("SIPS Required"); 
     3632 
     3633            if (tsx->role == PJSIP_ROLE_UAC) { 
     3634 
     3635                /* If we are UAC, terminate the session */ 
     3636                pjsip_tx_data *bye; 
     3637 
     3638                PJ_LOG(4,(inv->obj_name, 
     3639                          "Secure dialog requires SIPS scheme in Contact and " 
     3640                          "Record-Route headers, ending the session")); 
     3641 
     3642                status = pjsip_inv_end_session(inv, 480, NULL, &bye); 
     3643                if (status == PJ_SUCCESS && bye) { 
     3644                    pjsip_warning_hdr *w; 
     3645                    w = pjsip_warning_hdr_create(bye->pool, 381, 
     3646                                                 pjsip_endpt_name(dlg->endpt), 
     3647                                                 &warn_text); 
     3648                    if (w) 
     3649                        pjsip_msg_add_hdr(bye->msg, (pjsip_hdr*)w); 
     3650 
     3651                    status = pjsip_inv_send_msg(inv, bye); 
     3652                } 
     3653 
     3654            } else { 
     3655 
     3656                /* If we are UAS, reject the request */ 
     3657                pjsip_rx_data *rdata = e->body.tsx_state.src.rdata; 
     3658                pjsip_tx_data *tdata; 
     3659 
     3660                PJ_LOG(4,(inv->obj_name, 
     3661                          "Secure dialog requires SIPS scheme in Contact and " 
     3662                          "Route headers, rejecting the request")); 
     3663 
     3664                status = pjsip_dlg_create_response(inv->dlg, rdata, 480, 
     3665                                                   NULL, &tdata); 
     3666                if (status == PJ_SUCCESS) { 
     3667                    pjsip_warning_hdr *w; 
     3668                    w = pjsip_warning_hdr_create(tdata->pool, 381, 
     3669                                                 pjsip_endpt_name(dlg->endpt), 
     3670                                                 &warn_text); 
     3671                    if (w) 
     3672                        pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)w); 
     3673 
     3674                    pjsip_dlg_send_response(dlg, tsx, tdata); 
     3675                } 
     3676 
     3677            } 
     3678 
     3679            return PJ_FALSE; 
     3680        } 
     3681    } 
     3682 
     3683    return PJ_TRUE; 
     3684} 
     3685 
    35173686 
    35183687 
     
    38664035                pj_assert(0); 
    38674036 
     4037                inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e); 
     4038 
     4039                /* Check routing URI scheme for secure dialog */ 
     4040                if (!inv_check_secure_dlg(inv, e)) 
     4041                    break; 
     4042 
    38684043                /* Process session timer response. */ 
    38694044                status = handle_timer_response(inv, 
     
    38734048                    break; 
    38744049 
    3875                 inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e); 
    3876      
    38774050                inv_check_sdp_in_incoming_msg(inv, tsx,  
    38784051                                              e->body.tsx_state.src.rdata); 
     
    38904063            if (tsx->status_code/100 == 2) { 
    38914064                /* This must be receipt of 2xx response */ 
     4065                pj_assert(e->body.tsx_state.type == PJSIP_EVENT_RX_MSG); 
     4066 
     4067                /* Set state to CONNECTING */ 
     4068                inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e); 
     4069 
     4070                /* Check routing URI scheme for secure dialog */ 
     4071                if (!inv_check_secure_dlg(inv, e)) 
     4072                    break; 
    38924073 
    38934074                /* Process session timer response. */ 
     
    38984079                    break; 
    38994080 
    3900                 /* Set state to CONNECTING */ 
    3901                 inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e); 
    3902  
    39034081                inv_check_sdp_in_incoming_msg(inv, tsx,  
    39044082                                              e->body.tsx_state.src.rdata); 
    3905  
    39064083                /* Send ACK */ 
    3907                 pj_assert(e->body.tsx_state.type == PJSIP_EVENT_RX_MSG); 
    3908  
    39094084                inv_send_ack(inv, e); 
    39104085 
     
    39434118         * Handle a very early UPDATE 
    39444119         */ 
    3945         inv_respond_incoming_update(inv, e->body.tsx_state.src.rdata); 
     4120        inv_respond_incoming_update(inv, e); 
    39464121 
    39474122 
     
    40614236                    pj_status_t status; 
    40624237 
     4238                    /* Check routing URI scheme for secure dialog */ 
     4239                    if (!inv_check_secure_dlg(inv, e)) 
     4240                        break; 
     4241 
    40634242                    /* Process session timer response. */ 
    40644243                    status = handle_timer_response(inv,  
     
    41014280                    pj_status_t status; 
    41024281                     
     4282                    /* Check routing URI scheme for secure dialog */ 
     4283                    if (!inv_check_secure_dlg(inv, e)) 
     4284                        break; 
     4285 
    41034286                    /* Process session timer response. */ 
    41044287                    status = handle_timer_response(inv,  
     
    41504333         * Handle incoming UPDATE 
    41514334         */ 
    4152         inv_respond_incoming_update(inv, e->body.tsx_state.src.rdata); 
     4335        inv_respond_incoming_update(inv, e); 
    41534336 
    41544337 
     
    43584541         * Handle incoming UPDATE 
    43594542         */ 
    4360         inv_respond_incoming_update(inv, e->body.tsx_state.src.rdata); 
     4543        inv_respond_incoming_update(inv, e); 
    43614544 
    43624545 
     
    44874670                return; 
    44884671            } 
     4672 
     4673            /* Check routing URI scheme for secure dialog */ 
     4674            if (!inv_check_secure_dlg(inv, e)) 
     4675                return; 
    44894676 
    44904677            /* Save the invite transaction. */ 
     
    47304917            /* Re-INVITE was accepted. */ 
    47314918 
     4919            /* Check routing URI scheme for secure dialog */ 
     4920            if (!inv_check_secure_dlg(inv, e)) 
     4921                return; 
     4922 
    47324923            /* Process session timer response. */ 
    47334924            status = handle_timer_response(inv,  
     
    47884979         * Handle incoming UPDATE 
    47894980         */ 
    4790         inv_respond_incoming_update(inv, e->body.tsx_state.src.rdata); 
     4981        inv_respond_incoming_update(inv, e); 
    47914982 
    47924983    } else if (tsx->role == PJSIP_ROLE_UAC && 
  • pjproject/trunk/pjsip/src/pjsip/sip_config.c

    r4802 r4899  
    3434       PJSIP_FOLLOW_EARLY_MEDIA_FORK, 
    3535       PJSIP_REQ_HAS_VIA_ALIAS, 
    36        PJSIP_RESOLVE_HOSTNAME_TO_GET_INTERFACE 
     36       PJSIP_RESOLVE_HOSTNAME_TO_GET_INTERFACE, 
     37       0 
    3738    }, 
    3839 
Note: See TracChangeset for help on using the changeset viewer.