Compare commits

...
3 Commits
Author SHA1 Message Date
Dave Horton 8ce531ec81 revert change (for now) that caused audio issues when reinviting to partial media (#212) 2025-08-18 12:46:13 -04:00
Sam Machin 7bc2a1a6f4 Check for loops (#211)
* check for matching x-application-sid header

and tests

* lint

* update test scenario

* rename file

* now with valid test data!
2025-08-18 07:24:45 -04:00
Sam Machin 83461f99e8 Set strict source on rtpengine (#210)
* Set strict source on rtpengine

RTPBleed

* use env var for strict source

* lint

* Update utils.js

* arghhhh

* clarification

* change
2025-08-03 19:44:47 -04:00
8 changed files with 59 additions and 6 deletions
+1 -1
View File
@@ -3,6 +3,6 @@
"DTLS": "off",
"SDES": "off",
"ICE": "remove",
"flags": ["media handover", "port latching"],
"flags": ["port latching"],
"rtcp-mux": ["accept"]
}
+2 -2
View File
@@ -3,14 +3,14 @@
"transport-protocol": "UDP/TLS/RTP/SAVPF",
"ICE": "default",
"SDES": "off",
"flags": ["generate mid", "SDES-no", "media handover", "port latching"],
"flags": ["generate mid", "SDES-no", "port latching"],
"rtcp-mux": ["require"]
},
"teams": {
"transport-protocol": "RTP/SAVP",
"ICE": "default",
"SDES": "off",
"flags": ["generate mid", "SDES-no", "media handover", "port latching"],
"flags": ["generate mid", "SDES-no", "port latching"],
"rtcp-mux": ["accept"]
}
}
+2 -2
View File
@@ -258,7 +258,7 @@ module.exports = (srf, logger) => {
`SELECT * FROM phone_numbers WHERE number = '${did}'
AND voip_carrier_sid IN (${vc_sids})
AND account_sid = '${a[0].account_sid}'`;
logger.debug({voip_carriers, sql, did}, 'looking up DID');
//logger.debug({voip_carriers, sql, did}, 'looking up DID');
const [r] = await pp.query(sql);
if (r.length === 0) {
@@ -334,7 +334,7 @@ module.exports = (srf, logger) => {
`SELECT application_sid FROM phone_numbers WHERE number = '${did}'
AND voip_carrier_sid = '${matches[0].voip_carrier_sid}'
AND account_sid = '${matches[0].account_sid}'`;
logger.debug({matches: matches[0], sql, did}, 'looking up DID');
//logger.debug({matches: matches[0], sql, did}, 'looking up DID');
const [r] = await pp.query(sql);
return {
+5 -1
View File
@@ -131,7 +131,11 @@ module.exports = function(srf, logger) {
return res.send(404, 'Number Not Provisioned');
}
logger.info({gateway}, 'identifyAccount: incoming call from gateway');
const appSidHeader = req.get('x-application-sid');
if (appSidHeader && appSidHeader == application_sid) {
logger.info({callId}, 'Loop Detected, x-application-sid header on incoming call matches applicationSid');
return res.send(482, 'Loop Detected on x-application-sid');
}
let sid;
if (siprec) {
if (!account.siprec_hook_sid) {
+7
View File
@@ -30,6 +30,13 @@ function makeRtpEngineOpts(req, srcIsUsingSrtp, dstIsUsingSrtp, teams = false) {
dstOpts.flags.push('inject DTMF');
srcOpts.flags.push('inject DTMF');
}
/** By default, and for backwards compatibility, use media handover
* set env var to true to use strict source instead (needed for rtpbleed vulnerability)
*/
const enableStrictSource = !!process.env.RTPENGINE_ENABLE_STRICT_SOURCE;
dstOpts.flags.push(enableStrictSource ? 'strict source' : 'media handover');
srcOpts.flags.push(enableStrictSource ? 'strict source' : 'media handover');
const acceptCodecs = process.env.JAMBONES_ACCEPT_AND_TRANSCODE ?
process.env.JAMBONES_ACCEPT_AND_TRANSCODE :
process.env.JAMBONES_ACCEPT_G729 ? 'g729' : '';
+3
View File
@@ -72,6 +72,9 @@ values ('d458bf7a-bcea-47b2-ac96-66dfc9c5c220', '150822233*', '287c1452-620d-419
insert into phone_numbers (phone_number_sid, number, voip_carrier_sid, account_sid)
values ('f7ad205d-b92f-4363-8160-f8b5216b40d3', '15083871234', '287c1452-620d-4195-9f19-c9814ef90d78', 'd7cc37cb-d152-49ef-a51b-485f6e917089');
insert into phone_numbers (phone_number_sid, number, voip_carrier_sid, account_sid, application_sid)
values ('c17d5a7d-9328-4663-92c0-f65aa8381264', '12125551212', '287c1452-620d-4195-9f19-c9814ef90d78', 'ed649e33-e771-403a-8c99-1780eabbc803', '3b43e39f-4346-4218-8434-a53130e8be49');
-- two accounts that both have the same carrier with default routing (ambiguity test)
insert into accounts (account_sid, name, service_provider_sid, webhook_secret, sip_realm)
values ('239d7d49-b3e4-4fdb-9d66-661149f717e8', 'Account B1', '3f35518f-5a0d-4c2e-90a5-2407bb3b36f0', 'foobar', 'echo2.sip.jambonz.org');
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<scenario name="UAC with x-application-sid header">
<send retrans="500">
<![CDATA[
INVITE sip:+12125551212@jambonz.org SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag09[call_number]
To: <sip:12125551212@jambonz.org>
Call-ID: [call_id]
CSeq: 1 INVITE
Contact: sip:sipp@[local_ip]:[local_port]
Max-Forwards: 70
Subject: uac-pcap-carrier-success
Content-Type: application/sdp
Content-Length: [len]
X-Application-Sid: 3b43e39f-4346-4218-8434-a53130e8be49
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [media_port] RTP/AVP 0
a=rtpmap:0 PCMU/8000
]]>
</send>
<recv response="100" optional="true">
</recv>
<recv response="482" rtd="true" >
</recv>
</scenario>
+3
View File
@@ -37,6 +37,9 @@ test('incoming call tests', async(t) => {
await sippUac('uac-late-media.xml', '172.38.0.20');
t.pass('incoming call with no SDP packet is rejected with a 488');
await sippUac('uac-did-applicationsid-loop.xml', '172.38.0.20');
t.pass('incoming call with x-application-sid header is rejected with 482');
await sippUac('uac-pcap-carrier-success.xml', '172.38.0.20');
t.pass('incoming call from carrier completed successfully');