diff --git a/internal/config/config.go b/internal/config/config.go index 2a6e98f5..747d761a 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -855,25 +855,25 @@ func getRateLimitersFromEnv(idx int) { isSet := false - average, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__AVERAGE", idx)) + average, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__AVERAGE", idx), 64) if ok { rtlConfig.Average = average isSet = true } - period, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__PERIOD", idx)) + period, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__PERIOD", idx), 64) if ok { rtlConfig.Period = period isSet = true } - burst, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__BURST", idx)) + burst, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__BURST", idx), 0) if ok { rtlConfig.Burst = int(burst) isSet = true } - rtlType, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__TYPE", idx)) + rtlType, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__TYPE", idx), 0) if ok { rtlConfig.Type = int(rtlType) isSet = true @@ -891,13 +891,13 @@ func getRateLimitersFromEnv(idx int) { isSet = true } - softLimit, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__ENTRIES_SOFT_LIMIT", idx)) + softLimit, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__ENTRIES_SOFT_LIMIT", idx), 0) if ok { rtlConfig.EntriesSoftLimit = int(softLimit) isSet = true } - hardLimit, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__ENTRIES_HARD_LIMIT", idx)) + hardLimit, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__ENTRIES_HARD_LIMIT", idx), 0) if ok { rtlConfig.EntriesHardLimit = int(hardLimit) isSet = true @@ -933,7 +933,7 @@ func getKMSPluginFromEnv(idx int, pluginConfig *plugin.Config) bool { func getAuthPluginFromEnv(idx int, pluginConfig *plugin.Config) bool { isSet := false - authScope, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_PLUGINS__%v__AUTH_OPTIONS__SCOPE", idx)) + authScope, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_PLUGINS__%v__AUTH_OPTIONS__SCOPE", idx), 0) if ok { pluginConfig.AuthOptions.Scope = int(authScope) isSet = true @@ -963,13 +963,13 @@ func getNotifierPluginFromEnv(idx int, pluginConfig *plugin.Config) bool { isSet = true } - notifierRetryMaxTime, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_PLUGINS__%v__NOTIFIER_OPTIONS__RETRY_MAX_TIME", idx)) + notifierRetryMaxTime, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_PLUGINS__%v__NOTIFIER_OPTIONS__RETRY_MAX_TIME", idx), 0) if ok { pluginConfig.NotifierOptions.RetryMaxTime = int(notifierRetryMaxTime) isSet = true } - notifierRetryQueueMaxSize, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_PLUGINS__%v__NOTIFIER_OPTIONS__RETRY_QUEUE_MAX_SIZE", idx)) + notifierRetryQueueMaxSize, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_PLUGINS__%v__NOTIFIER_OPTIONS__RETRY_QUEUE_MAX_SIZE", idx), 0) if ok { pluginConfig.NotifierOptions.RetryQueueMaxSize = int(notifierRetryQueueMaxSize) isSet = true @@ -1045,7 +1045,7 @@ func getSFTPDBindindFromEnv(idx int) { isSet := false - port, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_SFTPD__BINDINGS__%v__PORT", idx)) + port, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_SFTPD__BINDINGS__%v__PORT", idx), 0) if ok { binding.Port = int(port) isSet = true @@ -1132,13 +1132,13 @@ func getFTPDBindingSecurityFromEnv(idx int, binding *ftpd.Binding) bool { isSet = true } - tlsMode, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__TLS_MODE", idx)) + tlsMode, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__TLS_MODE", idx), 0) if ok { binding.TLSMode = int(tlsMode) isSet = true } - tlsVer, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__MIN_TLS_VERSION", idx)) + tlsVer, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__MIN_TLS_VERSION", idx), 0) if ok { binding.MinTLSVersion = int(tlsVer) isSet = true @@ -1150,19 +1150,19 @@ func getFTPDBindingSecurityFromEnv(idx int, binding *ftpd.Binding) bool { isSet = true } - clientAuthType, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__CLIENT_AUTH_TYPE", idx)) + clientAuthType, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__CLIENT_AUTH_TYPE", idx), 0) if ok { binding.ClientAuthType = int(clientAuthType) isSet = true } - pasvSecurity, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__PASSIVE_CONNECTIONS_SECURITY", idx)) + pasvSecurity, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__PASSIVE_CONNECTIONS_SECURITY", idx), 0) if ok { binding.PassiveConnectionsSecurity = int(pasvSecurity) isSet = true } - activeSecurity, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__ACTIVE_CONNECTIONS_SECURITY", idx)) + activeSecurity, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__ACTIVE_CONNECTIONS_SECURITY", idx), 0) if ok { binding.ActiveConnectionsSecurity = int(activeSecurity) isSet = true @@ -1175,7 +1175,7 @@ func getFTPDBindingFromEnv(idx int) { binding := getDefaultFTPDBinding(idx) isSet := false - port, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__PORT", idx)) + port, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__PORT", idx), 0) if ok { binding.Port = int(port) isSet = true @@ -1249,7 +1249,7 @@ func getWebDAVDBindingProxyConfigsFromEnv(idx int, binding *webdavd.Binding) boo isSet = true } - clientIPHeaderDepth, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_WEBDAVD__BINDINGS__%v__CLIENT_IP_HEADER_DEPTH", idx)) + clientIPHeaderDepth, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_WEBDAVD__BINDINGS__%v__CLIENT_IP_HEADER_DEPTH", idx), 0) if ok { binding.ClientIPHeaderDepth = int(clientIPHeaderDepth) isSet = true @@ -1287,7 +1287,7 @@ func getWebDAVDBindingFromEnv(idx int) { isSet := false - port, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_WEBDAVD__BINDINGS__%v__PORT", idx)) + port, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_WEBDAVD__BINDINGS__%v__PORT", idx), 0) if ok { binding.Port = int(port) isSet = true @@ -1317,13 +1317,13 @@ func getWebDAVDBindingFromEnv(idx int) { isSet = true } - tlsVer, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_WEBDAVD__BINDINGS__%v__MIN_TLS_VERSION", idx)) + tlsVer, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_WEBDAVD__BINDINGS__%v__MIN_TLS_VERSION", idx), 0) if ok { binding.MinTLSVersion = int(tlsVer) isSet = true } - clientAuthType, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_WEBDAVD__BINDINGS__%v__CLIENT_AUTH_TYPE", idx)) + clientAuthType, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_WEBDAVD__BINDINGS__%v__CLIENT_AUTH_TYPE", idx), 0) if ok { binding.ClientAuthType = int(clientAuthType) isSet = true @@ -1444,7 +1444,7 @@ func getHTTPDSecurityConfFromEnv(idx int) (httpd.SecurityConf, bool) { //nolint: isSet = true } - stsSeconds, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__SECURITY__STS_SECONDS", idx)) + stsSeconds, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__SECURITY__STS_SECONDS", idx), 64) if ok { result.STSSeconds = stsSeconds isSet = true @@ -1746,7 +1746,7 @@ func getHTTPDBindingProxyConfigsFromEnv(idx int, binding *httpd.Binding) bool { isSet = true } - clientIPHeaderDepth, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__CLIENT_IP_HEADER_DEPTH", idx)) + clientIPHeaderDepth, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__CLIENT_IP_HEADER_DEPTH", idx), 0) if ok { binding.ClientIPHeaderDepth = int(clientIPHeaderDepth) isSet = true @@ -1759,7 +1759,7 @@ func getHTTPDBindingFromEnv(idx int) { //nolint:gocyclo binding := getDefaultHTTPBinding(idx) isSet := false - port, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__PORT", idx)) + port, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__PORT", idx), 0) if ok { binding.Port = int(port) isSet = true @@ -1801,7 +1801,7 @@ func getHTTPDBindingFromEnv(idx int) { //nolint:gocyclo isSet = true } - enabledLoginMethods, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__ENABLED_LOGIN_METHODS", idx)) + enabledLoginMethods, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__ENABLED_LOGIN_METHODS", idx), 0) if ok { binding.EnabledLoginMethods = int(enabledLoginMethods) isSet = true @@ -1819,13 +1819,13 @@ func getHTTPDBindingFromEnv(idx int) { //nolint:gocyclo isSet = true } - tlsVer, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__MIN_TLS_VERSION", idx)) + tlsVer, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__MIN_TLS_VERSION", idx), 0) if ok { binding.MinTLSVersion = int(tlsVer) isSet = true } - clientAuthType, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__CLIENT_AUTH_TYPE", idx)) + clientAuthType, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__CLIENT_AUTH_TYPE", idx), 0) if ok { binding.ClientAuthType = int(clientAuthType) isSet = true @@ -1841,7 +1841,7 @@ func getHTTPDBindingFromEnv(idx int) { //nolint:gocyclo isSet = true } - hideLoginURL, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__HIDE_LOGIN_URL", idx)) + hideLoginURL, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__HIDE_LOGIN_URL", idx), 0) if ok { binding.HideLoginURL = int(hideLoginURL) isSet = true @@ -1930,7 +1930,7 @@ func getCommandConfigsFromEnv(idx int) { cfg.Path = path } - timeout, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMAND__COMMANDS__%v__TIMEOUT", idx)) + timeout, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMAND__COMMANDS__%v__TIMEOUT", idx), 0) if ok { cfg.Timeout = int(timeout) } @@ -2148,10 +2148,10 @@ func lookupBoolFromEnv(envName string) (bool, bool) { return false, false } -func lookupIntFromEnv(envName string) (int64, bool) { +func lookupIntFromEnv(envName string, bitSize int) (int64, bool) { value, ok := os.LookupEnv(envName) if ok { - converted, err := strconv.ParseInt(strings.TrimSpace(value), 10, 64) + converted, err := strconv.ParseInt(strings.TrimSpace(value), 10, bitSize) if err == nil { return converted, ok } diff --git a/internal/httpd/api_events.go b/internal/httpd/api_events.go index 85fd8465..408dfb8f 100644 --- a/internal/httpd/api_events.go +++ b/internal/httpd/api_events.go @@ -98,7 +98,7 @@ func getFsSearchParamsFromRequest(r *http.Request) (eventsearcher.FsEventSearch, s.Protocols = getCommaSeparatedQueryParam(r, "protocols") statuses := getCommaSeparatedQueryParam(r, "statuses") for _, status := range statuses { - val, err := strconv.Atoi(status) + val, err := strconv.ParseInt(status, 10, 32) if err != nil { return s, util.NewValidationError(fmt.Sprintf("invalid status: %v", status)) } diff --git a/internal/httpd/webadmin.go b/internal/httpd/webadmin.go index 7b56b475..0c963322 100644 --- a/internal/httpd/webadmin.go +++ b/internal/httpd/webadmin.go @@ -1534,15 +1534,15 @@ func getFiltersFromUserPostFields(r *http.Request) (sdk.BaseUserFilters, error) if err != nil { return filters, fmt.Errorf("invalid max upload file size: %w", err) } - defaultSharesExpiration, err := strconv.ParseInt(r.Form.Get("default_shares_expiration"), 10, 64) + defaultSharesExpiration, err := strconv.Atoi(r.Form.Get("default_shares_expiration")) if err != nil { return filters, fmt.Errorf("invalid default shares expiration: %w", err) } - passwordExpiration, err := strconv.ParseInt(r.Form.Get("password_expiration"), 10, 64) + passwordExpiration, err := strconv.Atoi(r.Form.Get("password_expiration")) if err != nil { return filters, fmt.Errorf("invalid password expiration: %w", err) } - passwordStrength, err := strconv.ParseInt(r.Form.Get("password_strength"), 10, 64) + passwordStrength, err := strconv.Atoi(r.Form.Get("password_strength")) if err != nil { return filters, fmt.Errorf("invalid password strength: %w", err) } @@ -1559,9 +1559,9 @@ func getFiltersFromUserPostFields(r *http.Request) (sdk.BaseUserFilters, error) filters.FilePatterns = getFilePatternsFromPostField(r) filters.TLSUsername = sdk.TLSUsername(r.Form.Get("tls_username")) filters.WebClient = r.Form["web_client_options"] - filters.DefaultSharesExpiration = int(defaultSharesExpiration) - filters.PasswordExpiration = int(passwordExpiration) - filters.PasswordStrength = int(passwordStrength) + filters.DefaultSharesExpiration = defaultSharesExpiration + filters.PasswordExpiration = passwordExpiration + filters.PasswordStrength = passwordStrength hooks := r.Form["hooks"] if util.Contains(hooks, "external_auth_disabled") { filters.Hooks.ExternalAuthDisabled = true @@ -1830,11 +1830,11 @@ func getAdminFromPostFields(r *http.Request) (dataprovider.Admin, error) { admin.Filters.Preferences.HideUserPageSections = getAdminHiddenUserPageSections(r) admin.Filters.Preferences.DefaultUsersExpiration = 0 if val := r.Form.Get("default_users_expiration"); val != "" { - defaultUsersExpiration, err := strconv.ParseInt(r.Form.Get("default_users_expiration"), 10, 64) + defaultUsersExpiration, err := strconv.Atoi(r.Form.Get("default_users_expiration")) if err != nil { return admin, fmt.Errorf("invalid default users expiration: %w", err) } - admin.Filters.Preferences.DefaultUsersExpiration = int(defaultUsersExpiration) + admin.Filters.Preferences.DefaultUsersExpiration = defaultUsersExpiration } for k := range r.Form { if strings.HasPrefix(k, "group") { @@ -2130,7 +2130,7 @@ func getGroupFromPostFields(r *http.Request) (dataprovider.Group, error) { if err != nil { return group, err } - expiresIn, err := strconv.ParseInt(r.Form.Get("expires_in"), 10, 64) + expiresIn, err := strconv.Atoi(r.Form.Get("expires_in")) if err != nil { return group, fmt.Errorf("invalid expires in: %w", err) } @@ -2159,7 +2159,7 @@ func getGroupFromPostFields(r *http.Request) (dataprovider.Group, error) { UploadDataTransfer: dataTransferUL, DownloadDataTransfer: dataTransferDL, TotalDataTransfer: dataTransferTotal, - ExpiresIn: int(expiresIn), + ExpiresIn: expiresIn, Filters: filters, }, FsConfig: fsConfig, diff --git a/internal/httpd/webclient.go b/internal/httpd/webclient.go index e6224153..e03b5891 100644 --- a/internal/httpd/webclient.go +++ b/internal/httpd/webclient.go @@ -1492,7 +1492,7 @@ func (s *httpdServer) handleClientShareLoginPost(w http.ResponseWriter, r *http. s.renderShareLoginPage(w, r.RequestURI, common.ErrInternalFailure.Error(), ipAddr) return } - next := r.URL.Query().Get("next") + next := path.Clean(r.URL.Query().Get("next")) if strings.HasPrefix(next, path.Join(webClientPubSharesPath, share.ShareID)) { http.Redirect(w, r, next, http.StatusFound) } diff --git a/internal/sftpd/scp.go b/internal/sftpd/scp.go index d0218490..586bb80e 100644 --- a/internal/sftpd/scp.go +++ b/internal/sftpd/scp.go @@ -29,7 +29,6 @@ import ( "github.com/drakkan/sftpgo/v2/internal/common" "github.com/drakkan/sftpgo/v2/internal/dataprovider" "github.com/drakkan/sftpgo/v2/internal/logger" - "github.com/drakkan/sftpgo/v2/internal/util" "github.com/drakkan/sftpgo/v2/internal/vfs" ) @@ -58,10 +57,9 @@ func (c *scpCommand) handle() (err error) { defer common.Connections.Remove(c.connection.GetID()) destPath := c.getDestPath() - commandType := c.getCommandType() - c.connection.Log(logger.LevelDebug, "handle scp command, args: %v user: %v command type: %v, dest path: %q", - c.args, c.connection.User.Username, commandType, destPath) - if commandType == "-t" { + c.connection.Log(logger.LevelDebug, "handle scp command, args: %v user: %s, dest path: %q", + c.args, c.connection.User.Username, destPath) + if c.hasFlag("t") { // -t means "to", so upload err = c.sendConfirmationMessage() if err != nil { @@ -71,7 +69,7 @@ func (c *scpCommand) handle() (err error) { if err != nil { return err } - } else if commandType == "-f" { + } else if c.hasFlag("f") { // -f means "from" so download err = c.readConfirmationMessage() if err != nil { @@ -351,7 +349,7 @@ func (c *scpCommand) sendDownloadProtocolMessages(virtualDirPath string, stat os var err error if c.sendFileTime() { modTime := stat.ModTime().UnixNano() / 1000000000 - tCommand := fmt.Sprintf("T%v 0 %v 0\n", modTime, modTime) + tCommand := fmt.Sprintf("T%d 0 %d 0\n", modTime, modTime) err = c.sendProtocolMessage(tCommand) if err != nil { return err @@ -433,7 +431,7 @@ func (c *scpCommand) sendDownloadFileData(fs vfs.Fs, filePath string, stat os.Fi var err error if c.sendFileTime() { modTime := stat.ModTime().UnixNano() / 1000000000 - tCommand := fmt.Sprintf("T%v 0 %v 0\n", modTime, modTime) + tCommand := fmt.Sprintf("T%d 0 %d 0\n", modTime, modTime) err = c.sendProtocolMessage(tCommand) if err != nil { return err @@ -561,16 +559,22 @@ func (c *scpCommand) handleDownload(filePath string) error { return err } -func (c *scpCommand) getCommandType() string { - return c.args[len(c.args)-2] -} - func (c *scpCommand) sendFileTime() bool { - return util.Contains(c.args, "-p") + return c.hasFlag("p") } func (c *scpCommand) isRecursive() bool { - return util.Contains(c.args, "-r") + return c.hasFlag("r") +} + +func (c *scpCommand) hasFlag(flag string) bool { + for idx := 0; idx < len(c.args)-1; idx++ { + arg := c.args[idx] + if !strings.HasPrefix(arg, "--") && strings.HasPrefix(arg, "-") && strings.Contains(arg, flag) { + return true + } + } + return false } // read the SCP confirmation message and the optional text message