AST_MAJOR_VERSION:=16
PKG_NAME:=asterisk$(AST_MAJOR_VERSION)
-PKG_VERSION:=$(AST_MAJOR_VERSION).3.0
-PKG_RELEASE:=9
+PKG_VERSION:=$(AST_MAJOR_VERSION).22.0
+PKG_RELEASE:=1
PKG_SOURCE:=asterisk-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://downloads.asterisk.org/pub/telephony/asterisk/releases
-PKG_HASH:=8b22ee7c0c0b5557eff273118703c6fce8b743c12bbeb679ed86b3f197444a8e
+PKG_HASH:=46992482762818e096d92654b9ac96d42fa9505ad4bc8e628a683413793ab26f
PKG_BUILD_DIR:=$(BUILD_DIR)/asterisk-$(PKG_VERSION)
PKG_BUILD_DEPENDS:=libxml2/host
app-agent-pool \
app-alarmreceiver \
app-amd \
+ app-attended-transfer \
app-authenticate \
+ app-blind-transfer \
app-bridgeaddchan \
app-bridgewait \
app-celgenuserevent \
app-directed-pickup \
app-directory \
app-disa \
+ app-dtmfstore \
app-dumpchan \
app-exec \
app-externalivr \
app-ices \
app-image \
app-ivrdemo \
+ app-mf \
app-milliwatt \
app-minivm \
app-mixmonitor \
app-read \
app-readexten \
app-record \
+ app-reload \
app-saycounted \
app-sayunixtime \
app-senddtmf \
app-url \
app-userevent \
app-verbose \
+ app-waitforcond \
app-waitforring \
app-waitforsilence \
app-waituntil \
func-enum \
func-env \
func-extstate \
+ func-frame-drop \
func-frame-trace \
func-global \
func-groupcount \
func-presencestate \
func-rand \
func-realtime \
+ func-sayfiles \
+ func-scramble \
func-sha1 \
func-shell \
func-sorcery \
res-parking \
res-phoneprov \
res-pjsip-phoneprov \
+ res-pjsip-stir-shaken \
res-pjproject \
res-pktccops \
res-realtime \
res-stasis-recording \
res-stasis-snoop \
res-statsd \
+ res-stir-shaken \
res-stun-monitor \
res-timing-dahdi \
res-timing-pthread \
- res-timing-timerfd \
+ res-tonedetect \
res-xmpp \
voicemail
AST_EMB_MODULES:=\
app_dial app_echo app_macro app_playback \
func_callerid func_logic func_strings func_timeout \
- pbx_config res_crypto
+ pbx_config res_crypto res_timing_timerfd
define Package/$(PKG_NAME)/install
$(call Package/$(PKG_NAME)/install/lib,$(1),libasteriskssl)
$(eval $(call BuildAsteriskModule,app-agent-pool,Call center agent pool,Call center agent pool applications.,,agents.conf,app_agent_pool,,))
$(eval $(call BuildAsteriskModule,app-alarmreceiver,Alarm receiver,Alarm receiver for Asterisk.,,,app_alarmreceiver,,))
$(eval $(call BuildAsteriskModule,app-amd,Answering machine detection,Answering Machine Detection application.,,amd.conf,app_amd,,))
+$(eval $(call BuildAsteriskModule,app-attended-transfer,Attended transfer,Queues up an attended transfer to a given extension.,,,app_attended_transfer,,))
$(eval $(call BuildAsteriskModule,app-authenticate,Authenticate commands,Authentication application.,,,app_authenticate,,))
+$(eval $(call BuildAsteriskModule,app-blind-transfer,Blind transfer,Redirects all channels currently bridged to the caller channel to a specified destination.,,,app_blind_transfer,,))
$(eval $(call BuildAsteriskModule,app-bridgeaddchan,Bridge add channel,Bridge-add-channel application.,,,app_bridgeaddchan,,))
$(eval $(call BuildAsteriskModule,app-bridgewait,Holding bridge,Application to place a channel into a holding bridge.,+$(PKG_NAME)-bridge-holding,,app_bridgewait,,))
$(eval $(call BuildAsteriskModule,app-celgenuserevent,User-defined CEL event,Generate a user defined CEL event.,,,app_celgenuserevent,,))
$(eval $(call BuildAsteriskModule,app-directed-pickup,Directed call pickup,Directed call pickup application.,,,app_directed_pickup,,))
$(eval $(call BuildAsteriskModule,app-directory,Extension directory,Extension directory.,,,app_directory,,))
$(eval $(call BuildAsteriskModule,app-disa,Direct Inward System Access,Direct Inward System Access application.,,,app_disa,,))
+$(eval $(call BuildAsteriskModule,app-dtmfstore,DTMF storage,Technology independent async DTMF storage.,,,app_dtmfstore,,))
$(eval $(call BuildAsteriskModule,app-dumpchan,Dump info about channel,Dump info about the calling channel.,,,app_dumpchan,,))
$(eval $(call BuildAsteriskModule,app-exec,Exec application,Executes dialplan applications.,,,app_exec,,))
$(eval $(call BuildAsteriskModule,app-externalivr,External IVR interface,External IVR interface application.,,,app_externalivr,,))
$(eval $(call BuildAsteriskModule,app-festival,Simple festival interface,Simple Festival interface.,,festival.conf,app_festival,,))
$(eval $(call BuildAsteriskModule,app-flash,Flash channel,Flash channel application.,+$(PKG_NAME)-chan-dahdi,,app_flash,,))
$(eval $(call BuildAsteriskModule,app-followme,Find-me/follow-me,Find-Me/Follow-Me application.,,followme.conf,app_followme,,))
-$(eval $(call BuildAsteriskModule,app-getcpeid,Get ADSI CPE ID,Get ADSI CPE ID.,,,app_getcpeid,,))
+$(eval $(call BuildAsteriskModule,app-getcpeid,Get ADSI CPE ID,Get ADSI CPE ID.,+$(PKG_NAME)-res-adsi,,app_getcpeid,,))
$(eval $(call BuildAsteriskModule,app-ices,Encode and stream,Encode and stream via Icecast and IceS.,,,app_ices,,))
$(eval $(call BuildAsteriskModule,app-image,Image transmission,Image transmission application.,,,app_image,,))
$(eval $(call BuildAsteriskModule,app-ivrdemo,IVR demo,IVR demo application.,,,app_ivrdemo,,))
+$(eval $(call BuildAsteriskModule,app-mf,MF digits,Send MF digits Application.,,,app_mf,,))
$(eval $(call BuildAsteriskModule,app-milliwatt,Digital milliwatt [mu-law] test app,Digital milliwatt test application.,,,app_milliwatt,,))
$(eval $(call BuildAsteriskModule,app-minivm,Minimal voicemail system,A minimal voicemail e-mail system.,,extensions_minivm.conf minivm.conf,app_minivm,,))
$(eval $(call BuildAsteriskModule,app-mixmonitor,Record a call and mix the audio,Mixed audio monitoring application.,,,app_mixmonitor,,))
$(eval $(call BuildAsteriskModule,app-read,Variable read,Read variable application.,,,app_read,,))
$(eval $(call BuildAsteriskModule,app-readexten,Extension to variable,Read and evaluate extension validity.,,,app_readexten,,))
$(eval $(call BuildAsteriskModule,app-record,Record sound file,Trivial record application.,,,app_record,,))
+$(eval $(call BuildAsteriskModule,app-reload,Reload,Reload module[s].,,,app_reload,,))
$(eval $(call BuildAsteriskModule,app-saycounted,Decline words,Decline words according to channel language.,,,app_saycounted,,))
$(eval $(call BuildAsteriskModule,app-sayunixtime,Say Unix time,Say time.,,,app_sayunixtime,,))
$(eval $(call BuildAsteriskModule,app-senddtmf,Send DTMF digits,Send DTMF digits application.,,,app_senddtmf,,))
$(eval $(call BuildAsteriskModule,app-url,Send URL,Send URL applications.,,,app_url,,))
$(eval $(call BuildAsteriskModule,app-userevent,Custom user event,Custom user event application.,,,app_userevent,,))
$(eval $(call BuildAsteriskModule,app-verbose,Verbose logging,Send verbose output.,,,app_verbose,,))
+$(eval $(call BuildAsteriskModule,app-waitforcond,Wait for condition,Wait until condition is true.,,,app_waitforcond,,))
$(eval $(call BuildAsteriskModule,app-waitforring,Wait for first ring,Waits until first ring after time.,,,app_waitforring,,))
$(eval $(call BuildAsteriskModule,app-waitforsilence,Wait for silence/noise,Wait for silence/noise.,,,app_waitforsilence,,))
$(eval $(call BuildAsteriskModule,app-waituntil,Sleep,Wait until specified time.,,,app_waituntil,,))
$(eval $(call BuildAsteriskModule,chan-bridge-media,Bridge media channel driver,Bridge media channel driver.,,,chan_bridge_media,,))
$(eval $(call BuildAsteriskModule,chan-console,Console channel driver,Console channel driver.,+portaudio,console.conf,chan_console,,))
$(eval $(call BuildAsteriskModule,chan-dahdi,DAHDI channel,DAHDI telephony.,+dahdi-tools-libtonezone +kmod-dahdi +libpri @!aarch64,chan_dahdi.conf,chan_dahdi,,))
-$(eval $(call BuildAsteriskModule,chan-iax2,IAX2 channel,Inter Asterisk eXchange.,+$(PKG_NAME)-res-timing-timerfd,iax.conf iaxprov.conf,chan_iax2,,))
+$(eval $(call BuildAsteriskModule,chan-iax2,IAX2 channel,Inter Asterisk eXchange.,,iax.conf iaxprov.conf,chan_iax2,,))
$(eval $(call BuildAsteriskModule,chan-mgcp,MGCP,Media Gateway Control Protocol.,,mgcp.conf,chan_mgcp,,))
$(eval $(call BuildAsteriskModule,chan-mobile,Bluetooth channel,Bluetooth mobile device channel driver.,+bluez-libs,chan_mobile.conf,chan_mobile,,))
$(eval $(call BuildAsteriskModule,chan-motif,Jingle channel,Motif Jingle channel driver.,+$(PKG_NAME)-res-xmpp,motif.conf,chan_motif,,))
$(eval $(call BuildAsteriskModule,chan-ooh323,H.323 channel,Objective Systems H.323 channel.,,ooh323.conf,chan_ooh323,,))
$(eval $(call BuildAsteriskModule,chan-oss,OSS channel,OSS console channel driver.,,oss.conf,chan_oss,,))
$(eval $(call BuildAsteriskModule,chan-phone,Linux telephony API,Linux telephony API support.,,phone.conf,chan_phone,,))
-$(eval $(call BuildAsteriskModule,chan-rtp,RTP media channel,RTP media channel.,,,chan_rtp,,))
+$(eval $(call BuildAsteriskModule,chan-rtp,RTP media channel,RTP media channel.,+$(PKG_NAME)-res-rtp-multicast,,chan_rtp,,))
$(eval $(call BuildAsteriskModule,chan-sip,SIP channel,Session Initiation Protocol.,+$(PKG_NAME)-app-confbridge,sip.conf sip_notify.conf,chan_sip,,))
$(eval $(call BuildAsteriskModule,chan-skinny,Skinny channel,Skinny Client Control Protocol.,,skinny.conf,chan_skinny,,))
$(eval $(call BuildAsteriskModule,chan-unistim,Unistim channel,UNISTIM protocol.,,unistim.conf,chan_unistim,,))
$(eval $(call BuildAsteriskModule,func-enum,ENUM,ENUM related dialplan functions.,,enum.conf,func_enum,,))
$(eval $(call BuildAsteriskModule,func-env,Environment functions,Environment/filesystem dialplan functions.,,,func_env,,))
$(eval $(call BuildAsteriskModule,func-extstate,Hinted extension state,Gets the state of an extension in the dialplan.,,,func_extstate,,))
+$(eval $(call BuildAsteriskModule,func-frame-drop,Frame drop,Function to drop frames on a channel.,,,func_frame_drop,,))
$(eval $(call BuildAsteriskModule,func-frame-trace,Frame trace for internal ast_frame debugging,Frame trace for internal ast_frame debugging.,,,func_frame_trace,,))
$(eval $(call BuildAsteriskModule,func-global,Global variable,Variable dialplan functions.,,,func_global,,))
$(eval $(call BuildAsteriskModule,func-groupcount,Group count,Channel group dialplan functions.,,,func_groupcount,,))
$(eval $(call BuildAsteriskModule,func-presencestate,Hinted presence state,Gets or sets a presence state in the dialplan.,,,func_presencestate,,))
$(eval $(call BuildAsteriskModule,func-rand,RAND dialplan function,Random number dialplan function.,,,func_rand,,))
$(eval $(call BuildAsteriskModule,func-realtime,REALTIME dialplan function,Read/write/store/destroy values from a realtime repository.,,,func_realtime,,))
+$(eval $(call BuildAsteriskModule,func-sayfiles,Say files,Say application files.,,,func_sayfiles,,))
+$(eval $(call BuildAsteriskModule,func-scramble,Scramble,Frequency inverting voice scrambler.,,,func_scramble,,))
$(eval $(call BuildAsteriskModule,func-sha1,SHA-1 computation dialplan function,SHA-1 computation dialplan function.,,,func_sha1,,))
$(eval $(call BuildAsteriskModule,func-shell,Shell,Collects the output generated by a command executed by the system shell.,,,func_shell,,))
$(eval $(call BuildAsteriskModule,func-sorcery,Get a field from a sorcery object,Get a field from a sorcery object.,,,func_sorcery,,))
$(eval $(call BuildAsteriskModule,res-hep-pjsip,PJSIP HEPv3 Logger,PJSIP HEPv3 logger.,+$(PKG_NAME)-res-hep +$(PKG_NAME)-pjsip,,res_hep_pjsip,,))
$(eval $(call BuildAsteriskModule,res-hep-rtcp,RTCP HEPv3 Logger,RTCP HEPv3 logger.,+$(PKG_NAME)-res-hep,,res_hep_rtcp,,))
$(eval $(call BuildAsteriskModule,res-fax-spandsp,Spandsp T.38 and G.711,Spandsp G.711 and T.38 FAX technologies.,+$(PKG_NAME)-res-fax +libspandsp +libtiff,,res_fax_spandsp,,))
-$(eval $(call BuildAsteriskModule,res-fax,FAX modules,Generic FAX applications.,+$(PKG_NAME)-res-timing-pthread,res_fax.conf,res_fax,,))
+$(eval $(call BuildAsteriskModule,res-fax,FAX modules,Generic FAX applications.,,res_fax.conf,res_fax,,))
$(eval $(call BuildAsteriskModule,res-format-attr-celt,CELT format attribute module,CELT format attribute module.,,,res_format_attr_celt,,))
$(eval $(call BuildAsteriskModule,res-format-attr-g729,G.729 format attribute module,G.729 format attribute module.,,,res_format_attr_g729,,))
$(eval $(call BuildAsteriskModule,res-format-attr-h263,H.263 format attribute module,H.263 format attribute module.,,,res_format_attr_h263,,))
$(eval $(call BuildAsteriskModule,res-mwi-external-ami,AMI for external MWI,AMI support for external MWI.,+$(PKG_NAME)-res-mwi-external,,res_mwi_external_ami,,))
$(eval $(call BuildAsteriskModule,res-parking,Phone Parking,Call parking resource.,+$(PKG_NAME)-bridge-holding,res_parking.conf,res_parking,,))
$(eval $(call BuildAsteriskModule,res-phoneprov,Phone Provisioning,HTTP phone provisioning.,,phoneprov.conf,res_phoneprov,,))
+$(eval $(call BuildAsteriskModule,res-pjsip-stir-shaken,PJSIP STIR/SHAKEN resource,PJSIP STIR/SHAKEN resource module.,+$(PKG_NAME)-pjsip +$(PKG_NAME)-res-stir-shaken,,res_pjsip_stir_shaken,,))
$(eval $(call BuildAsteriskModule,res-pjsip-phoneprov,PJSIP Phone Provisioning,PJSIP phone provisioning.,+$(PKG_NAME)-pjsip +$(PKG_NAME)-res-phoneprov,,res_pjsip_phoneprov_provider,,))
-$(eval $(call BuildAsteriskModule,res-pjproject,Bridge PJPROJECT to Asterisk logging,PJProject log and utility support.,+libpj +libpjlib-util +libpjmedia +libpjmedia +libpjnath +libpjsip-simple +libpjsip-ua +libpjsip +libpjsua +libpjsua2 +libsrtp2,pjproject.conf,res_pjproject,,))
+$(eval $(call BuildAsteriskModule,res-pjproject,Bridge PJPROJECT to Asterisk logging,PJProject log and utility support.,+libpj +libpjlib-util +libpjmedia +libpjmedia +libpjnath +libpjsip-simple +libpjsip-ua +libpjsip +libpjsua +libpjsua2 +libsrtp2 +$(PKG_NAME)-res-sorcery,pjproject.conf,res_pjproject,,))
$(eval $(call BuildAsteriskModule,res-pktccops,PktcCOPS manager for MGCP,PktcCOPS manager for MGCP.,,res_pktccops.conf,res_pktccops,,))
$(eval $(call BuildAsteriskModule,res-realtime,RealTime CLI,Realtime data lookup/rewrite.,,,res_realtime,,))
$(eval $(call BuildAsteriskModule,res-remb-modifier,REMB modifier,REMB modifier module.,,,res_remb_modifier,,))
$(eval $(call BuildAsteriskModule,res-stasis-recording,Stasis application recording,Stasis application recording support.,+$(PKG_NAME)-res-stasis,,res_stasis_recording,,))
$(eval $(call BuildAsteriskModule,res-stasis-snoop,Stasis application snoop,Stasis application snoop support.,+$(PKG_NAME)-res-stasis-recording,,res_stasis_snoop,,))
$(eval $(call BuildAsteriskModule,res-statsd,statsd client,Statsd client support.,,statsd.conf,res_statsd,,))
+$(eval $(call BuildAsteriskModule,res-stir-shaken,STIR/SHAKEN resource module,STIR/SHAKEN resource module.,+$(PKG_NAME)-curl,stir_shaken.conf,res_stir_shaken,,))
$(eval $(call BuildAsteriskModule,res-stun-monitor,STUN monitoring,STUN network monitor.,,res_stun_monitor.conf,res_stun_monitor,,))
$(eval $(call BuildAsteriskModule,res-timing-dahdi,DAHDI Timing Interface,DAHDI timing interface.,+$(PKG_NAME)-chan-dahdi,,res_timing_dahdi,,))
$(eval $(call BuildAsteriskModule,res-timing-pthread,pthread Timing Interface,pthread timing interface.,,,res_timing_pthread,,))
-$(eval $(call BuildAsteriskModule,res-timing-timerfd,Timerfd Timing Interface,Timerfd timing interface.,,,res_timing_timerfd,,))
+$(eval $(call BuildAsteriskModule,res-tonedetect,Tone detection,Tone detection module.,,,res_tonedetect,,))
$(eval $(call BuildAsteriskModule,res-xmpp,XMPP client and component module,Asterisk XMPP interface.,+libiksemel +libopenssl,xmpp.conf,res_xmpp,,))
$(eval $(call BuildAsteriskModule,voicemail,Voicemail,Voicemail modules.,+$(PKG_NAME)-res-adsi +$(PKG_NAME)-res-smdi,voicemail.conf,app_voicemail,vm-*,))
--- a/configure.ac
+++ b/configure.ac
-@@ -1018,15 +1018,18 @@ AC_LINK_IFELSE(
+@@ -1033,15 +1033,18 @@ AC_LINK_IFELSE(
# Some platforms define sem_init(), but only support sem_open(). joyous.
AC_MSG_CHECKING(for working unnamed semaphores)
--- a/configure.ac
+++ b/configure.ac
-@@ -1412,7 +1412,11 @@ AC_LINK_IFELSE(
+@@ -1427,7 +1427,11 @@ AC_LINK_IFELSE(
#include <arpa/nameser.h>
#endif
#include <resolv.h>],
+++ /dev/null
-From 06e8d5ad8e4728a716bf357c8d7f70367ae10280 Mon Sep 17 00:00:00 2001
-From: Sebastian Kemper <sebastian_ml@gmx.net>
-Date: Sun, 12 Jan 2020 12:37:46 +0100
-Subject: [PATCH] check_expr2: fix cross-compile/hardening issues
-
-When building check_expr2 with ASLR PIE hardening enabled the linker
-fails. This is resolved by adding the regular compiler flags when
-building the object files from ast_expr2f.c and ast_expr2.c.
-
-Note: The STANDALONE define is removed because it is already defined in
-_ASTCFLAGS. YY_NO_INPUT is defined so that the compile survives
-'--enable-dev-mode'.
-
-ASTERISK-28685 #close
-
-Signed-off-by: Sebastian Kemper <sebastian_ml@gmx.net>
-Change-Id: If435b7db9f9ad8266245bda51c81c220f9658915
-Taken just Makefile changes from commit: 06e8d5ad8e4728a716bf357c8d7f70367ae10280
----
---- a/utils/Makefile
-+++ b/utils/Makefile
-@@ -180,14 +180,13 @@ conf2ael: conf2ael.o ast_expr2f.o ast_ex
-
- check_expr2: $(ASTTOPDIR)/main/ast_expr2f.c $(ASTTOPDIR)/main/ast_expr2.c $(ASTTOPDIR)/main/ast_expr2.h astmm.o
- $(ECHO_PREFIX) echo " [CC] ast_expr2f.c -> ast_expr2fz.o"
-- $(CC) -g -c -I$(ASTTOPDIR)/include -DSTANDALONE $(ASTTOPDIR)/main/ast_expr2f.c -o ast_expr2fz.o
-+ $(CC) -g -c -I$(ASTTOPDIR)/include $(_ASTCFLAGS) $(ASTTOPDIR)/main/ast_expr2f.c -o ast_expr2fz.o
- $(ECHO_PREFIX) echo " [CC] ast_expr2.c -> ast_expr2z.o"
-- $(CC) -g -c -I$(ASTTOPDIR)/include -DSTANDALONE2 $(ASTTOPDIR)/main/ast_expr2.c -o ast_expr2z.o
-+ $(CC) -g -c -I$(ASTTOPDIR)/include $(_ASTCFLAGS) -DSTANDALONE2 $(ASTTOPDIR)/main/ast_expr2.c -o ast_expr2z.o
- $(ECHO_PREFIX) echo " [LD] ast_expr2fz.o ast_expr2z.o -> check_expr2"
- $(CC) -g -o check_expr2 ast_expr2fz.o ast_expr2z.o astmm.o -lm $(_ASTLDFLAGS)
- $(ECHO_PREFIX) echo " [RM] ast_expr2fz.o ast_expr2z.o"
- rm ast_expr2z.o ast_expr2fz.o
-- ./check_expr2 expr2.testinput
-
- smsq: smsq.o strcompat.o
- smsq: LIBS+=$(POPT_LIB)
* build.h
--- a/Makefile
+++ b/Makefile
-@@ -484,7 +484,7 @@ doc/core-en_US.xml: makeopts .lastclean
+@@ -489,7 +489,7 @@ doc/core-en_US.xml: makeopts .lastclean
@echo "<docs xmlns:xi=\"http://www.w3.org/2001/XInclude\">" >> $@
@for x in $(MOD_SUBDIRS); do \
printf "$$x " ; \
- for i in `find $$x -name '*.c'`; do \
+ for i in `find $$x -name '*.c' | LC_ALL=C sort`; do \
- $(AWK) -f build_tools/get_documentation $$i >> $@ ; \
- done ; \
- done
+ MODULEINFO=$$($(AWK) -f build_tools/get_moduleinfo $$i) ; \
+ if [ -n "$$MODULEINFO" ] ; \
+ then \
+++ /dev/null
-commit 02fda2b478f98cf3b8a1df76f772bf0be73bddd5
-Author: Sebastian Kemper <sebastian_ml@gmx.net>
-Date: Tue Apr 2 22:49:52 2019 +0200
-
- loader: support for permanent dlopen()
-
- Asterisk assumes that dlopen() will always run the constructor of a
- shared library and every dlclose() will run its destructor. But dlopen()
- may be permanent, meaning the constructor will only be run once, as is
- the case with musl libc.
-
- With a permanent dlopen() the Asterisk module loader does not work
- correctly, because it's expectations regarding when the constructors and
- destructors are run are not met. In fact a segmentation fault will occur
- when the first module is "re-opened" that has AST_MODFLAG_GLOBAL_SYMBOLS
- set (the dlopen() does not call the constructor, resource_being_loaded
- is not set to NULL, then strlen is called with NULL instead of a string,
- see issue ASTERISK-28319).
-
- This commit adds code to the loader that will manually run the
- constructors/destructors of the (non-builtin) modules where needed. To
- achieve this a new ao2 container (linked list) is started and filled
- with objects that contain the names of the modules and the pointers to
- their respective info structs.
-
- This behavior can be activated when configuring Asterisk
- (--enable-permanent-dlopen). By default this is disabled, of course.
-
- ASTERISK-28319 #close
-
- Signed-off-by: Sebastian Kemper <sebastian_ml@gmx.net>
- Change-Id: I86693a0ecf25d5ba81c73773a03df4abc3426875
-
---- a/configure.ac
-+++ b/configure.ac
-@@ -727,6 +727,20 @@ if test "${DISABLE_XMLDOC}" != "yes"; th
-
- fi
-
-+AC_ARG_ENABLE([permanent-dlopen],
-+ [AS_HELP_STRING([--enable-permanent-dlopen],
-+ [Enable when your libc has a permanent dlopen like musl])],
-+ [case "${enableval}" in
-+ y|ye|yes) PERMANENT_DLOPEN=yes ;;
-+ n|no) PERMANENT_DLOPEN=no ;;
-+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-permanent-dlopen) ;;
-+ esac], [PERMANENT_DLOPEN=no])
-+
-+AC_SUBST([PERMANENT_DLOPEN])
-+if test "${PERMANENT_DLOPEN}" == "yes"; then
-+ AC_DEFINE([HAVE_PERMANENT_DLOPEN], 1, [Define to support libc with permanent dlopen.])
-+fi
-+
- # some embedded systems omit internationalization (locale) support
- AC_CHECK_HEADERS([xlocale.h])
-
---- a/main/loader.c
-+++ b/main/loader.c
-@@ -153,6 +153,117 @@ static unsigned int loader_ready;
- static struct ast_vector_string startup_errors;
- static struct ast_str *startup_error_builder;
-
-+#if defined(HAVE_PERMANENT_DLOPEN)
-+#define FIRST_DLOPEN 999
-+
-+struct ao2_container *info_list = NULL;
-+
-+struct info_list_obj {
-+ const struct ast_module_info *info;
-+ int dlopened;
-+ char name[0];
-+};
-+
-+static struct info_list_obj *info_list_obj_alloc(const char *name,
-+ const struct ast_module_info *info)
-+{
-+ struct info_list_obj *new_entry;
-+
-+ new_entry = ao2_alloc(sizeof(*new_entry) + strlen(name) + 1, NULL);
-+
-+ if (!new_entry) {
-+ return NULL;
-+ }
-+
-+ strcpy(new_entry->name, name); /* SAFE */
-+ new_entry->info = info;
-+ new_entry->dlopened = FIRST_DLOPEN;
-+
-+ return new_entry;
-+}
-+
-+AO2_STRING_FIELD_CMP_FN(info_list_obj, name)
-+
-+static char *get_name_from_resource(const char *resource)
-+{
-+ int len;
-+ const char *last_three;
-+ char *mod_name;
-+
-+ if (!resource) {
-+ return NULL;
-+ }
-+
-+ len = strlen(resource);
-+ if (len > 3) {
-+ last_three = &resource[len-3];
-+ if (!strcasecmp(last_three, ".so")) {
-+ mod_name = ast_calloc(1, len - 2);
-+ if (mod_name) {
-+ ast_copy_string(mod_name, resource, len - 2);
-+ return mod_name;
-+ } else {
-+ /* Unable to allocate memory. */
-+ return NULL;
-+ }
-+ }
-+ }
-+
-+ /* Resource is the name - happens when manually unloading a module. */
-+ mod_name = ast_calloc(1, len + 1);
-+ if (mod_name) {
-+ ast_copy_string(mod_name, resource, len + 1);
-+ return mod_name;
-+ }
-+
-+ /* Unable to allocate memory. */
-+ return NULL;
-+}
-+
-+static void manual_mod_reg(const void *lib, const char *resource)
-+{
-+ struct info_list_obj *obj_tmp;
-+ char *mod_name;
-+
-+ if (lib) {
-+ mod_name = get_name_from_resource(resource);
-+ if (mod_name) {
-+ obj_tmp = ao2_find(info_list, mod_name, OBJ_SEARCH_KEY);
-+ if (obj_tmp) {
-+ if (obj_tmp->dlopened == FIRST_DLOPEN) {
-+ obj_tmp->dlopened = 1;
-+ } else {
-+ ast_module_register(obj_tmp->info);
-+ }
-+ ao2_ref(obj_tmp, -1);
-+ }
-+ ast_free(mod_name);
-+ }
-+ }
-+}
-+
-+static void manual_mod_unreg(const char *resource)
-+{
-+ struct info_list_obj *obj_tmp;
-+ char *mod_name;
-+
-+ /* When Asterisk shuts down the destructor is called automatically. */
-+ if (ast_shutdown_final()) {
-+ return;
-+ }
-+
-+ mod_name = get_name_from_resource(resource);
-+ if (mod_name) {
-+ obj_tmp = ao2_find(info_list, mod_name, OBJ_SEARCH_KEY);
-+ if (obj_tmp) {
-+ ast_module_unregister(obj_tmp->info);
-+ ao2_ref(obj_tmp, -1);
-+ }
-+ ast_free(mod_name);
-+ }
-+}
-+#endif
-+
- static __attribute__((format(printf, 1, 2))) void module_load_error(const char *fmt, ...)
- {
- char *copy = NULL;
-@@ -597,6 +708,23 @@ void ast_module_register(const struct as
-
- /* give the module a copy of its own handle, for later use in registrations and the like */
- *((struct ast_module **) &(info->self)) = mod;
-+
-+#if defined(HAVE_PERMANENT_DLOPEN)
-+ if (mod->flags.builtin != 1) {
-+ struct info_list_obj *obj_tmp = ao2_find(info_list, info->name,
-+ OBJ_SEARCH_KEY);
-+
-+ if (!obj_tmp) {
-+ obj_tmp = info_list_obj_alloc(info->name, info);
-+ if (obj_tmp) {
-+ ao2_link(info_list, obj_tmp);
-+ ao2_ref(obj_tmp, -1);
-+ }
-+ } else {
-+ ao2_ref(obj_tmp, -1);
-+ }
-+ }
-+#endif
- }
-
- static int module_post_register(struct ast_module *mod)
-@@ -843,6 +971,10 @@ static void logged_dlclose(const char *n
- error = dlerror();
- ast_log(AST_LOG_ERROR, "Failure in dlclose for module '%s': %s\n",
- S_OR(name, "unknown"), S_OR(error, "Unknown error"));
-+#if defined(HAVE_PERMANENT_DLOPEN)
-+ } else {
-+ manual_mod_unreg(name);
-+#endif
- }
- }
-
-@@ -949,6 +1081,9 @@ static struct ast_module *load_dlopen(co
-
- resource_being_loaded = mod;
- mod->lib = dlopen(filename, flags);
-+#if defined(HAVE_PERMANENT_DLOPEN)
-+ manual_mod_reg(mod->lib, mod->resource);
-+#endif
- if (resource_being_loaded) {
- struct ast_str *list;
- int c = 0;
-@@ -968,6 +1103,9 @@ static struct ast_module *load_dlopen(co
-
- resource_being_loaded = mod;
- mod->lib = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
-+#if defined(HAVE_PERMANENT_DLOPEN)
-+ manual_mod_reg(mod->lib, mod->resource);
-+#endif
- if (resource_being_loaded) {
- resource_being_loaded = NULL;
-
-@@ -2206,6 +2344,15 @@ int load_modules(void)
-
- ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
-
-+#if defined(HAVE_PERMANENT_DLOPEN)
-+ info_list = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL,
-+ info_list_obj_cmp_fn); /* must not be cleaned at shutdown */
-+ if (!info_list) {
-+ fprintf(stderr, "Module info list allocation failure.\n");
-+ return 1;
-+ }
-+#endif
-+
- AST_LIST_HEAD_INIT_NOLOCK(&load_order);
- AST_DLLIST_LOCK(&module_list);
-
--- a/configure.ac
+++ b/configure.ac
-@@ -1205,7 +1205,7 @@ if test "${ac_cv_have_variable_fdset}x"
+@@ -1206,7 +1206,7 @@ if test "${ac_cv_have_variable_fdset}x"
fi
AC_MSG_CHECKING([if we have usable eventfd support])
+++ /dev/null
-From 785bf3a755e47d92caef110e6040295764d08127 Mon Sep 17 00:00:00 2001
-From: George Joseph <gjoseph@digium.com>
-Date: Wed, 12 Jun 2019 12:03:04 -0600
-Subject: [PATCH] res_pjsip_messaging: Check for body in in-dialog message
-
-We now check that a body exists and it has a length > 0 before
-attempting to process it.
-
-ASTERISK-28447
-Reported-by: Gil Richard
-
-Change-Id: Ic469544b22ab848734636588d4c93426cc6f4b1f
----
- res/res_pjsip_messaging.c | 9 ++++++---
- 1 file changed, 6 insertions(+), 3 deletions(-)
-
-diff --git a/res/res_pjsip_messaging.c b/res/res_pjsip_messaging.c
-index 0e10a8f047..930cf84a53 100644
---- a/res/res_pjsip_messaging.c
-+++ b/res/res_pjsip_messaging.c
-@@ -90,10 +90,13 @@ static enum pjsip_status_code check_content_type_in_dialog(const pjsip_rx_data *
- static const pj_str_t text = { "text", 4};
- static const pj_str_t application = { "application", 11};
-
-+ if (!(rdata->msg_info.msg->body && rdata->msg_info.msg->body->len > 0)) {
-+ return res;
-+ }
-+
- /* We'll accept any text/ or application/ content type */
-- if (rdata->msg_info.msg->body && rdata->msg_info.msg->body->len
-- && (pj_stricmp(&rdata->msg_info.msg->body->content_type.type, &text) == 0
-- || pj_stricmp(&rdata->msg_info.msg->body->content_type.type, &application) == 0)) {
-+ if (pj_stricmp(&rdata->msg_info.msg->body->content_type.type, &text) == 0
-+ || pj_stricmp(&rdata->msg_info.msg->body->content_type.type, &application) == 0) {
- res = PJSIP_SC_OK;
- } else if (rdata->msg_info.ctype
- && (pj_stricmp(&rdata->msg_info.ctype->media.type, &text) == 0
---
-2.21.0
-
+++ /dev/null
-From 1e4df0215af4f192ed06a7fc7589c799f1ec6091 Mon Sep 17 00:00:00 2001
-From: Francesco Castellano <francesco.castellano@messagenet.it>
-Date: Fri, 28 Jun 2019 18:15:31 +0200
-Subject: [PATCH] chan_sip: Handle invalid SDP answer to T.38 re-invite
-
-The chan_sip module performs a T.38 re-invite using a single media
-stream of udptl, and expects the SDP answer to be the same.
-
-If an SDP answer is received instead that contains an additional
-media stream with no joint codec a crash will occur as the code
-assumes that at least one joint codec will exist in this
-scenario.
-
-This change removes this assumption.
-
-ASTERISK-28465
-
-Change-Id: I8b02845b53344c6babe867a3f0a5231045c7ac87
----
-
-diff --git a/channels/chan_sip.c b/channels/chan_sip.c
-index 898b646..a609ff8 100644
---- a/channels/chan_sip.c
-+++ b/channels/chan_sip.c
-@@ -10965,7 +10965,13 @@
- ast_rtp_lookup_mime_multiple2(s3, NULL, newnoncodeccapability, 0, 0));
- }
-
-- if (portno != -1 || vportno != -1 || tportno != -1) {
-+ /* When UDPTL is negotiated it is expected that there are no compatible codecs as audio or
-+ * video is not being transported, thus we continue in this function further up if that is
-+ * the case. If we receive an SDP answer containing both a UDPTL stream and another media
-+ * stream however we need to check again to ensure that there is at least one joint codec
-+ * instead of assuming there is one.
-+ */
-+ if ((portno != -1 || vportno != -1 || tportno != -1) && ast_format_cap_count(newjointcapability)) {
- /* We are now ready to change the sip session and RTP structures with the offered codecs, since
- they are acceptable */
- unsigned int framing;
+++ /dev/null
-From 69ed619a6d9b64a297d3099b6455756912e21d0b Mon Sep 17 00:00:00 2001
-From: Kevin Harwell <kharwell@digium.com>
-Date: Tue, 20 Aug 2019 15:05:45 -0500
-Subject: [PATCH] AST-2019-004 - res_pjsip_t38.c: Add NULL checks before using session media
-
-After receiving a 200 OK with a declined stream in response to a T.38
-initiated re-invite Asterisk would crash when attempting to dereference
-a NULL session media object.
-
-This patch checks to make sure the session media object is not NULL before
-attempting to use it.
-
-ASTERISK-28495
-patches:
- ast-2019-004.patch submitted by Alexei Gradinari (license 5691)
-
-Change-Id: I168f45f4da29cfe739acf87e597baa2aae7aa572
----
-
-diff --git a/res/res_pjsip_t38.c b/res/res_pjsip_t38.c
-index 11804e2..e5c6090 100644
---- a/res/res_pjsip_t38.c
-+++ b/res/res_pjsip_t38.c
-@@ -203,7 +203,6 @@
- {
- RAII_VAR(struct ast_sip_session *, session, obj, ao2_cleanup);
- RAII_VAR(struct ast_datastore *, datastore, ast_sip_session_get_datastore(session, "t38"), ao2_cleanup);
-- struct ast_sip_session_media *session_media;
-
- if (!datastore) {
- return 0;
-@@ -212,8 +211,7 @@
- ast_debug(2, "Automatically rejecting T.38 request on channel '%s'\n",
- session->channel ? ast_channel_name(session->channel) : "<gone>");
-
-- session_media = session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
-- t38_change_state(session, session_media, datastore->data, T38_REJECTED);
-+ t38_change_state(session, NULL, datastore->data, T38_REJECTED);
- ast_sip_session_resume_reinvite(session);
-
- return 0;
-@@ -322,28 +320,37 @@
- int index;
-
- session_media = session->active_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
-- t38_change_state(session, session_media, state, T38_ENABLED);
-+ if (!session_media) {
-+ ast_log(LOG_WARNING, "Received %d response to T.38 re-invite on '%s' but no active session media\n",
-+ status.code, session->channel ? ast_channel_name(session->channel) : "unknown channel");
-+ } else {
-+ t38_change_state(session, session_media, state, T38_ENABLED);
-
-- /* Stop all the streams in the stored away active state, they'll go back to being active once
-- * we reinvite back.
-- */
-- for (index = 0; index < AST_VECTOR_SIZE(&state->media_state->sessions); ++index) {
-- struct ast_sip_session_media *session_media = AST_VECTOR_GET(&state->media_state->sessions, index);
-+ /* Stop all the streams in the stored away active state, they'll go back to being active once
-+ * we reinvite back.
-+ */
-+ for (index = 0; index < AST_VECTOR_SIZE(&state->media_state->sessions); ++index) {
-+ struct ast_sip_session_media *session_media = AST_VECTOR_GET(&state->media_state->sessions, index);
-
-- if (session_media && session_media->handler && session_media->handler->stream_stop) {
-- session_media->handler->stream_stop(session_media);
-+ if (session_media && session_media->handler && session_media->handler->stream_stop) {
-+ session_media->handler->stream_stop(session_media);
-+ }
- }
-+
-+ return 0;
- }
- } else {
- session_media = session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
-- t38_change_state(session, session_media, state, T38_REJECTED);
--
-- /* Abort this attempt at switching to T.38 by resetting the pending state and freeing our stored away active state */
-- ast_sip_session_media_state_free(state->media_state);
-- state->media_state = NULL;
-- ast_sip_session_media_state_reset(session->pending_media_state);
- }
-
-+ /* If no session_media then response contained a declined stream, so disable */
-+ t38_change_state(session, NULL, state, session_media ? T38_REJECTED : T38_DISABLED);
-+
-+ /* Abort this attempt at switching to T.38 by resetting the pending state and freeing our stored away active state */
-+ ast_sip_session_media_state_free(state->media_state);
-+ state->media_state = NULL;
-+ ast_sip_session_media_state_reset(session->pending_media_state);
-+
- return 0;
- }
-
-@@ -426,12 +433,10 @@
- /* Negotiation can not take place without a valid max_ifp value. */
- if (!parameters->max_ifp) {
- if (data->session->t38state == T38_PEER_REINVITE) {
-- session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
-- t38_change_state(data->session, session_media, state, T38_REJECTED);
-+ t38_change_state(data->session, NULL, state, T38_REJECTED);
- ast_sip_session_resume_reinvite(data->session);
- } else if (data->session->t38state == T38_ENABLED) {
-- session_media = data->session->active_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
-- t38_change_state(data->session, session_media, state, T38_DISABLED);
-+ t38_change_state(data->session, NULL, state, T38_DISABLED);
- ast_sip_session_refresh(data->session, NULL, NULL, NULL,
- AST_SIP_SESSION_REFRESH_METHOD_INVITE, 1, state->media_state);
- state->media_state = NULL;
-@@ -454,6 +459,11 @@
- state->our_parms.version = MIN(state->our_parms.version, state->their_parms.version);
- state->our_parms.rate_management = state->their_parms.rate_management;
- session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
-+ if (!session_media) {
-+ ast_log(LOG_ERROR, "Failed to negotiate parameters for reinvite on channel '%s' (No pending session media).\n",
-+ data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
-+ break;
-+ }
- ast_udptl_set_local_max_ifp(session_media->udptl, state->our_parms.max_ifp);
- t38_change_state(data->session, session_media, state, T38_ENABLED);
- ast_sip_session_resume_reinvite(data->session);
-@@ -468,8 +478,13 @@
- }
- state->our_parms = *parameters;
- session_media = media_state->default_session[AST_MEDIA_TYPE_IMAGE];
-+ if (!session_media) {
-+ ast_log(LOG_ERROR, "Failed to negotiate parameters on channel '%s' (No default session media).\n",
-+ data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
-+ break;
-+ }
- ast_udptl_set_local_max_ifp(session_media->udptl, state->our_parms.max_ifp);
-- t38_change_state(data->session, session_media, state, T38_LOCAL_REINVITE);
-+ t38_change_state(data->session, NULL, state, T38_LOCAL_REINVITE);
- ast_sip_session_refresh(data->session, NULL, t38_reinvite_sdp_cb, t38_reinvite_response_cb,
- AST_SIP_SESSION_REFRESH_METHOD_INVITE, 1, media_state);
- }
-@@ -478,12 +493,10 @@
- case AST_T38_REFUSED:
- case AST_T38_REQUEST_TERMINATE: /* Shutdown T38 */
- if (data->session->t38state == T38_PEER_REINVITE) {
-- session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
-- t38_change_state(data->session, session_media, state, T38_REJECTED);
-+ t38_change_state(data->session, NULL, state, T38_REJECTED);
- ast_sip_session_resume_reinvite(data->session);
- } else if (data->session->t38state == T38_ENABLED) {
-- session_media = data->session->active_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
-- t38_change_state(data->session, session_media, state, T38_DISABLED);
-+ t38_change_state(data->session, NULL, state, T38_DISABLED);
- ast_sip_session_refresh(data->session, NULL, NULL, NULL, AST_SIP_SESSION_REFRESH_METHOD_INVITE, 1, state->media_state);
- state->media_state = NULL;
- }
-@@ -493,6 +506,11 @@
-
- if (data->session->t38state == T38_PEER_REINVITE) {
- session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
-+ if (!session_media) {
-+ ast_log(LOG_ERROR, "Failed to request parameters for reinvite on channel '%s' (No pending session media).\n",
-+ data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
-+ break;
-+ }
- parameters.max_ifp = ast_udptl_get_far_max_ifp(session_media->udptl);
- parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
- ast_queue_control_data(data->session->channel, AST_CONTROL_T38_PARAMETERS, ¶meters, sizeof(parameters));
-@@ -788,7 +806,7 @@
-
- if ((session->t38state == T38_REJECTED) || (session->t38state == T38_DISABLED)) {
- ast_debug(3, "Declining; T.38 state is rejected or declined\n");
-- t38_change_state(session, session_media, state, T38_DISABLED);
-+ t38_change_state(session, NULL, state, T38_DISABLED);
- return 0;
- }
-
+++ /dev/null
-From 8cdaa93e658a46e7baf6b606468b5e2c88a0133b Mon Sep 17 00:00:00 2001
-From: Ben Ford <bford@digium.com>
-Date: Mon, 21 Oct 2019 14:55:06 -0500
-Subject: [PATCH] chan_sip.c: Prevent address change on unauthenticated SIP request.
-
-If the name of a peer is known and a SIP request is sent using that
-peer's name, the address of the peer will change even if the request
-fails the authentication challenge. This means that an endpoint can
-be altered and even rendered unusuable, even if it was in a working
-state previously. This can only occur when the nat option is set to the
-default, or auto_force_rport.
-
-This change checks the result of authentication first to ensure it is
-successful before setting the address and the nat option.
-
-ASTERISK-28589 #close
-
-Change-Id: I581c5ed1da60ca89f590bd70872de2b660de02df
----
-
-diff --git a/channels/chan_sip.c b/channels/chan_sip.c
-index 6ac2e61..4d79a47 100644
---- a/channels/chan_sip.c
-+++ b/channels/chan_sip.c
-@@ -19245,18 +19245,6 @@
- bogus_peer = NULL;
- }
-
-- /* build_peer, called through sip_find_peer, is not able to check the
-- * sip_pvt->natdetected flag in order to determine if the peer is behind
-- * NAT or not when SIP_PAGE3_NAT_AUTO_RPORT or SIP_PAGE3_NAT_AUTO_COMEDIA
-- * are set on the peer. So we check for that here and set the peer's
-- * address accordingly.
-- */
-- set_peer_nat(p, peer);
--
-- if (p->natdetected && ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
-- ast_sockaddr_copy(&peer->addr, &p->recv);
-- }
--
- if (!ast_apply_acl(peer->acl, addr, "SIP Peer ACL: ")) {
- ast_debug(2, "Found peer '%s' for '%s', but fails host access\n", peer->name, of);
- sip_unref_peer(peer, "sip_unref_peer: check_peer_ok: from sip_find_peer call, early return of AUTH_ACL_FAILED");
-@@ -19325,6 +19313,21 @@
- ast_string_field_set(p, peermd5secret, NULL);
- }
- if (!(res = check_auth(p, req, peer->name, p->peersecret, p->peermd5secret, sipmethod, uri2, reliable))) {
-+
-+ /* build_peer, called through sip_find_peer, is not able to check the
-+ * sip_pvt->natdetected flag in order to determine if the peer is behind
-+ * NAT or not when SIP_PAGE3_NAT_AUTO_RPORT or SIP_PAGE3_NAT_AUTO_COMEDIA
-+ * are set on the peer. So we check for that here and set the peer's
-+ * address accordingly. The address should ONLY be set once we are sure
-+ * authentication was a success. If, for example, an INVITE was sent that
-+ * matched the peer name but failed the authentication check, the address
-+ * would be updated, which is bad.
-+ */
-+ set_peer_nat(p, peer);
-+ if (p->natdetected && ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
-+ ast_sockaddr_copy(&peer->addr, &p->recv);
-+ }
-+
- /* If we have a call limit, set flag */
- if (peer->call_limit)
- ast_set_flag(&p->flags[0], SIP_CALL_LIMIT);
-@@ -19424,6 +19427,7 @@
- }
- }
- sip_unref_peer(peer, "check_peer_ok: sip_unref_peer: tossing temp ptr to peer from sip_find_peer");
-+
- return res;
- }
-
+++ /dev/null
-From 7574be5110e049a44b8c8ead52cd1c2a5d442afa Mon Sep 17 00:00:00 2001
-From: George Joseph <gjoseph@digium.com>
-Date: Thu, 24 Oct 2019 11:41:23 -0600
-Subject: [PATCH] manager.c: Prevent the Originate action from running the Originate app
-
-If an AMI user without the "system" authorization calls the
-Originate AMI command with the Originate application,
-the second Originate could run the "System" command.
-
-Action: Originate
-Channel: Local/1111
-Application: Originate
-Data: Local/2222,app,System,touch /tmp/owned
-
-If the "system" authorization isn't set, we now block the
-Originate app as well as the System, Exec, etc. apps.
-
-ASTERISK-28580
-Reported by: Eliel Sardañons
-
-Change-Id: Ic4c9dedc34c426f03c8c14fce334a71386d8a5fa
----
-
---- /dev/null
-+++ b/doc/UPGRADE-staging/AMI-Originate.txt
-@@ -0,0 +1,5 @@
-+Subject: AMI
-+
-+The AMI Originate action, which optionally takes a dialplan application as
-+an argument, no longer accepts "Originate" as the application due to
-+security concerns.
---- a/main/manager.c
-+++ b/main/manager.c
-@@ -5697,6 +5697,7 @@ static int action_originate(struct manse
- EAGI(/bin/rm,-rf /) */
- strcasestr(app, "mixmonitor") || /* MixMonitor(blah,,rm -rf) */
- strcasestr(app, "externalivr") || /* ExternalIVR(rm -rf) */
-+ strcasestr(app, "originate") || /* Originate(Local/1234,app,System,rm -rf) */
- (strstr(appdata, "SHELL") && (bad_appdata = 1)) || /* NoOp(${SHELL(rm -rf /)}) */
- (strstr(appdata, "EVAL") && (bad_appdata = 1)) /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
- )) {
+++ /dev/null
-commit 523ed150b16d799bcf223b841abd82f25b8cd6a0
-Author: Kevin Harwell <kharwell@digium.com>
-Date: Mon Oct 19 17:21:57 2020 -0500
-
- AST-2020-001 - res_pjsip: Return dialog locked and referenced
-
- pjproject returns the dialog locked and with a reference. However,
- in Asterisk the method that handles this decrements the reference
- and removes the lock prior to returning. This makes it possible,
- under some circumstances, for another thread to free said dialog
- before the thread that created it attempts to use it again. Of
- course when the thread that created it tries to use a freed dialog
- a crash can occur.
-
- This patch makes it so Asterisk now returns the newly created
- dialog both locked, and with an added reference. This allows the
- caller to de-reference, and unlock the dialog when it is safe to
- do so.
-
- In the case of a new SIP Invite the lock, and reference are now
- held for the entirety of the new invite handling process.
- Otherwise it's possible for the dialog, or its dependent objects,
- like the transaction, to disappear. For example if there is a TCP
- transport error.
-
- Change-Id: I5ef645a47829596f402cf383dc02c629c618969e
-
---- a/include/asterisk/res_pjsip.h
-+++ b/include/asterisk/res_pjsip.h
-@@ -1908,6 +1908,11 @@ pjsip_dialog *ast_sip_create_dialog_uac(
- /*!
- * \brief General purpose method for creating a UAS dialog with an endpoint
- *
-+ * \deprecated This function is unsafe (due to the returned object not being locked nor
-+ * having its reference incremented) and should no longer be used. Instead
-+ * use ast_sip_create_dialog_uas_locked so a properly locked and referenced
-+ * object is returned.
-+ *
- * \param endpoint A pointer to the endpoint
- * \param rdata The request that is starting the dialog
- * \param[out] status On failure, the reason for failure in creating the dialog
-@@ -1915,6 +1920,44 @@ pjsip_dialog *ast_sip_create_dialog_uac(
- pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status);
-
- /*!
-+ * \brief General purpose method for creating a UAS dialog with an endpoint
-+ *
-+ * This function creates and returns a locked, and referenced counted pjsip
-+ * dialog object. The caller is thus responsible for freeing the allocated
-+ * memory, decrementing the reference, and releasing the lock when done with
-+ * the returned object.
-+ *
-+ * \note The safest way to unlock the object, and decrement its reference is by
-+ * calling pjsip_dlg_dec_lock. Alternatively, pjsip_dlg_dec_session can be
-+ * used to decrement the reference only.
-+ *
-+ * The dialog is returned locked and with a reference in order to ensure that the
-+ * dialog object, and any of its associated objects (e.g. transaction) are not
-+ * untimely destroyed. For instance, that could happen when a transport error
-+ * occurs.
-+ *
-+ * As long as the caller maintains a reference to the dialog there should be no
-+ * worry that it might unknowningly be destroyed. However, once the caller unlocks
-+ * the dialog there is a danger that some of the dialog's internal objects could
-+ * be lost and/or compromised. For example, when the aforementioned transport error
-+ * occurs the dialog's associated transaction gets destroyed (see pjsip_dlg_on_tsx_state
-+ * in sip_dialog.c, and mod_inv_on_tsx_state in sip_inv.c).
-+ *
-+ * In this case and before using the dialog again the caller should re-lock the
-+ * dialog, check to make sure the dialog is still established, and the transaction
-+ * still exists and has not been destroyed.
-+ *
-+ * \param endpoint A pointer to the endpoint
-+ * \param rdata The request that is starting the dialog
-+ * \param[out] status On failure, the reason for failure in creating the dialog
-+ *
-+ * \retval A locked, and reference counted pjsip_dialog object.
-+ * \retval NULL on failure
-+ */
-+pjsip_dialog *ast_sip_create_dialog_uas_locked(const struct ast_sip_endpoint *endpoint,
-+ pjsip_rx_data *rdata, pj_status_t *status);
-+
-+/*!
- * \brief General purpose method for creating an rdata structure using specific information
- * \since 13.15.0
- *
---- a/res/res_pjsip.c
-+++ b/res/res_pjsip.c
-@@ -3645,7 +3645,11 @@ static int uas_use_sips_contact(pjsip_rx
- return 0;
- }
-
--pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status)
-+typedef pj_status_t (*create_dlg_uac)(pjsip_user_agent *ua, pjsip_rx_data *rdata,
-+ const pj_str_t *contact, pjsip_dialog **p_dlg);
-+
-+static pjsip_dialog *create_dialog_uas(const struct ast_sip_endpoint *endpoint,
-+ pjsip_rx_data *rdata, pj_status_t *status, create_dlg_uac create_fun)
- {
- pjsip_dialog *dlg;
- pj_str_t contact;
-@@ -3680,11 +3684,7 @@ pjsip_dialog *ast_sip_create_dialog_uas(
- (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
- (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
-
--#ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
-- *status = pjsip_dlg_create_uas_and_inc_lock(pjsip_ua_instance(), rdata, &contact, &dlg);
--#else
-- *status = pjsip_dlg_create_uas(pjsip_ua_instance(), rdata, &contact, &dlg);
--#endif
-+ *status = create_fun(pjsip_ua_instance(), rdata, &contact, &dlg);
- if (*status != PJ_SUCCESS) {
- char err[PJ_ERR_MSG_SIZE];
-
-@@ -3697,11 +3697,46 @@ pjsip_dialog *ast_sip_create_dialog_uas(
- dlg->sess_count++;
- pjsip_dlg_set_transport(dlg, &selector);
- dlg->sess_count--;
-+
-+ return dlg;
-+}
-+
-+pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status)
-+{
- #ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
-- pjsip_dlg_dec_lock(dlg);
-+ pjsip_dialog *dlg;
-+
-+ dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
-+ if (dlg) {
-+ pjsip_dlg_dec_lock(dlg);
-+ }
-+
-+ return dlg;
-+#else
-+ return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
- #endif
-+}
-+
-+pjsip_dialog *ast_sip_create_dialog_uas_locked(const struct ast_sip_endpoint *endpoint,
-+ pjsip_rx_data *rdata, pj_status_t *status)
-+{
-+#ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
-+ return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
-+#else
-+ /*
-+ * This is put here in order to be compatible with older versions of pjproject.
-+ * Best we can do in this case is immediately lock after getting the dialog.
-+ * However, that does leave a "gap" between creating and locking.
-+ */
-+ pjsip_dialog *dlg;
-+
-+ dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
-+ if (dlg) {
-+ pjsip_dlg_inc_lock(dlg);
-+ }
-
- return dlg;
-+#endif
- }
-
- int ast_sip_create_rdata_with_contact(pjsip_rx_data *rdata, char *packet, const char *src_name, int src_port,
---- a/res/res_pjsip_pubsub.c
-+++ b/res/res_pjsip_pubsub.c
-@@ -1457,7 +1457,7 @@ static struct sip_subscription_tree *cre
- }
- sub_tree->role = AST_SIP_NOTIFIER;
-
-- dlg = ast_sip_create_dialog_uas(endpoint, rdata, dlg_status);
-+ dlg = ast_sip_create_dialog_uas_locked(endpoint, rdata, dlg_status);
- if (!dlg) {
- if (*dlg_status != PJ_EEXISTS) {
- ast_log(LOG_WARNING, "Unable to create dialog for SIP subscription\n");
-@@ -1478,8 +1478,16 @@ static struct sip_subscription_tree *cre
- }
-
- pjsip_evsub_create_uas(dlg, &pubsub_cb, rdata, 0, &sub_tree->evsub);
-+
- subscription_setup_dialog(sub_tree, dlg);
-
-+ /*
-+ * The evsub and subscription setup both add dialog refs, so the dialog ref that
-+ * was added when the dialog was created (see ast_sip_create_dialog_uas_lock) can
-+ * now be removed. The lock should no longer be needed so can be removed too.
-+ */
-+ pjsip_dlg_dec_lock(dlg);
-+
- #ifdef HAVE_PJSIP_EVSUB_GRP_LOCK
- pjsip_evsub_add_ref(sub_tree->evsub);
- #endif
---- a/res/res_pjsip_session.c
-+++ b/res/res_pjsip_session.c
-@@ -2942,6 +2942,75 @@ static enum sip_get_destination_result g
- return SIP_GET_DEST_EXTEN_NOT_FOUND;
- }
-
-+/*
-+ * /internal
-+ * /brief Process initial answer for an incoming invite
-+ *
-+ * This function should only be called during the setup, and handling of a
-+ * new incoming invite. Most, if not all of the time, this will be called
-+ * when an error occurs and we need to respond as such.
-+ *
-+ * When a SIP session termination code is given for the answer it's assumed
-+ * this call then will be the final bit of processing before ending session
-+ * setup. As such, we've been holding a lock, and a reference on the invite
-+ * session's dialog. So before returning this function removes that reference,
-+ * and unlocks the dialog.
-+ *
-+ * \param inv_session The session on which to answer
-+ * \param rdata The original request
-+ * \param answer_code The answer's numeric code
-+ * \param terminate_code The termination code if the answer fails
-+ * \param notify Whether or not to call on_state_changed
-+ *
-+ * \retval 0 if invite successfully answered, -1 if an error occurred
-+ */
-+static int new_invite_initial_answer(pjsip_inv_session *inv_session, pjsip_rx_data *rdata,
-+ int answer_code, int terminate_code, pj_bool_t notify)
-+{
-+ pjsip_tx_data *tdata = NULL;
-+ int res = 0;
-+
-+ if (inv_session->state != PJSIP_INV_STATE_DISCONNECTED) {
-+ if (pjsip_inv_initial_answer(
-+ inv_session, rdata, answer_code, NULL, NULL, &tdata) != PJ_SUCCESS) {
-+
-+ pjsip_inv_terminate(inv_session, terminate_code ? terminate_code : answer_code, notify);
-+ res = -1;
-+ } else {
-+ pjsip_inv_send_msg(inv_session, tdata);
-+ }
-+ }
-+
-+ if (answer_code >= 300) {
-+ /*
-+ * A session is ending. The dialog has a reference that needs to be
-+ * removed and holds a lock that needs to be unlocked before returning.
-+ */
-+ pjsip_dlg_dec_lock(inv_session->dlg);
-+ }
-+
-+ return res;
-+}
-+
-+/*
-+ * /internal
-+ * /brief Create and initialize a pjsip invite session
-+
-+ * pjsip_inv_session adds, and maintains a reference to the dialog upon a successful
-+ * invite session creation until the session is destroyed. However, we'll wait to
-+ * remove the reference that was added for the dialog when it gets created since we're
-+ * not ready to unlock the dialog in this function.
-+ *
-+ * So, if this function successfully returns that means it returns with its newly
-+ * created, and associated dialog locked and with two references (i.e. dialog's
-+ * reference count should be 2).
-+ *
-+ * \param endpoint A pointer to the endpoint
-+ * \param rdata The request that is starting the dialog
-+ *
-+ * \retval A pjsip invite session object
-+ * \retval NULL on error
-+ */
- static pjsip_inv_session *pre_session_setup(pjsip_rx_data *rdata, const struct ast_sip_endpoint *endpoint)
- {
- pjsip_tx_data *tdata;
-@@ -2960,15 +3029,28 @@ static pjsip_inv_session *pre_session_se
- }
- return NULL;
- }
-- dlg = ast_sip_create_dialog_uas(endpoint, rdata, &dlg_status);
-+
-+ dlg = ast_sip_create_dialog_uas_locked(endpoint, rdata, &dlg_status);
- if (!dlg) {
- if (dlg_status != PJ_EEXISTS) {
- pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
- }
- return NULL;
- }
-+
-+ /*
-+ * The returned dialog holds a lock and has a reference added. Any paths where the
-+ * dialog invite session is not returned must unlock the dialog and remove its reference.
-+ */
-+
- if (pjsip_inv_create_uas(dlg, rdata, NULL, options, &inv_session) != PJ_SUCCESS) {
- pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
-+ /*
-+ * The acquired dialog holds a lock, and a reference. Since the dialog is not
-+ * going to be returned here it must first be unlocked and de-referenced. This
-+ * must be done prior to calling dialog termination.
-+ */
-+ pjsip_dlg_dec_lock(dlg);
- pjsip_dlg_terminate(dlg);
- return NULL;
- }
-@@ -2977,12 +3059,13 @@ static pjsip_inv_session *pre_session_se
- inv_session->sdp_neg_flags = PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE;
- #endif
- if (pjsip_dlg_add_usage(dlg, &session_module, NULL) != PJ_SUCCESS) {
-- if (pjsip_inv_initial_answer(inv_session, rdata, 500, NULL, NULL, &tdata) != PJ_SUCCESS) {
-- pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
-- }
-- pjsip_inv_send_msg(inv_session, tdata);
-+ /* Dialog's lock and a reference are removed in new_invite_initial_answer */
-+ new_invite_initial_answer(inv_session, rdata, 500, 500, PJ_FALSE);
-+ /* Remove 2nd reference added at inv_session creation */
-+ pjsip_dlg_dec_session(inv_session->dlg, &session_module);
- return NULL;
- }
-+
- return inv_session;
- }
-
-@@ -3121,7 +3204,6 @@ static void handle_new_invite_request(pj
- {
- RAII_VAR(struct ast_sip_endpoint *, endpoint,
- ast_pjsip_rdata_get_endpoint(rdata), ao2_cleanup);
-- pjsip_tx_data *tdata = NULL;
- pjsip_inv_session *inv_session = NULL;
- struct ast_sip_session *session;
- struct new_invite invite;
-@@ -3134,27 +3216,48 @@ static void handle_new_invite_request(pj
- return;
- }
-
-+ /*
-+ * Upon a successful pre_session_setup the associated dialog is returned locked
-+ * and with an added reference. Well actually two references. One added when the
-+ * dialog itself was created, and another added when the pjsip invite session was
-+ * created and the dialog was added to it.
-+ *
-+ * In order to ensure the dialog's, and any of its internal attributes, lifetimes
-+ * we'll hold the lock and maintain the reference throughout the entire new invite
-+ * handling process. See ast_sip_create_dialog_uas_locked for more details but,
-+ * basically we do this to make sure a transport failure does not destroy the dialog
-+ * and/or transaction out from underneath us between pjsip calls. Alternatively, we
-+ * could probably release the lock if we needed to, but then we'd have to re-lock and
-+ * check the dialog and transaction prior to every pjsip call.
-+ *
-+ * That means any off nominal/failure paths in this function must remove the associated
-+ * dialog reference added at dialog creation, and remove the lock. As well the
-+ * referenced pjsip invite session must be "cleaned up", which should also then
-+ * remove its reference to the dialog at that time.
-+ *
-+ * Nominally we'll unlock the dialog, and release the reference when all new invite
-+ * process handling has successfully completed.
-+ */
-+
- #ifdef HAVE_PJSIP_INV_SESSION_REF
- if (pjsip_inv_add_ref(inv_session) != PJ_SUCCESS) {
- ast_log(LOG_ERROR, "Can't increase the session reference counter\n");
-- if (inv_session->state != PJSIP_INV_STATE_DISCONNECTED) {
-- if (pjsip_inv_initial_answer(inv_session, rdata, 500, NULL, NULL, &tdata) == PJ_SUCCESS) {
-- pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
-- } else {
-- pjsip_inv_send_msg(inv_session, tdata);
-- }
-+ /* Dialog's lock and a reference are removed in new_invite_initial_answer */
-+ if (!new_invite_initial_answer(inv_session, rdata, 500, 500, PJ_FALSE)) {
-+ /* Terminate the session if it wasn't done in the answer */
-+ pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
- }
- return;
- }
- #endif
--
- session = ast_sip_session_alloc(endpoint, NULL, inv_session, rdata);
- if (!session) {
-- if (pjsip_inv_initial_answer(inv_session, rdata, 500, NULL, NULL, &tdata) == PJ_SUCCESS) {
-+ /* Dialog's lock and reference are removed in new_invite_initial_answer */
-+ if (!new_invite_initial_answer(inv_session, rdata, 500, 500, PJ_FALSE)) {
-+ /* Terminate the session if it wasn't done in the answer */
- pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
-- } else {
-- pjsip_inv_send_msg(inv_session, tdata);
- }
-+
- #ifdef HAVE_PJSIP_INV_SESSION_REF
- pjsip_inv_dec_ref(inv_session);
- #endif
-@@ -3172,6 +3275,17 @@ static void handle_new_invite_request(pj
- invite.rdata = rdata;
- new_invite(&invite);
-
-+ /*
-+ * The dialog lock and reference added at dialog creation time must be
-+ * maintained throughout the new invite process. Since we're pretty much
-+ * done at this point with things it's safe to go ahead and remove the lock
-+ * and the reference here. See ast_sip_create_dialog_uas_locked for more info.
-+ *
-+ * Note, any future functionality added that does work using the dialog must
-+ * be done before this.
-+ */
-+ pjsip_dlg_dec_lock(inv_session->dlg);
-+
- ao2_ref(session, -1);
- }
-
+++ /dev/null
-From f83efa12f7411dd100f49933bf71297c8ed9f765 Mon Sep 17 00:00:00 2001
-From: Ben Ford <bford@digium.com>
-Date: Mon, 02 Nov 2020 10:29:31 -0600
-Subject: [PATCH] AST-2020-002 - res_pjsip: Stop sending INVITEs after challenge limit.
-
-If Asterisk sends out an INVITE and receives a challenge with a
-different nonce value each time, it will continuously send out INVITEs,
-even if the call is hung up. The endpoint must be configured for
-outbound authentication for this to occur. A limit has been set on
-outbound INVITEs so that, once reached, Asterisk will stop sending
-INVITEs and the transaction will terminate.
-
-ASTERISK-29013
-
-Change-Id: I2d001ca745b00ca8aa12030f2240cd72363b46f7
----
-
---- a/include/asterisk/res_pjsip.h
-+++ b/include/asterisk/res_pjsip.h
-@@ -63,6 +63,9 @@ struct pjsip_tpselector;
- /*! \brief Maximum number of ciphers supported for a TLS transport */
- #define SIP_TLS_MAX_CIPHERS 64
-
-+/*! Maximum number of challenges before assuming that we are in a loop */
-+#define MAX_RX_CHALLENGES 10
-+
- /*!
- * \brief Structure for SIP transport information
- */
---- a/include/asterisk/res_pjsip_session.h
-+++ b/include/asterisk/res_pjsip_session.h
-@@ -215,8 +215,10 @@ struct ast_sip_session {
- enum ast_sip_dtmf_mode dtmf;
- /*! Initial incoming INVITE Request-URI. NULL otherwise. */
- pjsip_uri *request_uri;
-- /* Media statistics for negotiated RTP streams */
-+ /*! Media statistics for negotiated RTP streams */
- AST_VECTOR(, struct ast_rtp_instance_stats *) media_stats;
-+ /*! Number of challenges received during outgoing requests to determine if we are in a loop */
-+ unsigned int authentication_challenge_count:4;
- };
-
- typedef int (*ast_sip_session_request_creation_cb)(struct ast_sip_session *session, pjsip_tx_data *tdata);
---- a/res/res_pjsip.c
-+++ b/res/res_pjsip.c
-@@ -4027,8 +4027,6 @@ static pj_bool_t does_method_match(const
- return pj_stristr(&method, message_method) ? PJ_TRUE : PJ_FALSE;
- }
-
--/*! Maximum number of challenges before assuming that we are in a loop */
--#define MAX_RX_CHALLENGES 10
- #define TIMER_INACTIVE 0
- #define TIMEOUT_TIMER2 5
-
---- a/res/res_pjsip_session.c
-+++ b/res/res_pjsip_session.c
-@@ -2052,7 +2052,6 @@ static pjsip_module session_reinvite_mod
- .on_rx_request = session_reinvite_on_rx_request,
- };
-
--
- void ast_sip_session_send_request_with_cb(struct ast_sip_session *session, pjsip_tx_data *tdata,
- ast_sip_session_response_cb on_response)
- {
-@@ -2301,6 +2300,9 @@ struct ast_sip_session *ast_sip_session_
- return NULL;
- }
-
-+ /* Track the number of challenges received on outbound requests */
-+ session->authentication_challenge_count = 0;
-+
- /* Fire seesion begin handlers */
- handle_session_begin(session);
-
-@@ -2470,6 +2472,11 @@ static pj_bool_t outbound_invite_auth(pj
-
- session = inv->mod_data[session_module.id];
-
-+ if (++session->authentication_challenge_count > MAX_RX_CHALLENGES) {
-+ ast_debug(1, "Initial INVITE reached maximum number of auth attempts.\n");
-+ return PJ_FALSE;
-+ }
-+
- if (ast_sip_create_request_with_auth(&session->endpoint->outbound_auths, rdata,
- tsx->last_tx, &tdata)) {
- return PJ_FALSE;
-@@ -3846,6 +3853,7 @@ static void session_inv_on_tsx_state_cha
- ast_debug(1, "reINVITE received final response code %d\n",
- tsx->status_code);
- if ((tsx->status_code == 401 || tsx->status_code == 407)
-+ && ++session->authentication_challenge_count < MAX_RX_CHALLENGES
- && !ast_sip_create_request_with_auth(
- &session->endpoint->outbound_auths,
- e->body.tsx_state.src.rdata, tsx->last_tx, &tdata)) {
-@@ -3920,6 +3928,7 @@ static void session_inv_on_tsx_state_cha
- (int) pj_strlen(&tsx->method.name), pj_strbuf(&tsx->method.name),
- tsx->status_code);
- if ((tsx->status_code == 401 || tsx->status_code == 407)
-+ && ++session->authentication_challenge_count < MAX_RX_CHALLENGES
- && !ast_sip_create_request_with_auth(
- &session->endpoint->outbound_auths,
- e->body.tsx_state.src.rdata, tsx->last_tx, &tdata)) {
+++ /dev/null
-From 757b7f8d7cfee4f541e8d7586e2408556a74201d Mon Sep 17 00:00:00 2001
-From: Ivan Poddubnyi <ivan.poddubny@gmail.com>
-Date: Mon, 28 Dec 2020 13:43:23 +0100
-Subject: [PATCH] res_pjsip_diversion: Fix adding more than one histinfo to
- Supported
-
-New responses sent within a PJSIP sessions are based on those that were
-sent before. Therefore, adding/modifying a header once causes it to be
-sent on all responses that follow.
-
-Sending 181 Call Is Being Forwarded many times first adds "histinfo"
-duplicated more and more, and eventually overflows past the array
-boundary.
-
-This commit adds a check preventing adding "histinfo" more than once,
-and skipping it if there is no more space in the header.
-
-Similar overflow situations can also occur in res_pjsip_path and
-res_pjsip_outbound_registration so those were also modified to
-check the bounds and suppress duplicate Supported values.
-
-ASTERISK-29227
-Reported by: Ivan Poddubny
-
-Change-Id: Id43704a1f1a0293e35cc7f844026f0b04f2ac322
----
- res/res_pjsip_diversion.c | 14 ++++++++++++++
- res/res_pjsip_outbound_registration.c | 12 ++++++++++++
- res/res_pjsip_path.c | 12 ++++++++++++
- 3 files changed, 38 insertions(+)
-
---- a/res/res_pjsip_outbound_registration.c
-+++ b/res/res_pjsip_outbound_registration.c
-@@ -580,6 +580,7 @@ static int handle_client_registration(vo
-
- if (client_state->support_path) {
- pjsip_supported_hdr *hdr;
-+ int i;
-
- hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL);
- if (!hdr) {
-@@ -593,6 +594,17 @@ static int handle_client_registration(vo
- pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
- }
-
-+ /* Don't add the value if it's already there */
-+ for (i = 0; i < hdr->count; ++i) {
-+ if (pj_stricmp(&hdr->values[i], &PATH_NAME) == 0) {
-+ return 1;
-+ }
-+ }
-+
-+ if (hdr->count >= PJSIP_GENERIC_ARRAY_MAX_COUNT) {
-+ return 0;
-+ }
-+
- /* add on to the existing Supported header */
- pj_strassign(&hdr->values[hdr->count++], &PATH_NAME);
- }
---- a/res/res_pjsip_path.c
-+++ b/res/res_pjsip_path.c
-@@ -122,6 +122,7 @@ static int path_get_string(pj_pool_t *po
- static int add_supported(pjsip_tx_data *tdata)
- {
- pjsip_supported_hdr *hdr;
-+ int i;
-
- hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL);
- if (!hdr) {
-@@ -134,6 +135,17 @@ static int add_supported(pjsip_tx_data *
- pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
- }
-
-+ /* Don't add the value if it's already there */
-+ for (i = 0; i < hdr->count; ++i) {
-+ if (pj_stricmp(&hdr->values[i], &PATH_SUPPORTED_NAME) == 0) {
-+ return 0;
-+ }
-+ }
-+
-+ if (hdr->count >= PJSIP_GENERIC_ARRAY_MAX_COUNT) {
-+ return -1;
-+ }
-+
- /* add on to the existing Supported header */
- pj_strassign(&hdr->values[hdr->count++], &PATH_SUPPORTED_NAME);
-