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

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
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
16 changes: 8 additions & 8 deletions library/DataFixtures/Stub/Provider/SurvivalDeviceStub.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ protected function load()
{
$dto = (new SurvivalDeviceDto(1))
->setName("survival test 1")
->setProxy("23123")
->setOutboundProxy("43322")
->setProxy("survival1.test.com")
->setOutboundProxy("192.168.1.100:5060")
->setUdpPort(5060)
->setTcpPort(5060)
->setTlsPort(5061)
Expand All @@ -32,8 +32,8 @@ protected function load()

$dto = (new SurvivalDeviceDto(2))
->setName("Survival Test 2")
->setProxy("56789")
->setOutboundProxy("67890")
->setProxy("survival2.test.com")
->setOutboundProxy("192.168.1.100:5070")
->setUdpPort(5070)
->setTcpPort(5071)
->setTlsPort(5062)
Expand All @@ -44,8 +44,8 @@ protected function load()

$dto = (new SurvivalDeviceDto(3))
->setName("Survival Test 3")
->setProxy("98765")
->setOutboundProxy("54321")
->setProxy("survival3.test.com")
->setOutboundProxy("192.168.1.100:5080")
->setUdpPort(5080)
->setTcpPort(5081)
->setTlsPort(5063)
Expand All @@ -56,8 +56,8 @@ protected function load()

$dto = (new SurvivalDeviceDto(4))
->setName("Survival Test 4")
->setProxy("11223")
->setOutboundProxy("44556")
->setProxy("survival4.test.com")
->setOutboundProxy("192.168.1.100:5090")
->setUdpPort(5090)
->setTcpPort(5091)
->setTlsPort(5064)
Expand Down
136 changes: 107 additions & 29 deletions library/Ivoz/Provider/Domain/Model/CarrierServer/CarrierServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ protected function sanitizeValues(): void
{
$this->sanitizeBrandByCarrier();
$this->sanitizeAuth();
$this->sanitizeProxyLogic();
}

protected function sanitizeBrandByCarrier(): void
Expand All @@ -61,31 +60,59 @@ protected function sanitizeAuth(): void
}
}

protected function sanitizeProxyLogic(): void
public function setOutboundProxy(?string $outboundProxy = null): static
{
$sip_proxy = explode(':', $this->getSipProxy());
$hostname = array_shift($sip_proxy);
$port = array_shift($sip_proxy);
if ($this->getOutboundProxy()) {
$outbound_proxy = explode(':', $this->getOutboundProxy());
$ip = array_shift($outbound_proxy);
$obPort = array_shift($outbound_proxy);
if (!is_null($port)) {
throw new \DomainException('When Outbound Proxy is used, SIP Proxy must not include a port.', 70003);
if ($outboundProxy) {
$outboundProxy = trim($outboundProxy);

if ($outboundProxy === '') {
return parent::setOutboundProxy(null);
}

if (str_contains($outboundProxy, ' ')) {
throw new \DomainException('Outbound Proxy must not contain spaces.', 70001);
}

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

if (count($parts) > 2) {
throw new \DomainException('Outbound Proxy must be in format IP or IP:port, not more than one colon.', 70002);
}

$ip = $parts[0];

if (!preg_match('/^(\d{1,3}\.){3}\d{1,3}$/', $ip)) {
throw new \DomainException('IP format is invalid in Outbound Proxy.', 70003);
}

foreach (explode('.', $ip) as $octet) {
$value = (int) $octet;
if ($value < 0 || $value > 255) {
throw new \DomainException('Each segment of the IP must be between 0 and 255.', 70006);
}
}

$this->setIp($ip);

if (isset($parts[1])) {
$port = $parts[1];

if (!ctype_digit($port)) {
throw new \DomainException('Port must be a numeric value.', 70007);
}

$port = (int) $port;
if ($port < 1 || $port > 65535) {
throw new \DomainException('Port must be between 1 and 65535.', 70004);
}

$this->setPort($port);
} else {
$this->setPort(5060);
}
$port = $obPort;
} else {
$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);
return parent::setOutboundProxy($outboundProxy);
}

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

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

if ($sipProxy === '') {
throw new \InvalidArgumentException('SIP Proxy cannot be empty.');
}

if (str_contains($sipProxy, ' ')) {
throw new \InvalidArgumentException('SIP Proxy must not contain spaces.');
}

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

if (count($parts) > 2) {
throw new \DomainException('SIP Proxy can only contain one colon at most.');
}

$host = $parts[0];

if (preg_match('/^(\d{1,3}\.){3}\d{1,3}$/', $host)) {
foreach (explode('.', $host) as $octet) {
$value = (int) $octet;
if ($value < 0 || $value > 255) {
throw new \DomainException('Each segment of the IP must be between 0 and 255.');
}
}
} else {
if (str_contains($host, ':') || str_contains($host, ' ')) {
throw new \DomainException('Invalid domain format for SIP Proxy.');
}

if (!str_contains($host, '.')) {
throw new \DomainException('Domain must contain at least one dot.');
}

if (str_ends_with($host, '.')) {
throw new \DomainException('Domain must not end with a dot.');
}
}

if (isset($parts[1])) {
$port = $parts[1];

if (!ctype_digit($port)) {
throw new \DomainException('SIP Proxy port must be numeric.');
}

$port = (int) $port;
if ($port < 1 || $port > 65535) {
throw new \DomainException('SIP Proxy port must be between 1 and 65535.');
}

$this->setPort($port);
} else {
$this->setPort(5060);
}

$sipProxy = trim($sipProxy);
if ($sipProxy === "") {
throw new \DomainException('Sip Proxy cannot be empty');
$this->setHostname($host);
}

return parent::setSipProxy($sipProxy);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,17 @@ public function getChangeSet(): array;
*/
public function getId(): ?int;

public function setOutboundProxy(?string $outboundProxy = null): static;

/**
* {@inheritDoc}
*/
public function setIp(?string $ip = null): static;

public function getName(): string;

public function setSipProxy(?string $sipProxy = null): static;

/**
* @param int | null $id
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public function getId(): ?int

protected function sanitizeValues(): void
{
$this->sanitizeProxyLogic();
$this->sanitizeOutboundProxy();
$this->sanitizeProxy();
}

protected function setUdpPort(int $udpPort): static
Expand All @@ -58,26 +59,89 @@ protected function setWssPort(int $wssPort): static
return parent::setWssPort($wssPort);
}

protected function setProxy(string $proxy): static
protected function sanitizeProxy(): void
{
$proxy = trim($proxy);
if (empty($proxy)) {
throw new \DomainException('Proxy cannot be empty');
$proxy = trim($this->getProxy());

if ($proxy === '') {
return;
}

if (str_contains($proxy, ' ')) {
throw new \InvalidArgumentException('Proxy must not contain spaces.');
}

if (preg_match('/^(\d{1,3}\.){3}\d{1,3}$/', $proxy)) {
foreach (explode('.', $proxy) as $octet) {
$intOctet = (int) $octet;
if ($intOctet < 0 || $intOctet > 255) {
throw new \DomainException("Each segment of the IP must be between 0 and 255.");
}
}

$this->setProxy($proxy);
return;
}

if (str_contains($proxy, ':')) {
throw new \DomainException("Domain must not contain colons.");
}

if (!str_contains($proxy, '.')) {
throw new \DomainException("Domain must contain at least one dot.");
}

if (str_ends_with($proxy, '.')) {
throw new \DomainException("Domain must not end with a dot.");
}

return parent::setProxy($proxy);
$this->setProxy($proxy);
}

protected function sanitizeProxyLogic(): void
protected function sanitizeOutboundProxy(): void
{
$outboundProxy = $this->getOutboundProxy();
if (is_null($outboundProxy)) {
$proxy = trim($this->getOutboundProxy() ?? '');

if ($proxy === '') {
return;
}

$sipProxyIncludesPort = strpos($this->getProxy(), ':') !== false;
if ($sipProxyIncludesPort) {
throw new \DomainException('When Outbound Proxy is used, SIP Proxy must not include a port.', 70003);
if (str_contains($proxy, ' ')) {
throw new \DomainException('Outbound Proxy must not contain spaces.', 70001);
}

$parts = explode(':', $proxy);

if (count($parts) > 2) {
throw new \DomainException('Outbound Proxy must be in format IP or IP:port, not more than one colon.', 70002);
}

$ip = $parts[0];

if (!preg_match('/^(\d{1,3}\.){3}\d{1,3}$/', $ip)) {
throw new \DomainException('IP format is invalid in Outbound Proxy.', 70003);
}

foreach (explode('.', $ip) as $octet) {
$value = (int) $octet;
if ($value < 0 || $value > 255) {
throw new \DomainException('Each segment of the IP must be between 0 and 255.', 70006);
}
}

if (isset($parts[1])) {
$port = $parts[1];

if (!ctype_digit($port)) {
throw new \DomainException('Port must be a numeric value.', 70007);
}

$port = (int) $port;
if ($port < 1 || $port > 65535) {
throw new \DomainException('Port must be between 1 and 65535.', 70004);
}
}

return;
}
}
Empty file added library/a.out
Empty file.
10 changes: 0 additions & 10 deletions library/phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -1785,16 +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
path: Ivoz/Provider/Domain/Model/CarrierServer/CarrierServer.php

-
message: "#^Interface Ivoz\\\\Provider\\\\Domain\\\\Model\\\\CarrierServer\\\\CarrierServerRepository extends generic interface Doctrine\\\\Common\\\\Collections\\\\Selectable but does not specify its types\\: TKey, T$#"
count: 1
Expand Down
Loading