Skip to content

[PROVIDER-2231] Fix sanitizer on carrier server and survival device #2941

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions library/DataFixtures/ORM/ProviderSurvivalDevice.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public function load(ObjectManager $manager)

(function () use ($fixture) {
$this->setName("survival test 1");
$this->setProxy("23123");
$this->setOutboundProxy("43322");
$this->setProxy("survival1.test.com");
$this->setOutboundProxy("192.168.1.100:5060");
$this->setUdpPort(5060);
$this->setTcpPort(5060);
$this->setTlsPort(5061);
Expand All @@ -39,8 +39,8 @@ public function load(ObjectManager $manager)
$item2 = $this->createEntityInstance(SurvivalDevice::class);
(function () use ($fixture) {
$this->setName("survival test 2");
$this->setProxy("56789");
$this->setOutboundProxy("67890");
$this->setProxy("survival2.test.com");
$this->setOutboundProxy("192.168.1.100:5070");
$this->setUdpPort(5070);
$this->setTcpPort(5071);
$this->setTlsPort(5062);
Expand All @@ -55,8 +55,8 @@ public function load(ObjectManager $manager)
$item3 = $this->createEntityInstance(SurvivalDevice::class);
(function () use ($fixture) {
$this->setName("Survival Test 3");
$this->setProxy("98765");
$this->setOutboundProxy("54321");
$this->setProxy("survival3.test.com");
$this->setOutboundProxy("192.168.1.100:5080");
$this->setUdpPort(5080);
$this->setTcpPort(5081);
$this->setTlsPort(5063);
Expand All @@ -71,8 +71,8 @@ public function load(ObjectManager $manager)
$item4 = $this->createEntityInstance(SurvivalDevice::class);
(function () use ($fixture) {
$this->setName("Survival Test 4");
$this->setProxy("11223");
$this->setOutboundProxy("44556");
$this->setProxy("survival4.test.com");
$this->setOutboundProxy("192.168.1.100:5090");
$this->setUdpPort(5090);
$this->setTcpPort(5091);
$this->setTlsPort(5064);
Expand Down
109 changes: 100 additions & 9 deletions library/Ivoz/Provider/Domain/Model/CarrierServer/CarrierServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,15 @@ protected function sanitizeProxyLogic(): void
$ip = null;
$this->setOutboundProxy(null);
}
if (!is_numeric($port) or !$port) {
$port = 5060;
}

// Save validated values
$this->setHostname($hostname);
$this->setIp($ip);
$this->setPort($port);
$this->setPort(
is_numeric($port)
? (int) $port
: null
);
}

/**
Expand Down Expand Up @@ -119,17 +120,107 @@ protected function setAuthPassword(?string $authPassword = null): static
return parent::setAuthPassword($authPassword);
}

protected function setPort(?int $port = null): static
{
$port = $port ?? 5060;

Assertion::between(
$port,
1,
65535,
'Port must be a number between 1 and 65535'
);

return parent::setPort($port);
}

protected function setSipProxy(?string $sipProxy = null): static
{
if (! $sipProxy) {
throw new \DomainException('Sip Proxy cannot be null');
}
Assertion::notNull($sipProxy, 'Sip Proxy cannot be null');

$sipProxy = trim($sipProxy);
if ($sipProxy === "") {
throw new \DomainException('Sip Proxy cannot be empty');

Assertion::notEmpty($sipProxy, 'Sip Proxy cannot be empty');

Assertion::false(
str_contains($sipProxy, ' '),
'Sip Proxy cannot contain spaces'
);

$sipProxyParts = explode(':', $sipProxy);

if (count($sipProxyParts) === 2) {
$port = $sipProxyParts[1];
Assertion::integerish($port, 'Port must be an integer-like value');
$port = (int) $port;
Assertion::between(
$port,
1,
65535,
'Port in Sip Proxy must be a number between 1 and 65535'
);
}

Assertion::true(
count($sipProxyParts) <= 2,
'Sip Proxy cannot contain more than one colon'
);

$host = $sipProxyParts[0];

$isIpLike = (bool) preg_match('/^\d{1,3}(\.\d{1,3}){3}$/', $host);
$isHostName = preg_match(
'~^(?=.{1,253}$)(?!\-)([\pL\pN\pM]+(-[\pL\pN\pM]+)*\.)+[\pL\pN\pM]{2,}$~ixuD',
$host
);
$isIPv4 = (bool) filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);

$isValidHost = ($isHostName && !$isIpLike) || $isIPv4;

Assertion::true(
$isValidHost,
'Sip Proxy must be a valid host name or IPv4 address'
);

return parent::setSipProxy($sipProxy);
}

protected function setOutboundProxy(?string $outboundProxy = null): static
{
if (empty($outboundProxy)) {
return parent::setOutboundProxy(null);
}

$outboundProxy = trim($outboundProxy);

$sipOutboundProxyParts = explode(':', $outboundProxy);

Assertion::true(
count($sipOutboundProxyParts) <= 2,
'Outbound Proxy cannot contain more than one colon'
);

if (count($sipOutboundProxyParts) === 2) {
$port = $sipOutboundProxyParts[1];

Assertion::integerish($port, 'Outbound Proxy port must be an integer-like value');
$port = (int) $port;

Assertion::between(
$port,
1,
65535,
'Outbound Proxy port must be a number between 1 and 65535'
);
}

$host = $sipOutboundProxyParts[0];
$isIp = (bool) filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
Assertion::true(
$isIp,
'Outbound Proxy must be a valid IPv4 address'
);

return parent::setOutboundProxy($outboundProxy);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,72 @@ protected function setWssPort(int $wssPort): static
protected function setProxy(string $proxy): static
{
$proxy = trim($proxy);
if (empty($proxy)) {
throw new \DomainException('Proxy cannot be empty');
}

Assertion::notEmpty($proxy, 'Proxy cannot be empty');

Assertion::false(
str_contains($proxy, ' '),
'Sip Proxy cannot contain spaces'
);

$isIpLike = (bool) preg_match('/^\d{1,3}(\.\d{1,3}){3}$/', $proxy);

$isHostName = preg_match(
'~^(?=.{1,253}$)(?!\-)([\pL\pN\pM]+(-[\pL\pN\pM]+)*\.)+[\pL\pN\pM]{2,}$~ixuD',
$proxy
);

$isIPv4 = (bool) filter_var($proxy, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);

$isValidHost = ($isHostName && !$isIpLike) || $isIPv4;

Assertion::true(
$isValidHost,
'Sip Proxy must be a valid host name or IPv4 address'
);

return parent::setProxy($proxy);
}

protected function setOutboundProxy(?string $outboundProxy = null): static
{
if (empty($outboundProxy)) {
return parent::setOutboundProxy(null);
}

$outboundProxy = trim($outboundProxy);

$sipOutboundProxyParts = explode(':', $outboundProxy);

Assertion::true(
count($sipOutboundProxyParts) <= 2,
'Outbound Proxy cannot contain more than one colon'
);

if (count($sipOutboundProxyParts) === 2) {
$port = $sipOutboundProxyParts[1];

Assertion::integerish($port, 'Outbound Proxy port must be an integer-like value');
$port = (int) $port;

Assertion::between(
$port,
1,
65535,
'Outbound Proxy port must be a number between 1 and 65535'
);
}

$ip = $sipOutboundProxyParts[0];
$isIp = (bool) filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
Assertion::true(
$isIp,
'Outbound Proxy must be a valid IPv4 address'
);

return parent::setOutboundProxy($outboundProxy);
}

protected function sanitizeProxyLogic(): void
{
$outboundProxy = $this->getOutboundProxy();
Expand Down
5 changes: 0 additions & 5 deletions library/phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -1785,11 +1785,6 @@ parameters:
count: 1
path: Ivoz/Provider/Domain/Model/Carrier/CarrierRepository.php

-
message: "#^Parameter \\#1 \\$port of method Ivoz\\\\Provider\\\\Domain\\\\Model\\\\CarrierServer\\\\CarrierServerAbstract\\:\\:setPort\\(\\) expects int\\|null, int\\|string given\\.$#"
count: 1
path: Ivoz/Provider/Domain/Model/CarrierServer/CarrierServer.php

-
message: "#^Parameter \\#2 \\$string of function explode expects string, string\\|null given\\.$#"
count: 2
Expand Down
3 changes: 0 additions & 3 deletions library/psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1845,9 +1845,6 @@
</MixedArgument>
</file>
<file src="Ivoz/Provider/Domain/Model/CarrierServer/CarrierServer.php">
<InvalidScalarArgument occurrences="1">
<code>$port</code>
</InvalidScalarArgument>
<MethodSignatureMismatch occurrences="1">
<code>CarrierServer</code>
</MethodSignatureMismatch>
Expand Down
4 changes: 2 additions & 2 deletions microservices/provision/features/specificProvision.feature
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Feature: Specific Provision
lang.gui = es
lang.wui = es

account.1.sip_server.2.host = 23123
account.1.sip_server.2.host = survival1.test.com
account.1.sip_server.2.port = 10081
"""

Expand All @@ -42,7 +42,7 @@ Feature: Specific Provision
lang.gui = es
lang.wui = es

account.1.sip_server.2.host = 23123
account.1.sip_server.2.host = survival1.test.com
account.1.sip_server.2.port = 10081
"""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ const properties: SurvivalDeviceProperties = {
},
proxy: {
label: _('Proxy'),
helpText: _('IP or domain'),
},
outboundProxy: {
label: _('Outbound Proxy'),
helpText: _('Send to IP[:PORT] instead of SIP Proxy address'),
},
description: {
label: _('Description'),
Expand Down
2 changes: 2 additions & 0 deletions web/portal/client/src/translations/ca.json
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@
"Hunt Group_many": "Grups de salt",
"Hunt Group_one": "Grup de salt",
"Hunt Group_other": "Grups de salt",
"IP or domain": "IP o domini",
"IVR entry_many": "Entrades IVR",
"IVR entry_one": "Entrada IVR",
"IVR entry_other": "Entrades IVR",
Expand Down Expand Up @@ -522,6 +523,7 @@
"Selected users will find this fax in their user portal.": "Els usuaris seleccionats veuran aquest fax al seu portal d'usuari.",
"Send": "Enviar",
"Send by email": "Envia per email",
"Send to IP[:PORT] instead of SIP Proxy address": "Envia a IP[:PORT] enlloc de l'adreça intermediària del Proxy",
"Sent to": "Envia a",
"Service Information": "Informació de servei",
"Service_many": "Serveis",
Expand Down
2 changes: 2 additions & 0 deletions web/portal/client/src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@
"Hunt Group member_other": "Hunt Group members",
"Hunt Group_one": "Hunt Group",
"Hunt Group_other": "Hunt Groups",
"IP or domain": "IP or domain",
"IVR entry_one": "IVR entry",
"IVR entry_other": "IVR entries",
"IVR_one": "IVR",
Expand Down Expand Up @@ -465,6 +466,7 @@
"Selected users will find this fax in their user portal.": "Selected users will find this fax in their user portal.",
"Send": "Send",
"Send by email": "Send by email",
"Send to IP[:PORT] instead of SIP Proxy address": "Send to IP[:PORT] instead of SIP Proxy address",
"Sent to": "Sent to",
"Service Information": "Service Information",
"Service_one": "Service",
Expand Down
2 changes: 2 additions & 0 deletions web/portal/client/src/translations/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@
"Hunt Group_many": "Grupos de salto",
"Hunt Group_one": "Grupo de salto",
"Hunt Group_other": "Grupos de salto",
"IP or domain": "IP o dominio",
"IVR entry_many": "Entradas IVR",
"IVR entry_one": "Entrada IVR",
"IVR entry_other": "Entradas IVR",
Expand Down Expand Up @@ -522,6 +523,7 @@
"Selected users will find this fax in their user portal.": "Los usuarios seleccionados verán este fax en su portal de usuario.",
"Send": "Enviar",
"Send by email": "Enviar por email",
"Send to IP[:PORT] instead of SIP Proxy address": "Se enviará a IP:[PUERTO] en lugar de la dirección del Proxy SIP",
"Sent to": "Dirección de envío",
"Service Information": "Información de Servicios",
"Service_many": "Servicios",
Expand Down
2 changes: 2 additions & 0 deletions web/portal/client/src/translations/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@
"Hunt Group_many": "Gruppi di Chiamata",
"Hunt Group_one": "Gruppo di Chiamata",
"Hunt Group_other": "Gruppi di Chiamata",
"IP or domain": "IP o dominio",
"IVR entry_many": "Voci IVR",
"IVR entry_one": "Voce IVR",
"IVR entry_other": "Voci IVR",
Expand Down Expand Up @@ -522,6 +523,7 @@
"Selected users will find this fax in their user portal.": "Gli utenti selezionati vedranno questo fax nel loro portale utente.",
"Send": "Inviare",
"Send by email": "Invia per email",
"Send to IP[:PORT] instead of SIP Proxy address": "Invia a IP [: PORT] invece di SIP Proxy address",
"Sent to": "Inviato a",
"Service Information": "Informazioni di servizio",
"Service_many": "Servizi",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ Feature: Retrieve locations
"id": 1,
"survivalDevice": {
"name": "survival test 1",
"proxy": "23123",
"outboundProxy": "43322",
"proxy": "survival1.test.com",
"outboundProxy": "192.168.1.100:5060",
"udpPort": 5060,
"tcpPort": 5060,
"tlsPort": 5061,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Feature: Retrieve survival devices
[
{
"name": "survival test 1",
"proxy": "23123",
"proxy": "survival1.test.com",
"description": "new survival device 1",
"id": 1
}
Expand All @@ -34,8 +34,8 @@ Feature: Retrieve survival devices
"""
{
"name": "survival test 1",
"proxy": "23123",
"outboundProxy": "43322",
"proxy": "survival1.test.com",
"outboundProxy": "192.168.1.100:5060",
"udpPort": 5060,
"tcpPort": 5060,
"tlsPort": 5061,
Expand Down
Loading