mirror of
https://github.com/drakkan/sftpgo.git
synced 2024-11-22 07:30:25 +00: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:
parent
f7c7e2951d
commit
54c0c1b80d
5 changed files with 27 additions and 3 deletions
|
@ -211,6 +211,7 @@ func (c *Configuration) Initialize(configDir string) error {
|
|||
go func(s *Server) {
|
||||
ftpServer := ftpserver.NewFtpServer(s)
|
||||
logger.Info(logSender, "", "starting FTP serving, binding: %v", s.binding.GetAddress())
|
||||
utils.CheckTCP4Port(s.binding.Port)
|
||||
exitChannel <- ftpServer.ListenAndServe()
|
||||
}(server)
|
||||
|
||||
|
|
|
@ -232,6 +232,7 @@ func (c *Configuration) Initialize(configDir string) error {
|
|||
|
||||
go func(binding Binding) {
|
||||
addr := binding.GetAddress()
|
||||
utils.CheckTCP4Port(binding.Port)
|
||||
listener, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
logger.Warn(logSender, "", "error starting listener on address %v: %v", addr, err)
|
||||
|
|
|
@ -34,6 +34,7 @@ import (
|
|||
|
||||
const (
|
||||
logSender = "utils"
|
||||
osWindows = "windows"
|
||||
)
|
||||
|
||||
// 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`
|
||||
// since the backslash after SFTPGO escape the double quote. This is definitely a bad user input
|
||||
func CleanDirInput(dirInput string) string {
|
||||
if runtime.GOOS == "windows" {
|
||||
if runtime.GOOS == osWindows {
|
||||
for strings.HasSuffix(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 err error
|
||||
|
||||
if filepath.IsAbs(address) && runtime.GOOS != "windows" {
|
||||
if filepath.IsAbs(address) && runtime.GOOS != osWindows {
|
||||
if !IsFileInputValid(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)
|
||||
} else {
|
||||
CheckTCP4Port(port)
|
||||
listener, err = net.Listen("tcp", fmt.Sprintf("%s:%d", address, port))
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -462,7 +464,7 @@ func GetTLSCiphersFromNames(cipherNames []string) []uint16 {
|
|||
// This can be verified using openssl x509 -in cert.crt -text -noout
|
||||
func EncodeTLSCertToPem(tlsCert *x509.Certificate) (string, error) {
|
||||
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{
|
||||
Type: "CERTIFICATE",
|
||||
|
@ -470,3 +472,20 @@ func EncodeTLSCertToPem(tlsCert *x509.Certificate) (string, error) {
|
|||
}
|
||||
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"`
|
||||
}
|
||||
|
||||
// GetFilesystem returns the filesystem for this folder
|
||||
func (v *VirtualFolder) GetFilesystem(connectionID string) (Fs, error) {
|
||||
switch v.FsConfig.Provider {
|
||||
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())
|
||||
utils.CheckTCP4Port(s.binding.Port)
|
||||
return httpServer.ListenAndServeTLS("", "")
|
||||
}
|
||||
s.binding.EnableHTTPS = false
|
||||
serviceStatus.Bindings = append(serviceStatus.Bindings, s.binding)
|
||||
logger.Info(logSender, "", "starting HTTP serving, binding: %v", s.binding.GetAddress())
|
||||
utils.CheckTCP4Port(s.binding.Port)
|
||||
return httpServer.ListenAndServe()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue