mirror of
https://github.com/drakkan/sftpgo.git
synced 2024-11-21 23:20:24 +00:00
ssh: remove moduli, log negotiated algorithms
Fixes #1324 Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
a577d8b3cd
commit
f7d9e56cac
14 changed files with 198 additions and 285 deletions
|
@ -2,7 +2,7 @@ FROM golang:1.22-bookworm as builder
|
||||||
|
|
||||||
ENV GOFLAGS="-mod=readonly"
|
ENV GOFLAGS="-mod=readonly"
|
||||||
|
|
||||||
RUN apt-get update && apt-get -y upgrade && apt-get install --no-install-recommends -y openssh-server && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update && apt-get -y upgrade && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
RUN mkdir -p /workspace
|
RUN mkdir -p /workspace
|
||||||
WORKDIR /workspace
|
WORKDIR /workspace
|
||||||
|
@ -47,7 +47,6 @@ RUN groupadd --system -g 1000 sftpgo && \
|
||||||
--comment "SFTPGo user" --uid 1000 sftpgo
|
--comment "SFTPGo user" --uid 1000 sftpgo
|
||||||
|
|
||||||
COPY --from=builder /workspace/sftpgo.json /etc/sftpgo/sftpgo.json
|
COPY --from=builder /workspace/sftpgo.json /etc/sftpgo/sftpgo.json
|
||||||
COPY --from=builder /etc/ssh/moduli /etc/sftpgo/moduli
|
|
||||||
COPY --from=builder /workspace/templates /usr/share/sftpgo/templates
|
COPY --from=builder /workspace/templates /usr/share/sftpgo/templates
|
||||||
COPY --from=builder /workspace/static /usr/share/sftpgo/static
|
COPY --from=builder /workspace/static /usr/share/sftpgo/static
|
||||||
COPY --from=builder /workspace/openapi /usr/share/sftpgo/openapi
|
COPY --from=builder /workspace/openapi /usr/share/sftpgo/openapi
|
||||||
|
|
|
@ -25,8 +25,6 @@ RUN set -xe && \
|
||||||
export COMMIT_SHA=${COMMIT_SHA:-$(git describe --always --abbrev=8 --dirty)} && \
|
export COMMIT_SHA=${COMMIT_SHA:-$(git describe --always --abbrev=8 --dirty)} && \
|
||||||
go build $(if [ -n "${FEATURES}" ]; then echo "-tags ${FEATURES}"; fi) -trimpath -ldflags "-s -w -X github.com/drakkan/sftpgo/v2/internal/version.commit=${COMMIT_SHA} -X github.com/drakkan/sftpgo/v2/internal/version.date=`date -u +%FT%TZ`" -v -o sftpgo
|
go build $(if [ -n "${FEATURES}" ]; then echo "-tags ${FEATURES}"; fi) -trimpath -ldflags "-s -w -X github.com/drakkan/sftpgo/v2/internal/version.commit=${COMMIT_SHA} -X github.com/drakkan/sftpgo/v2/internal/version.date=`date -u +%FT%TZ`" -v -o sftpgo
|
||||||
|
|
||||||
RUN apk add --update --no-cache openssh-client-common
|
|
||||||
|
|
||||||
FROM alpine:3.19
|
FROM alpine:3.19
|
||||||
|
|
||||||
# Set to "true" to install jq and the optional git and rsync dependencies
|
# Set to "true" to install jq and the optional git and rsync dependencies
|
||||||
|
@ -42,7 +40,6 @@ RUN addgroup -g 1000 -S sftpgo && \
|
||||||
adduser -u 1000 -h /var/lib/sftpgo -s /sbin/nologin -G sftpgo -S -D -H -g "SFTPGo user" sftpgo
|
adduser -u 1000 -h /var/lib/sftpgo -s /sbin/nologin -G sftpgo -S -D -H -g "SFTPGo user" sftpgo
|
||||||
|
|
||||||
COPY --from=builder /workspace/sftpgo.json /etc/sftpgo/sftpgo.json
|
COPY --from=builder /workspace/sftpgo.json /etc/sftpgo/sftpgo.json
|
||||||
COPY --from=builder /etc/ssh/moduli /etc/sftpgo/moduli
|
|
||||||
COPY --from=builder /workspace/templates /usr/share/sftpgo/templates
|
COPY --from=builder /workspace/templates /usr/share/sftpgo/templates
|
||||||
COPY --from=builder /workspace/static /usr/share/sftpgo/static
|
COPY --from=builder /workspace/static /usr/share/sftpgo/static
|
||||||
COPY --from=builder /workspace/openapi /usr/share/sftpgo/openapi
|
COPY --from=builder /workspace/openapi /usr/share/sftpgo/openapi
|
||||||
|
|
|
@ -2,7 +2,7 @@ FROM golang:1.22-bookworm as builder
|
||||||
|
|
||||||
ENV CGO_ENABLED=0 GOFLAGS="-mod=readonly"
|
ENV CGO_ENABLED=0 GOFLAGS="-mod=readonly"
|
||||||
|
|
||||||
RUN apt-get update && apt-get -y upgrade && apt-get install --no-install-recommends -y media-types openssh-server && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update && apt-get -y upgrade && apt-get install --no-install-recommends -y media-types && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
RUN mkdir -p /workspace
|
RUN mkdir -p /workspace
|
||||||
WORKDIR /workspace
|
WORKDIR /workspace
|
||||||
|
@ -38,7 +38,6 @@ COPY --from=builder --chown=1000:1000 /etc/sftpgo /etc/sftpgo
|
||||||
COPY --from=builder --chown=1000:1000 /srv/sftpgo /srv/sftpgo
|
COPY --from=builder --chown=1000:1000 /srv/sftpgo /srv/sftpgo
|
||||||
COPY --from=builder --chown=1000:1000 /var/lib/sftpgo /var/lib/sftpgo
|
COPY --from=builder --chown=1000:1000 /var/lib/sftpgo /var/lib/sftpgo
|
||||||
COPY --from=builder --chown=1000:1000 /workspace/sftpgo.json /etc/sftpgo/sftpgo.json
|
COPY --from=builder --chown=1000:1000 /workspace/sftpgo.json /etc/sftpgo/sftpgo.json
|
||||||
COPY --from=builder --chown=1000:1000 /etc/ssh/moduli /etc/sftpgo/moduli
|
|
||||||
COPY --from=builder /workspace/templates /usr/share/sftpgo/templates
|
COPY --from=builder /workspace/templates /usr/share/sftpgo/templates
|
||||||
COPY --from=builder /workspace/static /usr/share/sftpgo/static
|
COPY --from=builder /workspace/static /usr/share/sftpgo/static
|
||||||
COPY --from=builder /workspace/openapi /usr/share/sftpgo/openapi
|
COPY --from=builder /workspace/openapi /usr/share/sftpgo/openapi
|
||||||
|
|
|
@ -143,8 +143,7 @@ The configuration file contains the following sections:
|
||||||
- `host_keys`, list of strings. It contains the daemon's private host keys. Each host key can be defined as a path relative to the configuration directory or an absolute one. If empty, the daemon will search or try to generate `id_rsa`, `id_ecdsa` and `id_ed25519` keys inside the configuration directory. If you configure absolute paths to files named `id_rsa`, `id_ecdsa` and/or `id_ed25519` then SFTPGo will try to generate these keys using the default settings.
|
- `host_keys`, list of strings. It contains the daemon's private host keys. Each host key can be defined as a path relative to the configuration directory or an absolute one. If empty, the daemon will search or try to generate `id_rsa`, `id_ecdsa` and `id_ed25519` keys inside the configuration directory. If you configure absolute paths to files named `id_rsa`, `id_ecdsa` and/or `id_ed25519` then SFTPGo will try to generate these keys using the default settings.
|
||||||
- `host_certificates`, list of strings. Public host certificates. Each certificate can be defined as a path relative to the configuration directory or an absolute one. Certificate's public key must match a private host key otherwise it will be silently ignored. Default: empty.
|
- `host_certificates`, list of strings. Public host certificates. Each certificate can be defined as a path relative to the configuration directory or an absolute one. Certificate's public key must match a private host key otherwise it will be silently ignored. Default: empty.
|
||||||
- `host_key_algorithms`, list of strings. Public key algorithms that the server will accept for host key authentication. The supported values are: `rsa-sha2-512-cert-v01@openssh.com`, `rsa-sha2-256-cert-v01@openssh.com`, `ssh-rsa-cert-v01@openssh.com`, `ssh-dss-cert-v01@openssh.com`, `ecdsa-sha2-nistp256-cert-v01@openssh.com`, `ecdsa-sha2-nistp384-cert-v01@openssh.com`, `ecdsa-sha2-nistp521-cert-v01@openssh.com`, `ssh-ed25519-cert-v01@openssh.com`, `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`, `rsa-sha2-512`, `rsa-sha2-256`, `ssh-rsa`, `ssh-dss`, `ssh-ed25519`. Certificate algorithms are listed for backward compatibility purposes only, they are not used. Default values: `rsa-sha2-512`, `rsa-sha2-256`, `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`, `ssh-ed25519`.
|
- `host_key_algorithms`, list of strings. Public key algorithms that the server will accept for host key authentication. The supported values are: `rsa-sha2-512-cert-v01@openssh.com`, `rsa-sha2-256-cert-v01@openssh.com`, `ssh-rsa-cert-v01@openssh.com`, `ssh-dss-cert-v01@openssh.com`, `ecdsa-sha2-nistp256-cert-v01@openssh.com`, `ecdsa-sha2-nistp384-cert-v01@openssh.com`, `ecdsa-sha2-nistp521-cert-v01@openssh.com`, `ssh-ed25519-cert-v01@openssh.com`, `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`, `rsa-sha2-512`, `rsa-sha2-256`, `ssh-rsa`, `ssh-dss`, `ssh-ed25519`. Certificate algorithms are listed for backward compatibility purposes only, they are not used. Default values: `rsa-sha2-512`, `rsa-sha2-256`, `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`, `ssh-ed25519`.
|
||||||
- `moduli`, list of strings. Diffie-Hellman moduli files. Each moduli file can be defined as a path relative to the configuration directory or an absolute one. If set and valid, `diffie-hellman-group-exchange-sha256` and `diffie-hellman-group-exchange-sha1` KEX algorithms will be available, `diffie-hellman-group-exchange-sha256` will be enabled by default if you don't explicitly set KEXs. Invalid moduli file will be silently ignored. Default: empty.
|
- `kex_algorithms`, list of strings. Available KEX (Key Exchange) algorithms in preference order. Leave empty to use default values. The supported values are: `curve25519-sha256` (will also enable the alias `curve25519-sha256@libssh.org`), `ecdh-sha2-nistp256`, `ecdh-sha2-nistp384`, `ecdh-sha2-nistp521`, `diffie-hellman-group14-sha256`, `diffie-hellman-group16-sha512`, `diffie-hellman-group14-sha1`, `diffie-hellman-group1-sha1`, `diffie-hellman-group-exchange-sha256`, `diffie-hellman-group-exchange-sha1`. Default values: `curve25519-sha256`, `ecdh-sha2-nistp256`, `ecdh-sha2-nistp384`, `ecdh-sha2-nistp521`, `diffie-hellman-group14-sha256`, `diffie-hellman-group-exchange-sha256`. SHA512 based KEXs are disabled by default because they are slow.
|
||||||
- `kex_algorithms`, list of strings. Available KEX (Key Exchange) algorithms in preference order. Leave empty to use default values. The supported values are: `curve25519-sha256`, `curve25519-sha256@libssh.org`, `ecdh-sha2-nistp256`, `ecdh-sha2-nistp384`, `ecdh-sha2-nistp521`, `diffie-hellman-group14-sha256`, `diffie-hellman-group16-sha512`, `diffie-hellman-group14-sha1`, `diffie-hellman-group1-sha1`. Default values: `curve25519-sha256`, `curve25519-sha256@libssh.org`, `ecdh-sha2-nistp256`, `ecdh-sha2-nistp384`, `ecdh-sha2-nistp521`, `diffie-hellman-group14-sha256`. SHA512 based KEXs are disabled by default because they are slow. If you set one or more moduli files, `diffie-hellman-group-exchange-sha256` and `diffie-hellman-group-exchange-sha1` will be available.
|
|
||||||
- `ciphers`, list of strings. Allowed ciphers in preference order. Leave empty to use default values. The supported values are: `aes128-gcm@openssh.com`, `aes256-gcm@openssh.com`, `chacha20-poly1305@openssh.com`, `aes128-ctr`, `aes192-ctr`, `aes256-ctr`, `aes128-cbc`, `aes192-cbc`, `aes256-cbc`, `3des-cbc`, `arcfour256`, `arcfour128`, `arcfour`. Default values: `aes128-gcm@openssh.com`, `aes256-gcm@openssh.com`, `chacha20-poly1305@openssh.com`, `aes128-ctr`, `aes192-ctr`, `aes256-ctr`. Please note that the ciphers disabled by default are insecure, you should expect that an active attacker can recover plaintext if you enable them.
|
- `ciphers`, list of strings. Allowed ciphers in preference order. Leave empty to use default values. The supported values are: `aes128-gcm@openssh.com`, `aes256-gcm@openssh.com`, `chacha20-poly1305@openssh.com`, `aes128-ctr`, `aes192-ctr`, `aes256-ctr`, `aes128-cbc`, `aes192-cbc`, `aes256-cbc`, `3des-cbc`, `arcfour256`, `arcfour128`, `arcfour`. Default values: `aes128-gcm@openssh.com`, `aes256-gcm@openssh.com`, `chacha20-poly1305@openssh.com`, `aes128-ctr`, `aes192-ctr`, `aes256-ctr`. Please note that the ciphers disabled by default are insecure, you should expect that an active attacker can recover plaintext if you enable them.
|
||||||
- `macs`, list of strings. Available MAC (message authentication code) algorithms in preference order. Leave empty to use default values. The supported values are: `hmac-sha2-256-etm@openssh.com`, `hmac-sha2-256`, `hmac-sha2-512-etm@openssh.com`, `hmac-sha2-512`, `hmac-sha1`, `hmac-sha1-96`. Default values: `hmac-sha2-256-etm@openssh.com`, `hmac-sha2-256`.
|
- `macs`, list of strings. Available MAC (message authentication code) algorithms in preference order. Leave empty to use default values. The supported values are: `hmac-sha2-256-etm@openssh.com`, `hmac-sha2-256`, `hmac-sha2-512-etm@openssh.com`, `hmac-sha2-512`, `hmac-sha1`, `hmac-sha1-96`. Default values: `hmac-sha2-256-etm@openssh.com`, `hmac-sha2-256`.
|
||||||
- `public_key_algorithms`, list of strings. Public key algorithms that the server will accept for client authentication. The supported values are: `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`, `rsa-sha2-512`, `rsa-sha2-256`, `ssh-rsa`, `ssh-dss`, `ssh-ed25519`, `sk-ssh-ed25519@openssh.com`, `sk-ecdsa-sha2-nistp256@openssh.com`. Default values: `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`, `rsa-sha2-512`, `rsa-sha2-256`, `ssh-ed25519`, `sk-ssh-ed25519@openssh.com`, `sk-ecdsa-sha2-nistp256@openssh.com`.
|
- `public_key_algorithms`, list of strings. Public key algorithms that the server will accept for client authentication. The supported values are: `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`, `rsa-sha2-512`, `rsa-sha2-256`, `ssh-rsa`, `ssh-dss`, `ssh-ed25519`, `sk-ssh-ed25519@openssh.com`, `sk-ecdsa-sha2-nistp256@openssh.com`. Default values: `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`, `rsa-sha2-512`, `rsa-sha2-256`, `ssh-ed25519`, `sk-ssh-ed25519@openssh.com`, `sk-ecdsa-sha2-nistp256@openssh.com`.
|
||||||
|
|
44
go.mod
44
go.mod
|
@ -9,15 +9,15 @@ require (
|
||||||
github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5
|
github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5
|
||||||
github.com/alexedwards/argon2id v1.0.0
|
github.com/alexedwards/argon2id v1.0.0
|
||||||
github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964
|
github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964
|
||||||
github.com/aws/aws-sdk-go-v2 v1.25.1
|
github.com/aws/aws-sdk-go-v2 v1.25.2
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.27.3
|
github.com/aws/aws-sdk-go-v2/config v1.27.4
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.3
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.4
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.1
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2
|
||||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.5
|
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.6
|
||||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.21.0
|
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.21.1
|
||||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.51.0
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.51.1
|
||||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.28.0
|
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.28.1
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.0
|
github.com/aws/aws-sdk-go-v2/service/sts v1.28.1
|
||||||
github.com/bmatcuk/doublestar/v4 v4.6.1
|
github.com/bmatcuk/doublestar/v4 v4.6.1
|
||||||
github.com/cockroachdb/cockroach-go/v2 v2.3.6
|
github.com/cockroachdb/cockroach-go/v2 v2.3.6
|
||||||
github.com/coreos/go-oidc/v3 v3.9.0
|
github.com/coreos/go-oidc/v3 v3.9.0
|
||||||
|
@ -65,7 +65,7 @@ require (
|
||||||
github.com/wagslane/go-password-validator v0.3.0
|
github.com/wagslane/go-password-validator v0.3.0
|
||||||
github.com/wneessen/go-mail v0.4.1
|
github.com/wneessen/go-mail v0.4.1
|
||||||
github.com/yl2chen/cidranger v1.0.3-0.20210928021809-d1cb2c52f37a
|
github.com/yl2chen/cidranger v1.0.3-0.20210928021809-d1cb2c52f37a
|
||||||
go.etcd.io/bbolt v1.3.8
|
go.etcd.io/bbolt v1.3.9
|
||||||
go.uber.org/automaxprocs v1.5.3
|
go.uber.org/automaxprocs v1.5.3
|
||||||
gocloud.dev v0.36.0
|
gocloud.dev v0.36.0
|
||||||
golang.org/x/crypto v0.19.0
|
golang.org/x/crypto v0.19.0
|
||||||
|
@ -86,16 +86,16 @@ require (
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect
|
||||||
github.com/ajg/form v1.5.1 // indirect
|
github.com/ajg/form v1.5.1 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 // indirect
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.1 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.1 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.2 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.1 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.2 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.1 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.2 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.1 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.2 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.1 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.2 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.0 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sso v1.20.1 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.0 // indirect
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1 // indirect
|
||||||
github.com/aws/smithy-go v1.20.1 // indirect
|
github.com/aws/smithy-go v1.20.1 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/boombuler/barcode v1.0.1 // indirect
|
github.com/boombuler/barcode v1.0.1 // indirect
|
||||||
|
@ -108,7 +108,7 @@ require (
|
||||||
github.com/fatih/color v1.16.0 // indirect
|
github.com/fatih/color v1.16.0 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||||
github.com/go-jose/go-jose/v3 v3.0.1 // indirect
|
github.com/go-jose/go-jose/v3 v3.0.2 // indirect
|
||||||
github.com/go-logr/logr v1.4.1 // indirect
|
github.com/go-logr/logr v1.4.1 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
|
@ -160,8 +160,8 @@ require (
|
||||||
github.com/tklauser/numcpus v0.7.0 // indirect
|
github.com/tklauser/numcpus v0.7.0 // indirect
|
||||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.24.0 // indirect
|
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||||
|
@ -187,5 +187,5 @@ replace (
|
||||||
github.com/jlaffaye/ftp => github.com/drakkan/ftp v0.0.0-20240210102745-f1ffc43f78d2
|
github.com/jlaffaye/ftp => github.com/drakkan/ftp v0.0.0-20240210102745-f1ffc43f78d2
|
||||||
github.com/pkg/sftp => github.com/drakkan/sftp v0.0.0-20240214104840-fbb0b8bdb30c
|
github.com/pkg/sftp => github.com/drakkan/sftp v0.0.0-20240214104840-fbb0b8bdb30c
|
||||||
github.com/robfig/cron/v3 => github.com/drakkan/cron/v3 v3.0.0-20230222140221-217a1e4d96c0
|
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-20231218163632-74b52eafd2c0
|
golang.org/x/crypto => github.com/drakkan/crypto v0.0.0-20240224191538-9f4629f0732c
|
||||||
)
|
)
|
||||||
|
|
94
go.sum
94
go.sum
|
@ -33,46 +33,46 @@ github.com/alexedwards/argon2id v1.0.0 h1:wJzDx66hqWX7siL/SRUmgz3F8YMrd/nfX/xHHc
|
||||||
github.com/alexedwards/argon2id v1.0.0/go.mod h1:tYKkqIjzXvZdzPvADMWOEZ+l6+BD6CtBXMj5fnJppiw=
|
github.com/alexedwards/argon2id v1.0.0/go.mod h1:tYKkqIjzXvZdzPvADMWOEZ+l6+BD6CtBXMj5fnJppiw=
|
||||||
github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964 h1:I9YN9WMo3SUh7p/4wKeNvD/IQla3U3SUa61U7ul+xM4=
|
github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964 h1:I9YN9WMo3SUh7p/4wKeNvD/IQla3U3SUa61U7ul+xM4=
|
||||||
github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964/go.mod h1:eFiR01PwTcpbzXtdMces7zxg6utvFM5puiWHpWB8D/k=
|
github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964/go.mod h1:eFiR01PwTcpbzXtdMces7zxg6utvFM5puiWHpWB8D/k=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.25.1 h1:P7hU6A5qEdmajGwvae/zDkOq+ULLC9tQBTwqqiwFGpI=
|
github.com/aws/aws-sdk-go-v2 v1.25.2 h1:/uiG1avJRgLGiQM9X3qJM8+Qa6KRGK5rRPuXE0HUM+w=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.25.1/go.mod h1:Evoc5AsmtveRt1komDwIsjHFyrP5tDuF1D1U+6z6pNo=
|
github.com/aws/aws-sdk-go-v2 v1.25.2/go.mod h1:Evoc5AsmtveRt1komDwIsjHFyrP5tDuF1D1U+6z6pNo=
|
||||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 h1:gTK2uhtAPtFcdRRJilZPx8uJLL2J85xK11nKtWL0wfU=
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 h1:gTK2uhtAPtFcdRRJilZPx8uJLL2J85xK11nKtWL0wfU=
|
||||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1/go.mod h1:sxpLb+nZk7tIfCWChfd+h4QwHNUR57d8hA1cleTkjJo=
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1/go.mod h1:sxpLb+nZk7tIfCWChfd+h4QwHNUR57d8hA1cleTkjJo=
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.27.3 h1:0PRdb/q5a77HVYj+2rvPiCObfMfl/pWhwa5cs3cnl3c=
|
github.com/aws/aws-sdk-go-v2/config v1.27.4 h1:AhfWb5ZwimdsYTgP7Od8E9L1u4sKmDW2ZVeLcf2O42M=
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.27.3/go.mod h1:WeRAr9ENap9NAegbfNsLqGQd8ERz5ypdIUx4j0/ZgKI=
|
github.com/aws/aws-sdk-go-v2/config v1.27.4/go.mod h1:zq2FFXK3A416kiukwpsd+rD4ny6JC7QSkp4QdN1Mp2g=
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.3 h1:dDM5wrgwOL5gTZ0Gv/bvewPldjBcJywoaO5ClERrOGE=
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.4 h1:h5Vztbd8qLppiPwX+y0Q6WiwMZgpd9keKe2EAENgAuI=
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.3/go.mod h1:G96Nuaw9qJS+s3OnK8RW8VEKEOjXi8H5Jk4lC/ZyZbw=
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.4/go.mod h1:+30tpwrkOgvkJL1rUZuRLoxcJwtI/OkeBLYnHxJtVe0=
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.1 h1:lk1ZZFbdb24qpOwVC1AwYNrswUjAxeyey6kFBVANudQ=
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2 h1:AK0J8iYBFeUk2Ax7O8YpLtFsfhdOByh2QIkHmigpRYk=
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.1/go.mod h1:/xJ6x1NehNGCX4tvGzzj2bq5TBOT/Yxq+qbL9Jpx2Vk=
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2/go.mod h1:iRlGzMix0SExQEviAyptRWRGdYNo3+ufW/lCzvKVTUc=
|
||||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.5 h1:IEv6homMJMnedG/2VWfNuV34ouXUmK8E7y4rAl59Fhs=
|
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.6 h1:prcsGA3onmpc7ea1W/m+SMj4uOn5vZ63uJp805UhJJs=
|
||||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.5/go.mod h1:a+wq9mSuG13iSkVMR1O8VApmAISm1ca+E2RQpcB3flw=
|
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.6/go.mod h1:7eQrvATnVFDY0WfMYhfKkSQ1YtZlClT71fAAlsA1s34=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.1 h1:evvi7FbTAoFxdP/mixmP7LIYzQWAmzBcwNB/es9XPNc=
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2 h1:bNo4LagzUKbjdxE0tIcR9pMzLR2U/Tgie1Hq1HQ3iH8=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.1/go.mod h1:rH61DT6FDdikhPghymripNUCsf+uVF4Cnk4c4DBKH64=
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2/go.mod h1:wRQv0nN6v9wDXuWThpovGQjqF1HFdcgWjporw14lS8k=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.1 h1:RAnaIrbxPtlXNVI/OIlh1sidTQ3e1qM6LRjs7N0bE0I=
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.2 h1:EtOU5jsPdIQNP+6Q2C5e3d65NKT1PeCiQk+9OdzO12Q=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.1/go.mod h1:nbgAGkH5lk0RZRMh6A4K/oG6Xj11eC/1CyDow+DUAFI=
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.2/go.mod h1:tyF5sKccmDz0Bv4NrstEr+/9YkSPJHrcO7UsUKf7pWM=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.1 h1:rtYJd3w6IWCTVS8vmMaiXjW198noh2PBm5CiXyJea9o=
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.2 h1:en92G0Z7xlksoOylkUhuBSfJgijC7rHVLRdnIlHEs0E=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.1/go.mod h1:zvXu+CTlib30LUy4LTNFc6HTZ/K6zCae5YIHTdX9wIo=
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.2/go.mod h1:HgtQ/wN5G+8QSlK62lbOtNwQ3wTSByJ4wH2rCkPt+AE=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE=
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8=
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.1 h1:5Wxh862HkXL9CbQ83BIkWKLIgQapGeuh5zG2G9OZtQk=
|
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.2 h1:zSdTXYLwuXDNPUS+V41i1SFDXG7V0ITp0D9UT9Cvl18=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.1/go.mod h1:V7GLA01pNUxMCYSQsibdVrqUrNIYIT/9lCOyR8ExNvQ=
|
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.2/go.mod h1:v8m8k+qVy95nYi7d56uP1QImleIIY25BPiNJYzPBdFE=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.1 h1:cVP8mng1RjDyI3JN/AXFCn5FHNlsBaBH0/MBtG1bg0o=
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.2 h1:5ffmXjPtwRExp1zc7gENLgCPyHFbhEPwVTkTiH9niSk=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.1/go.mod h1:C8sQjoyAsdfjC7hpy4+S6B92hnFzx0d0UAyHicaOTIE=
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.2/go.mod h1:Ru7vg1iQ7cR4i7SZ/JTLYN9kaXtbL69UdgG0OQWQxW0=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.1 h1:OYmmIcyw19f7x0qLBLQ3XsrCZSSyLhxd9GXng5evsN4=
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.2 h1:1oY1AVEisRI4HNuFoLdRUB0hC63ylDAN6Me3MrfclEg=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.1/go.mod h1:s5rqdn74Vdg10k61Pwf4ZHEApOSD6CKRe6qpeHDq32I=
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.2/go.mod h1:KZ03VgvZwSjkT7fOetQ/wF3MZUvYFirlI1H5NklUNsY=
|
||||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.21.0 h1:NEWfVJgrDwEXrKDNrrX+2LtWhKVLYpJ2d7/gr1N1B54=
|
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.21.1 h1:cy+x/R8zd4Zluf+6ZWzbPPdLh+l4MeYPlYxdqK+Qr0M=
|
||||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.21.0/go.mod h1:TzgisXFoXgCssgP11SzC6KrvcyCErz5c3w++m3xFOfo=
|
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.21.1/go.mod h1:ITcPsa7HwiY6ddwbwmtuf+/q7sfr4MjH5HzUvn5FHBQ=
|
||||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.51.0 h1:rNVsCe3bqTAhG+qjnHJKgYKdHEsqqo/GMK3gEYY8W6g=
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.51.1 h1:juZ+uGargZOrQGNxkVHr9HHR/0N+Yu8uekQnV7EAVRs=
|
||||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.51.0/go.mod h1:lTW7O4iMAnO2o7H3XJTvqaWFZCH6zIPs+eP7RdG/yp0=
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.51.1/go.mod h1:SoR0c7Jnq8Tpmt0KSLXIavhjmaagRqQpe9r70W3POJg=
|
||||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.28.0 h1:Xf3s55N9cqKvFK6D70zCXvXXN4ZovTCy7glL+gUhLEc=
|
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.28.1 h1:DtKw4TxZT3VrzYupXQJPBqT9ImyobZZE+JIQPPAVxqs=
|
||||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.28.0/go.mod h1:RA3ERghFSivbTf0Sbsxv/grUuLMcyAjm0F/PylJMmEs=
|
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.28.1/go.mod h1:bit9G2ORpSjUTr4PA4usvbBfbOyvMj0LbE1dXF14Sug=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.0 h1:6YL8G91QZ52KlPrLkEgEez5kejIVwChVCgND3qgY5j0=
|
github.com/aws/aws-sdk-go-v2/service/sso v1.20.1 h1:utEGkfdQ4L6YW/ietH7111ZYglLJvS+sLriHJ1NBJEQ=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.0/go.mod h1:x6/tCd1o/AOKQR+iYnjrzhJxD+w0xRN34asGPaSV7ew=
|
github.com/aws/aws-sdk-go-v2/service/sso v1.20.1/go.mod h1:RsYqzYr2F2oPDdpy+PdhephuZxTfjHQe7SOBcZGoAU8=
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.0 h1:+DqIa5Ll7W311QLUvGFDdVit9uC4G0VioDdw08cXcow=
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1 h1:9/GylMS45hGGFCcMrUZDVayQE1jYSIN6da9jo7RAYIw=
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.0/go.mod h1:lZB123q0SVQ3dfIbEOcGzhQHrwVBcHVReNS9tm20oU4=
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1/go.mod h1:YjAPFn4kGFqKC54VsHs5fn5B6d+PCY2tziEa3U/GB5Y=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.0 h1:F7tQr61zYnTaeY50Rn4jwfVQbtcqJuBRwN/nGGNwzb0=
|
github.com/aws/aws-sdk-go-v2/service/sts v1.28.1 h1:3I2cBEYgKhrWlwyZgfpSO2BpaMY1LHPqXYk/QGlu2ew=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.0/go.mod h1:ozhhG9/NB5c9jcmhGq6tX9dpp21LYdmRWRQVppASim4=
|
github.com/aws/aws-sdk-go-v2/service/sts v1.28.1/go.mod h1:uQ7YYKZt3adCRrdCBREm1CD3efFLOUNH77MrUCvx5oA=
|
||||||
github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw=
|
github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw=
|
||||||
github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
|
github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
@ -91,8 +91,6 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj
|
||||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ=
|
|
||||||
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM=
|
|
||||||
github.com/cockroachdb/cockroach-go/v2 v2.3.6 h1:Wlv9TzkrG9V7i6u8dEtmXPrBzvfFp+CgJNs696rAajM=
|
github.com/cockroachdb/cockroach-go/v2 v2.3.6 h1:Wlv9TzkrG9V7i6u8dEtmXPrBzvfFp+CgJNs696rAajM=
|
||||||
github.com/cockroachdb/cockroach-go/v2 v2.3.6/go.mod h1:1wNJ45eSXW9AnOc3skntW9ZUZz6gxrQK3cOj3rK+BC8=
|
github.com/cockroachdb/cockroach-go/v2 v2.3.6/go.mod h1:1wNJ45eSXW9AnOc3skntW9ZUZz6gxrQK3cOj3rK+BC8=
|
||||||
github.com/coreos/go-oidc/v3 v3.9.0 h1:0J/ogVOd4y8P0f0xUh8l9t07xRP/d8tccvjHl2dcsSo=
|
github.com/coreos/go-oidc/v3 v3.9.0 h1:0J/ogVOd4y8P0f0xUh8l9t07xRP/d8tccvjHl2dcsSo=
|
||||||
|
@ -111,8 +109,8 @@ github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
|
||||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||||
github.com/drakkan/cron/v3 v3.0.0-20230222140221-217a1e4d96c0 h1:EW9gIJRmt9lzk66Fhh4S8VEtURA6QHZqGeSRE9Nb2/U=
|
github.com/drakkan/cron/v3 v3.0.0-20230222140221-217a1e4d96c0 h1:EW9gIJRmt9lzk66Fhh4S8VEtURA6QHZqGeSRE9Nb2/U=
|
||||||
github.com/drakkan/cron/v3 v3.0.0-20230222140221-217a1e4d96c0/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
github.com/drakkan/cron/v3 v3.0.0-20230222140221-217a1e4d96c0/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||||
github.com/drakkan/crypto v0.0.0-20231218163632-74b52eafd2c0 h1:Yel8NcrK4jg+biIcTxnszKh0eIpF2Vj25XEygQcTweI=
|
github.com/drakkan/crypto v0.0.0-20240224191538-9f4629f0732c h1:Jwxc0vhD7t484x2GDv8B5WbvrSwxML9V+A8esl7vkh8=
|
||||||
github.com/drakkan/crypto v0.0.0-20231218163632-74b52eafd2c0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
github.com/drakkan/crypto v0.0.0-20240224191538-9f4629f0732c/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
github.com/drakkan/ftp v0.0.0-20240210102745-f1ffc43f78d2 h1:ufiGMPFBjndWSQOst9FNP11IuMqPblI2NXbpRMUWNhk=
|
github.com/drakkan/ftp v0.0.0-20240210102745-f1ffc43f78d2 h1:ufiGMPFBjndWSQOst9FNP11IuMqPblI2NXbpRMUWNhk=
|
||||||
github.com/drakkan/ftp v0.0.0-20240210102745-f1ffc43f78d2/go.mod h1:4p8lUl4vQ80L598CygL+3IFtm+3nggvvW/palOlViwE=
|
github.com/drakkan/ftp v0.0.0-20240210102745-f1ffc43f78d2/go.mod h1:4p8lUl4vQ80L598CygL+3IFtm+3nggvvW/palOlViwE=
|
||||||
github.com/drakkan/ftpserverlib v0.0.0-20240212100826-a241365cb085 h1:LAKYR9z9USKeyEQK91sRWldmMOjEHLOt2NuLDx+x1UQ=
|
github.com/drakkan/ftpserverlib v0.0.0-20240212100826-a241365cb085 h1:LAKYR9z9USKeyEQK91sRWldmMOjEHLOt2NuLDx+x1UQ=
|
||||||
|
@ -127,8 +125,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
|
|
||||||
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
|
|
||||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||||
|
@ -148,8 +144,8 @@ github.com/go-chi/jwtauth/v5 v5.3.0 h1:X7RKGks1lrVeIe2omGyz47pNaNjG2YmwlRN5UKhN8
|
||||||
github.com/go-chi/jwtauth/v5 v5.3.0/go.mod h1:2PoGm/KbnzRN9ILY6HFZAI6fTnb1gEZAKogAyqkd6fY=
|
github.com/go-chi/jwtauth/v5 v5.3.0/go.mod h1:2PoGm/KbnzRN9ILY6HFZAI6fTnb1gEZAKogAyqkd6fY=
|
||||||
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
|
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
|
||||||
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
||||||
github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
|
github.com/go-jose/go-jose/v3 v3.0.2 h1:2Edjn8Nrb44UvTdp84KU0bBPs1cO7noRCybtS3eJEUQ=
|
||||||
github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
|
github.com/go-jose/go-jose/v3 v3.0.2/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
|
||||||
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
|
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
|
||||||
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||||
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
|
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
|
||||||
|
@ -411,14 +407,14 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
|
||||||
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA=
|
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
|
||||||
go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
|
||||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 h1:P+/g8GpuJGYbOp2tAdKrIPUX9JO02q8Q0YNlHolpibA=
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg=
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg=
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 h1:doUP+ExOpH3spVTLS0FcWGLnQrPct/hD/bCPbDRUEAU=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0/go.mod h1:rdENBZMT2OE6Ne/KLwpiXudnAsbdrdBaqBvTN8M8BgA=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
|
||||||
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
|
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
|
||||||
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
|
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
|
||||||
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
|
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
|
||||||
|
@ -491,7 +487,6 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|
||||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
@ -499,7 +494,6 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
|
||||||
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
|
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
|
||||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
|
|
@ -259,7 +259,6 @@ func Init() {
|
||||||
HostKeys: []string{},
|
HostKeys: []string{},
|
||||||
HostCertificates: []string{},
|
HostCertificates: []string{},
|
||||||
HostKeyAlgorithms: []string{},
|
HostKeyAlgorithms: []string{},
|
||||||
Moduli: []string{},
|
|
||||||
KexAlgorithms: []string{},
|
KexAlgorithms: []string{},
|
||||||
Ciphers: []string{},
|
Ciphers: []string{},
|
||||||
MACs: []string{},
|
MACs: []string{},
|
||||||
|
@ -2020,7 +2019,6 @@ func setViperDefaults() {
|
||||||
viper.SetDefault("sftpd.host_keys", globalConf.SFTPD.HostKeys)
|
viper.SetDefault("sftpd.host_keys", globalConf.SFTPD.HostKeys)
|
||||||
viper.SetDefault("sftpd.host_certificates", globalConf.SFTPD.HostCertificates)
|
viper.SetDefault("sftpd.host_certificates", globalConf.SFTPD.HostCertificates)
|
||||||
viper.SetDefault("sftpd.host_key_algorithms", globalConf.SFTPD.HostKeyAlgorithms)
|
viper.SetDefault("sftpd.host_key_algorithms", globalConf.SFTPD.HostKeyAlgorithms)
|
||||||
viper.SetDefault("sftpd.moduli", globalConf.SFTPD.Moduli)
|
|
||||||
viper.SetDefault("sftpd.kex_algorithms", globalConf.SFTPD.KexAlgorithms)
|
viper.SetDefault("sftpd.kex_algorithms", globalConf.SFTPD.KexAlgorithms)
|
||||||
viper.SetDefault("sftpd.ciphers", globalConf.SFTPD.Ciphers)
|
viper.SetDefault("sftpd.ciphers", globalConf.SFTPD.Ciphers)
|
||||||
viper.SetDefault("sftpd.macs", globalConf.SFTPD.MACs)
|
viper.SetDefault("sftpd.macs", globalConf.SFTPD.MACs)
|
||||||
|
|
|
@ -28,18 +28,18 @@ import (
|
||||||
// Supported values for host keys, KEXs, ciphers, MACs
|
// Supported values for host keys, KEXs, ciphers, MACs
|
||||||
var (
|
var (
|
||||||
supportedHostKeyAlgos = []string{ssh.KeyAlgoRSA}
|
supportedHostKeyAlgos = []string{ssh.KeyAlgoRSA}
|
||||||
supportedPublicKeyAlgos = []string{ssh.KeyAlgoRSA, ssh.KeyAlgoDSA}
|
supportedPublicKeyAlgos = []string{ssh.KeyAlgoRSA, ssh.InsecureKeyAlgoDSA}
|
||||||
supportedKexAlgos = []string{
|
supportedKexAlgos = []string{
|
||||||
"diffie-hellman-group16-sha512", "diffie-hellman-group14-sha1", "diffie-hellman-group1-sha1",
|
ssh.KeyExchangeDH16SHA512, ssh.InsecureKeyExchangeDH14SHA1, ssh.InsecureKeyExchangeDH1SHA1,
|
||||||
"diffie-hellman-group-exchange-sha256", "diffie-hellman-group-exchange-sha1",
|
ssh.InsecureKeyExchangeDHGEXSHA1,
|
||||||
}
|
}
|
||||||
supportedCiphers = []string{
|
supportedCiphers = []string{
|
||||||
"aes128-cbc", "aes192-cbc", "aes256-cbc",
|
ssh.InsecureCipherAES128CBC, ssh.InsecureCipherAES192CBC, ssh.InsecureCipherAES256CBC,
|
||||||
"3des-cbc",
|
ssh.InsecureCipherTripleDESCBC,
|
||||||
}
|
}
|
||||||
supportedMACs = []string{
|
supportedMACs = []string{
|
||||||
"hmac-sha2-512-etm@openssh.com", "hmac-sha2-512",
|
ssh.HMACSHA512ETM, ssh.HMACSHA512,
|
||||||
"hmac-sha1", "hmac-sha1-96",
|
ssh.InsecureHMACSHA1, ssh.InsecureHMACSHA196,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ func (c *SFTPDConfigs) validate() error {
|
||||||
c.HostKeyAlgos = hostKeyAlgos
|
c.HostKeyAlgos = hostKeyAlgos
|
||||||
var kexAlgos []string
|
var kexAlgos []string
|
||||||
for _, algo := range c.KexAlgorithms {
|
for _, algo := range c.KexAlgorithms {
|
||||||
if algo == "diffie-hellman-group18-sha512" {
|
if algo == "diffie-hellman-group18-sha512" || algo == ssh.KeyExchangeDHGEXSHA256 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !util.Contains(supportedKexAlgos, algo) {
|
if !util.Contains(supportedKexAlgos, algo) {
|
||||||
|
|
|
@ -8140,7 +8140,7 @@ func TestLoaddata(t *testing.T) {
|
||||||
configs := dataprovider.Configs{
|
configs := dataprovider.Configs{
|
||||||
SFTPD: &dataprovider.SFTPDConfigs{
|
SFTPD: &dataprovider.SFTPDConfigs{
|
||||||
HostKeyAlgos: []string{ssh.KeyAlgoRSA, ssh.CertAlgoRSAv01},
|
HostKeyAlgos: []string{ssh.KeyAlgoRSA, ssh.CertAlgoRSAv01},
|
||||||
PublicKeyAlgos: []string{ssh.KeyAlgoDSA},
|
PublicKeyAlgos: []string{ssh.InsecureKeyAlgoDSA},
|
||||||
},
|
},
|
||||||
SMTP: &dataprovider.SMTPConfigs{
|
SMTP: &dataprovider.SMTPConfigs{
|
||||||
Host: "mail.example.com",
|
Host: "mail.example.com",
|
||||||
|
@ -8207,7 +8207,7 @@ func TestLoaddata(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, configs.SMTP, configsGet.SMTP)
|
assert.Equal(t, configs.SMTP, configsGet.SMTP)
|
||||||
assert.Equal(t, []string{ssh.KeyAlgoRSA}, configsGet.SFTPD.HostKeyAlgos)
|
assert.Equal(t, []string{ssh.KeyAlgoRSA}, configsGet.SFTPD.HostKeyAlgos)
|
||||||
assert.Equal(t, []string{ssh.KeyAlgoDSA}, configsGet.SFTPD.PublicKeyAlgos)
|
assert.Equal(t, []string{ssh.InsecureKeyAlgoDSA}, configsGet.SFTPD.PublicKeyAlgos)
|
||||||
assert.Len(t, configsGet.SFTPD.KexAlgorithms, 0)
|
assert.Len(t, configsGet.SFTPD.KexAlgorithms, 0)
|
||||||
assert.Len(t, configsGet.SFTPD.Ciphers, 0)
|
assert.Len(t, configsGet.SFTPD.Ciphers, 0)
|
||||||
assert.Len(t, configsGet.SFTPD.MACs, 0)
|
assert.Len(t, configsGet.SFTPD.MACs, 0)
|
||||||
|
@ -8554,7 +8554,7 @@ func TestLoaddataMode(t *testing.T) {
|
||||||
entry, _, err = httpdtest.UpdateIPListEntry(entry, http.StatusOK)
|
entry, _, err = httpdtest.UpdateIPListEntry(entry, http.StatusOK)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
configs.SFTPD.PublicKeyAlgos = append(configs.SFTPD.PublicKeyAlgos, ssh.KeyAlgoDSA)
|
configs.SFTPD.PublicKeyAlgos = append(configs.SFTPD.PublicKeyAlgos, ssh.InsecureKeyAlgoDSA)
|
||||||
err = dataprovider.UpdateConfigs(&configs, "", "", "")
|
err = dataprovider.UpdateConfigs(&configs, "", "", "")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
backupData.Configs = &configs
|
backupData.Configs = &configs
|
||||||
|
@ -13088,8 +13088,8 @@ func TestWebConfigsMock(t *testing.T) {
|
||||||
checkResponseCode(t, http.StatusBadRequest, rr)
|
checkResponseCode(t, http.StatusBadRequest, rr)
|
||||||
// save SFTP configs
|
// save SFTP configs
|
||||||
form.Set("sftp_host_key_algos", ssh.KeyAlgoRSA)
|
form.Set("sftp_host_key_algos", ssh.KeyAlgoRSA)
|
||||||
form.Add("sftp_host_key_algos", ssh.CertAlgoDSAv01)
|
form.Add("sftp_host_key_algos", ssh.InsecureCertAlgoDSAv01)
|
||||||
form.Set("sftp_pub_key_algos", ssh.KeyAlgoDSA)
|
form.Set("sftp_pub_key_algos", ssh.InsecureKeyAlgoDSA)
|
||||||
form.Set("form_action", "sftp_submit")
|
form.Set("form_action", "sftp_submit")
|
||||||
req, err = http.NewRequest(http.MethodPost, webConfigsPath, bytes.NewBuffer([]byte(form.Encode())))
|
req, err = http.NewRequest(http.MethodPost, webConfigsPath, bytes.NewBuffer([]byte(form.Encode())))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -13100,9 +13100,9 @@ func TestWebConfigsMock(t *testing.T) {
|
||||||
assert.Contains(t, rr.Body.String(), util.I18nError500Message) // invalid algo
|
assert.Contains(t, rr.Body.String(), util.I18nError500Message) // invalid algo
|
||||||
form.Set("sftp_host_key_algos", ssh.KeyAlgoRSA)
|
form.Set("sftp_host_key_algos", ssh.KeyAlgoRSA)
|
||||||
form.Add("sftp_host_key_algos", ssh.CertAlgoRSAv01)
|
form.Add("sftp_host_key_algos", ssh.CertAlgoRSAv01)
|
||||||
form.Set("sftp_pub_key_algos", ssh.KeyAlgoDSA)
|
form.Set("sftp_pub_key_algos", ssh.InsecureKeyAlgoDSA)
|
||||||
form.Set("sftp_kex_algos", "diffie-hellman-group18-sha512")
|
form.Set("sftp_kex_algos", "diffie-hellman-group18-sha512")
|
||||||
form.Add("sftp_kex_algos", "diffie-hellman-group16-sha512")
|
form.Add("sftp_kex_algos", ssh.KeyExchangeDH16SHA512)
|
||||||
req, err = http.NewRequest(http.MethodPost, webConfigsPath, bytes.NewBuffer([]byte(form.Encode())))
|
req, err = http.NewRequest(http.MethodPost, webConfigsPath, bytes.NewBuffer([]byte(form.Encode())))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
setJWTCookieForReq(req, webToken)
|
setJWTCookieForReq(req, webToken)
|
||||||
|
@ -13116,9 +13116,9 @@ func TestWebConfigsMock(t *testing.T) {
|
||||||
assert.Len(t, configs.SFTPD.HostKeyAlgos, 1)
|
assert.Len(t, configs.SFTPD.HostKeyAlgos, 1)
|
||||||
assert.Contains(t, configs.SFTPD.HostKeyAlgos, ssh.KeyAlgoRSA)
|
assert.Contains(t, configs.SFTPD.HostKeyAlgos, ssh.KeyAlgoRSA)
|
||||||
assert.Len(t, configs.SFTPD.PublicKeyAlgos, 1)
|
assert.Len(t, configs.SFTPD.PublicKeyAlgos, 1)
|
||||||
assert.Contains(t, configs.SFTPD.PublicKeyAlgos, ssh.KeyAlgoDSA)
|
assert.Contains(t, configs.SFTPD.PublicKeyAlgos, ssh.InsecureKeyAlgoDSA)
|
||||||
assert.Len(t, configs.SFTPD.KexAlgorithms, 1)
|
assert.Len(t, configs.SFTPD.KexAlgorithms, 1)
|
||||||
assert.Contains(t, configs.SFTPD.KexAlgorithms, "diffie-hellman-group16-sha512")
|
assert.Contains(t, configs.SFTPD.KexAlgorithms, ssh.KeyExchangeDH16SHA512)
|
||||||
// invalid form action
|
// invalid form action
|
||||||
form.Set("form_action", "")
|
form.Set("form_action", "")
|
||||||
req, err = http.NewRequest(http.MethodPost, webConfigsPath, bytes.NewBuffer([]byte(form.Encode())))
|
req, err = http.NewRequest(http.MethodPost, webConfigsPath, bytes.NewBuffer([]byte(form.Encode())))
|
||||||
|
@ -13163,7 +13163,7 @@ func TestWebConfigsMock(t *testing.T) {
|
||||||
assert.Len(t, configs.SFTPD.HostKeyAlgos, 1)
|
assert.Len(t, configs.SFTPD.HostKeyAlgos, 1)
|
||||||
assert.Contains(t, configs.SFTPD.HostKeyAlgos, ssh.KeyAlgoRSA)
|
assert.Contains(t, configs.SFTPD.HostKeyAlgos, ssh.KeyAlgoRSA)
|
||||||
assert.Len(t, configs.SFTPD.PublicKeyAlgos, 1)
|
assert.Len(t, configs.SFTPD.PublicKeyAlgos, 1)
|
||||||
assert.Contains(t, configs.SFTPD.PublicKeyAlgos, ssh.KeyAlgoDSA)
|
assert.Contains(t, configs.SFTPD.PublicKeyAlgos, ssh.InsecureKeyAlgoDSA)
|
||||||
assert.Equal(t, "mail.example.net", configs.SMTP.Host)
|
assert.Equal(t, "mail.example.net", configs.SMTP.Host)
|
||||||
assert.Equal(t, 587, configs.SMTP.Port)
|
assert.Equal(t, 587, configs.SMTP.Port)
|
||||||
assert.Equal(t, "Example <info@example.net>", configs.SMTP.From)
|
assert.Equal(t, "Example <info@example.net>", configs.SMTP.From)
|
||||||
|
@ -13234,7 +13234,7 @@ func TestWebConfigsMock(t *testing.T) {
|
||||||
assert.Len(t, configs.SFTPD.HostKeyAlgos, 1)
|
assert.Len(t, configs.SFTPD.HostKeyAlgos, 1)
|
||||||
assert.Contains(t, configs.SFTPD.HostKeyAlgos, ssh.KeyAlgoRSA)
|
assert.Contains(t, configs.SFTPD.HostKeyAlgos, ssh.KeyAlgoRSA)
|
||||||
assert.Len(t, configs.SFTPD.PublicKeyAlgos, 1)
|
assert.Len(t, configs.SFTPD.PublicKeyAlgos, 1)
|
||||||
assert.Contains(t, configs.SFTPD.PublicKeyAlgos, ssh.KeyAlgoDSA)
|
assert.Contains(t, configs.SFTPD.PublicKeyAlgos, ssh.InsecureKeyAlgoDSA)
|
||||||
assert.Equal(t, 80, configs.ACME.HTTP01Challenge.Port)
|
assert.Equal(t, 80, configs.ACME.HTTP01Challenge.Port)
|
||||||
assert.Equal(t, 7, configs.ACME.Protocols)
|
assert.Equal(t, 7, configs.ACME.Protocols)
|
||||||
assert.Empty(t, configs.ACME.Domain)
|
assert.Empty(t, configs.ACME.Domain)
|
||||||
|
|
|
@ -1837,7 +1837,6 @@ func TestConfigsFromProvider(t *testing.T) {
|
||||||
err = c.loadFromProvider()
|
err = c.loadFromProvider()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, c.HostKeyAlgorithms, 0)
|
assert.Len(t, c.HostKeyAlgorithms, 0)
|
||||||
assert.Len(t, c.Moduli, 0)
|
|
||||||
assert.Len(t, c.KexAlgorithms, 0)
|
assert.Len(t, c.KexAlgorithms, 0)
|
||||||
assert.Len(t, c.Ciphers, 0)
|
assert.Len(t, c.Ciphers, 0)
|
||||||
assert.Len(t, c.MACs, 0)
|
assert.Len(t, c.MACs, 0)
|
||||||
|
@ -1845,10 +1844,10 @@ func TestConfigsFromProvider(t *testing.T) {
|
||||||
configs := dataprovider.Configs{
|
configs := dataprovider.Configs{
|
||||||
SFTPD: &dataprovider.SFTPDConfigs{
|
SFTPD: &dataprovider.SFTPDConfigs{
|
||||||
HostKeyAlgos: []string{ssh.KeyAlgoRSA},
|
HostKeyAlgos: []string{ssh.KeyAlgoRSA},
|
||||||
KexAlgorithms: []string{kexDHGroupExchangeSHA256},
|
KexAlgorithms: []string{ssh.InsecureKeyExchangeDHGEXSHA1},
|
||||||
Ciphers: []string{"aes128-cbc", "aes192-cbc", "aes256-cbc"},
|
Ciphers: []string{ssh.InsecureCipherAES128CBC, ssh.InsecureCipherAES192CBC, ssh.InsecureCipherAES256CBC},
|
||||||
MACs: []string{"hmac-sha2-512-etm@openssh.com"},
|
MACs: []string{ssh.HMACSHA512ETM},
|
||||||
PublicKeyAlgos: []string{ssh.KeyAlgoDSA},
|
PublicKeyAlgos: []string{ssh.InsecureKeyAlgoDSA},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err = dataprovider.UpdateConfigs(&configs, "", "", "")
|
err = dataprovider.UpdateConfigs(&configs, "", "", "")
|
||||||
|
@ -1876,58 +1875,33 @@ func TestSupportedSecurityOptions(t *testing.T) {
|
||||||
MACs: supportedMACs,
|
MACs: supportedMACs,
|
||||||
Ciphers: supportedCiphers,
|
Ciphers: supportedCiphers,
|
||||||
}
|
}
|
||||||
|
var defaultKexs []string
|
||||||
|
for _, k := range supportedKexAlgos {
|
||||||
|
defaultKexs = append(defaultKexs, k)
|
||||||
|
if k == ssh.KeyExchangeCurve25519SHA256 {
|
||||||
|
defaultKexs = append(defaultKexs, keyExchangeCurve25519SHA256LibSSH)
|
||||||
|
}
|
||||||
|
}
|
||||||
serverConfig := &ssh.ServerConfig{}
|
serverConfig := &ssh.ServerConfig{}
|
||||||
err := c.configureSecurityOptions(serverConfig)
|
err := c.configureSecurityOptions(serverConfig)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, supportedCiphers, serverConfig.Ciphers)
|
assert.Equal(t, supportedCiphers, serverConfig.Ciphers)
|
||||||
assert.Equal(t, supportedMACs, serverConfig.MACs)
|
assert.Equal(t, supportedMACs, serverConfig.MACs)
|
||||||
assert.Equal(t, supportedKexAlgos, serverConfig.KeyExchanges)
|
assert.Equal(t, defaultKexs, serverConfig.KeyExchanges)
|
||||||
c.KexAlgorithms = append(c.KexAlgorithms, "not a kex")
|
c.KexAlgorithms = append(c.KexAlgorithms, "not a kex")
|
||||||
err = c.configureSecurityOptions(serverConfig)
|
err = c.configureSecurityOptions(serverConfig)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
c.KexAlgorithms = supportedKexAlgos
|
c.KexAlgorithms = append(supportedKexAlgos, "diffie-hellman-group18-sha512")
|
||||||
c.MACs = []string{
|
c.MACs = []string{
|
||||||
" hmac-sha2-256-etm@openssh.com ", "hmac-sha2-256",
|
" hmac-sha2-256-etm@openssh.com ", " hmac-sha2-512-etm@openssh.com",
|
||||||
" hmac-sha2-512-etm@openssh.com", "hmac-sha2-512 ",
|
"hmac-sha2-256", "hmac-sha2-512 ",
|
||||||
"hmac-sha1 ", " hmac-sha1-96",
|
" hmac-sha1-96", "hmac-sha1 ",
|
||||||
}
|
}
|
||||||
err = c.configureSecurityOptions(serverConfig)
|
err = c.configureSecurityOptions(serverConfig)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, supportedCiphers, serverConfig.Ciphers)
|
assert.Equal(t, supportedCiphers, serverConfig.Ciphers)
|
||||||
assert.Equal(t, supportedMACs, serverConfig.MACs)
|
assert.Equal(t, supportedMACs, serverConfig.MACs)
|
||||||
assert.Equal(t, supportedKexAlgos, serverConfig.KeyExchanges)
|
assert.Equal(t, defaultKexs, serverConfig.KeyExchanges)
|
||||||
c.KexAlgorithms = append(preferredKexAlgos, kexDHGroupExchangeSHA256) // removed because no moduli is provided
|
|
||||||
err = c.configureSecurityOptions(serverConfig)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, supportedCiphers, serverConfig.Ciphers)
|
|
||||||
assert.Equal(t, supportedMACs, serverConfig.MACs)
|
|
||||||
assert.Equal(t, preferredKexAlgos, serverConfig.KeyExchanges)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLoadModuli(t *testing.T) {
|
|
||||||
dhGEXSha1 := "diffie-hellman-group-exchange-sha1"
|
|
||||||
dhGEXSha256 := "diffie-hellman-group-exchange-sha256"
|
|
||||||
c := Configuration{}
|
|
||||||
c.Moduli = []string{".", "missing file"}
|
|
||||||
c.loadModuli(configDir)
|
|
||||||
assert.NotContains(t, supportedKexAlgos, dhGEXSha1)
|
|
||||||
assert.NotContains(t, supportedKexAlgos, dhGEXSha256)
|
|
||||||
assert.NotContains(t, preferredKexAlgos, dhGEXSha1)
|
|
||||||
assert.NotContains(t, preferredKexAlgos, dhGEXSha256)
|
|
||||||
assert.Len(t, supportedKexAlgos, 10)
|
|
||||||
moduli := []byte("20220414072358 2 6 100 2047 5 F19C2D09AD49978F8A0C1B84168A4011A26F9CD516815934764A319FDC5975FA514AAF11B747D8CA6B3919532BEFB68FA118079473895674F3770F71FBB742F176883841EB3DE679BEF53C6AFE437A662F228B03C1E34B5A0D3909F608CEAA16C1F8131DE11E67878EFD918A89205E5E4DE323054010CA4711F25D466BB7727A016DD3F9F53BDBCE093055A4F2497ADEFB5A2500F9C5C3B0BCD88C6489F4C1CBC7CFB67BA6EABA0195794E4188CE9060F431041AD52FB9BAC4DF7FA536F585FBE67746CD57BFAD67567E9706C24D95C49BE95B759657C6BB5151E2AEA32F4CD557C40298A5C402101520EE8AAB8DFEED6FFC11AAF8036D6345923CFB5D1B922F")
|
|
||||||
moduliFile := filepath.Join(os.TempDir(), "moduli")
|
|
||||||
err := os.WriteFile(moduliFile, moduli, 0600)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
c.Moduli = []string{moduliFile}
|
|
||||||
c.loadModuli(configDir)
|
|
||||||
assert.Contains(t, supportedKexAlgos, dhGEXSha1)
|
|
||||||
assert.Contains(t, supportedKexAlgos, dhGEXSha256)
|
|
||||||
assert.NotContains(t, preferredKexAlgos, dhGEXSha1)
|
|
||||||
assert.Contains(t, preferredKexAlgos, dhGEXSha256)
|
|
||||||
assert.Len(t, supportedKexAlgos, 12)
|
|
||||||
err = os.Remove(moduliFile)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadHostKeys(t *testing.T) {
|
func TestLoadHostKeys(t *testing.T) {
|
||||||
|
|
|
@ -45,75 +45,32 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultPrivateRSAKeyName = "id_rsa"
|
defaultPrivateRSAKeyName = "id_rsa"
|
||||||
defaultPrivateECDSAKeyName = "id_ecdsa"
|
defaultPrivateECDSAKeyName = "id_ecdsa"
|
||||||
defaultPrivateEd25519KeyName = "id_ed25519"
|
defaultPrivateEd25519KeyName = "id_ed25519"
|
||||||
sourceAddressCriticalOption = "source-address"
|
sourceAddressCriticalOption = "source-address"
|
||||||
kexDHGroupExchangeSHA1 = "diffie-hellman-group-exchange-sha1"
|
keyExchangeCurve25519SHA256LibSSH = "curve25519-sha256@libssh.org"
|
||||||
kexDHGroupExchangeSHA256 = "diffie-hellman-group-exchange-sha256"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
supportedAlgos = ssh.SupportedAlgorithms()
|
||||||
|
insecureAlgos = ssh.InsecureAlgorithms()
|
||||||
sftpExtensions = []string{"statvfs@openssh.com"}
|
sftpExtensions = []string{"statvfs@openssh.com"}
|
||||||
supportedHostKeyAlgos = []string{
|
supportedHostKeyAlgos = append(supportedAlgos.HostKeys, insecureAlgos.HostKeys...)
|
||||||
ssh.CertAlgoRSASHA512v01, ssh.CertAlgoRSASHA256v01,
|
|
||||||
ssh.CertAlgoRSAv01, ssh.CertAlgoDSAv01, ssh.CertAlgoECDSA256v01,
|
|
||||||
ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01, ssh.CertAlgoED25519v01,
|
|
||||||
ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521,
|
|
||||||
ssh.KeyAlgoRSASHA512, ssh.KeyAlgoRSASHA256,
|
|
||||||
ssh.KeyAlgoRSA, ssh.KeyAlgoDSA,
|
|
||||||
ssh.KeyAlgoED25519,
|
|
||||||
}
|
|
||||||
preferredHostKeyAlgos = []string{
|
preferredHostKeyAlgos = []string{
|
||||||
ssh.KeyAlgoRSASHA256, ssh.KeyAlgoRSASHA512,
|
ssh.KeyAlgoRSASHA256, ssh.KeyAlgoRSASHA512,
|
||||||
ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521,
|
ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521,
|
||||||
ssh.KeyAlgoED25519,
|
ssh.KeyAlgoED25519,
|
||||||
}
|
}
|
||||||
supportedPublicKeyAlgos = []string{
|
supportedPublicKeyAlgos = append(supportedAlgos.PublicKeyAuths, insecureAlgos.PublicKeyAuths...)
|
||||||
ssh.KeyAlgoED25519,
|
preferredPublicKeyAlgos = supportedAlgos.PublicKeyAuths
|
||||||
ssh.KeyAlgoSKED25519, ssh.KeyAlgoSKECDSA256,
|
supportedKexAlgos = append(supportedAlgos.KeyExchanges, insecureAlgos.KeyExchanges...)
|
||||||
ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521,
|
preferredKexAlgos = supportedAlgos.KeyExchanges
|
||||||
ssh.KeyAlgoRSASHA256, ssh.KeyAlgoRSASHA512, ssh.KeyAlgoRSA,
|
supportedCiphers = append(supportedAlgos.Ciphers, insecureAlgos.Ciphers...)
|
||||||
ssh.KeyAlgoDSA,
|
preferredCiphers = supportedAlgos.Ciphers
|
||||||
}
|
supportedMACs = append(supportedAlgos.MACs, insecureAlgos.MACs...)
|
||||||
preferredPublicKeyAlgos = []string{
|
preferredMACs = []string{
|
||||||
ssh.KeyAlgoED25519,
|
ssh.HMACSHA256ETM, ssh.HMACSHA256,
|
||||||
ssh.KeyAlgoSKED25519, ssh.KeyAlgoSKECDSA256,
|
|
||||||
ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521,
|
|
||||||
ssh.KeyAlgoRSASHA256, ssh.KeyAlgoRSASHA512,
|
|
||||||
}
|
|
||||||
supportedKexAlgos = []string{
|
|
||||||
"curve25519-sha256", "curve25519-sha256@libssh.org",
|
|
||||||
"ecdh-sha2-nistp256", "ecdh-sha2-nistp384", "ecdh-sha2-nistp521",
|
|
||||||
"diffie-hellman-group14-sha256", "diffie-hellman-group16-sha512",
|
|
||||||
"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",
|
|
||||||
"aes128-ctr", "aes192-ctr", "aes256-ctr",
|
|
||||||
"aes128-cbc", "aes192-cbc", "aes256-cbc",
|
|
||||||
"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{
|
revokedCertManager = revokedCertificates{
|
||||||
|
@ -170,12 +127,6 @@ type Configuration struct {
|
||||||
// HostKeyAlgorithms lists the public key algorithms that the server will accept for host
|
// HostKeyAlgorithms lists the public key algorithms that the server will accept for host
|
||||||
// key authentication.
|
// key authentication.
|
||||||
HostKeyAlgorithms []string `json:"host_key_algorithms" mapstructure:"host_key_algorithms"`
|
HostKeyAlgorithms []string `json:"host_key_algorithms" mapstructure:"host_key_algorithms"`
|
||||||
// Diffie-Hellman moduli files.
|
|
||||||
// Each moduli file can be defined as a path relative to the configuration directory or an absolute one.
|
|
||||||
// If set and valid, "diffie-hellman-group-exchange-sha256" and "diffie-hellman-group-exchange-sha1" KEX algorithms
|
|
||||||
// will be available, `diffie-hellman-group-exchange-sha256` will be enabled by default if you
|
|
||||||
// don't explicitly set KEXs
|
|
||||||
Moduli []string `json:"moduli" mapstructure:"moduli"`
|
|
||||||
// KexAlgorithms specifies the available KEX (Key Exchange) algorithms in
|
// KexAlgorithms specifies the available KEX (Key Exchange) algorithms in
|
||||||
// preference order.
|
// preference order.
|
||||||
KexAlgorithms []string `json:"kex_algorithms" mapstructure:"kex_algorithms"`
|
KexAlgorithms []string `json:"kex_algorithms" mapstructure:"kex_algorithms"`
|
||||||
|
@ -373,8 +324,6 @@ func (c *Configuration) Initialize(configDir string) error {
|
||||||
return common.ErrNoBinding
|
return common.ErrNoBinding
|
||||||
}
|
}
|
||||||
|
|
||||||
c.loadModuli(configDir)
|
|
||||||
|
|
||||||
sftp.SetSFTPExtensions(sftpExtensions...) //nolint:errcheck // we configure valid SFTP Extensions so we cannot get an error
|
sftp.SetSFTPExtensions(sftpExtensions...) //nolint:errcheck // we configure valid SFTP Extensions so we cannot get an error
|
||||||
sftp.MaxFilelist = vfs.ListerBatchSize
|
sftp.MaxFilelist = vfs.ListerBatchSize
|
||||||
|
|
||||||
|
@ -491,21 +440,34 @@ func (c *Configuration) configureKeyAlgos(serverConfig *ssh.ServerConfig) error
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Configuration) checkKeyExchangeAlgorithms() {
|
||||||
|
var kexs []string
|
||||||
|
for _, k := range c.KexAlgorithms {
|
||||||
|
if k == "diffie-hellman-group18-sha512" {
|
||||||
|
logger.Warn(logSender, "", "KEX %q is not supported and will be ignored", k)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
kexs = append(kexs, k)
|
||||||
|
if strings.TrimSpace(k) == keyExchangeCurve25519SHA256LibSSH {
|
||||||
|
kexs = append(kexs, ssh.KeyExchangeCurve25519SHA256)
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(k) == ssh.KeyExchangeCurve25519SHA256 {
|
||||||
|
kexs = append(kexs, keyExchangeCurve25519SHA256LibSSH)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.KexAlgorithms = util.RemoveDuplicates(kexs, true)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Configuration) configureSecurityOptions(serverConfig *ssh.ServerConfig) error {
|
func (c *Configuration) configureSecurityOptions(serverConfig *ssh.ServerConfig) error {
|
||||||
if err := c.configureKeyAlgos(serverConfig); err != nil {
|
if err := c.configureKeyAlgos(serverConfig); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.KexAlgorithms) > 0 {
|
if len(c.KexAlgorithms) > 0 {
|
||||||
hasDHGroupKEX := util.Contains(supportedKexAlgos, kexDHGroupExchangeSHA256)
|
c.checkKeyExchangeAlgorithms()
|
||||||
if !hasDHGroupKEX {
|
|
||||||
c.KexAlgorithms = util.Remove(c.KexAlgorithms, kexDHGroupExchangeSHA1)
|
|
||||||
c.KexAlgorithms = util.Remove(c.KexAlgorithms, kexDHGroupExchangeSHA256)
|
|
||||||
}
|
|
||||||
c.KexAlgorithms = util.RemoveDuplicates(c.KexAlgorithms, true)
|
|
||||||
for _, kex := range c.KexAlgorithms {
|
for _, kex := range c.KexAlgorithms {
|
||||||
if kex == "diffie-hellman-group18-sha512" {
|
if kex == keyExchangeCurve25519SHA256LibSSH {
|
||||||
logger.Warn(logSender, "", "KEX %q is not supported and will be ignored", kex)
|
continue
|
||||||
}
|
}
|
||||||
if !util.Contains(supportedKexAlgos, kex) {
|
if !util.Contains(supportedKexAlgos, kex) {
|
||||||
return fmt.Errorf("unsupported key-exchange algorithm %q", kex)
|
return fmt.Errorf("unsupported key-exchange algorithm %q", kex)
|
||||||
|
@ -513,6 +475,7 @@ func (c *Configuration) configureSecurityOptions(serverConfig *ssh.ServerConfig)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c.KexAlgorithms = preferredKexAlgos
|
c.KexAlgorithms = preferredKexAlgos
|
||||||
|
c.checkKeyExchangeAlgorithms()
|
||||||
}
|
}
|
||||||
serverConfig.KeyExchanges = c.KexAlgorithms
|
serverConfig.KeyExchanges = c.KexAlgorithms
|
||||||
serviceStatus.KexAlgorithms = c.KexAlgorithms
|
serviceStatus.KexAlgorithms = c.KexAlgorithms
|
||||||
|
@ -643,8 +606,8 @@ func (c *Configuration) AcceptInboundConnection(conn net.Conn, config *ssh.Serve
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Log(logger.LevelInfo, common.ProtocolSSH, connectionID,
|
logger.Log(logger.LevelInfo, common.ProtocolSSH, connectionID,
|
||||||
"User %q logged in with %q, from ip %q, client version %q", user.Username, loginType,
|
"User %q logged in with %q, from ip %q, client version %q, negotiated algorithms: %+v",
|
||||||
ipAddr, string(sconn.ClientVersion()))
|
user.Username, loginType, ipAddr, string(sconn.ClientVersion()), sconn.Conn.(ssh.AlgorithmsConnMetadata).Algorithms())
|
||||||
dataprovider.UpdateLastLogin(&user)
|
dataprovider.UpdateLastLogin(&user)
|
||||||
|
|
||||||
sshConnection := common.NewSSHConnection(connectionID, conn)
|
sshConnection := common.NewSSHConnection(connectionID, conn)
|
||||||
|
@ -812,7 +775,8 @@ func checkAuthError(ip string, err error) {
|
||||||
common.AddDefenderEvent(ip, common.ProtocolSSH, common.HostEventNoLoginTried)
|
common.AddDefenderEvent(ip, common.ProtocolSSH, common.HostEventNoLoginTried)
|
||||||
dataprovider.ExecutePostLoginHook(&dataprovider.User{}, dataprovider.LoginMethodNoAuthTried, ip, common.ProtocolSSH, err)
|
dataprovider.ExecutePostLoginHook(&dataprovider.User{}, dataprovider.LoginMethodNoAuthTried, ip, common.ProtocolSSH, err)
|
||||||
logEv := notifier.LogEventTypeNoLoginTried
|
logEv := notifier.LogEventTypeNoLoginTried
|
||||||
if errors.Is(err, ssh.ErrNoCommonAlgo) {
|
var negotiationError *ssh.AlgorithmNegotiationError
|
||||||
|
if errors.As(err, &negotiationError) {
|
||||||
logEv = notifier.LogEventTypeNotNegotiated
|
logEv = notifier.LogEventTypeNotNegotiated
|
||||||
}
|
}
|
||||||
plugin.Handler.NotifyLogEvent(logEv, common.ProtocolSSH, "", ip, "", err)
|
plugin.Handler.NotifyLogEvent(logEv, common.ProtocolSSH, "", ip, "", err)
|
||||||
|
@ -851,7 +815,7 @@ func loginUser(user *dataprovider.User, loginMethod, publicKey string, conn ssh.
|
||||||
user.Username)
|
user.Username)
|
||||||
return nil, fmt.Errorf("second factor authentication is not set for user %q", user.Username)
|
return nil, fmt.Errorf("second factor authentication is not set for user %q", user.Username)
|
||||||
}
|
}
|
||||||
remoteAddr := conn.RemoteAddr().String()
|
remoteAddr := util.GetIPFromRemoteAddress(conn.RemoteAddr().String())
|
||||||
if !user.IsLoginFromAddrAllowed(remoteAddr) {
|
if !user.IsLoginFromAddrAllowed(remoteAddr) {
|
||||||
logger.Info(logSender, connectionID, "cannot login user %q, remote address is not allowed: %v",
|
logger.Info(logSender, connectionID, "cannot login user %q, remote address is not allowed: %v",
|
||||||
user.Username, remoteAddr)
|
user.Username, remoteAddr)
|
||||||
|
@ -981,38 +945,6 @@ func (c *Configuration) checkHostKeyAutoGeneration(configDir string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Configuration) loadModuli(configDir string) {
|
|
||||||
supportedKexAlgos = util.Remove(supportedKexAlgos, kexDHGroupExchangeSHA1)
|
|
||||||
supportedKexAlgos = util.Remove(supportedKexAlgos, kexDHGroupExchangeSHA256)
|
|
||||||
preferredKexAlgos = util.Remove(preferredKexAlgos, kexDHGroupExchangeSHA256)
|
|
||||||
c.Moduli = util.RemoveDuplicates(c.Moduli, false)
|
|
||||||
for _, m := range c.Moduli {
|
|
||||||
m = strings.TrimSpace(m)
|
|
||||||
if !util.IsFileInputValid(m) {
|
|
||||||
logger.Warn(logSender, "", "unable to load invalid moduli file %q", m)
|
|
||||||
logger.WarnToConsole("unable to load invalid host moduli file %q", m)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !filepath.IsAbs(m) {
|
|
||||||
m = filepath.Join(configDir, m)
|
|
||||||
}
|
|
||||||
logger.Info(logSender, "", "loading moduli file %q", m)
|
|
||||||
if err := ssh.ParseModuli(m); err != nil {
|
|
||||||
logger.Warn(logSender, "", "ignoring moduli file %q, error: %v", m, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Configuration) getHostKeyAlgorithms(keyFormat string) []string {
|
func (c *Configuration) getHostKeyAlgorithms(keyFormat string) []string {
|
||||||
var algos []string
|
var algos []string
|
||||||
for _, algo := range algorithmsForKeyFormat(keyFormat) {
|
for _, algo := range algorithmsForKeyFormat(keyFormat) {
|
||||||
|
@ -1188,12 +1120,12 @@ func (c *Configuration) initializeCertChecker(configDir string) error {
|
||||||
func (c *Configuration) getPartialSuccessError(nextAuthMethods []string) error {
|
func (c *Configuration) getPartialSuccessError(nextAuthMethods []string) error {
|
||||||
err := &ssh.PartialSuccessError{}
|
err := &ssh.PartialSuccessError{}
|
||||||
if c.PasswordAuthentication && util.Contains(nextAuthMethods, dataprovider.LoginMethodPassword) {
|
if c.PasswordAuthentication && util.Contains(nextAuthMethods, dataprovider.LoginMethodPassword) {
|
||||||
err.PasswordCallback = func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
|
err.Next.PasswordCallback = func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
|
||||||
return c.validatePasswordCredentials(conn, password, dataprovider.SSHLoginMethodKeyAndPassword)
|
return c.validatePasswordCredentials(conn, password, dataprovider.SSHLoginMethodKeyAndPassword)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if c.KeyboardInteractiveAuthentication && util.Contains(nextAuthMethods, dataprovider.SSHLoginMethodKeyboardInteractive) {
|
if c.KeyboardInteractiveAuthentication && util.Contains(nextAuthMethods, dataprovider.SSHLoginMethodKeyboardInteractive) {
|
||||||
err.KeyboardInteractiveCallback = func(conn ssh.ConnMetadata, client ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error) {
|
err.Next.KeyboardInteractiveCallback = func(conn ssh.ConnMetadata, client ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error) {
|
||||||
return c.validateKeyboardInteractiveCredentials(conn, client, dataprovider.SSHLoginMethodKeyAndKeyboardInt, true)
|
return c.validateKeyboardInteractiveCredentials(conn, client, dataprovider.SSHLoginMethodKeyAndKeyboardInt, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,16 +37,16 @@ var (
|
||||||
systemCommands = []string{"git-receive-pack", "git-upload-pack", "git-upload-archive", "rsync"}
|
systemCommands = []string{"git-receive-pack", "git-upload-pack", "git-upload-archive", "rsync"}
|
||||||
serviceStatus ServiceStatus
|
serviceStatus ServiceStatus
|
||||||
certKeyAlgoNames = map[string]string{
|
certKeyAlgoNames = map[string]string{
|
||||||
ssh.CertAlgoRSAv01: ssh.KeyAlgoRSA,
|
ssh.CertAlgoRSAv01: ssh.KeyAlgoRSA,
|
||||||
ssh.CertAlgoRSASHA256v01: ssh.KeyAlgoRSASHA256,
|
ssh.CertAlgoRSASHA256v01: ssh.KeyAlgoRSASHA256,
|
||||||
ssh.CertAlgoRSASHA512v01: ssh.KeyAlgoRSASHA512,
|
ssh.CertAlgoRSASHA512v01: ssh.KeyAlgoRSASHA512,
|
||||||
ssh.CertAlgoDSAv01: ssh.KeyAlgoDSA,
|
ssh.InsecureCertAlgoDSAv01: ssh.InsecureKeyAlgoDSA,
|
||||||
ssh.CertAlgoECDSA256v01: ssh.KeyAlgoECDSA256,
|
ssh.CertAlgoECDSA256v01: ssh.KeyAlgoECDSA256,
|
||||||
ssh.CertAlgoECDSA384v01: ssh.KeyAlgoECDSA384,
|
ssh.CertAlgoECDSA384v01: ssh.KeyAlgoECDSA384,
|
||||||
ssh.CertAlgoECDSA521v01: ssh.KeyAlgoECDSA521,
|
ssh.CertAlgoECDSA521v01: ssh.KeyAlgoECDSA521,
|
||||||
ssh.CertAlgoSKECDSA256v01: ssh.KeyAlgoSKECDSA256,
|
ssh.CertAlgoSKECDSA256v01: ssh.KeyAlgoSKECDSA256,
|
||||||
ssh.CertAlgoED25519v01: ssh.KeyAlgoED25519,
|
ssh.CertAlgoED25519v01: ssh.KeyAlgoED25519,
|
||||||
ssh.CertAlgoSKED25519v01: ssh.KeyAlgoSKED25519,
|
ssh.CertAlgoSKED25519v01: ssh.KeyAlgoSKED25519,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -255,11 +255,10 @@ func TestMain(m *testing.M) {
|
||||||
ApplyProxyConfig: true,
|
ApplyProxyConfig: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
sftpdConf.KexAlgorithms = []string{"curve25519-sha256@libssh.org", "ecdh-sha2-nistp256",
|
sftpdConf.KexAlgorithms = []string{"curve25519-sha256@libssh.org", ssh.KeyExchangeECDHP256,
|
||||||
"ecdh-sha2-nistp384"}
|
ssh.KeyExchangeECDHP384}
|
||||||
sftpdConf.Ciphers = []string{"chacha20-poly1305@openssh.com", "aes128-gcm@openssh.com",
|
sftpdConf.Ciphers = []string{ssh.CipherChacha20Poly1305, ssh.CipherAES128GCM,
|
||||||
"aes256-ctr"}
|
ssh.CipherAES256CTR}
|
||||||
sftpdConf.MACs = []string{"hmac-sha2-256-etm@openssh.com", "hmac-sha2-256"}
|
|
||||||
sftpdConf.LoginBannerFile = loginBannerFileName
|
sftpdConf.LoginBannerFile = loginBannerFileName
|
||||||
// we need to test all supported ssh commands
|
// we need to test all supported ssh commands
|
||||||
sftpdConf.EnabledSSHCommands = []string{"*"}
|
sftpdConf.EnabledSSHCommands = []string{"*"}
|
||||||
|
@ -8245,6 +8244,32 @@ func TestOpenUnhandledChannel(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAlgorithmNotNegotiated(t *testing.T) {
|
||||||
|
u := getTestUser(false)
|
||||||
|
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
config := &ssh.ClientConfig{
|
||||||
|
Config: ssh.Config{
|
||||||
|
Ciphers: []string{ssh.InsecureCipherRC4},
|
||||||
|
},
|
||||||
|
User: user.Username,
|
||||||
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||||
|
Auth: []ssh.AuthMethod{ssh.Password(defaultPassword)},
|
||||||
|
Timeout: 5 * time.Second,
|
||||||
|
}
|
||||||
|
_, err = ssh.Dial("tcp", sftpServerAddr, config)
|
||||||
|
if assert.Error(t, err) {
|
||||||
|
negotiationErr := &ssh.AlgorithmNegotiationError{}
|
||||||
|
assert.ErrorAs(t, err, &negotiationErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = os.RemoveAll(user.GetHomeDir())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestPermsSubDirsCommands(t *testing.T) {
|
func TestPermsSubDirsCommands(t *testing.T) {
|
||||||
usePubKey := true
|
usePubKey := true
|
||||||
u := getTestUser(usePubKey)
|
u := getTestUser(usePubKey)
|
||||||
|
|
|
@ -956,17 +956,13 @@ func (c *sftpConnection) openConnNoLock() error {
|
||||||
if c.config.Password.GetPayload() != "" {
|
if c.config.Password.GetPayload() != "" {
|
||||||
clientConfig.Auth = append(clientConfig.Auth, ssh.Password(c.config.Password.GetPayload()))
|
clientConfig.Auth = append(clientConfig.Auth, ssh.Password(c.config.Password.GetPayload()))
|
||||||
}
|
}
|
||||||
// add more ciphers, KEXs and MACs, they are negotiated according to the order
|
supportedAlgos := ssh.SupportedAlgorithms()
|
||||||
clientConfig.Ciphers = []string{"aes128-gcm@openssh.com", "aes256-gcm@openssh.com", "chacha20-poly1305@openssh.com",
|
insecureAlgos := ssh.InsecureAlgorithms()
|
||||||
"aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-cbc", "aes192-cbc", "aes256-cbc"}
|
// add all available ciphers, KEXs and MACs, they are negotiated according to the order
|
||||||
clientConfig.KeyExchanges = []string{"curve25519-sha256", "curve25519-sha256@libssh.org",
|
clientConfig.Ciphers = append(supportedAlgos.Ciphers, ssh.InsecureCipherAES128CBC,
|
||||||
"ecdh-sha2-nistp256", "ecdh-sha2-nistp384", "ecdh-sha2-nistp521",
|
ssh.InsecureCipherAES192CBC, ssh.InsecureCipherAES256CBC)
|
||||||
"diffie-hellman-group14-sha256", "diffie-hellman-group-exchange-sha256",
|
clientConfig.KeyExchanges = append(supportedAlgos.KeyExchanges, insecureAlgos.KeyExchanges...)
|
||||||
"diffie-hellman-group16-sha512", "diffie-hellman-group-exchange-sha1",
|
clientConfig.MACs = append(supportedAlgos.MACs, insecureAlgos.MACs...)
|
||||||
"diffie-hellman-group14-sha1", "diffie-hellman-group1-sha1"}
|
|
||||||
clientConfig.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"}
|
|
||||||
sshClient, err := ssh.Dial("tcp", c.config.Endpoint, clientConfig)
|
sshClient, err := ssh.Dial("tcp", c.config.Endpoint, clientConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("sftpfs: unable to connect: %w", err)
|
return fmt.Errorf("sftpfs: unable to connect: %w", err)
|
||||||
|
|
Loading…
Reference in a new issue