diff --git a/Dockerfile.alpine b/Dockerfile.alpine index aa3b6029..19452483 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -26,7 +26,7 @@ RUN set -xe && \ go build $(if [ -n "${FEATURES}" ]; then echo "-tags ${FEATURES}"; fi) -trimpath -ldflags "-s -w -X github.com/drakkan/sftpgo/v2/version.commit=${COMMIT_SHA} -X github.com/drakkan/sftpgo/v2/version.date=`date -u +%FT%TZ`" -v -o sftpgo -FROM alpine:3.15 +FROM alpine:3.16 # Set to "true" to install jq and the optional git and rsync dependencies ARG INSTALL_OPTIONAL_PACKAGES=false diff --git a/acme/acme.go b/acme/acme.go index d55e268e..76900192 100644 --- a/acme/acme.go +++ b/acme/acme.go @@ -216,7 +216,7 @@ func (c *Configuration) checkDomains() { domains = append(domains, d) } } - c.Domains = util.RemoveDuplicates(domains) + c.Domains = util.RemoveDuplicates(domains, true) } func (c *Configuration) setLockTime() error { diff --git a/common/common.go b/common/common.go index 196e1203..d961b77e 100644 --- a/common/common.go +++ b/common/common.go @@ -141,6 +141,9 @@ var ( // Initialize sets the common configuration func Initialize(c Configuration, isShared int) error { Config = c + Config.Actions.ExecuteOn = util.RemoveDuplicates(Config.Actions.ExecuteOn, true) + Config.Actions.ExecuteSync = util.RemoveDuplicates(Config.Actions.ExecuteSync, true) + Config.ProxyAllowed = util.RemoveDuplicates(Config.ProxyAllowed, true) Config.idleLoginTimeout = 2 * time.Minute Config.idleTimeoutAsDuration = time.Duration(Config.IdleTimeout) * time.Minute startPeriodicTimeoutTicker(periodicTimeoutCheckInterval) diff --git a/common/defender.go b/common/defender.go index 1d137067..3b02df55 100644 --- a/common/defender.go +++ b/common/defender.go @@ -299,6 +299,7 @@ func addEntriesToList(entries []string, hostList *HostList, listName string) *Ho cdrLoaded := 0 for _, entry := range entries { + entry = strings.TrimSpace(entry) if strings.LastIndex(entry, "/") > 0 { cdrCount++ _, network, err := net.ParseCIDR(entry) diff --git a/common/ratelimiter.go b/common/ratelimiter.go index 1f68b4f0..bdaac675 100644 --- a/common/ratelimiter.go +++ b/common/ratelimiter.go @@ -81,7 +81,7 @@ func (r *RateLimiterConfig) validate() error { return fmt.Errorf("invalid entries_hard_limit %v must be > %v", r.EntriesHardLimit, r.EntriesSoftLimit) } } - r.Protocols = util.RemoveDuplicates(r.Protocols) + r.Protocols = util.RemoveDuplicates(r.Protocols, true) for _, protocol := range r.Protocols { if !util.Contains(rateLimiterProtocolValues, protocol) { return fmt.Errorf("invalid protocol %#v", protocol) diff --git a/common/tlsutils.go b/common/tlsutils.go index 2e58eb5c..f12147b4 100644 --- a/common/tlsutils.go +++ b/common/tlsutils.go @@ -204,13 +204,13 @@ func (m *CertManager) LoadRootCAs() error { // SetCACertificates sets the root CA authorities file paths. // This should not be changed at runtime func (m *CertManager) SetCACertificates(caCertificates []string) { - m.caCertificates = caCertificates + m.caCertificates = util.RemoveDuplicates(caCertificates, true) } // SetCARevocationLists sets the CA revocation lists file paths. // This should not be changed at runtime func (m *CertManager) SetCARevocationLists(caRevocationLists []string) { - m.caRevocationLists = caRevocationLists + m.caRevocationLists = util.RemoveDuplicates(caRevocationLists, true) } // NewCertManager creates a new certificate manager diff --git a/dataprovider/admin.go b/dataprovider/admin.go index 938b77e6..aab891f3 100644 --- a/dataprovider/admin.go +++ b/dataprovider/admin.go @@ -176,7 +176,7 @@ func (a *Admin) validateRecoveryCodes() error { } func (a *Admin) validatePermissions() error { - a.Permissions = util.RemoveDuplicates(a.Permissions) + a.Permissions = util.RemoveDuplicates(a.Permissions, false) if len(a.Permissions) == 0 { return util.NewValidationError("please grant some permissions to this admin") } @@ -220,7 +220,7 @@ func (a *Admin) validate() error { if a.Email != "" && !util.IsEmailValid(a.Email) { return util.NewValidationError(fmt.Sprintf("email %#v is not valid", a.Email)) } - a.Filters.AllowList = util.RemoveDuplicates(a.Filters.AllowList) + a.Filters.AllowList = util.RemoveDuplicates(a.Filters.AllowList, false) for _, IPMask := range a.Filters.AllowList { _, _, err := net.ParseCIDR(IPMask) if err != nil { diff --git a/dataprovider/dataprovider.go b/dataprovider/dataprovider.go index af50bf21..73c2f221 100644 --- a/dataprovider/dataprovider.go +++ b/dataprovider/dataprovider.go @@ -712,6 +712,8 @@ func SetTempPath(fsPath string) { func Initialize(cnf Config, basePath string, checkAdmins bool) error { var err error config = cnf + config.Actions.ExecuteOn = util.RemoveDuplicates(config.Actions.ExecuteOn, true) + config.Actions.ExecuteFor = util.RemoveDuplicates(config.Actions.ExecuteFor, true) cnf.BackupsPath = getConfigPath(cnf.BackupsPath, basePath) if cnf.BackupsPath == "" { @@ -1736,7 +1738,7 @@ func UpdateFolder(folder *vfs.BaseVirtualFolder, users []string, groups []string usersInGroups, errGrp := provider.getUsersInGroups(groups) if errGrp == nil { users = append(users, usersInGroups...) - users = util.RemoveDuplicates(users) + users = util.RemoveDuplicates(users, false) } else { providerLog(logger.LevelWarn, "unable to get users in groups %+v: %v", groups, errGrp) } @@ -1767,7 +1769,7 @@ func DeleteFolder(folderName, executor, ipAddress string) error { usersInGroups, errGrp := provider.getUsersInGroups(folder.Groups) if errGrp == nil { users = append(users, usersInGroups...) - users = util.RemoveDuplicates(users) + users = util.RemoveDuplicates(users, false) } else { providerLog(logger.LevelWarn, "unable to get users in groups %+v: %v", folder.Groups, errGrp) } @@ -2156,7 +2158,7 @@ func validateUserPermissions(permsToCheck map[string][]string) (map[string][]str if util.Contains(perms, PermAny) { permissions[cleanedDir] = []string{PermAny} } else { - permissions[cleanedDir] = util.RemoveDuplicates(perms) + permissions[cleanedDir] = util.RemoveDuplicates(perms, false) } } @@ -2193,7 +2195,7 @@ func validatePublicKeys(user *User) error { } validatedKeys = append(validatedKeys, k) } - user.PublicKeys = util.RemoveDuplicates(validatedKeys) + user.PublicKeys = util.RemoveDuplicates(validatedKeys, false) return nil } @@ -2235,8 +2237,8 @@ func validateFiltersPatternExtensions(baseFilters *sdk.BaseUserFilters) error { } denied = append(denied, strings.ToLower(pattern)) } - f.AllowedPatterns = util.RemoveDuplicates(allowed) - f.DeniedPatterns = util.RemoveDuplicates(denied) + f.AllowedPatterns = util.RemoveDuplicates(allowed, false) + f.DeniedPatterns = util.RemoveDuplicates(denied, false) filters = append(filters, f) filteredPaths = append(filteredPaths, cleanedPath) } @@ -2260,14 +2262,14 @@ func checkEmptyFiltersStruct(filters *sdk.BaseUserFilters) { } func validateIPFilters(filters *sdk.BaseUserFilters) error { - filters.DeniedIP = util.RemoveDuplicates(filters.DeniedIP) + filters.DeniedIP = util.RemoveDuplicates(filters.DeniedIP, false) for _, IPMask := range filters.DeniedIP { _, _, err := net.ParseCIDR(IPMask) if err != nil { return util.NewValidationError(fmt.Sprintf("could not parse denied IP/Mask %#v: %v", IPMask, err)) } } - filters.AllowedIP = util.RemoveDuplicates(filters.AllowedIP) + filters.AllowedIP = util.RemoveDuplicates(filters.AllowedIP, false) for _, IPMask := range filters.AllowedIP { _, _, err := net.ParseCIDR(IPMask) if err != nil { @@ -2307,7 +2309,7 @@ func validateBandwidthLimitsFilter(filters *sdk.BaseUserFilters) error { func validateTransferLimitsFilter(filters *sdk.BaseUserFilters) error { for idx, limit := range filters.DataTransferLimits { - filters.DataTransferLimits[idx].Sources = util.RemoveDuplicates(limit.Sources) + filters.DataTransferLimits[idx].Sources = util.RemoveDuplicates(limit.Sources, false) if len(limit.Sources) == 0 { return util.NewValidationError("no data transfer limit source specified") } diff --git a/dataprovider/share.go b/dataprovider/share.go index e4ec1193..8589cb42 100644 --- a/dataprovider/share.go +++ b/dataprovider/share.go @@ -196,7 +196,7 @@ func (s *Share) validatePaths() error { for idx := range s.Paths { s.Paths[idx] = util.CleanPath(s.Paths[idx]) } - s.Paths = util.RemoveDuplicates(s.Paths) + s.Paths = util.RemoveDuplicates(s.Paths, false) if s.Scope >= ShareScopeWrite && len(s.Paths) != 1 { return util.NewValidationError("the write share scope requires exactly one path") } @@ -248,7 +248,7 @@ func (s *Share) validate() error { if err := s.hashPassword(); err != nil { return err } - s.AllowFrom = util.RemoveDuplicates(s.AllowFrom) + s.AllowFrom = util.RemoveDuplicates(s.AllowFrom, false) for _, IPMask := range s.AllowFrom { _, _, err := net.ParseCIDR(IPMask) if err != nil { diff --git a/dataprovider/sqlcommon.go b/dataprovider/sqlcommon.go index 865e34fe..d0f82128 100644 --- a/dataprovider/sqlcommon.go +++ b/dataprovider/sqlcommon.go @@ -1301,7 +1301,7 @@ func sqlCommonGetRecentlyUpdatedUsers(after int64, dbHandle sqlQuerier) ([]User, groupNames = append(groupNames, g.Name) } } - groupNames = util.RemoveDuplicates(groupNames) + groupNames = util.RemoveDuplicates(groupNames, false) groups, err := sqlCommonGetGroupsWithNames(groupNames, dbHandle) if err != nil { return users, err @@ -1372,7 +1372,7 @@ func sqlCommonGetUsersForQuotaCheck(toFetch map[string]bool, dbHandle sqlQuerier groupNames = append(groupNames, g.Name) } } - groupNames = util.RemoveDuplicates(groupNames) + groupNames = util.RemoveDuplicates(groupNames, false) if len(groupNames) == 0 { return users, nil } diff --git a/dataprovider/user.go b/dataprovider/user.go index 505a1392..8bfcd5bd 100644 --- a/dataprovider/user.go +++ b/dataprovider/user.go @@ -1728,12 +1728,12 @@ func (u *User) mergeFilePatterns(group Group, groupType int) { } func (u *User) removeDuplicatesAfterGroupMerge() { - u.Filters.AllowedIP = util.RemoveDuplicates(u.Filters.AllowedIP) - u.Filters.DeniedIP = util.RemoveDuplicates(u.Filters.DeniedIP) - u.Filters.DeniedLoginMethods = util.RemoveDuplicates(u.Filters.DeniedLoginMethods) - u.Filters.DeniedProtocols = util.RemoveDuplicates(u.Filters.DeniedProtocols) - u.Filters.WebClient = util.RemoveDuplicates(u.Filters.WebClient) - u.Filters.TwoFactorAuthProtocols = util.RemoveDuplicates(u.Filters.TwoFactorAuthProtocols) + u.Filters.AllowedIP = util.RemoveDuplicates(u.Filters.AllowedIP, false) + u.Filters.DeniedIP = util.RemoveDuplicates(u.Filters.DeniedIP, false) + u.Filters.DeniedLoginMethods = util.RemoveDuplicates(u.Filters.DeniedLoginMethods, false) + u.Filters.DeniedProtocols = util.RemoveDuplicates(u.Filters.DeniedProtocols, false) + u.Filters.WebClient = util.RemoveDuplicates(u.Filters.WebClient, false) + u.Filters.TwoFactorAuthProtocols = util.RemoveDuplicates(u.Filters.TwoFactorAuthProtocols, false) u.SetEmptySecretsIfNil() u.groupSettingsApplied = true } diff --git a/go.mod b/go.mod index b63d4425..21648fe5 100644 --- a/go.mod +++ b/go.mod @@ -154,10 +154,10 @@ require ( golang.org/x/tools v0.1.10 // indirect golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20220527130721-00d5c0f3be58 // indirect + google.golang.org/genproto v0.0.0-20220531134929-86cf59382f1b // indirect google.golang.org/grpc v1.46.2 // indirect google.golang.org/protobuf v1.28.0 // indirect - gopkg.in/ini.v1 v1.66.5 // indirect + gopkg.in/ini.v1 v1.66.6 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index f2169f3c..84b56ff7 100644 --- a/go.sum +++ b/go.sum @@ -1200,8 +1200,8 @@ google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220527130721-00d5c0f3be58 h1:a221mAAEAzq4Lz6ZWRkcS8ptb2mxoxYSt4N68aRyQHM= -google.golang.org/genproto v0.0.0-20220527130721-00d5c0f3be58/go.mod h1:yKyY4AMRwFiC8yMMNaMi+RkCnjZJt9LoWuvhXjMs+To= +google.golang.org/genproto v0.0.0-20220531134929-86cf59382f1b h1:X+VXcq/YthmZqFvppQm4Wleg4o//OmY2uttDv1vDvRo= +google.golang.org/genproto v0.0.0-20220531134929-86cf59382f1b/go.mod h1:yKyY4AMRwFiC8yMMNaMi+RkCnjZJt9LoWuvhXjMs+To= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1257,8 +1257,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= -gopkg.in/ini.v1 v1.66.5 h1:zfiCO0p88Fj4f6NR6KR5WdGMQ02U8vlDnN6HuD2xv5o= -gopkg.in/ini.v1 v1.66.5/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI= +gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= diff --git a/httpd/api_http_user.go b/httpd/api_http_user.go index a9d3cb02..4fe3c23e 100644 --- a/httpd/api_http_user.go +++ b/httpd/api_http_user.go @@ -374,7 +374,7 @@ func getUserFilesAsZipStream(w http.ResponseWriter, r *http.Request) { filesList[idx] = util.CleanPath(filesList[idx]) } - filesList = util.RemoveDuplicates(filesList) + filesList = util.RemoveDuplicates(filesList, false) w.Header().Set("Content-Disposition", "attachment; filename=\"sftpgo-download.zip\"") renderCompressedFiles(w, connection, baseDir, filesList, nil) diff --git a/httpd/api_utils.go b/httpd/api_utils.go index b86155df..dd0c9a87 100644 --- a/httpd/api_utils.go +++ b/httpd/api_utils.go @@ -131,7 +131,7 @@ func getCommaSeparatedQueryParam(r *http.Request, key string) []string { } } - return util.RemoveDuplicates(result) + return util.RemoveDuplicates(result, false) } func getBoolQueryParam(r *http.Request, param string) bool { diff --git a/httpd/server.go b/httpd/server.go index 39ed5842..0e6b1819 100644 --- a/httpd/server.go +++ b/httpd/server.go @@ -1112,10 +1112,10 @@ func (s *httpdServer) initializeRouter() { } if s.cors.Enabled { c := cors.New(cors.Options{ - AllowedOrigins: s.cors.AllowedOrigins, - AllowedMethods: s.cors.AllowedMethods, - AllowedHeaders: s.cors.AllowedHeaders, - ExposedHeaders: s.cors.ExposedHeaders, + AllowedOrigins: util.RemoveDuplicates(s.cors.AllowedOrigins, true), + AllowedMethods: util.RemoveDuplicates(s.cors.AllowedMethods, true), + AllowedHeaders: util.RemoveDuplicates(s.cors.AllowedHeaders, true), + ExposedHeaders: util.RemoveDuplicates(s.cors.ExposedHeaders, true), MaxAge: s.cors.MaxAge, AllowCredentials: s.cors.AllowCredentials, }) diff --git a/sftpd/internal_test.go b/sftpd/internal_test.go index 60fe472a..bb203a5c 100644 --- a/sftpd/internal_test.go +++ b/sftpd/internal_test.go @@ -1886,6 +1886,17 @@ func TestSupportedSecurityOptions(t *testing.T) { c.KexAlgorithms = append(c.KexAlgorithms, "not a kex") err = c.configureSecurityOptions(serverConfig) assert.Error(t, err) + c.KexAlgorithms = supportedKexAlgos + c.MACs = []string{ + " hmac-sha2-256-etm@openssh.com ", "hmac-sha2-256", + " hmac-sha2-512-etm@openssh.com", "hmac-sha2-512 ", + "hmac-sha1 ", " hmac-sha1-96", + } + err = c.configureSecurityOptions(serverConfig) + assert.NoError(t, err) + assert.Equal(t, supportedCiphers, serverConfig.Ciphers) + assert.Equal(t, supportedMACs, serverConfig.MACs) + assert.Equal(t, supportedKexAlgos, serverConfig.KeyExchanges) } func TestLoadHostKeys(t *testing.T) { diff --git a/sftpd/server.go b/sftpd/server.go index 5060ed0d..c196ceeb 100644 --- a/sftpd/server.go +++ b/sftpd/server.go @@ -249,7 +249,7 @@ func (c *Configuration) getServerConfig() *ssh.ServerConfig { } func (c *Configuration) updateSupportedAuthentications() { - serviceStatus.Authentications = util.RemoveDuplicates(serviceStatus.Authentications) + serviceStatus.Authentications = util.RemoveDuplicates(serviceStatus.Authentications, false) if util.Contains(serviceStatus.Authentications, dataprovider.LoginMethodPassword) && util.Contains(serviceStatus.Authentications, dataprovider.SSHLoginMethodPublicKey) { @@ -364,7 +364,7 @@ func (c *Configuration) configureSecurityOptions(serverConfig *ssh.ServerConfig) if len(c.HostKeyAlgorithms) == 0 { c.HostKeyAlgorithms = preferredHostKeyAlgos } else { - c.HostKeyAlgorithms = util.RemoveDuplicates(c.HostKeyAlgorithms) + c.HostKeyAlgorithms = util.RemoveDuplicates(c.HostKeyAlgorithms, true) } for _, hostKeyAlgo := range c.HostKeyAlgorithms { if !util.Contains(supportedHostKeyAlgos, hostKeyAlgo) { @@ -374,7 +374,7 @@ func (c *Configuration) configureSecurityOptions(serverConfig *ssh.ServerConfig) serverConfig.HostKeyAlgorithms = c.HostKeyAlgorithms if len(c.KexAlgorithms) > 0 { - c.KexAlgorithms = util.RemoveDuplicates(c.KexAlgorithms) + c.KexAlgorithms = util.RemoveDuplicates(c.KexAlgorithms, true) for _, kex := range c.KexAlgorithms { if !util.Contains(supportedKexAlgos, kex) { return fmt.Errorf("unsupported key-exchange algorithm %#v", kex) @@ -383,7 +383,7 @@ func (c *Configuration) configureSecurityOptions(serverConfig *ssh.ServerConfig) serverConfig.KeyExchanges = c.KexAlgorithms } if len(c.Ciphers) > 0 { - c.Ciphers = util.RemoveDuplicates(c.Ciphers) + c.Ciphers = util.RemoveDuplicates(c.Ciphers, true) for _, cipher := range c.Ciphers { if !util.Contains(supportedCiphers, cipher) { return fmt.Errorf("unsupported cipher %#v", cipher) @@ -392,7 +392,7 @@ func (c *Configuration) configureSecurityOptions(serverConfig *ssh.ServerConfig) serverConfig.Ciphers = c.Ciphers } if len(c.MACs) > 0 { - c.MACs = util.RemoveDuplicates(c.MACs) + c.MACs = util.RemoveDuplicates(c.MACs, true) for _, mac := range c.MACs { if !util.Contains(supportedMACs, mac) { return fmt.Errorf("unsupported MAC algorithm %#v", mac) @@ -727,6 +727,7 @@ func (c *Configuration) checkSSHCommands() { } sshCommands := []string{} for _, command := range c.EnabledSSHCommands { + command = strings.TrimSpace(command) if util.Contains(supportedSSHCommands, command) { sshCommands = append(sshCommands, command) } else { @@ -780,6 +781,7 @@ func (c *Configuration) generateDefaultHostKeys(configDir string) error { func (c *Configuration) checkHostKeyAutoGeneration(configDir string) error { for _, k := range c.HostKeys { + k = strings.TrimSpace(k) if filepath.IsAbs(k) { if _, err := os.Stat(k); errors.Is(err, fs.ErrNotExist) { keyName := filepath.Base(k) @@ -837,6 +839,7 @@ func (c *Configuration) checkAndLoadHostKeys(configDir string, serverConfig *ssh } serviceStatus.HostKeys = nil for _, hostKey := range c.HostKeys { + hostKey = strings.TrimSpace(hostKey) if !util.IsFileInputValid(hostKey) { logger.Warn(logSender, "", "unable to load invalid host key %#v", hostKey) logger.WarnToConsole("unable to load invalid host key %#v", hostKey) @@ -887,6 +890,7 @@ func (c *Configuration) checkAndLoadHostKeys(configDir string, serverConfig *ssh func (c *Configuration) loadHostCertificates(configDir string) ([]*ssh.Certificate, error) { var certs []*ssh.Certificate for _, certPath := range c.HostCertificates { + certPath = strings.TrimSpace(certPath) if !util.IsFileInputValid(certPath) { logger.Warn(logSender, "", "unable to load invalid host certificate %#v", certPath) logger.WarnToConsole("unable to load invalid host certificate %#v", certPath) @@ -917,6 +921,7 @@ func (c *Configuration) loadHostCertificates(configDir string) ([]*ssh.Certifica func (c *Configuration) initializeCertChecker(configDir string) error { for _, keyPath := range c.TrustedUserCAKeys { + keyPath = strings.TrimSpace(keyPath) if !util.IsFileInputValid(keyPath) { logger.Warn(logSender, "", "unable to load invalid trusted user CA key %#v", keyPath) logger.WarnToConsole("unable to load invalid trusted user CA key %#v", keyPath) diff --git a/util/util.go b/util/util.go index 9dccdded..5464aa01 100644 --- a/util/util.go +++ b/util/util.go @@ -66,13 +66,16 @@ func IsStringPrefixInSlice(obj string, list []string) bool { } // RemoveDuplicates returns a new slice removing any duplicate element from the initial one -func RemoveDuplicates(obj []string) []string { +func RemoveDuplicates(obj []string, trim bool) []string { if len(obj) == 0 { return obj } seen := make(map[string]bool) validIdx := 0 for _, item := range obj { + if trim { + item = strings.TrimSpace(item) + } if !seen[item] { seen[item] = true obj[validIdx] = item @@ -462,7 +465,7 @@ func HTTPListenAndServe(srv *http.Server, address string, port int, isTLS bool, func GetTLSCiphersFromNames(cipherNames []string) []uint16 { var ciphers []uint16 - for _, name := range RemoveDuplicates(cipherNames) { + for _, name := range RemoveDuplicates(cipherNames, false) { for _, c := range tls.CipherSuites() { if c.Name == strings.TrimSpace(name) { ciphers = append(ciphers, c.ID) diff --git a/webdavd/server.go b/webdavd/server.go index 07490ba5..ee7c339e 100644 --- a/webdavd/server.go +++ b/webdavd/server.go @@ -43,10 +43,10 @@ func (s *webDavServer) listenAndServe(compressor *middleware.Compressor) error { } if s.config.Cors.Enabled { c := cors.New(cors.Options{ - AllowedOrigins: s.config.Cors.AllowedOrigins, - AllowedMethods: s.config.Cors.AllowedMethods, - AllowedHeaders: s.config.Cors.AllowedHeaders, - ExposedHeaders: s.config.Cors.ExposedHeaders, + AllowedOrigins: util.RemoveDuplicates(s.config.Cors.AllowedOrigins, true), + AllowedMethods: util.RemoveDuplicates(s.config.Cors.AllowedMethods, true), + AllowedHeaders: util.RemoveDuplicates(s.config.Cors.AllowedHeaders, true), + ExposedHeaders: util.RemoveDuplicates(s.config.Cors.ExposedHeaders, true), MaxAge: s.config.Cors.MaxAge, AllowCredentials: s.config.Cors.AllowCredentials, OptionsPassthrough: true,