Skip to content

Commit 40c74ae

Browse files
committed
Add validation to prevent invalid ports, closes pterodactyl#1034
1 parent bc3cb7b commit 40c74ae

File tree

10 files changed

+199
-146
lines changed

10 files changed

+199
-146
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ This project follows [Semantic Versioning](http://semver.org) guidelines.
99
* Correct permissions check in UI to allow subusers with permission to `view-allocations` the ability to actually see the sidebar link.
1010
* Fixes improper behavior when marking an egg as copying the configuration from another.
1111
* Debug bar is only checked when the app is set to debug mode in the API session handler, rather than when it is in local mode to match the plugin settings.
12+
* Added validation to port allocations to prevent allocation of restricted or invalid ports.
1213

1314
### Changed
1415
* Panel now throws proper 504: Gateway Timeout errors on server listing when daemon is offline.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Pterodactyl\Exceptions\Service\Allocation;
4+
5+
use Pterodactyl\Exceptions\DisplayException;
6+
7+
class CidrOutOfRangeException extends DisplayException
8+
{
9+
/**
10+
* CidrOutOfRangeException constructor.
11+
*/
12+
public function __construct()
13+
{
14+
parent::__construct(trans('exceptions.allocations.cidr_out_of_range'));
15+
}
16+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Pterodactyl\Exceptions\Service\Allocation;
4+
5+
use Pterodactyl\Exceptions\DisplayException;
6+
7+
class InvalidPortMappingException extends DisplayException
8+
{
9+
/**
10+
* InvalidPortMappingException constructor.
11+
*
12+
* @param mixed $port
13+
*/
14+
public function __construct($port)
15+
{
16+
parent::__construct(trans('exceptions.allocations.invalid_mapping', ['port' => $port]));
17+
}
18+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Pterodactyl\Exceptions\Service\Allocation;
4+
5+
use Pterodactyl\Exceptions\DisplayException;
6+
7+
class PortOutOfRangeException extends DisplayException
8+
{
9+
/**
10+
* PortOutOfRangeException constructor.
11+
*/
12+
public function __construct()
13+
{
14+
parent::__construct(trans('exceptions.allocations.port_out_of_range'));
15+
}
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Pterodactyl\Exceptions\Service\Allocation;
4+
5+
use Pterodactyl\Exceptions\DisplayException;
6+
7+
class TooManyPortsInRangeException extends DisplayException
8+
{
9+
/**
10+
* TooManyPortsInRangeException constructor.
11+
*/
12+
public function __construct()
13+
{
14+
parent::__construct(trans('exceptions.allocations.too_many_ports'));
15+
}
16+
}

app/Http/Controllers/Admin/NodesController.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,10 @@ public function allocationSetAlias(AllocationAliasFormRequest $request)
331331
* @param int|\Pterodactyl\Models\Node $node
332332
* @return \Illuminate\Http\RedirectResponse
333333
*
334-
* @throws \Pterodactyl\Exceptions\DisplayException
334+
* @throws \Pterodactyl\Exceptions\Service\Allocation\CidrOutOfRangeException
335+
* @throws \Pterodactyl\Exceptions\Service\Allocation\InvalidPortMappingException
336+
* @throws \Pterodactyl\Exceptions\Service\Allocation\PortOutOfRangeException
337+
* @throws \Pterodactyl\Exceptions\Service\Allocation\TooManyPortsInRangeException
335338
*/
336339
public function createAllocation(AllocationFormRequest $request, Node $node)
337340
{

app/Http/Controllers/Api/Application/Nodes/AllocationController.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,10 @@ public function index(GetAllocationsRequest $request): array
7373
* @param \Pterodactyl\Http\Requests\Api\Application\Allocations\StoreAllocationRequest $request
7474
* @return array
7575
*
76-
* @throws \Pterodactyl\Exceptions\DisplayException
76+
* @throws \Pterodactyl\Exceptions\Service\Allocation\CidrOutOfRangeException
77+
* @throws \Pterodactyl\Exceptions\Service\Allocation\InvalidPortMappingException
78+
* @throws \Pterodactyl\Exceptions\Service\Allocation\PortOutOfRangeException
79+
* @throws \Pterodactyl\Exceptions\Service\Allocation\TooManyPortsInRangeException
7780
*/
7881
public function store(StoreAllocationRequest $request): array
7982
{

app/Services/Allocations/AssignmentService.php

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,24 @@
11
<?php
2-
/**
3-
* Pterodactyl - Panel
4-
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
5-
*
6-
* This software is licensed under the terms of the MIT license.
7-
* https://opensource.org/licenses/MIT
8-
*/
92

103
namespace Pterodactyl\Services\Allocations;
114

125
use IPTools\Network;
136
use Pterodactyl\Models\Node;
147
use Illuminate\Database\ConnectionInterface;
15-
use Pterodactyl\Exceptions\DisplayException;
168
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
9+
use Pterodactyl\Exceptions\Service\Allocation\CidrOutOfRangeException;
10+
use Pterodactyl\Exceptions\Service\Allocation\PortOutOfRangeException;
11+
use Pterodactyl\Exceptions\Service\Allocation\InvalidPortMappingException;
12+
use Pterodactyl\Exceptions\Service\Allocation\TooManyPortsInRangeException;
1713

1814
class AssignmentService
1915
{
2016
const CIDR_MAX_BITS = 27;
2117
const CIDR_MIN_BITS = 32;
18+
const PORT_FLOOR = 1024;
19+
const PORT_CEIL = 65535;
2220
const PORT_RANGE_LIMIT = 1000;
23-
const PORT_RANGE_REGEX = '/^(\d{1,5})-(\d{1,5})$/';
21+
const PORT_RANGE_REGEX = '/^(\d{4,5})-(\d{4,5})$/';
2422

2523
/**
2624
* @var \Illuminate\Database\ConnectionInterface
@@ -38,62 +36,67 @@ class AssignmentService
3836
* @param \Pterodactyl\Contracts\Repository\AllocationRepositoryInterface $repository
3937
* @param \Illuminate\Database\ConnectionInterface $connection
4038
*/
41-
public function __construct(
42-
AllocationRepositoryInterface $repository,
43-
ConnectionInterface $connection
44-
) {
39+
public function __construct(AllocationRepositoryInterface $repository, ConnectionInterface $connection)
40+
{
4541
$this->connection = $connection;
4642
$this->repository = $repository;
4743
}
4844

4945
/**
5046
* Insert allocations into the database and link them to a specific node.
5147
*
52-
* @param int|\Pterodactyl\Models\Node $node
53-
* @param array $data
48+
* @param \Pterodactyl\Models\Node $node
49+
* @param array $data
5450
*
55-
* @throws \Pterodactyl\Exceptions\DisplayException
51+
* @throws \Pterodactyl\Exceptions\Service\Allocation\CidrOutOfRangeException
52+
* @throws \Pterodactyl\Exceptions\Service\Allocation\PortOutOfRangeException
53+
* @throws \Pterodactyl\Exceptions\Service\Allocation\InvalidPortMappingException
54+
* @throws \Pterodactyl\Exceptions\Service\Allocation\TooManyPortsInRangeException
5655
*/
57-
public function handle($node, array $data)
56+
public function handle(Node $node, array $data)
5857
{
59-
if ($node instanceof Node) {
60-
$node = $node->id;
61-
}
62-
6358
$explode = explode('/', $data['allocation_ip']);
6459
if (count($explode) !== 1) {
6560
if (! ctype_digit($explode[1]) || ($explode[1] > self::CIDR_MIN_BITS || $explode[1] < self::CIDR_MAX_BITS)) {
66-
throw new DisplayException(trans('exceptions.allocations.cidr_out_of_range'));
61+
throw new CidrOutOfRangeException;
6762
}
6863
}
6964

7065
$this->connection->beginTransaction();
7166
foreach (Network::parse(gethostbyname($data['allocation_ip'])) as $ip) {
7267
foreach ($data['allocation_ports'] as $port) {
7368
if (! is_digit($port) && ! preg_match(self::PORT_RANGE_REGEX, $port)) {
74-
throw new DisplayException(trans('exceptions.allocations.invalid_mapping', ['port' => $port]));
69+
throw new InvalidPortMappingException($port);
7570
}
7671

7772
$insertData = [];
7873
if (preg_match(self::PORT_RANGE_REGEX, $port, $matches)) {
7974
$block = range($matches[1], $matches[2]);
8075

8176
if (count($block) > self::PORT_RANGE_LIMIT) {
82-
throw new DisplayException(trans('exceptions.allocations.too_many_ports'));
77+
throw new TooManyPortsInRangeException;
78+
}
79+
80+
if ((int) $matches[1] <= self::PORT_FLOOR || (int) $matches[2] > self::PORT_CEIL) {
81+
throw new PortOutOfRangeException;
8382
}
8483

8584
foreach ($block as $unit) {
8685
$insertData[] = [
87-
'node_id' => $node,
86+
'node_id' => $node->id,
8887
'ip' => $ip->__toString(),
8988
'port' => (int) $unit,
9089
'ip_alias' => array_get($data, 'allocation_alias'),
9190
'server_id' => null,
9291
];
9392
}
9493
} else {
94+
if ((int) $port <= self::PORT_FLOOR || (int) $port > self::PORT_CEIL) {
95+
throw new PortOutOfRangeException;
96+
}
97+
9598
$insertData[] = [
96-
'node_id' => $node,
99+
'node_id' => $node->id,
97100
'ip' => $ip->__toString(),
98101
'port' => (int) $port,
99102
'ip_alias' => array_get($data, 'allocation_alias'),

resources/lang/en/exceptions.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
],
99
'allocations' => [
1010
'server_using' => 'A server is currently assigned to this allocation. An allocation can only be deleted if no server is currently assigned.',
11-
'too_many_ports' => 'Adding more than 1000 ports at a single time is not supported. Please use a smaller range.',
11+
'too_many_ports' => 'Adding more than 1000 ports in a single range at once is not supported.',
1212
'invalid_mapping' => 'The mapping provided for :port was invalid and could not be processed.',
1313
'cidr_out_of_range' => 'CIDR notation only allows masks between /25 and /32.',
14+
'port_out_of_range' => 'Ports in an allocation must be greater than 1024 and less than or equal to 65535.',
1415
],
1516
'nest' => [
1617
'delete_has_servers' => 'A Nest with active servers attached to it cannot be deleted from the Panel.',

0 commit comments

Comments
 (0)