mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-06 22:30:56 +03:00
Windows: manually check if we can bind on the configured port/ports
Windows allows the coexistence of three types of sockets on the same transport-layer service port, for example, 127.0.0.1:8080, [::1]:8080 and [::ffff:0.0.0.0]:8080 Go don't properly handles this, so we use a ugly hack Fixes #350
This commit is contained in:
@@ -211,6 +211,7 @@ func (c *Configuration) Initialize(configDir string) error {
|
|||||||
go func(s *Server) {
|
go func(s *Server) {
|
||||||
ftpServer := ftpserver.NewFtpServer(s)
|
ftpServer := ftpserver.NewFtpServer(s)
|
||||||
logger.Info(logSender, "", "starting FTP serving, binding: %v", s.binding.GetAddress())
|
logger.Info(logSender, "", "starting FTP serving, binding: %v", s.binding.GetAddress())
|
||||||
|
utils.CheckTCP4Port(s.binding.Port)
|
||||||
exitChannel <- ftpServer.ListenAndServe()
|
exitChannel <- ftpServer.ListenAndServe()
|
||||||
}(server)
|
}(server)
|
||||||
|
|
||||||
|
|||||||
@@ -232,6 +232,7 @@ func (c *Configuration) Initialize(configDir string) error {
|
|||||||
|
|
||||||
go func(binding Binding) {
|
go func(binding Binding) {
|
||||||
addr := binding.GetAddress()
|
addr := binding.GetAddress()
|
||||||
|
utils.CheckTCP4Port(binding.Port)
|
||||||
listener, err := net.Listen("tcp", addr)
|
listener, err := net.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn(logSender, "", "error starting listener on address %v: %v", addr, err)
|
logger.Warn(logSender, "", "error starting listener on address %v: %v", addr, err)
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
logSender = "utils"
|
logSender = "utils"
|
||||||
|
osWindows = "windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsStringInSlice searches a string in a slice and returns true if the string is found
|
// IsStringInSlice searches a string in a slice and returns true if the string is found
|
||||||
@@ -373,7 +374,7 @@ func IsFileInputValid(fileInput string) bool {
|
|||||||
// the -l flag will be ignored and the -c flag will get the value `C:\ProgramData\SFTPGO" -l sftpgo.log`
|
// the -l flag will be ignored and the -c flag will get the value `C:\ProgramData\SFTPGO" -l sftpgo.log`
|
||||||
// since the backslash after SFTPGO escape the double quote. This is definitely a bad user input
|
// since the backslash after SFTPGO escape the double quote. This is definitely a bad user input
|
||||||
func CleanDirInput(dirInput string) string {
|
func CleanDirInput(dirInput string) string {
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == osWindows {
|
||||||
for strings.HasSuffix(dirInput, "\"") {
|
for strings.HasSuffix(dirInput, "\"") {
|
||||||
dirInput = strings.TrimSuffix(dirInput, "\"")
|
dirInput = strings.TrimSuffix(dirInput, "\"")
|
||||||
}
|
}
|
||||||
@@ -414,7 +415,7 @@ func HTTPListenAndServe(srv *http.Server, address string, port int, isTLS bool,
|
|||||||
var listener net.Listener
|
var listener net.Listener
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if filepath.IsAbs(address) && runtime.GOOS != "windows" {
|
if filepath.IsAbs(address) && runtime.GOOS != osWindows {
|
||||||
if !IsFileInputValid(address) {
|
if !IsFileInputValid(address) {
|
||||||
return fmt.Errorf("invalid socket address %#v", address)
|
return fmt.Errorf("invalid socket address %#v", address)
|
||||||
}
|
}
|
||||||
@@ -427,6 +428,7 @@ func HTTPListenAndServe(srv *http.Server, address string, port int, isTLS bool,
|
|||||||
|
|
||||||
listener, err = net.Listen("unix", address)
|
listener, err = net.Listen("unix", address)
|
||||||
} else {
|
} else {
|
||||||
|
CheckTCP4Port(port)
|
||||||
listener, err = net.Listen("tcp", fmt.Sprintf("%s:%d", address, port))
|
listener, err = net.Listen("tcp", fmt.Sprintf("%s:%d", address, port))
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -462,7 +464,7 @@ func GetTLSCiphersFromNames(cipherNames []string) []uint16 {
|
|||||||
// This can be verified using openssl x509 -in cert.crt -text -noout
|
// This can be verified using openssl x509 -in cert.crt -text -noout
|
||||||
func EncodeTLSCertToPem(tlsCert *x509.Certificate) (string, error) {
|
func EncodeTLSCertToPem(tlsCert *x509.Certificate) (string, error) {
|
||||||
if len(tlsCert.Raw) == 0 {
|
if len(tlsCert.Raw) == 0 {
|
||||||
return "", errors.New("Invalid x509 certificate, no der contents")
|
return "", errors.New("invalid x509 certificate, no der contents")
|
||||||
}
|
}
|
||||||
publicKeyBlock := pem.Block{
|
publicKeyBlock := pem.Block{
|
||||||
Type: "CERTIFICATE",
|
Type: "CERTIFICATE",
|
||||||
@@ -470,3 +472,20 @@ func EncodeTLSCertToPem(tlsCert *x509.Certificate) (string, error) {
|
|||||||
}
|
}
|
||||||
return string(pem.EncodeToMemory(&publicKeyBlock)), nil
|
return string(pem.EncodeToMemory(&publicKeyBlock)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckTCP4Port quits the app if bind to the given IPv4 port.
|
||||||
|
// This is a ugly hack to avoid to bind on an already used port.
|
||||||
|
// It is required on Windows only.
|
||||||
|
// https://github.com/golang/go/issues/45150
|
||||||
|
func CheckTCP4Port(port int) {
|
||||||
|
if runtime.GOOS != osWindows {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
listener, err := net.Listen("tcp4", fmt.Sprintf(":%d", port))
|
||||||
|
if err != nil {
|
||||||
|
logger.ErrorToConsole("unable to bind tcp4 address: %v", err)
|
||||||
|
logger.Error(logSender, "", "unable to bind tcp4 address: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
listener.Close()
|
||||||
|
}
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ type VirtualFolder struct {
|
|||||||
QuotaFiles int `json:"quota_files"`
|
QuotaFiles int `json:"quota_files"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetFilesystem returns the filesystem for this folder
|
||||||
func (v *VirtualFolder) GetFilesystem(connectionID string) (Fs, error) {
|
func (v *VirtualFolder) GetFilesystem(connectionID string) (Fs, error) {
|
||||||
switch v.FsConfig.Provider {
|
switch v.FsConfig.Provider {
|
||||||
case S3FilesystemProvider:
|
case S3FilesystemProvider:
|
||||||
|
|||||||
@@ -80,11 +80,13 @@ func (s *webDavServer) listenAndServe(compressor *middleware.Compressor) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.Info(logSender, "", "starting HTTPS serving, binding: %v", s.binding.GetAddress())
|
logger.Info(logSender, "", "starting HTTPS serving, binding: %v", s.binding.GetAddress())
|
||||||
|
utils.CheckTCP4Port(s.binding.Port)
|
||||||
return httpServer.ListenAndServeTLS("", "")
|
return httpServer.ListenAndServeTLS("", "")
|
||||||
}
|
}
|
||||||
s.binding.EnableHTTPS = false
|
s.binding.EnableHTTPS = false
|
||||||
serviceStatus.Bindings = append(serviceStatus.Bindings, s.binding)
|
serviceStatus.Bindings = append(serviceStatus.Bindings, s.binding)
|
||||||
logger.Info(logSender, "", "starting HTTP serving, binding: %v", s.binding.GetAddress())
|
logger.Info(logSender, "", "starting HTTP serving, binding: %v", s.binding.GetAddress())
|
||||||
|
utils.CheckTCP4Port(s.binding.Port)
|
||||||
return httpServer.ListenAndServe()
|
return httpServer.ListenAndServe()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user