On 02.09.19 at 19:03 Michael Maier wrote: > On 30.05.19 at 10:24 Michael Maier wrote: >> Hello! >> >> I wrote some code, which adds basic media encryption support to be used with >> Deutsche Telekom. The attached patch is based on Asterisk 16.3 >> and works for me :-) - not fully tested yet. If you want to use it, you have >> to enable media_encryption=sdes for the extension (and >> transport tls and tls1.2). Use at your own risk! >> >> >> The current patch lacks a basic mediasec option, which prevents adding the >> mediasec headers to each *initial* REGISTER or to each INVITE (if >> sdes is activated). As of today, I don't know how to solve this problem >> without too much changes. >> Anyway: It looks like the additional HEADERs seem not to disrupt other ISPs >> (tested with one other ISP). This option should be accessible in >> rtp, session and register environment. Maybe there is a possibility to >> exchange data between register, session and rtp environment. This way, it >> would be possible to dynamically set mediasec in session and rtp based on >> the result of the initial register. It would be necessary at the >> same time, to dynamically disable sdes encryption if activation of mediasec >> didn't succeed. >> >> One more open point is the check for the 3 headers using the same name >> (Security-Server and Security-Verify). How can they be checked >> regarding order? Is there a function to get each value of the same header? >> Maybe based on an array index? This way it would be possible to >> create the Security-Verify headers dynamically based on the 494 or 401 >> response. >> >> The UPDATE package (used as a watchdog circuit during a call each 15 >> minutes) seems not to be affected - I couldn't find any problem at this >> point. > > Attached is a new version of the mediasec patch. The following items changed:
The patch now contains too mediasec on ReINVITES initiated by our selves. Regards Michael
diff -urN asterisk-16.5.0/res/res_pjsip/pjsip_options.c asterisk-16.5.0.new/res/res_pjsip/pjsip_options.c --- a/res/res_pjsip/pjsip_options.c 2019-07-25 11:38:14.000000000 +0200 +++ b/res/res_pjsip/pjsip_options.c 2019-08-31 12:59:33.399000000 +0200 @@ -212,6 +212,8 @@ */ static struct ast_taskprocessor *management_serializer; +static int sip_options_qualify_contact(void *obj, void *arg, int flags); + static pj_status_t send_options_response(pjsip_rx_data *rdata, int code) { pjsip_endpoint *endpt = ast_sip_get_pjsip_endpoint(); @@ -801,6 +803,15 @@ break; } + /* check for 494 */ + if (status == AVAILABLE && e->body.tsx_state.src.rdata->msg_info.msg->line.status.code == 494) { + /* need to resend the options request with mediasec headers */ + ast_debug(3,"detected 494 - call sip_options_qualify_contact again with mediasec header\n"); + sip_options_qualify_contact(contact_callback_data->contact, contact_callback_data->aor_options, 494); + ao2_ref(contact_callback_data, -1); + return; + } + /* Update the callback data with the new status, this will get handled in the AOR serializer */ contact_callback_data->status = status; @@ -905,6 +916,14 @@ return 0; } + if (flags && flags == 494) { + /* add mediasec header */ + ast_debug(3,"OPTIONS: adding MEDIASEC headers\n"); + ast_sip_add_header(tdata,"Security-Verify","msrp-tls;mediasec"); + ast_sip_add_header(tdata,"Security-Verify","sdes-srtp;mediasec"); + ast_sip_add_header(tdata,"Security-Verify","dtls-srtp;mediasec"); + } + if (ast_sip_send_out_of_dialog_request(tdata, endpoint, (int)(aor_options->qualify_timeout * 1000), contact_callback_data, qualify_contact_cb)) { diff -urN a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c --- a/res/res_pjsip_outbound_registration.c 2019-07-25 11:38:14.000000000 +0200 +++ b/res/res_pjsip_outbound_registration.c 2019-09-02 15:07:27.383000000 +0200 @@ -361,6 +361,8 @@ char *transport_name; /*! \brief The name of the registration sorcery object */ char *registration_name; + /*! \brief Indicator, if there was a 494 response before */ + unsigned int is494; }; /*! \brief Outbound registration state information (persists for lifetime that registration should exist) */ @@ -597,6 +599,19 @@ pj_strassign(&hdr->values[hdr->count++], &PATH_NAME); } + /* Add some header for mediasec */ + if (client_state->is494) { + /* answer for 494 */ + ast_sip_add_header(tdata,"Security-Verify","msrp-tls;mediasec"); + ast_sip_add_header(tdata,"Security-Verify","sdes-srtp;mediasec"); + ast_sip_add_header(tdata,"Security-Verify","dtls-srtp;mediasec"); + } + else { + ast_sip_add_header(tdata,"Security-Client","sdes-srtp;mediasec"); + ast_sip_add_header(tdata,"Proxy-Require","mediasec"); + ast_sip_add_header(tdata,"Require","mediasec"); + } + registration_client_send(client_state, tdata); return 0; @@ -917,6 +932,27 @@ response->client_state->auth_attempted = 1; ast_debug(1, "Sending authenticated REGISTER to server '%s' from client '%s'\n", server_uri, client_uri); + + /* Add MEDIASEC headers */ + static const pj_str_t headerName = { "Security-Server", 15 }; + pjsip_generic_string_hdr *secSrv; + secSrv = pjsip_msg_find_hdr_by_name(response->rdata->msg_info.msg, &headerName, NULL); + if (secSrv) { + response->client_state->is494=0; + + static const pj_str_t headerNameVrfy = { "Security-Verify", 15 }; + pjsip_generic_string_hdr *secVrfy; + secVrfy = pjsip_msg_find_hdr_by_name(tdata->msg, &headerNameVrfy, NULL); + + /* initial register doesn't contain it */ + if (! secVrfy) { + ast_debug(3, "Adding MEDIASEC headers\n"); + ast_sip_add_header(tdata,"Security-Verify","msrp-tls;mediasec"); + ast_sip_add_header(tdata,"Security-Verify","sdes-srtp;mediasec"); + ast_sip_add_header(tdata,"Security-Verify","dtls-srtp;mediasec"); + } + } + pjsip_tx_data_add_ref(tdata); res = registration_client_send(response->client_state, tdata); @@ -943,6 +979,8 @@ if (response->expiration) { int next_registration_round; + response->client_state->is494=0; + /* If the registration went fine simply reschedule registration for the future */ ast_debug(1, "Outbound registration to '%s' with client '%s' successful\n", server_uri, client_uri); update_client_state_status(response->client_state, SIP_REGISTRATION_REGISTERED); @@ -959,6 +997,8 @@ response->client_state->registration_name); } else { ast_debug(1, "Outbound unregistration to '%s' with client '%s' successful\n", server_uri, client_uri); + response->client_state->is494=0; + update_client_state_status(response->client_state, SIP_REGISTRATION_UNREGISTERED); ast_sip_transport_monitor_unregister(response->rdata->tp_info.transport, registration_transport_shutdown_cb, response->client_state->registration_name, @@ -966,6 +1006,22 @@ } } else if (response->client_state->destroy) { /* We need to deal with the pending destruction instead. */ + } else if (response->code == 494) { + if (response->client_state->is494) { + ast_log(LOG_WARNING, "MEDIASEC registration to '%s' with client '%s' failed (494-loop detected), stopping registration attempt\n", + server_uri, client_uri); + /* 494 loop detected! This is fatal! */ + update_client_state_status(response->client_state, SIP_REGISTRATION_REJECTED_PERMANENT); + /* reset is494 */ + response->client_state->is494=0; + } else { + /* Try (initial) registration again - but now with additional headers */ + response->client_state->is494=1; + ao2_ref(response->client_state, +1); + handle_client_registration(response->client_state); + ao2_ref(response, -1); + return 0; + } } else if (response->retry_after) { /* If we have been instructed to retry after a period of time, schedule it as such */ schedule_retry(response, response->retry_after, server_uri, client_uri); diff -urN a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c --- a/res/res_pjsip_sdp_rtp.c 2019-07-25 11:38:14.000000000 +0200 +++ b/res/res_pjsip_sdp_rtp.c 2019-08-27 21:12:34.183000000 +0200 @@ -1429,6 +1429,7 @@ static const pj_str_t STR_PASSIVE = { "passive", 7 }; static const pj_str_t STR_ACTPASS = { "actpass", 7 }; static const pj_str_t STR_HOLDCONN = { "holdconn", 8 }; + static const pj_str_t STR_MEDSECREQ = { "requested", 9 }; enum ast_rtp_dtls_setup setup; switch (session_media->encryption) { @@ -1444,6 +1445,8 @@ } tmp = session_media->srtp; + attr = pjmedia_sdp_attr_create(pool, "3ge2ae", &STR_MEDSECREQ); + media->attr[media->attr_count++] = attr; do { crypto_attribute = ast_sdp_srtp_get_attrib(tmp, diff -urN a/res/res_pjsip_session.c b/res/res_pjsip_session.c --- a/res/res_pjsip_session.c 2019-07-25 11:38:14.000000000 +0200 +++ b/res/res_pjsip_session.c 2019-09-02 21:07:13.437000000 +0200 @@ -1760,6 +1760,14 @@ ast_debug(3, "Sending session refresh SDP via %s to %s\n", method == AST_SIP_SESSION_REFRESH_METHOD_INVITE ? "re-INVITE" : "UPDATE", ast_sorcery_object_get_id(session->endpoint)); + + if (session->endpoint->media.rtp.encryption == AST_SIP_MEDIA_ENCRYPT_SDES) { + ast_debug(3, "ReINVITE: Adding MEDIASEC headers\n"); + ast_sip_add_header(tdata,"Security-Verify","msrp-tls;mediasec"); + ast_sip_add_header(tdata,"Security-Verify","sdes-srtp;mediasec"); + ast_sip_add_header(tdata,"Security-Verify","dtls-srtp;mediasec"); + } + ast_sip_session_send_request_with_cb(session, tdata, on_response); return 0; } @@ -2109,6 +2117,13 @@ return -1; } + if (session->endpoint->media.rtp.encryption == AST_SIP_MEDIA_ENCRYPT_SDES) { + ast_debug(3, "INVITE: Adding MEDIASEC headers\n"); + ast_sip_add_header(*tdata,"Security-Verify","msrp-tls;mediasec"); + ast_sip_add_header(*tdata,"Security-Verify","sdes-srtp;mediasec"); + ast_sip_add_header(*tdata,"Security-Verify","dtls-srtp;mediasec"); + } + return 0; }
-- _____________________________________________________________________ -- Bandwidth and Colocation Provided by http://www.api-digital.com -- asterisk-dev mailing list To UNSUBSCRIBE or update options visit: http://lists.digium.com/mailman/listinfo/asterisk-dev