diff --git a/README.md b/README.md index 14456d226..cbceedc05 100644 --- a/README.md +++ b/README.md @@ -1264,6 +1264,24 @@ Optionally included keys are: will accepted, meanwhile no new is going to be generated by RTPEngine. It takes precedence over the `SDES-no` and `SDES-only` flags, if used in combination. + - `order:`*SUITES LIST* + + The order, in which crypto suites are being added to the SDP. + Example: `SDES-order:AES_256_CM_HMAC_SHA;AES_256_CM_HMAC_SHA1_32;AES_192_CM_HMAC_SHA1_80;`, + this means — those listed SDES crypto suites will be added into the generated SDP body at the top + of crypto suites list, in the given order. But, each of them is added, only if it is + about to be added/generated. In other words, the `SDES-order:` flag itself doesn't add crypto suites, + it just affects the order of those suites to be added. + + And the rest of non-mentioned suites (not mentioned in the `SDES-order:` list), + which are also to be added, will be appended after those given, in the free manner of ordering. + + Important thing to remember - it doesn't change the crypto suite tag + for the recipient, even though changing the order of them. + + This flag does not contradict with `SDES-nonew`, `SDES-only-` and `SDES-no-` flags. + It just orders the list of crypto suites already prepared to be sent out. + - `pad` RFC 4568 (section 6.1) is somewhat ambiguous regarding the base64 encoding format of diff --git a/daemon/call.c b/daemon/call.c index 1f4e0f5ea..ac7b49917 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -1686,8 +1686,12 @@ static void __generate_crypto(const struct sdp_ng_flags *flags, struct call_medi GQueue *cpq = &this->sdes_out; /* SDES options coming to us for processing */ GQueue *cpq_in = &this->sdes_in; + const GQueue *offered_cpq = other ? &other->sdes_in : NULL; + /* requested order of crypto suites */ + const GQueue *cpq_order = &flags->sdes_order; + if (!flags) return; @@ -1857,6 +1861,44 @@ static void __generate_crypto(const struct sdp_ng_flags *flags, struct call_medi __sdes_flags(cps, flags); } } + + /* order the crypto suites list before to send out, if needed */ + if (cpq_order && cpq_order->head) { + ilog(LOG_DEBUG, "The crypto suites in the outbound SDP will be re-ordered."); + + GQueue cpq_orig_list = *cpq; + g_queue_init(cpq); /* re-initialize sdes_out */ + + /* first add those mentioned in the order list, + * but only, if they were previously generated/added to the sdes_out */ + for (GList *l = cpq_order ? cpq_order->head : NULL; l; l = l->next) + { + str * cs_name = l->data; + struct crypto_params_sdes * cps_order; + + GList * elem = g_queue_find_custom(&cpq_orig_list, cs_name, crypto_params_sdes_cmp); + + if (!elem) + continue; + + cps_order = elem->data; + + ilog(LOG_DEBUG, "New suites order, adding: %s (cps tag: %d)", + cps_order->params.crypto_suite->name, cps_order->tag); + + g_queue_push_tail(cpq, cps_order); + g_queue_delete_link(&cpq_orig_list, elem); + } + + /* now add the rest */ + while ((cps_orig = g_queue_pop_head(&cpq_orig_list))) + { + ilog(LOG_DEBUG, "New suites order, adding: %s (cps tag: %d)", + cps_orig->params.crypto_suite->name, cps_orig->tag); + + g_queue_push_tail(cpq, cps_orig); + } + } } /* OP_ANSWER */ diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 90a509254..a9f8c801b 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -516,6 +516,10 @@ INLINE void ng_sdes_option(struct sdp_ng_flags *out, str *s, void *dummy) { if (call_ng_flags_prefix(out, s, "no-", call_ng_flags_str_ht, &out->sdes_no)) return; + /* Order individual crypto suites */ + if (call_ng_flags_prefix(out, s, "order:", call_ng_flags_str_q_multi, &out->sdes_order)) + return; + switch (__csh_lookup(s)) { case CSH_LOOKUP("no"): case CSH_LOOKUP("off"): @@ -958,6 +962,8 @@ static void call_ng_flags_flags(struct sdp_ng_flags *out, str *s, void *dummy) { return; if (call_ng_flags_prefix(out, s, "SDES-no-", call_ng_flags_str_ht, &out->sdes_no)) return; + if (call_ng_flags_prefix(out, s, "SDES-order:", call_ng_flags_str_q_multi, &out->sdes_order)) + return; if (call_ng_flags_prefix(out, s, "SDES-", ng_sdes_option, NULL)) return; if (call_ng_flags_prefix(out, s, "OSRTP-", ng_osrtp_option, NULL)) @@ -1592,6 +1598,7 @@ void call_ng_free_flags(struct sdp_ng_flags *flags) { g_queue_clear_full(&flags->codec_accept, free); g_queue_clear_full(&flags->codec_consume, free); g_queue_clear_full(&flags->codec_mask, free); + g_queue_clear_full(&flags->sdes_order, free); } static enum load_limit_reasons call_offer_session_limit(void) { diff --git a/include/call_interfaces.h b/include/call_interfaces.h index 4968bbf16..9fa577d69 100644 --- a/include/call_interfaces.h +++ b/include/call_interfaces.h @@ -55,6 +55,7 @@ struct sdp_ng_flags { rev_ptime; GHashTable *sdes_no; /* individual crypto suites which are excluded */ GHashTable *sdes_only; /* individual crypto suites which are only accepted */ + GQueue sdes_order; /* the order, in which crypto suites are being added to the SDP */ str dtls_fingerprint; enum { ICE_DEFAULT = 0, diff --git a/t/auto-daemon-tests.pl b/t/auto-daemon-tests.pl index e077a6213..9f61ffca5 100755 --- a/t/auto-daemon-tests.pl +++ b/t/auto-daemon-tests.pl @@ -14261,6 +14261,226 @@ a=rtcp:PORT a=crypto:1 AES_CM_128_HMAC_SHA1_32 inline:CRYPTO128 SDP +new_call; + +offer('SDES re-ordered crypto suites', { ICE => 'remove', DTLS => 'off', SDES => [ 'order:AES_256_CM_HMAC_SHA1_32;AES_256_CM_HMAC_SHA1_80;AES_CM_128_HMAC_SHA1_32;AES_CM_128_HMAC_SHA1_80' ] }, < 'remove' }, < 'remove', DTLS => 'off', SDES => [ 'nonew', 'order:AES_256_CM_HMAC_SHA1_32;AES_256_CM_HMAC_SHA1_80;AES_CM_128_HMAC_SHA1_32;AES_CM_128_HMAC_SHA1_80' ] }, < 'remove' }, < 'remove', DTLS => 'off', SDES => [ 'no-AES_CM_128_HMAC_SHA1_32', 'order:AES_256_CM_HMAC_SHA1_32;AES_256_CM_HMAC_SHA1_80;AES_CM_128_HMAC_SHA1_80' ] }, < 'remove' }, < 'remove', DTLS => 'off', SDES => [ 'only-AES_256_CM_HMAC_SHA1_32', 'order:AES_256_CM_HMAC_SHA1_32;AES_256_CM_HMAC_SHA1_80;AES_CM_128_HMAC_SHA1_32;AES_CM_128_HMAC_SHA1_80' ] }, < 'remove' }, <