X-Git-Url: http://git.asterisk.org/gitweb/?p=asterisk%2Fasterisk.git;a=blobdiff_plain;f=res%2Fres_srtp.c;h=a232314fae8a2d468492424964099f373fe943e9;hp=f92154f90ff17ebc9a90dda96cea65b287898ee5;hb=78b17e6d41e8bac9b65a0240b56ab3649547566c;hpb=920f5ea8b7ba39394b23037da82c92529b6b61a7;ds=sidebyside diff --git a/res/res_srtp.c b/res/res_srtp.c index f92154f..a232314 100644 --- a/res/res_srtp.c +++ b/res/res_srtp.c @@ -29,18 +29,11 @@ */ /*** MODULEINFO - srtp + srtp + core ***/ -/* The SIP channel will automatically use sdescriptions if received in a SDP offer, - and res_srtp is loaded. SRTP with sdescriptions key exchange can be activated - in outgoing offers by setting _SIPSRTP_CRYPTO=enable in extension.conf before executing Dial - - The dial fails if the callee doesn't support SRTP and sdescriptions. - - exten => 2345,1,Set(_SIPSRTP_CRYPTO=enable) - exten => 2345,2,Dial(SIP/1001) -*/ +/* See https://wiki.asterisk.org/wiki/display/AST/Secure+Calling */ #include "asterisk.h" @@ -61,7 +54,9 @@ struct ast_srtp { srtp_t session; const struct ast_srtp_cb *cb; void *data; + int warned; unsigned char buf[8192 + AST_FRIENDLY_OFFSET]; + unsigned char rtcpbuf[8192 + AST_FRIENDLY_OFFSET]; }; struct ast_srtp_policy { @@ -186,6 +181,8 @@ static struct ast_srtp *res_srtp_new(void) ast_free(srtp); return NULL; } + + srtp->warned = 1; return srtp; } @@ -322,8 +319,11 @@ static int ast_srtp_unprotect(struct ast_srtp *srtp, void *buf, int *len, int rt { int res = 0; int i; + int retry = 0; struct ast_rtp_instance_stats stats = {0,}; + tryagain: + for (i = 0; i < 2; i++) { res = rtcp ? srtp_unprotect_rtcp(srtp->session, buf, len) : srtp_unprotect(srtp->session, buf, len); if (res != err_status_no_ctx) { @@ -342,8 +342,57 @@ static int ast_srtp_unprotect(struct ast_srtp *srtp, void *buf, int *len, int rt } } + if (retry == 0 && res == err_status_replay_old) { + ast_log(LOG_WARNING, "SRTP unprotect: %s\n", srtp_errstr(res)); + + if (srtp->session) { + struct ast_srtp_policy *policy; + struct ao2_iterator it; + int policies_count = 0; + + // dealloc first + ast_log(LOG_WARNING, "SRTP destroy before re-create\n"); + srtp_dealloc(srtp->session); + + // get the count + policies_count = ao2_container_count(srtp->policies); + + // get the first to build up + it = ao2_iterator_init(srtp->policies, 0); + policy = ao2_iterator_next(&it); + + ast_log(LOG_WARNING, "SRTP try to re-create\n"); + if (srtp_create(&srtp->session, &policy->sp) == err_status_ok) { + ast_log(LOG_WARNING, "SRTP re-created with first policy\n"); + + // unref first element + ao2_t_ref(policy, -1, "Unreffing first policy for re-creating srtp session"); + + // if we have more than one policy, add them afterwards + if (policies_count > 1) { + ast_log(LOG_WARNING, "Add all the other %d policies\n", policies_count-1); + while ((policy = ao2_iterator_next(&it))) { + srtp_add_stream(srtp->session, &policy->sp); + ao2_t_ref(policy, -1, "Unreffing n-th policy for re-creating srtp session"); + } + } + + retry++; + ao2_iterator_destroy(&it); + goto tryagain; + } + ao2_iterator_destroy(&it); + } + } + if (res != err_status_ok && res != err_status_replay_fail ) { - ast_debug(1, "SRTP unprotect: %s\n", srtp_errstr(res)); + if ((srtp->warned >= 10) && !((srtp->warned - 10) % 100)) { + ast_log(LOG_WARNING, "SRTP unprotect: %s %d\n", srtp_errstr(res), srtp->warned); + srtp->warned = 11; + } else { + srtp->warned++; + } + errno = EAGAIN; return -1; } @@ -353,19 +402,22 @@ static int ast_srtp_unprotect(struct ast_srtp *srtp, void *buf, int *len, int rt static int ast_srtp_protect(struct ast_srtp *srtp, void **buf, int *len, int rtcp) { int res; + unsigned char *localbuf; if ((*len + SRTP_MAX_TRAILER_LEN) > sizeof(srtp->buf)) { return -1; } + + localbuf = rtcp ? srtp->rtcpbuf : srtp->buf; - memcpy(srtp->buf, *buf, *len); + memcpy(localbuf, *buf, *len); - if ((res = rtcp ? srtp_protect_rtcp(srtp->session, srtp->buf, len) : srtp_protect(srtp->session, srtp->buf, len)) != err_status_ok && res != err_status_replay_fail) { - ast_debug(1, "SRTP protect: %s\n", srtp_errstr(res)); + if ((res = rtcp ? srtp_protect_rtcp(srtp->session, localbuf, len) : srtp_protect(srtp->session, localbuf, len)) != err_status_ok && res != err_status_replay_fail) { + ast_log(LOG_WARNING, "SRTP protect: %s\n", srtp_errstr(res)); return -1; } - *buf = srtp->buf; + *buf = localbuf; return *len; } @@ -381,6 +433,7 @@ static int ast_srtp_create(struct ast_srtp **srtp, struct ast_rtp_instance *rtp, return -1; } + ast_module_ref(ast_module_info->self); temp->rtp = rtp; *srtp = temp; @@ -399,6 +452,7 @@ static void ast_srtp_destroy(struct ast_srtp *srtp) ao2_t_ref(srtp->policies, -1, "Destroying container"); ast_free(srtp); + ast_module_unref(ast_module_info->self); } static int ast_srtp_add_stream(struct ast_srtp *srtp, struct ast_srtp_policy *policy)