mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-06 14:20:55 +03:00
Git integration has been removed as it is out of scope for a file transfer solution like SFTPGo. Maintaining Git support introduces unnecessary complexity and potential security risks due to reliance on system commands. In particular, allowing Git operations could enable authorized users to upload repositories containing hooks, which might then be executed and abused. To reduce the attack surface and simplify the codebase, Git support has been fully dropped. Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
140 lines
4.6 KiB
Go
140 lines
4.6 KiB
Go
// Copyright (C) 2019 Nicola Murino
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published
|
|
// by the Free Software Foundation, version 3.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
// Package sftpd implements the SSH File Transfer Protocol as described in https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02.
|
|
// It uses pkg/sftp library:
|
|
// https://github.com/pkg/sftp
|
|
package sftpd
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
|
|
"golang.org/x/crypto/ssh"
|
|
)
|
|
|
|
const (
|
|
logSender = "sftpd"
|
|
handshakeTimeout = 2 * time.Minute
|
|
)
|
|
|
|
var (
|
|
supportedSSHCommands = []string{"scp", "md5sum", "sha1sum", "sha256sum", "sha384sum", "sha512sum", "cd", "pwd",
|
|
"rsync", "sftpgo-copy", "sftpgo-remove"}
|
|
defaultSSHCommands = []string{"md5sum", "sha1sum", "sha256sum", "cd", "pwd", "scp"}
|
|
sshHashCommands = []string{"md5sum", "sha1sum", "sha256sum", "sha384sum", "sha512sum"}
|
|
systemCommands = []string{"rsync"}
|
|
serviceStatus ServiceStatus
|
|
certKeyAlgoNames = map[string]string{
|
|
ssh.CertAlgoRSAv01: ssh.KeyAlgoRSA,
|
|
ssh.CertAlgoRSASHA256v01: ssh.KeyAlgoRSASHA256,
|
|
ssh.CertAlgoRSASHA512v01: ssh.KeyAlgoRSASHA512,
|
|
ssh.InsecureCertAlgoDSAv01: ssh.InsecureKeyAlgoDSA, //nolint:staticcheck
|
|
ssh.CertAlgoECDSA256v01: ssh.KeyAlgoECDSA256,
|
|
ssh.CertAlgoECDSA384v01: ssh.KeyAlgoECDSA384,
|
|
ssh.CertAlgoECDSA521v01: ssh.KeyAlgoECDSA521,
|
|
ssh.CertAlgoSKECDSA256v01: ssh.KeyAlgoSKECDSA256,
|
|
ssh.CertAlgoED25519v01: ssh.KeyAlgoED25519,
|
|
ssh.CertAlgoSKED25519v01: ssh.KeyAlgoSKED25519,
|
|
}
|
|
)
|
|
|
|
type sshSubsystemExitStatus struct {
|
|
Status uint32
|
|
}
|
|
|
|
type sshSubsystemExecMsg struct {
|
|
Command string
|
|
}
|
|
|
|
type hostCertificate struct {
|
|
Certificate *ssh.Certificate
|
|
Path string
|
|
}
|
|
|
|
// HostKey defines the details for a used host key
|
|
type HostKey struct {
|
|
Path string `json:"path"`
|
|
Fingerprint string `json:"fingerprint"`
|
|
Algorithms []string `json:"algorithms"`
|
|
}
|
|
|
|
// GetAlgosAsString returns the host key algorithms as comma separated string
|
|
func (h *HostKey) GetAlgosAsString() string {
|
|
return strings.Join(h.Algorithms, ", ")
|
|
}
|
|
|
|
// ServiceStatus defines the service status
|
|
type ServiceStatus struct {
|
|
IsActive bool `json:"is_active"`
|
|
Bindings []Binding `json:"bindings"`
|
|
SSHCommands []string `json:"ssh_commands"`
|
|
HostKeys []HostKey `json:"host_keys"`
|
|
Authentications []string `json:"authentications"`
|
|
MACs []string `json:"macs"`
|
|
KexAlgorithms []string `json:"kex_algorithms"`
|
|
Ciphers []string `json:"ciphers"`
|
|
PublicKeyAlgorithms []string `json:"public_key_algorithms"`
|
|
}
|
|
|
|
// GetSSHCommandsAsString returns enabled SSH commands as comma separated string
|
|
func (s *ServiceStatus) GetSSHCommandsAsString() string {
|
|
return strings.Join(s.SSHCommands, ", ")
|
|
}
|
|
|
|
// GetSupportedAuthsAsString returns the supported authentications as comma separated string
|
|
func (s *ServiceStatus) GetSupportedAuthsAsString() string {
|
|
return strings.Join(s.Authentications, ", ")
|
|
}
|
|
|
|
// GetMACsAsString returns the enabled MAC algorithms as comma separated string
|
|
func (s *ServiceStatus) GetMACsAsString() string {
|
|
return strings.Join(s.MACs, ", ")
|
|
}
|
|
|
|
// GetKEXsAsString returns the enabled KEX algorithms as comma separated string
|
|
func (s *ServiceStatus) GetKEXsAsString() string {
|
|
return strings.Join(s.KexAlgorithms, ", ")
|
|
}
|
|
|
|
// GetCiphersAsString returns the enabled ciphers as comma separated string
|
|
func (s *ServiceStatus) GetCiphersAsString() string {
|
|
return strings.Join(s.Ciphers, ", ")
|
|
}
|
|
|
|
// GetPublicKeysAlgosAsString returns enabled public key authentication
|
|
// algorithms as comma separated string
|
|
func (s *ServiceStatus) GetPublicKeysAlgosAsString() string {
|
|
return strings.Join(s.PublicKeyAlgorithms, ", ")
|
|
}
|
|
|
|
// GetStatus returns the server status
|
|
func GetStatus() ServiceStatus {
|
|
return serviceStatus
|
|
}
|
|
|
|
// GetDefaultSSHCommands returns the SSH commands enabled as default
|
|
func GetDefaultSSHCommands() []string {
|
|
result := make([]string, len(defaultSSHCommands))
|
|
copy(result, defaultSSHCommands)
|
|
return result
|
|
}
|
|
|
|
// GetSupportedSSHCommands returns the supported SSH commands
|
|
func GetSupportedSSHCommands() []string {
|
|
result := make([]string, len(supportedSSHCommands))
|
|
copy(result, supportedSSHCommands)
|
|
return result
|
|
}
|