update deps
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
8e86782d85
commit
be2e24e63d
16 changed files with 606 additions and 2915 deletions
16
.github/workflows/development.yml
vendored
16
.github/workflows/development.yml
vendored
|
@ -11,11 +11,11 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.19]
|
||||
go: ['1.20']
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
upload-coverage: [true]
|
||||
include:
|
||||
- go: 1.19
|
||||
- go: '1.20'
|
||||
os: windows-latest
|
||||
upload-coverage: false
|
||||
|
||||
|
@ -232,7 +232,7 @@ jobs:
|
|||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
go-version: '1.20'
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
|
@ -252,7 +252,7 @@ jobs:
|
|||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
go-version: '1.20'
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
|
@ -326,7 +326,7 @@ jobs:
|
|||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
go-version: '1.20'
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
|
@ -438,7 +438,7 @@ jobs:
|
|||
echo 'apt-get install -q -y curl gcc' >> build.sh
|
||||
if [ ${{ matrix.go }} == 'latest' ]
|
||||
then
|
||||
echo 'GO_VERSION=$(curl -L https://go.dev/VERSION?m=text)' >> build.sh
|
||||
echo 'GO_VERSION=$(curl -L https://go.dev/VERSION?m=text | head -n 1)' >> build.sh
|
||||
else
|
||||
echo 'GO_VERSION=${{ matrix.go }}' >> build.sh
|
||||
fi
|
||||
|
@ -481,7 +481,7 @@ jobs:
|
|||
apt-get install -q -y curl gcc
|
||||
if [ ${{ matrix.go }} == 'latest' ]
|
||||
then
|
||||
GO_VERSION=$(curl -L https://go.dev/VERSION?m=text)
|
||||
GO_VERSION=$(curl -L https://go.dev/VERSION?m=text | head -n 1)
|
||||
else
|
||||
GO_VERSION=${{ matrix.go }}
|
||||
fi
|
||||
|
@ -546,7 +546,7 @@ jobs:
|
|||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
go-version: '1.19'
|
||||
- uses: actions/checkout@v3
|
||||
- name: Run golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
|
|
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
|
@ -5,7 +5,7 @@ on:
|
|||
# - cron: '0 4 * * *' # everyday at 4:00 AM UTC
|
||||
push:
|
||||
branches:
|
||||
- 2.4.x
|
||||
- main
|
||||
tags:
|
||||
- v*
|
||||
pull_request:
|
||||
|
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
@ -5,7 +5,7 @@ on:
|
|||
tags: 'v*'
|
||||
|
||||
env:
|
||||
GO_VERSION: 1.19.8
|
||||
GO_VERSION: 1.20.12
|
||||
|
||||
jobs:
|
||||
prepare-sources-with-deps:
|
||||
|
|
234
go.mod
234
go.mod
|
@ -3,166 +3,182 @@ module github.com/drakkan/sftpgo/v2
|
|||
go 1.19
|
||||
|
||||
require (
|
||||
cloud.google.com/go/storage v1.30.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0
|
||||
cloud.google.com/go/storage v1.35.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0
|
||||
github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5
|
||||
github.com/alexedwards/argon2id v0.0.0-20230305115115-4b3c3280a736
|
||||
github.com/aws/aws-sdk-go-v2 v1.17.8
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.20
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.19
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.2
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.61
|
||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.14.8
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.31.2
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.19.2
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.18.8
|
||||
github.com/cockroachdb/cockroach-go/v2 v2.3.3
|
||||
github.com/coreos/go-oidc/v3 v3.5.0
|
||||
github.com/alexedwards/argon2id v1.0.0
|
||||
github.com/aws/aws-sdk-go-v2 v1.24.0
|
||||
github.com/aws/aws-sdk-go-v2/config v1.26.1
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.16.12
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.15.7
|
||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.19.5
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.25.5
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.26.5
|
||||
github.com/cockroachdb/cockroach-go/v2 v2.3.5
|
||||
github.com/coreos/go-oidc/v3 v3.9.0
|
||||
github.com/drakkan/webdav v0.0.0-20230227175313-32996838bcd8
|
||||
github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001
|
||||
github.com/fclairamb/ftpserverlib v0.21.0
|
||||
github.com/fclairamb/ftpserverlib v0.22.0
|
||||
github.com/fclairamb/go-log v0.4.1
|
||||
github.com/go-acme/lego/v4 v4.10.2
|
||||
github.com/go-chi/chi/v5 v5.0.8
|
||||
github.com/go-chi/jwtauth/v5 v5.1.0
|
||||
github.com/go-chi/render v1.0.2
|
||||
github.com/go-sql-driver/mysql v1.7.0
|
||||
github.com/go-acme/lego/v4 v4.14.2
|
||||
github.com/go-chi/chi/v5 v5.0.10
|
||||
github.com/go-chi/jwtauth/v5 v5.3.0
|
||||
github.com/go-chi/render v1.0.3
|
||||
github.com/go-sql-driver/mysql v1.7.1
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/google/uuid v1.5.0
|
||||
github.com/grandcat/zeroconf v1.0.0
|
||||
github.com/hashicorp/go-hclog v1.5.0
|
||||
github.com/hashicorp/go-plugin v1.4.10-0.20230321181155-4b35dc2fedaa
|
||||
github.com/hashicorp/go-retryablehttp v0.7.2
|
||||
github.com/jackc/pgx/v5 v5.3.2-0.20230324225134-e9d64ec29d90
|
||||
github.com/hashicorp/go-hclog v1.6.2
|
||||
github.com/hashicorp/go-plugin v1.6.0
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5
|
||||
github.com/jackc/pgx/v5 v5.4.3
|
||||
github.com/jlaffaye/ftp v0.0.0-20201112195030-9aae4d151126
|
||||
github.com/klauspost/compress v1.16.4
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.9
|
||||
github.com/klauspost/compress v1.17.4
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.18
|
||||
github.com/lithammer/shortuuid/v3 v3.0.7
|
||||
github.com/mattn/go-sqlite3 v1.14.16
|
||||
github.com/mhale/smtpd v0.8.0
|
||||
github.com/mattn/go-sqlite3 v1.14.18
|
||||
github.com/mhale/smtpd v0.8.1
|
||||
github.com/minio/sio v0.3.1
|
||||
github.com/otiai10/copy v1.10.0
|
||||
github.com/otiai10/copy v1.14.0
|
||||
github.com/pires/go-proxyproto v0.7.0
|
||||
github.com/pkg/sftp v1.13.6-0.20230213180117-971c283182b6
|
||||
github.com/pkg/sftp v1.13.6
|
||||
github.com/pquerna/otp v1.4.0
|
||||
github.com/prometheus/client_golang v1.14.0
|
||||
github.com/prometheus/client_golang v1.17.0
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/rs/cors v1.8.3
|
||||
github.com/rs/xid v1.4.0
|
||||
github.com/rs/zerolog v1.29.0
|
||||
github.com/sftpgo/sdk v0.1.2
|
||||
github.com/shirou/gopsutil/v3 v3.23.3
|
||||
github.com/spf13/afero v1.9.5
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/spf13/viper v1.15.0
|
||||
github.com/stretchr/testify v1.8.2
|
||||
github.com/studio-b12/gowebdav v0.0.0-20230203202212-3282f94193f2
|
||||
github.com/subosito/gotenv v1.4.2
|
||||
github.com/rs/cors v1.10.1
|
||||
github.com/rs/xid v1.5.0
|
||||
github.com/rs/zerolog v1.31.0
|
||||
github.com/sftpgo/sdk v0.0.0-20231214102927-0493fcf3bc52
|
||||
github.com/shirou/gopsutil/v3 v3.23.11
|
||||
github.com/spf13/afero v1.11.0
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/spf13/viper v1.18.1
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/studio-b12/gowebdav v0.9.0
|
||||
github.com/subosito/gotenv v1.6.0
|
||||
github.com/unrolled/secure v1.13.0
|
||||
github.com/wagslane/go-password-validator v0.3.0
|
||||
github.com/xhit/go-simple-mail/v2 v2.13.0
|
||||
github.com/xhit/go-simple-mail/v2 v2.16.0
|
||||
github.com/yl2chen/cidranger v1.0.3-0.20210928021809-d1cb2c52f37a
|
||||
go.etcd.io/bbolt v1.3.7
|
||||
go.uber.org/automaxprocs v1.5.2
|
||||
gocloud.dev v0.29.0
|
||||
golang.org/x/crypto v0.7.0
|
||||
golang.org/x/net v0.9.0
|
||||
golang.org/x/oauth2 v0.7.0
|
||||
golang.org/x/sys v0.7.0
|
||||
golang.org/x/time v0.3.0
|
||||
google.golang.org/api v0.116.0
|
||||
go.etcd.io/bbolt v1.3.8
|
||||
go.uber.org/automaxprocs v1.5.3
|
||||
gocloud.dev v0.35.0
|
||||
golang.org/x/crypto v0.16.0
|
||||
golang.org/x/net v0.19.0
|
||||
golang.org/x/oauth2 v0.15.0
|
||||
golang.org/x/sys v0.15.0
|
||||
golang.org/x/time v0.5.0
|
||||
google.golang.org/api v0.154.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.110.0 // indirect
|
||||
cloud.google.com/go/compute v1.19.0 // indirect
|
||||
cloud.google.com/go v0.111.0 // indirect
|
||||
cloud.google.com/go/compute v1.23.3 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/iam v1.0.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
|
||||
cloud.google.com/go/iam v1.1.5 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 // indirect
|
||||
github.com/ajg/form v1.5.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.32 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.26 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.33 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.24 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.27 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.26 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.12.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.7 // indirect
|
||||
github.com/aws/smithy-go v1.13.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.18.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5 // indirect
|
||||
github.com/aws/smithy-go v1.19.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/boombuler/barcode v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.1 // indirect
|
||||
github.com/go-logr/logr v1.3.0 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/go-test/deep v1.1.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.8.0 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/lestrrat-go/blackmagic v1.0.1 // indirect
|
||||
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
|
||||
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
||||
github.com/lestrrat-go/httprc v1.0.4 // indirect
|
||||
github.com/lestrrat-go/iter v1.0.2 // indirect
|
||||
github.com/lestrrat-go/option v1.0.1 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.18 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/miekg/dns v1.1.53 // indirect
|
||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
|
||||
github.com/miekg/dns v1.1.57 // indirect
|
||||
github.com/minio/sha256-simd v1.0.1 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
|
||||
github.com/prometheus/client_model v0.3.0 // indirect
|
||||
github.com/prometheus/common v0.42.0 // indirect
|
||||
github.com/prometheus/procfs v0.9.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.45.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.5 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/segmentio/asm v1.2.0 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
||||
github.com/tklauser/numcpus v0.6.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.13 // indirect
|
||||
github.com/tklauser/numcpus v0.7.0 // indirect
|
||||
github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
golang.org/x/mod v0.10.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
golang.org/x/tools v0.8.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd // indirect
|
||||
google.golang.org/grpc v1.54.0 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect
|
||||
go.opentelemetry.io/otel v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.21.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/sync v0.5.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.16.1 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect
|
||||
google.golang.org/grpc v1.60.0 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
@ -170,5 +186,5 @@ require (
|
|||
replace (
|
||||
github.com/jlaffaye/ftp => github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9
|
||||
github.com/robfig/cron/v3 => github.com/drakkan/cron/v3 v3.0.0-20230222140221-217a1e4d96c0
|
||||
golang.org/x/crypto => github.com/drakkan/crypto v0.0.0-20230106095953-5417b4dfde62
|
||||
golang.org/x/crypto => github.com/drakkan/crypto v0.0.0-20231109074321-cb261f488895
|
||||
)
|
||||
|
|
|
@ -219,7 +219,7 @@ func getUsersInGroupsQuery(numArgs int) string {
|
|||
} else {
|
||||
sb.WriteString("('')")
|
||||
}
|
||||
return fmt.Sprintf(`SELECT username FROM %s WHERE id IN (SELECT user_id from %s WHERE group_id IN (SELECT id FROM %s WHERE name IN (%s)))`,
|
||||
return fmt.Sprintf(`SELECT username FROM %s WHERE id IN (SELECT user_id from %s WHERE group_id IN (SELECT id FROM %s WHERE name IN %s))`,
|
||||
sqlTableUsers, sqlTableUsersGroupsMapping, getSQLQuotedName(sqlTableGroups), sb.String())
|
||||
}
|
||||
|
||||
|
|
|
@ -1784,6 +1784,9 @@ func (u *User) mergeVirtualFolders(group Group, groupType int, replacer *strings
|
|||
}
|
||||
|
||||
func (u *User) mergePermissions(group Group, groupType int, replacer *strings.Replacer) {
|
||||
if u.Permissions == nil {
|
||||
u.Permissions = make(map[string][]string)
|
||||
}
|
||||
for k, v := range group.UserSettings.Permissions {
|
||||
if k == "/" {
|
||||
if groupType == sdk.GroupTypePrimary {
|
||||
|
|
|
@ -1975,6 +1975,13 @@ func TestLoadHostKeys(t *testing.T) {
|
|||
c.HostKeys = []string{nonDefaultKeyName, rsaKeyName, ecdsaKeyName, ed25519KeyName}
|
||||
err = c.checkAndLoadHostKeys(configDir, serverConfig)
|
||||
assert.Error(t, err)
|
||||
c.HostKeyAlgorithms = []string{ssh.KeyAlgoRSASHA256}
|
||||
c.HostKeys = []string{ecdsaKeyName}
|
||||
err = c.checkAndLoadHostKeys(configDir, serverConfig)
|
||||
assert.Error(t, err)
|
||||
c.HostKeyAlgorithms = preferredHostKeyAlgos
|
||||
err = c.checkAndLoadHostKeys(configDir, serverConfig)
|
||||
assert.NoError(t, err)
|
||||
assert.FileExists(t, rsaKeyName)
|
||||
assert.FileExists(t, ecdsaKeyName)
|
||||
assert.FileExists(t, ed25519KeyName)
|
||||
|
|
|
@ -47,6 +47,8 @@ const (
|
|||
defaultPrivateECDSAKeyName = "id_ecdsa"
|
||||
defaultPrivateEd25519KeyName = "id_ed25519"
|
||||
sourceAddressCriticalOption = "source-address"
|
||||
kexDHGroupExchangeSHA1 = "diffie-hellman-group-exchange-sha1"
|
||||
kexDHGroupExchangeSHA256 = "diffie-hellman-group-exchange-sha256"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -61,11 +63,8 @@ var (
|
|||
ssh.KeyAlgoED25519,
|
||||
}
|
||||
preferredHostKeyAlgos = []string{
|
||||
ssh.CertAlgoRSASHA512v01, ssh.CertAlgoRSASHA256v01,
|
||||
ssh.CertAlgoECDSA256v01,
|
||||
ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01, ssh.CertAlgoED25519v01,
|
||||
ssh.KeyAlgoRSASHA256, ssh.KeyAlgoRSASHA512,
|
||||
ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521,
|
||||
ssh.KeyAlgoRSASHA512, ssh.KeyAlgoRSASHA256,
|
||||
ssh.KeyAlgoED25519,
|
||||
}
|
||||
supportedKexAlgos = []string{
|
||||
|
@ -75,6 +74,11 @@ var (
|
|||
"diffie-hellman-group18-sha512", "diffie-hellman-group14-sha1",
|
||||
"diffie-hellman-group1-sha1",
|
||||
}
|
||||
preferredKexAlgos = []string{
|
||||
"curve25519-sha256", "curve25519-sha256@libssh.org",
|
||||
"ecdh-sha2-nistp256", "ecdh-sha2-nistp384", "ecdh-sha2-nistp521",
|
||||
"diffie-hellman-group14-sha256",
|
||||
}
|
||||
supportedCiphers = []string{
|
||||
"aes128-gcm@openssh.com", "aes256-gcm@openssh.com",
|
||||
"chacha20-poly1305@openssh.com",
|
||||
|
@ -83,11 +87,19 @@ var (
|
|||
"3des-cbc",
|
||||
"arcfour", "arcfour128", "arcfour256",
|
||||
}
|
||||
preferredCiphers = []string{
|
||||
"aes128-gcm@openssh.com", "aes256-gcm@openssh.com",
|
||||
"chacha20-poly1305@openssh.com",
|
||||
"aes128-ctr", "aes192-ctr", "aes256-ctr",
|
||||
}
|
||||
supportedMACs = []string{
|
||||
"hmac-sha2-256-etm@openssh.com", "hmac-sha2-256",
|
||||
"hmac-sha2-512-etm@openssh.com", "hmac-sha2-512",
|
||||
"hmac-sha1", "hmac-sha1-96",
|
||||
}
|
||||
preferredMACs = []string{
|
||||
"hmac-sha2-256-etm@openssh.com", "hmac-sha2-256",
|
||||
}
|
||||
|
||||
revokedCertManager = revokedCertificates{
|
||||
certs: map[string]bool{},
|
||||
|
@ -315,15 +327,6 @@ func (c *Configuration) Initialize(configDir string) error {
|
|||
return common.ErrNoBinding
|
||||
}
|
||||
|
||||
if err := c.checkAndLoadHostKeys(configDir, serverConfig); err != nil {
|
||||
serviceStatus.HostKeys = nil
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.initializeCertChecker(configDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.loadModuli(configDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -333,6 +336,14 @@ func (c *Configuration) Initialize(configDir string) error {
|
|||
if err := c.configureSecurityOptions(serverConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.checkAndLoadHostKeys(configDir, serverConfig); err != nil {
|
||||
serviceStatus.HostKeys = nil
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.initializeCertChecker(configDir); err != nil {
|
||||
return err
|
||||
}
|
||||
c.configureKeyboardInteractiveAuth(serverConfig)
|
||||
c.configureLoginBanner(serverConfig, configDir)
|
||||
c.checkSSHCommands()
|
||||
|
@ -419,35 +430,43 @@ func (c *Configuration) configureSecurityOptions(serverConfig *ssh.ServerConfig)
|
|||
return fmt.Errorf("unsupported host key algorithm %#v", hostKeyAlgo)
|
||||
}
|
||||
}
|
||||
serverConfig.HostKeyAlgorithms = c.HostKeyAlgorithms
|
||||
|
||||
if len(c.KexAlgorithms) > 0 {
|
||||
if len(c.KexAlgorithms) == 0 {
|
||||
c.KexAlgorithms = preferredKexAlgos
|
||||
} else {
|
||||
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)
|
||||
}
|
||||
}
|
||||
serverConfig.KeyExchanges = c.KexAlgorithms
|
||||
}
|
||||
if len(c.Ciphers) > 0 {
|
||||
for _, kex := range c.KexAlgorithms {
|
||||
if !util.Contains(supportedKexAlgos, kex) {
|
||||
return fmt.Errorf("unsupported key-exchange algorithm %q", kex)
|
||||
}
|
||||
}
|
||||
serverConfig.KeyExchanges = c.KexAlgorithms
|
||||
|
||||
if len(c.Ciphers) == 0 {
|
||||
c.Ciphers = preferredCiphers
|
||||
} else {
|
||||
c.Ciphers = util.RemoveDuplicates(c.Ciphers, true)
|
||||
for _, cipher := range c.Ciphers {
|
||||
if !util.Contains(supportedCiphers, cipher) {
|
||||
return fmt.Errorf("unsupported cipher %#v", cipher)
|
||||
}
|
||||
}
|
||||
serverConfig.Ciphers = c.Ciphers
|
||||
}
|
||||
if len(c.MACs) > 0 {
|
||||
for _, cipher := range c.Ciphers {
|
||||
if !util.Contains(supportedCiphers, cipher) {
|
||||
return fmt.Errorf("unsupported cipher %#v", cipher)
|
||||
}
|
||||
}
|
||||
serverConfig.Ciphers = c.Ciphers
|
||||
|
||||
if len(c.MACs) == 0 {
|
||||
c.MACs = preferredMACs
|
||||
} else {
|
||||
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)
|
||||
}
|
||||
}
|
||||
serverConfig.MACs = c.MACs
|
||||
}
|
||||
for _, mac := range c.MACs {
|
||||
if !util.Contains(supportedMACs, mac) {
|
||||
return fmt.Errorf("unsupported MAC algorithm %#v", mac)
|
||||
}
|
||||
}
|
||||
serverConfig.MACs = c.MACs
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -876,8 +895,9 @@ func (c *Configuration) checkHostKeyAutoGeneration(configDir string) error {
|
|||
}
|
||||
|
||||
func (c *Configuration) loadModuli(configDir string) error {
|
||||
supportedKexAlgos = util.Remove(supportedKexAlgos, "diffie-hellman-group-exchange-sha1")
|
||||
supportedKexAlgos = util.Remove(supportedKexAlgos, "diffie-hellman-group-exchange-sha256")
|
||||
supportedKexAlgos = util.Remove(supportedKexAlgos, kexDHGroupExchangeSHA1)
|
||||
supportedKexAlgos = util.Remove(supportedKexAlgos, kexDHGroupExchangeSHA256)
|
||||
preferredKexAlgos = util.Remove(preferredKexAlgos, kexDHGroupExchangeSHA256)
|
||||
for _, m := range c.Moduli {
|
||||
m = strings.TrimSpace(m)
|
||||
if !util.IsFileInputValid(m) {
|
||||
|
@ -892,12 +912,29 @@ func (c *Configuration) loadModuli(configDir string) error {
|
|||
if err := ssh.ParseModuli(m); err != nil {
|
||||
return err
|
||||
}
|
||||
supportedKexAlgos = append(supportedKexAlgos, "diffie-hellman-group-exchange-sha1",
|
||||
"diffie-hellman-group-exchange-sha256")
|
||||
if !util.Contains(supportedKexAlgos, kexDHGroupExchangeSHA1) {
|
||||
supportedKexAlgos = append(supportedKexAlgos, kexDHGroupExchangeSHA1)
|
||||
}
|
||||
if !util.Contains(supportedKexAlgos, kexDHGroupExchangeSHA256) {
|
||||
supportedKexAlgos = append(supportedKexAlgos, kexDHGroupExchangeSHA256)
|
||||
}
|
||||
if !util.Contains(preferredKexAlgos, kexDHGroupExchangeSHA256) {
|
||||
preferredKexAlgos = append(preferredKexAlgos, kexDHGroupExchangeSHA256)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Configuration) getHostKeyAlgorithms(keyFormat string) []string {
|
||||
var algos []string
|
||||
for _, algo := range algorithmsForKeyFormat(keyFormat) {
|
||||
if util.Contains(c.HostKeyAlgorithms, algo) {
|
||||
algos = append(algos, algo)
|
||||
}
|
||||
}
|
||||
return algos
|
||||
}
|
||||
|
||||
// If no host keys are defined we try to use or generate the default ones.
|
||||
func (c *Configuration) checkAndLoadHostKeys(configDir string, serverConfig *ssh.ServerConfig) error {
|
||||
if err := c.checkHostKeyAutoGeneration(configDir); err != nil {
|
||||
|
@ -932,22 +969,45 @@ func (c *Configuration) checkAndLoadHostKeys(configDir string, serverConfig *ssh
|
|||
k := HostKey{
|
||||
Path: hostKey,
|
||||
Fingerprint: ssh.FingerprintSHA256(private.PublicKey()),
|
||||
Algorithms: c.getHostKeyAlgorithms(private.PublicKey().Type()),
|
||||
}
|
||||
mas, err := ssh.NewSignerWithAlgorithms(private.(ssh.AlgorithmSigner), k.Algorithms)
|
||||
if err != nil {
|
||||
logger.Warn(logSender, "", "could not create signer for key %q with algorithms %+v: %v", k.Path, k.Algorithms, err)
|
||||
logger.WarnToConsole("could not create signer for key %q with algorithms %+v: %v", k.Path, k.Algorithms, err)
|
||||
continue
|
||||
}
|
||||
serviceStatus.HostKeys = append(serviceStatus.HostKeys, k)
|
||||
logger.Info(logSender, "", "Host key %#v loaded, type %#v, fingerprint %#v", hostKey,
|
||||
private.PublicKey().Type(), k.Fingerprint)
|
||||
logger.Info(logSender, "", "Host key %q loaded, type %q, fingerprint %q, algorithms %+v", hostKey,
|
||||
private.PublicKey().Type(), k.Fingerprint, k.Algorithms)
|
||||
|
||||
// Add private key to the server configuration.
|
||||
serverConfig.AddHostKey(private)
|
||||
serverConfig.AddHostKey(mas)
|
||||
for _, cert := range hostCertificates {
|
||||
signer, err := ssh.NewCertSigner(cert, private)
|
||||
signer, err := ssh.NewCertSigner(cert.Certificate, mas)
|
||||
if err == nil {
|
||||
var algos []string
|
||||
for _, algo := range algorithmsForKeyFormat(signer.PublicKey().Type()) {
|
||||
if underlyingAlgo, ok := certKeyAlgoNames[algo]; ok {
|
||||
if util.Contains(mas.Algorithms(), underlyingAlgo) {
|
||||
algos = append(algos, algo)
|
||||
}
|
||||
}
|
||||
}
|
||||
serviceStatus.HostKeys = append(serviceStatus.HostKeys, HostKey{
|
||||
Path: cert.Path,
|
||||
Fingerprint: ssh.FingerprintSHA256(signer.PublicKey()),
|
||||
Algorithms: algos,
|
||||
})
|
||||
serverConfig.AddHostKey(signer)
|
||||
logger.Info(logSender, "", "Host certificate loaded for host key %#v, fingerprint %#v",
|
||||
hostKey, ssh.FingerprintSHA256(signer.PublicKey()))
|
||||
logger.Info(logSender, "", "Host certificate loaded for host key %q, fingerprint %q, algorithms %+v",
|
||||
hostKey, ssh.FingerprintSHA256(signer.PublicKey()), algos)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(serviceStatus.HostKeys) == 0 {
|
||||
return errors.New("ssh: server has no host keys")
|
||||
}
|
||||
var fp []string
|
||||
for idx := range serviceStatus.HostKeys {
|
||||
h := &serviceStatus.HostKeys[idx]
|
||||
|
@ -957,8 +1017,8 @@ func (c *Configuration) checkAndLoadHostKeys(configDir string, serverConfig *ssh
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Configuration) loadHostCertificates(configDir string) ([]*ssh.Certificate, error) {
|
||||
var certs []*ssh.Certificate
|
||||
func (c *Configuration) loadHostCertificates(configDir string) ([]hostCertificate, error) {
|
||||
var certs []hostCertificate
|
||||
for _, certPath := range c.HostCertificates {
|
||||
certPath = strings.TrimSpace(certPath)
|
||||
if !util.IsFileInputValid(certPath) {
|
||||
|
@ -984,7 +1044,10 @@ func (c *Configuration) loadHostCertificates(configDir string) ([]*ssh.Certifica
|
|||
if cert.CertType != ssh.HostCert {
|
||||
return nil, fmt.Errorf("the file %#v is not an host certificate", certPath)
|
||||
}
|
||||
certs = append(certs, cert)
|
||||
certs = append(certs, hostCertificate{
|
||||
Path: certPath,
|
||||
Certificate: cert,
|
||||
})
|
||||
}
|
||||
return certs, nil
|
||||
}
|
||||
|
@ -1218,3 +1281,14 @@ func (r *revokedCertificates) isRevoked(fp string) bool {
|
|||
func Reload() error {
|
||||
return revokedCertManager.load()
|
||||
}
|
||||
|
||||
func algorithmsForKeyFormat(keyFormat string) []string {
|
||||
switch keyFormat {
|
||||
case ssh.KeyAlgoRSA:
|
||||
return []string{ssh.KeyAlgoRSASHA256, ssh.KeyAlgoRSASHA512, ssh.KeyAlgoRSA}
|
||||
case ssh.CertAlgoRSAv01:
|
||||
return []string{ssh.CertAlgoRSASHA256v01, ssh.CertAlgoRSASHA512v01, ssh.CertAlgoRSAv01}
|
||||
default:
|
||||
return []string{keyFormat}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ package sftpd
|
|||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -34,6 +36,18 @@ var (
|
|||
sshHashCommands = []string{"md5sum", "sha1sum", "sha256sum", "sha384sum", "sha512sum"}
|
||||
systemCommands = []string{"git-receive-pack", "git-upload-pack", "git-upload-archive", "rsync"}
|
||||
serviceStatus ServiceStatus
|
||||
certKeyAlgoNames = map[string]string{
|
||||
ssh.CertAlgoRSAv01: ssh.KeyAlgoRSA,
|
||||
ssh.CertAlgoRSASHA256v01: ssh.KeyAlgoRSASHA256,
|
||||
ssh.CertAlgoRSASHA512v01: ssh.KeyAlgoRSASHA512,
|
||||
ssh.CertAlgoDSAv01: ssh.KeyAlgoDSA,
|
||||
ssh.CertAlgoECDSA256v01: ssh.KeyAlgoECDSA256,
|
||||
ssh.CertAlgoECDSA384v01: ssh.KeyAlgoECDSA384,
|
||||
ssh.CertAlgoECDSA521v01: ssh.KeyAlgoECDSA521,
|
||||
ssh.CertAlgoSKECDSA256v01: ssh.KeyAlgoSKECDSA256,
|
||||
ssh.CertAlgoED25519v01: ssh.KeyAlgoED25519,
|
||||
ssh.CertAlgoSKED25519v01: ssh.KeyAlgoSKED25519,
|
||||
}
|
||||
)
|
||||
|
||||
type sshSubsystemExitStatus struct {
|
||||
|
@ -44,10 +58,21 @@ type sshSubsystemExecMsg struct {
|
|||
Command string
|
||||
}
|
||||
|
||||
type hostCertificate struct {
|
||||
Certificate *ssh.Certificate
|
||||
Path string
|
||||
}
|
||||
|
||||
// HostKey defines the details for a used host key
|
||||
type HostKey struct {
|
||||
Path string `json:"path"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
Path string `json:"path"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
Algorithms []string `json:"algorithms"`
|
||||
}
|
||||
|
||||
// GetAlgosAsString returns the host key algorithms as comma separated string
|
||||
func (h *HostKey) GetAlgosAsString() string {
|
||||
return strings.Join(h.Algorithms, ", ")
|
||||
}
|
||||
|
||||
// ServiceStatus defines the service status
|
||||
|
|
|
@ -429,11 +429,13 @@ func TestInitialization(t *testing.T) {
|
|||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "unsupported MAC algorithm")
|
||||
}
|
||||
sftpdConf.MACs = nil
|
||||
sftpdConf.KexAlgorithms = []string{"not a KEX"}
|
||||
err = sftpdConf.Initialize(configDir)
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "unsupported key-exchange algorithm")
|
||||
}
|
||||
sftpdConf.KexAlgorithms = nil
|
||||
sftpdConf.HostKeyAlgorithms = []string{"not a host key algo"}
|
||||
err = sftpdConf.Initialize(configDir)
|
||||
if assert.Error(t, err) {
|
||||
|
@ -562,6 +564,7 @@ func TestBasicSFTPHandling(t *testing.T) {
|
|||
assert.NotEmpty(t, sshCommands)
|
||||
sshAuths := status.GetSupportedAuthsAsString()
|
||||
assert.NotEmpty(t, sshAuths)
|
||||
assert.NotEmpty(t, status.HostKeys[0].GetAlgosAsString())
|
||||
}
|
||||
|
||||
func TestBasicSFTPFsHandling(t *testing.T) {
|
||||
|
|
|
@ -313,7 +313,7 @@ func GetIntFromPointer(val *int64) int64 {
|
|||
// GetTimeFromPointer returns the time value or now
|
||||
func GetTimeFromPointer(val *time.Time) time.Time {
|
||||
if val == nil {
|
||||
return time.Now()
|
||||
return time.Unix(0, 0)
|
||||
}
|
||||
return *val
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ package version
|
|||
|
||||
import "strings"
|
||||
|
||||
const version = "2.4.5"
|
||||
const version = "2.4.6-dev"
|
||||
|
||||
var (
|
||||
commit = ""
|
||||
|
|
|
@ -165,11 +165,11 @@ func (fs *S3Fs) Stat(name string) (os.FileInfo, error) {
|
|||
// Some S3 providers (like SeaweedFS) remove the trailing '/' from object keys.
|
||||
// So we check some common content types to detect if this is a "directory".
|
||||
isDir := util.Contains(s3DirMimeTypes, util.GetStringFromPointer(obj.ContentType))
|
||||
if obj.ContentLength == 0 && !isDir {
|
||||
if util.GetIntFromPointer(obj.ContentLength) == 0 && !isDir {
|
||||
_, err = fs.headObject(name + "/")
|
||||
isDir = err == nil
|
||||
}
|
||||
return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, isDir, obj.ContentLength,
|
||||
return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, isDir, util.GetIntFromPointer(obj.ContentLength),
|
||||
util.GetTimeFromPointer(obj.LastModified), false))
|
||||
}
|
||||
if !fs.IsNotExist(err) {
|
||||
|
@ -195,7 +195,7 @@ func (fs *S3Fs) getStatForDir(name string) (os.FileInfo, error) {
|
|||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, obj.ContentLength,
|
||||
return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, util.GetIntFromPointer(obj.ContentLength),
|
||||
util.GetTimeFromPointer(obj.LastModified), false))
|
||||
}
|
||||
|
||||
|
@ -492,6 +492,7 @@ func (fs *S3Fs) ReadDir(dirname string) ([]os.FileInfo, error) {
|
|||
}
|
||||
for _, fileObject := range page.Contents {
|
||||
objectModTime := util.GetTimeFromPointer(fileObject.LastModified)
|
||||
objectSize := util.GetIntFromPointer(fileObject.Size)
|
||||
name, isDir := fs.resolve(fileObject.Key, prefix)
|
||||
if name == "" || name == "/" {
|
||||
continue
|
||||
|
@ -505,7 +506,7 @@ func (fs *S3Fs) ReadDir(dirname string) ([]os.FileInfo, error) {
|
|||
if t, ok := modTimes[name]; ok {
|
||||
objectModTime = util.GetTimeFromMsecSinceEpoch(t)
|
||||
}
|
||||
result = append(result, NewFileInfo(name, (isDir && fileObject.Size == 0), fileObject.Size,
|
||||
result = append(result, NewFileInfo(name, (isDir && objectSize == 0), objectSize,
|
||||
objectModTime, false))
|
||||
}
|
||||
}
|
||||
|
@ -647,11 +648,12 @@ func (fs *S3Fs) GetDirSize(dirname string) (int, int64, error) {
|
|||
}
|
||||
for _, fileObject := range page.Contents {
|
||||
isDir := strings.HasSuffix(util.GetStringFromPointer(fileObject.Key), "/")
|
||||
if isDir && fileObject.Size == 0 {
|
||||
objectSize := util.GetIntFromPointer(fileObject.Size)
|
||||
if isDir && objectSize == 0 {
|
||||
continue
|
||||
}
|
||||
numFiles++
|
||||
size += fileObject.Size
|
||||
size += objectSize
|
||||
if numFiles%1000 == 0 {
|
||||
fsLog(fs, logger.LevelDebug, "dirname %q scan in progress, files: %d, size: %d", dirname, numFiles, size)
|
||||
}
|
||||
|
@ -716,7 +718,8 @@ func (fs *S3Fs) Walk(root string, walkFn filepath.WalkFunc) error {
|
|||
continue
|
||||
}
|
||||
err := walkFn(util.GetStringFromPointer(fileObject.Key),
|
||||
NewFileInfo(name, isDir, fileObject.Size, util.GetTimeFromPointer(fileObject.LastModified), false), nil)
|
||||
NewFileInfo(name, isDir, util.GetIntFromPointer(fileObject.Size),
|
||||
util.GetTimeFromPointer(fileObject.LastModified), false), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -794,10 +797,11 @@ func (fs *S3Fs) mkdirInternal(name string) error {
|
|||
|
||||
func (fs *S3Fs) hasContents(name string) (bool, error) {
|
||||
prefix := fs.getPrefix(name)
|
||||
maxKeys := int32(2)
|
||||
paginator := s3.NewListObjectsV2Paginator(fs.svc, &s3.ListObjectsV2Input{
|
||||
Bucket: aws.String(fs.config.Bucket),
|
||||
Prefix: aws.String(prefix),
|
||||
MaxKeys: 2,
|
||||
MaxKeys: &maxKeys,
|
||||
})
|
||||
|
||||
if paginator.HasMorePages() {
|
||||
|
@ -891,7 +895,7 @@ func (fs *S3Fs) doMultipartCopy(source, target, contentType string, fileSize int
|
|||
Bucket: aws.String(fs.config.Bucket),
|
||||
CopySource: aws.String(source),
|
||||
Key: aws.String(target),
|
||||
PartNumber: partNum,
|
||||
PartNumber: &partNum,
|
||||
UploadId: aws.String(uploadID),
|
||||
CopySourceRange: aws.String(fmt.Sprintf("bytes=%d-%d", partStart, partEnd-1)),
|
||||
})
|
||||
|
@ -920,7 +924,7 @@ func (fs *S3Fs) doMultipartCopy(source, target, contentType string, fileSize int
|
|||
partMutex.Lock()
|
||||
completedParts = append(completedParts, types.CompletedPart{
|
||||
ETag: partResp.CopyPartResult.ETag,
|
||||
PartNumber: partNum,
|
||||
PartNumber: &partNum,
|
||||
})
|
||||
partMutex.Unlock()
|
||||
}(partNumber, start, end)
|
||||
|
@ -933,7 +937,13 @@ func (fs *S3Fs) doMultipartCopy(source, target, contentType string, fileSize int
|
|||
return copyError
|
||||
}
|
||||
sort.Slice(completedParts, func(i, j int) bool {
|
||||
return completedParts[i].PartNumber < completedParts[j].PartNumber
|
||||
getPartNumber := func(number *int32) int32 {
|
||||
if number == nil {
|
||||
return 0
|
||||
}
|
||||
return *number
|
||||
}
|
||||
return getPartNumber(completedParts[i].PartNumber) < getPartNumber(completedParts[j].PartNumber)
|
||||
})
|
||||
|
||||
completeCtx, completeCancelFn := context.WithDeadline(context.Background(), time.Now().Add(fs.ctxTimeout))
|
||||
|
|
|
@ -27,7 +27,7 @@ info:
|
|||
SFTPGo supports groups to simplify the administration of multiple accounts by letting you assign settings once to a group, instead of multiple times to each individual user.
|
||||
The SFTPGo WebClient allows end users to change their credentials, browse and manage their files in the browser and setup two-factor authentication which works with Authy, Google Authenticator and other compatible apps.
|
||||
From the WebClient each authorized user can also create HTTP/S links to externally share files and folders securely, by setting limits to the number of downloads/uploads, protecting the share with a password, limiting access by source IP address, setting an automatic expiration date.
|
||||
version: 2.4.5
|
||||
version: 2.4.6
|
||||
contact:
|
||||
name: API support
|
||||
url: 'https://github.com/drakkan/sftpgo'
|
||||
|
@ -5532,6 +5532,10 @@ components:
|
|||
type: string
|
||||
fingerprint:
|
||||
type: string
|
||||
algorithms:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
SSHBinding:
|
||||
type: object
|
||||
properties:
|
||||
|
|
|
@ -46,6 +46,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
<br>
|
||||
Fingerprint: "{{.Fingerprint}}"
|
||||
<br>
|
||||
Algorithms: "{{.GetAlgosAsString}}"
|
||||
<br>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</p>
|
||||
|
|
Loading…
Reference in a new issue