33namespace Pterodactyl \Http \Controllers \Api \Remote ;
44
55use Illuminate \Http \Request ;
6- use Illuminate \Http \Response ;
76use Illuminate \Http \JsonResponse ;
7+ use Pterodactyl \Models \Permission ;
88use Pterodactyl \Http \Controllers \Controller ;
99use Illuminate \Foundation \Auth \ThrottlesLogins ;
10- use Pterodactyl \Exceptions \Repository \RecordNotFoundException ;
11- use Pterodactyl \Services \Sftp \AuthenticateUsingPasswordService ;
10+ use Pterodactyl \Repositories \Eloquent \UserRepository ;
11+ use Pterodactyl \Exceptions \Http \HttpForbiddenException ;
12+ use Pterodactyl \Repositories \Eloquent \ServerRepository ;
13+ use Pterodactyl \Services \Servers \GetUserPermissionsService ;
14+ use Symfony \Component \HttpKernel \Exception \NotFoundHttpException ;
1215use Symfony \Component \HttpKernel \Exception \BadRequestHttpException ;
1316use Pterodactyl \Http \Requests \Api \Remote \SftpAuthenticationFormRequest ;
1417
@@ -17,18 +20,35 @@ class SftpAuthenticationController extends Controller
1720 use ThrottlesLogins;
1821
1922 /**
20- * @var \Pterodactyl\Services\Sftp\AuthenticateUsingPasswordService
23+ * @var \Pterodactyl\Repositories\Eloquent\UserRepository
2124 */
22- private $ authenticationService ;
25+ private $ userRepository ;
26+
27+ /**
28+ * @var \Pterodactyl\Repositories\Eloquent\ServerRepository
29+ */
30+ private $ serverRepository ;
31+
32+ /**
33+ * @var \Pterodactyl\Services\Servers\GetUserPermissionsService
34+ */
35+ private $ permissionsService ;
2336
2437 /**
2538 * SftpController constructor.
2639 *
27- * @param \Pterodactyl\Services\Sftp\AuthenticateUsingPasswordService $authenticationService
40+ * @param \Pterodactyl\Services\Servers\GetUserPermissionsService $permissionsService
41+ * @param \Pterodactyl\Repositories\Eloquent\UserRepository $userRepository
42+ * @param \Pterodactyl\Repositories\Eloquent\ServerRepository $serverRepository
2843 */
29- public function __construct (AuthenticateUsingPasswordService $ authenticationService )
30- {
31- $ this ->authenticationService = $ authenticationService ;
44+ public function __construct (
45+ GetUserPermissionsService $ permissionsService ,
46+ UserRepository $ userRepository ,
47+ ServerRepository $ serverRepository
48+ ) {
49+ $ this ->userRepository = $ userRepository ;
50+ $ this ->serverRepository = $ serverRepository ;
51+ $ this ->permissionsService = $ permissionsService ;
3252 }
3353
3454 /**
@@ -38,7 +58,7 @@ public function __construct(AuthenticateUsingPasswordService $authenticationServ
3858 * @param \Pterodactyl\Http\Requests\Api\Remote\SftpAuthenticationFormRequest $request
3959 * @return \Illuminate\Http\JsonResponse
4060 *
41- * @throws \Pterodactyl\Exceptions\Model\DataValidationException
61+ * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
4262 */
4363 public function __invoke (SftpAuthenticationFormRequest $ request ): JsonResponse
4464 {
@@ -52,33 +72,54 @@ public function __invoke(SftpAuthenticationFormRequest $request): JsonResponse
5272 ];
5373
5474 $ this ->incrementLoginAttempts ($ request );
55-
5675 if ($ this ->hasTooManyLoginAttempts ($ request )) {
57- return response ()-> json ([
58- 'error ' => 'Logins throttled . ' ,
59- ], Response ::HTTP_TOO_MANY_REQUESTS );
76+ return JsonResponse:: create ([
77+ 'error ' => 'Too many logins attempted too quickly . ' ,
78+ ], JsonResponse ::HTTP_TOO_MANY_REQUESTS );
6079 }
6180
62- try {
63- $ data = $ this ->authenticationService ->handle (
64- $ connection ['username ' ],
65- $ request ->input ('password ' ),
66- object_get ($ request ->attributes ->get ('node ' ), 'id ' , 0 ),
67- empty ($ connection ['server ' ]) ? null : $ connection ['server ' ]
81+ /** @var \Pterodactyl\Models\Node $node */
82+ $ node = $ request ->attributes ->get ('node ' );
83+ if (empty ($ connection ['server ' ])) {
84+ throw new NotFoundHttpException ;
85+ }
86+
87+ /** @var \Pterodactyl\Models\User $user */
88+ $ user = $ this ->userRepository ->findFirstWhere ([
89+ ['username ' , '= ' , $ connection ['username ' ]],
90+ ]);
91+
92+ $ server = $ this ->serverRepository ->getByUuid ($ connection ['server ' ] ?? '' );
93+ if (! password_verify ($ request ->input ('password ' ), $ user ->password ) || $ server ->node_id !== $ node ->id ) {
94+ throw new HttpForbiddenException (
95+ 'Authorization credentials were not correct, please try again. '
6896 );
97+ }
6998
70- $ this ->clearLoginAttempts ($ request );
71- } catch (BadRequestHttpException $ exception ) {
72- return response ()->json ([
73- 'error ' => 'The server you are trying to access is not installed or is suspended. ' ,
74- ], Response::HTTP_BAD_REQUEST );
75- } catch (RecordNotFoundException $ exception ) {
76- return response ()->json ([
77- 'error ' => 'Unable to locate a resource using the username and password provided. ' ,
78- ], Response::HTTP_NOT_FOUND );
99+ if (! $ user ->root_admin && $ server ->owner_id !== $ user ->id ) {
100+ $ permissions = $ this ->permissionsService ->handle ($ server , $ user );
101+
102+ if (! in_array (Permission::ACTION_FILE_SFTP , $ permissions )) {
103+ throw new HttpForbiddenException (
104+ 'You do not have permission to access SFTP for this server. '
105+ );
106+ }
107+ }
108+
109+ // Remeber, for security purposes, only reveal the existence of the server to people that
110+ // have provided valid credentials, and have permissions to know about it.
111+ if ($ server ->installed !== 1 || $ server ->suspended ) {
112+ throw new BadRequestHttpException (
113+ 'Server is not installed or is currently suspended. '
114+ );
79115 }
80116
81- return response ()->json ($ data );
117+ return JsonResponse::create ([
118+ 'server ' => $ server ->uuid ,
119+ // Deprecated, but still needed at the moment for Wings.
120+ 'token ' => '' ,
121+ 'permissions ' => $ permissions ?? ['* ' ],
122+ ]);
82123 }
83124
84125 /**
0 commit comments