RFC 3329 and mediasec implementation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


Hi all,

I'm implementing client-initiated mediasec negotiation[2] with partial RFC 3329[1] support in the PJSIP library. My target application uses the PJSUA interface. This is still at an early stage and since I'd like to upstream this change I think it's best to start a discussion about the approach and get your views on it.

Outline of expected behaviour:
1) In initial REGISTER message, set the following headers:
Require: mediasec
Proxy-Require: mediasec
Security-Client: sdes-srtp; mediasec // A separate header for every supported mechanism. At least one mechanism must be enabled for the build.
* We refer to this set of headers as the "mediasec initial headers"
2) Server responds with 401 Unauthorised and a set of Security-Server headers:
Security-Server: msrp-tls;mediasec
Security-Server: sdes-srtp;mediasec
Security-Server: dtls-srtp;mediasec
* We refer to this set of headers as the "mediasec server headers"
These headers must be stored for this session. The client must send these to the server as Security-Verify headers in every request message for this session.
** If the Server does not send the Security-Server headers in the REGISTER response, registration is aborted.
3) client responds to 401 Unauthorised message as usual and also adds the following headers (the saved Security-Server headers are sent back as Security-Verify headers):
Require: mediasec
Proxy-Require: mediasec
Security-Client: sdes-srtp; mediasec
Security-Verify: msrp-tls;mediasec
Security-Verify: sdes-srtp;mediasec
Security-Verify: dtls-srtp;mediasec
* We refer to this set of headers as the "mediasec verification headers"
4) Server responds with 200 OK
5) client sends INVITE request with the mediasec verification headers and sets an additional SDP attribute:
6) Server responds with 200 OK
7) Any further SIP Request messages must also include the mediasec verification headers.

Outline of code changes:
I will send an update if I come across alternative implementation ideas. Please let me know if the following looks like the correct way to proceed.
1) Inserting the mediasec headers
sip_auth_client.c: pjsip_auth_clt_init_req() looks like the right place for this. I inserted some test headers and they appear in all requests.

/* Initialize outgoing request. */
PJ_DEF(pj_status_t) pjsip_auth_clt_init_req( pjsip_auth_clt_sess *sess,
                         pjsip_tx_data *tdata )
                    pj_strdup(tdata->pool,&hs->credential.digest.uri, &uri);
                    pj_strdup(tdata->pool, &hs->credential.digest.algorithm,
                pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hs);
 +   pjsip_hdr hdr_list;
 +   pj_list_init(&hdr_list);
 +   pjsip_generic_string_hdr *tmp_hdr;
 +   const pj_str_t STR_PROXY_REQ = { "Proxy-Require", 13 };
 +   pj_str_t security_proxy_req_val = { "mediasec", 8 };
 +   tmp_hdr = pjsip_generic_string_hdr_create(tdata->pool, &STR_PROXY_REQ,
 +                                       &security_proxy_req_val);
 +   pj_list_push_back(&hdr_list, (pjsip_hdr*)tmp_hdr);
 +   const pj_str_t STR_REQ = { "Require", 7 };
 +   pj_str_t security_req_val = { "mediasec", 8 };
 +   tmp_hdr = pjsip_generic_string_hdr_create(tdata->pool, &STR_REQ,
 +                                       &security_req_val);
 +   pj_list_push_back(&hdr_list, (pjsip_hdr*)tmp_hdr);
 +   const pj_str_t STR_SECURITY_CLIENT = { "Security-Client", 15 };
 +   pj_str_t security_client_val = { "sdes-srtp;mediasec", 18 };
 +   tmp_hdr = pjsip_generic_string_hdr_create(tdata->pool, &STR_SECURITY_CLIENT,
 +                                       &security_client_val);
 +   pj_list_push_back(&hdr_list, (pjsip_hdr*)tmp_hdr);
 +   pjsip_hdr *hdr = hdr_list.next;
 +   while (hdr != &hdr_list) {
 +       pjsip_hdr *next = hdr->next;
 +       pjsip_msg_add_hdr(tdata->msg, hdr);
 +       hdr = next;
 +   }

    return PJ_SUCCESS;

2) Pass in a list of security negotiation parameters to pjsip_auth_clt_init_req() that need to be added to SIP requests (instead of hardcoded values in the above test code)
This can be done by adding a new data member to struct pjsip_auth_clt_sess in sip_auth.h of type struct pjsip_security_neg {pj_str_t security_param_list; pj_str_t security_client_list; pj_str_t security_server_list;}

3) Initialise auth_clt_sess.security_neg to send the "mediasec initial headers"
This can be done in pjsua_ac.c: pjsua_acc_set_registration()

4) New parameters to enable/disable the features
pjsua_ac.c: pjsua_acc_set_registration() should only add the headers if the application has enabled the feature.
RFC 3329 first hop security negotiation is a separate feature that may be fully implemented if needed by someone else in the future. The mediasec feature works as an extension to RFC 3329. Therefore these features must have separate flags to enable/disable.
struct pjsua_acc_config in pjsua.h can be extended to add two new fields:
    pjsua_acc_config.use_first_hop_security_neg = PJ_TRUE
    //enables rfc 3329 first hop security negotiation
    pjsua_acc_config.use_srtp_mediasec = PJMEDIA_SRTP_MEDIASEC_ENABLE;
    //enables mediasec support for SRTP. Requires use_first_hop_security_neg = PJ_TRUE.

These can be used to set similarly named members in struct pjsua_acc in pjsua_acc.c: pjsua_acc_add()

In (3) above, pjsua_acc_set_registration() will then have access to these parameters to check if the security negotiation headers need to be added.

5) Update pjsip_auth_clt_sess.pjsip_security_neg.security_server_list when client receives the Security-Server headers in a 401 Unauthorized message from the server.
So far, the client is set up to only send the "mediasec initial headers" in all SIP request messages. To create the set of "mediasec verification headers" pjsip_auth_clt_sess.pjsip_security_neg.security_server_list must be updated.

I'm still working on this and will send another update for that. The options I'm exploring include implementing Security-Server header parsing in sip_parser.c and adding it to a new field in struct pjsip_rx_data; or extracting the info from pjsip_rx_data.msg in pjsip_auth_clt_reinit_req().

6) Instantiate the media plane security mechanism based on the client and server side mediasec parameters. Add support sdes-srtp only for now.

7) In the INVITE message, add attribute "a=3ge2ae:requested" to the SDP attributes
This can be done in sdp.c: print_session() based on some flags set in struct pjmedia_sdp_session to indicate mediasec support.

PJSIP must be built with
#   define PJMEDIA_HAS_SRTP                1
// At least one out of SDES or DTLS support:
#   define PJMEDIA_SRTP_HAS_SDES            1
#   define PJMEDIA_SRTP_HAS_DTLS            1

[1] https://tools.ietf.org/html/rfc3329
[2] https://tools.ietf.org/html/draft-dawes-dispatch-mediasec-parameter-07

Visit our blog: http://blog.pjsip.org

pjsip mailing list

[Index of Archives]     [Asterisk Users]     [Asterisk App Development]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [Linux API]
  Powered by Linux