Skip to content

Commit 058e490

Browse files
authored
Implement Panel changes to support internal SFTP subsystem on Daemon (pterodactyl#703)
1 parent 57db949 commit 058e490

File tree

23 files changed

+484
-247
lines changed

23 files changed

+484
-247
lines changed
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
namespace Pterodactyl\Http\Controllers\API\Remote;
4+
5+
use Illuminate\Http\Request;
6+
use Illuminate\Http\JsonResponse;
7+
use Illuminate\Auth\AuthenticationException;
8+
use Pterodactyl\Http\Controllers\Controller;
9+
use Illuminate\Foundation\Auth\ThrottlesLogins;
10+
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
11+
use Pterodactyl\Services\Sftp\AuthenticateUsingPasswordService;
12+
use Pterodactyl\Http\Requests\API\Remote\SftpAuthenticationFormRequest;
13+
14+
class SftpController extends Controller
15+
{
16+
use ThrottlesLogins;
17+
18+
/**
19+
* @var \Pterodactyl\Services\Sftp\AuthenticateUsingPasswordService
20+
*/
21+
private $authenticationService;
22+
23+
/**
24+
* SftpController constructor.
25+
*
26+
* @param \Pterodactyl\Services\Sftp\AuthenticateUsingPasswordService $authenticationService
27+
*/
28+
public function __construct(AuthenticateUsingPasswordService $authenticationService)
29+
{
30+
$this->authenticationService = $authenticationService;
31+
}
32+
33+
/**
34+
* Authenticate a set of credentials and return the associated server details
35+
* for a SFTP connection on the daemon.
36+
*
37+
* @param \Pterodactyl\Http\Requests\API\Remote\SftpAuthenticationFormRequest $request
38+
* @return \Illuminate\Http\JsonResponse
39+
*
40+
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
41+
*/
42+
public function index(SftpAuthenticationFormRequest $request): JsonResponse
43+
{
44+
$connection = explode('.', $request->input('username'));
45+
$this->incrementLoginAttempts($request);
46+
47+
if ($this->hasTooManyLoginAttempts($request)) {
48+
return response()->json([
49+
'error' => 'Logins throttled.',
50+
], 429);
51+
}
52+
53+
try {
54+
$data = $this->authenticationService->handle(
55+
array_get($connection, 0),
56+
$request->input('password'),
57+
object_get($request->attributes->get('node'), 'id', 0),
58+
array_get($connection, 1)
59+
);
60+
61+
$this->clearLoginAttempts($request);
62+
} catch (AuthenticationException $exception) {
63+
return response()->json([
64+
'error' => 'Invalid credentials.',
65+
], 403);
66+
} catch (RecordNotFoundException $exception) {
67+
return response()->json([
68+
'error' => 'Invalid server.',
69+
], 404);
70+
}
71+
72+
return response()->json($data);
73+
}
74+
75+
/**
76+
* Get the throttle key for the given request.
77+
*
78+
* @param \Illuminate\Http\Request $request
79+
* @return string
80+
*/
81+
protected function throttleKey(Request $request)
82+
{
83+
return strtolower(array_get(explode('.', $request->input('username')), 0) . '|' . $request->ip());
84+
}
85+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Pterodactyl\Http\Controllers\Server\Settings;
4+
5+
use Illuminate\View\View;
6+
use Illuminate\Http\Request;
7+
use Pterodactyl\Http\Controllers\Controller;
8+
use Pterodactyl\Traits\Controllers\JavascriptInjection;
9+
10+
class SftpController extends Controller
11+
{
12+
use JavascriptInjection;
13+
14+
/**
15+
* Render the server SFTP settings page.
16+
*
17+
* @param \Illuminate\Http\Request $request
18+
* @return \Illuminate\View\View
19+
*/
20+
public function index(Request $request): View
21+
{
22+
$this->setRequest($request)->injectJavascript();
23+
24+
return view('server.settings.sftp');
25+
}
26+
}

app/Http/Middleware/Daemon/DaemonAuthenticate.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public function handle(Request $request, Closure $next)
7575
throw new HttpException(403);
7676
}
7777

78-
$request->attributes->set('node.model', $node);
78+
$request->attributes->set('node', $node);
7979

8080
return $next($request);
8181
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace Pterodactyl\Http\Requests\API\Remote;
4+
5+
use Pterodactyl\Http\Requests\Request;
6+
7+
class SftpAuthenticationFormRequest extends Request
8+
{
9+
/**
10+
* Authenticate the request.
11+
*
12+
* @return bool
13+
*/
14+
public function authorize()
15+
{
16+
return true;
17+
}
18+
19+
/**
20+
* Rules to apply to the request.
21+
*
22+
* @return array
23+
*/
24+
public function rules()
25+
{
26+
return [
27+
'username' => 'required|string',
28+
'password' => 'required|string',
29+
];
30+
}
31+
32+
/**
33+
* Return only the fields that we are interested in from the request.
34+
* This will include empty fields as a null value.
35+
*
36+
* @return array
37+
*/
38+
public function normalize()
39+
{
40+
return $this->only(
41+
array_keys($this->rules())
42+
);
43+
}
44+
}

app/Models/Node.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,23 @@ public function getConfigurationAsJson($pretty = false)
144144
],
145145
],
146146
'docker' => [
147+
'container' => [
148+
'user' => null,
149+
],
150+
'network' => [
151+
'name' => 'pterodactyl_nw',
152+
],
147153
'socket' => '/var/run/docker.sock',
148154
'autoupdate_images' => true,
149155
],
150156
'sftp' => [
151157
'path' => $this->daemonBase,
158+
'ip' => '0.0.0.0',
152159
'port' => $this->daemonSFTP,
153-
'container' => 'ptdl-sftp',
160+
'keypair' => [
161+
'bits' => 2048,
162+
'e' => 65537,
163+
],
154164
],
155165
'logger' => [
156166
'path' => 'logs/',

app/Models/Server.php

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,12 @@ class Server extends Model implements CleansAttributes, ValidableContract
2929
*/
3030
protected $table = 'servers';
3131

32-
/**
33-
* The attributes excluded from the model's JSON form.
34-
*
35-
* @var array
36-
*/
37-
protected $hidden = ['sftp_password'];
38-
3932
/**
4033
* The attributes that should be mutated to dates.
4134
*
4235
* @var array
4336
*/
44-
protected $dates = ['deleted_at'];
37+
protected $dates = [self::CREATED_AT, self::UPDATED_AT, 'deleted_at'];
4538

4639
/**
4740
* Always eager load these relationships on the model.
@@ -55,7 +48,7 @@ class Server extends Model implements CleansAttributes, ValidableContract
5548
*
5649
* @var array
5750
*/
58-
protected $guarded = ['id', 'installed', 'created_at', 'updated_at', 'deleted_at'];
51+
protected $guarded = ['id', 'installed', self::CREATED_AT, self::UPDATED_AT, 'deleted_at'];
5952

6053
/**
6154
* @var array
@@ -73,8 +66,6 @@ class Server extends Model implements CleansAttributes, ValidableContract
7366
'node_id' => 'required',
7467
'allocation_id' => 'required',
7568
'pack_id' => 'sometimes',
76-
'auto_deploy' => 'sometimes',
77-
'custom_id' => 'sometimes',
7869
'skip_scripts' => 'sometimes',
7970
];
8071

@@ -95,10 +86,7 @@ class Server extends Model implements CleansAttributes, ValidableContract
9586
'nest_id' => 'exists:nests,id',
9687
'egg_id' => 'exists:eggs,id',
9788
'pack_id' => 'nullable|numeric|min:0',
98-
'custom_container' => 'nullable|string',
9989
'startup' => 'nullable|string',
100-
'auto_deploy' => 'accepted',
101-
'custom_id' => 'numeric|unique:servers,id',
10290
'skip_scripts' => 'boolean',
10391
];
10492

@@ -132,7 +120,6 @@ class Server extends Model implements CleansAttributes, ValidableContract
132120
*/
133121
protected $searchableColumns = [
134122
'name' => 10,
135-
'username' => 10,
136123
'uuidShort' => 9,
137124
'uuid' => 8,
138125
'pack.name' => 7,

app/Services/Servers/ServerCreationService.php

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,6 @@ class ServerCreationService
6363
*/
6464
protected $userRepository;
6565

66-
/**
67-
* @var \Pterodactyl\Services\Servers\UsernameGenerationService
68-
*/
69-
protected $usernameService;
70-
7166
/**
7267
* @var \Pterodactyl\Services\Servers\VariableValidatorService
7368
*/
@@ -84,7 +79,6 @@ class ServerCreationService
8479
* @param \Pterodactyl\Contracts\Repository\ServerRepositoryInterface $repository
8580
* @param \Pterodactyl\Contracts\Repository\ServerVariableRepositoryInterface $serverVariableRepository
8681
* @param \Pterodactyl\Contracts\Repository\UserRepositoryInterface $userRepository
87-
* @param \Pterodactyl\Services\Servers\UsernameGenerationService $usernameService
8882
* @param \Pterodactyl\Services\Servers\VariableValidatorService $validatorService
8983
*/
9084
public function __construct(
@@ -96,7 +90,6 @@ public function __construct(
9690
ServerRepositoryInterface $repository,
9791
ServerVariableRepositoryInterface $serverVariableRepository,
9892
UserRepositoryInterface $userRepository,
99-
UsernameGenerationService $usernameService,
10093
VariableValidatorService $validatorService
10194
) {
10295
$this->allocationRepository = $allocationRepository;
@@ -107,7 +100,6 @@ public function __construct(
107100
$this->repository = $repository;
108101
$this->serverVariableRepository = $serverVariableRepository;
109102
$this->userRepository = $userRepository;
110-
$this->usernameService = $usernameService;
111103
$this->validatorService = $validatorService;
112104
}
113105

@@ -151,8 +143,6 @@ public function create(array $data)
151143
'startup' => $data['startup'],
152144
'daemonSecret' => str_random(NodeCreationService::DAEMON_SECRET_LENGTH),
153145
'image' => $data['docker_image'],
154-
'username' => $this->usernameService->generate($data['name'], $uniqueShort),
155-
'sftp_password' => null,
156146
]);
157147

158148
// Process allocations and assign them to the server in the database.

app/Services/Servers/UsernameGenerationService.php

Lines changed: 0 additions & 40 deletions
This file was deleted.

0 commit comments

Comments
 (0)