1
0
mirror of https://github.com/drakkan/sftpgo.git synced 2025-12-05 22:17:20 +02: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:
Nicola Murino
2021-03-21 22:21:04 +01:00
parent f7c7e2951d
commit 54c0c1b80d
5 changed files with 27 additions and 3 deletions

View File

@@ -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()
}