From e0a9035d38afbca25aa161e0cbde55d3f14366c4 Mon Sep 17 00:00:00 2001 From: Sam Machin Date: Fri, 29 May 2026 14:07:10 +0100 Subject: [PATCH] prvent 0.0.0.0 & /0 gateways (#553) --- lib/routes/api/sip-gateways.js | 17 ++++++++--- test/sip-gateways.js | 56 +++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/lib/routes/api/sip-gateways.js b/lib/routes/api/sip-gateways.js index 199b2da..4f1dbc5 100644 --- a/lib/routes/api/sip-gateways.js +++ b/lib/routes/api/sip-gateways.js @@ -60,15 +60,22 @@ const validate = async(req, sid) => { voip_carrier_sid = req.body.voip_carrier_sid; if (!voip_carrier_sid) throw new DbErrorBadRequest('missing voip_carrier_sid'); } - if (netmask && - process.env.JAMBONZ_MIN_GATEWAY_NETMASK && - parseInt(netmask) < process.env.JAMBONZ_MIN_GATEWAY_NETMASK) { - throw new DbErrorBadRequest( - `netmask required to have value equal or greater than ${process.env.JAMBONZ_MIN_GATEWAY_NETMASK}`); + if (netmask !== undefined && netmask !== null) { + const mask = parseInt(netmask); + if (mask < 1 || mask > 32) { + throw new DbErrorBadRequest('netmask must be between 1 and 32'); + } + if (process.env.JAMBONZ_MIN_GATEWAY_NETMASK && mask < process.env.JAMBONZ_MIN_GATEWAY_NETMASK) { + throw new DbErrorBadRequest( + `netmask required to have value equal or greater than ${process.env.JAMBONZ_MIN_GATEWAY_NETMASK}`); + } } if (hasWhitespace(ipv4)) { throw new DbErrorBadRequest('Gateway must not contain whitespace'); } + if (ipv4 && net.isIPv4(ipv4) && ipv4 === '0.0.0.0') { + throw new DbErrorBadRequest('0.0.0.0 is not allowed as a gateway address'); + } if (inbound && !net.isIPv4(ipv4)) { throw new DbErrorBadRequest('Inbound gateway must be IPv4 address'); } diff --git a/test/sip-gateways.js b/test/sip-gateways.js index eab54a5..42fa241 100644 --- a/test/sip-gateways.js +++ b/test/sip-gateways.js @@ -18,10 +18,58 @@ test('sip gateway tests', async(t) => { let result; const voip_carrier_sid = await createVoipCarrier(request); - /* add a invalid sip gateway */ + /* reject 0.0.0.0 as gateway address */ + result = await request.post('/SipGateways', { + resolveWithFullResponse: true, + auth: authAdmin, + json: true, + simple: false, + body: { + voip_carrier_sid, + ipv4: '0.0.0.0', + netmask: 32, + inbound: true, + outbound: true, + } + }); + t.ok(result.statusCode === 400, 'rejects 0.0.0.0 as gateway address'); + + /* reject netmask of 0 */ + result = await request.post('/SipGateways', { + resolveWithFullResponse: true, + auth: authAdmin, + json: true, + simple: false, + body: { + voip_carrier_sid, + ipv4: '1.2.3.4', + netmask: 0, + inbound: true, + outbound: true, + } + }); + t.ok(result.statusCode === 400, 'rejects netmask of 0'); + + /* reject netmask greater than 32 */ + result = await request.post('/SipGateways', { + resolveWithFullResponse: true, + auth: authAdmin, + json: true, + simple: false, + body: { + voip_carrier_sid, + ipv4: '1.2.3.4', + netmask: 33, + inbound: true, + outbound: true, + } + }); + t.ok(result.statusCode === 400, 'rejects netmask greater than 32'); + + /* add a invalid sip gateway - env var min netmask */ const STORED_JAMBONZ_MIN_GATEWAY_NETMASK = process.env.JAMBONZ_MIN_GATEWAY_NETMASK; process.env.JAMBONZ_MIN_GATEWAY_NETMASK = 24; - + result = await request.post('/SipGateways', { resolveWithFullResponse: true, auth: authAdmin, @@ -36,7 +84,7 @@ test('sip gateway tests', async(t) => { protocol: 'tcp' } }); - t.ok(result.statusCode === 400, 'successfully created sip gateway '); + t.ok(result.statusCode === 400, 'rejects netmask below JAMBONZ_MIN_GATEWAY_NETMASK'); result = await request.post('/SipGateways', { resolveWithFullResponse: true, @@ -51,7 +99,7 @@ test('sip gateway tests', async(t) => { protocol: 'tcp' } }); - t.ok(result.statusCode === 201, 'successfully created sip gateway '); + t.ok(result.statusCode === 201, 'successfully created sip gateway with valid netmask'); process.env.JAMBONZ_MIN_GATEWAY_NETMASK = STORED_JAMBONZ_MIN_GATEWAY_NETMASK;