2019-12-07 22:01:40 +00:00
package sftp
import (
2019-12-07 23:53:07 +00:00
"github.com/pkg/errors"
"github.com/pterodactyl/sftp-server"
"github.com/pterodactyl/wings/api"
2019-12-07 22:01:40 +00:00
"github.com/pterodactyl/wings/config"
2019-12-08 01:35:45 +00:00
"github.com/pterodactyl/wings/server"
2019-12-07 23:53:07 +00:00
"go.uber.org/zap"
2019-12-07 22:01:40 +00:00
)
func Initialize ( config * config . Configuration ) error {
2019-12-07 23:53:07 +00:00
c := & sftp_server . Server {
User : sftp_server . SftpUser {
2019-12-07 22:01:40 +00:00
Uid : config . System . User . Uid ,
Gid : config . System . User . Gid ,
} ,
2019-12-07 23:53:07 +00:00
Settings : sftp_server . Settings {
2019-12-07 22:01:40 +00:00
BasePath : config . System . Data ,
ReadOnly : config . System . Sftp . ReadOnly ,
BindAddress : config . System . Sftp . Address ,
BindPort : config . System . Sftp . Port ,
} ,
2019-12-07 23:53:07 +00:00
CredentialValidator : validateCredentials ,
2019-12-08 00:43:00 +00:00
PathValidator : validatePath ,
DiskSpaceValidator : validateDiskSpace ,
2019-12-07 22:01:40 +00:00
}
2019-12-07 23:53:07 +00:00
if err := sftp_server . New ( c ) ; err != nil {
return err
}
c . ConfigureLogger ( func ( ) * zap . SugaredLogger {
return zap . S ( ) . Named ( "sftp" )
} )
// Initialize the SFTP server in a background thread since this is
// a long running operation.
go func ( instance * sftp_server . Server ) {
if err := c . Initalize ( ) ; err != nil {
zap . S ( ) . Named ( "sftp" ) . Errorw ( "failed to initialize SFTP subsystem" , zap . Error ( errors . WithStack ( err ) ) )
}
} ( c )
return nil
}
2019-12-08 00:43:00 +00:00
func validatePath ( fs sftp_server . FileSystem , p string ) ( string , error ) {
2019-12-08 01:35:45 +00:00
s := server . GetServers ( ) . Find ( func ( server * server . Server ) bool {
return server . Uuid == fs . UUID
} )
if s == nil {
return "" , errors . New ( "no server found with that UUID" )
}
return s . Filesystem . SafePath ( p )
2019-12-08 00:43:00 +00:00
}
func validateDiskSpace ( fs sftp_server . FileSystem ) bool {
2019-12-08 01:35:45 +00:00
s := server . GetServers ( ) . Find ( func ( server * server . Server ) bool {
return server . Uuid == fs . UUID
} )
if s == nil {
return false
}
return s . Filesystem . HasSpaceAvailable ( )
2019-12-08 00:43:00 +00:00
}
2019-12-07 23:53:07 +00:00
// Validates a set of credentials for a SFTP login aganist Pterodactyl Panel and returns
// the server's UUID if the credentials were valid.
func validateCredentials ( c sftp_server . AuthenticationRequest ) ( * sftp_server . AuthenticationResponse , error ) {
2019-12-08 01:35:45 +00:00
resp , err := api . NewRequester ( ) . ValidateSftpCredentials ( c )
2020-05-10 00:46:22 +00:00
zap . S ( ) . Named ( "sftp" ) . Debugw ( "validating credentials for SFTP connection" , zap . String ( "username" , c . User ) )
2019-12-08 01:35:45 +00:00
if err != nil {
return resp , err
}
s := server . GetServers ( ) . Find ( func ( server * server . Server ) bool {
return server . Uuid == resp . Server
} )
if s == nil {
2020-05-10 00:46:22 +00:00
return resp , errors . New ( "no matching server with UUID found" )
2019-12-08 01:35:45 +00:00
}
2020-05-10 00:46:22 +00:00
zap . S ( ) . Named ( "sftp" ) . Debugw ( "matched user to server instance, credentials successfully validated" , zap . String ( "username" , c . User ) , zap . String ( "server" , s . Uuid ) )
2019-12-08 01:35:45 +00:00
return resp , err
2019-12-07 22:01:40 +00:00
}