check second factor after plugin authentication

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
Nicola Murino 2023-06-25 07:16:26 +02:00
parent 66f360e66c
commit 76964a6b85
No known key found for this signature in database
GPG key ID: 935D2952DEC4EECF
4 changed files with 533 additions and 131 deletions

View file

@ -22,7 +22,7 @@ I'd like to make SFTPGo into a sustainable long term project and would not like
If you use SFTPGo, it is in your best interest to ensure that the project you rely on stays healthy and well maintained. If you use SFTPGo, it is in your best interest to ensure that the project you rely on stays healthy and well maintained.
This can only happen with your donations and [sponsorships](https://github.com/sponsors/drakkan) :heart: This can only happen with your donations and [sponsorships](https://github.com/sponsors/drakkan) :heart:
You can also purchase support plans from the [SFTPGo website](https://sftpgo.com/#pricing). You can also purchase, using many payment methods, support plans from the [SFTPGo website](https://sftpgo.com/#pricing).
With sponsorships/donations or support plans we establish a channel for reciprocal access, ensuring better outcomes for both you and the project. With sponsorships/donations or support plans we establish a channel for reciprocal access, ensuring better outcomes for both you and the project.

20
go.mod
View file

@ -25,7 +25,7 @@ require (
github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001 github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001
github.com/fclairamb/ftpserverlib v0.21.0 github.com/fclairamb/ftpserverlib v0.21.0
github.com/fclairamb/go-log v0.4.1 github.com/fclairamb/go-log v0.4.1
github.com/go-acme/lego/v4 v4.12.1 github.com/go-acme/lego/v4 v4.12.3
github.com/go-chi/chi/v5 v5.0.9-0.20230502103705-7f280968675b github.com/go-chi/chi/v5 v5.0.9-0.20230502103705-7f280968675b
github.com/go-chi/jwtauth/v5 v5.1.0 github.com/go-chi/jwtauth/v5 v5.1.0
github.com/go-chi/render v1.0.2 github.com/go-chi/render v1.0.2
@ -36,7 +36,7 @@ require (
github.com/hashicorp/go-hclog v1.5.0 github.com/hashicorp/go-hclog v1.5.0
github.com/hashicorp/go-plugin v1.4.10 github.com/hashicorp/go-plugin v1.4.10
github.com/hashicorp/go-retryablehttp v0.7.4 github.com/hashicorp/go-retryablehttp v0.7.4
github.com/jackc/pgx/v5 v5.4.0 github.com/jackc/pgx/v5 v5.4.1
github.com/jlaffaye/ftp v0.0.0-20201112195030-9aae4d151126 github.com/jlaffaye/ftp v0.0.0-20201112195030-9aae4d151126
github.com/klauspost/compress v1.16.6 github.com/klauspost/compress v1.16.6
github.com/lestrrat-go/jwx/v2 v2.0.11 github.com/lestrrat-go/jwx/v2 v2.0.11
@ -44,7 +44,7 @@ require (
github.com/mattn/go-sqlite3 v1.14.17 github.com/mattn/go-sqlite3 v1.14.17
github.com/mhale/smtpd v0.8.0 github.com/mhale/smtpd v0.8.0
github.com/minio/sio v0.3.1 github.com/minio/sio v0.3.1
github.com/otiai10/copy v1.11.0 github.com/otiai10/copy v1.12.0
github.com/pires/go-proxyproto v0.7.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-0.20230213180117-971c283182b6
github.com/pquerna/otp v1.4.0 github.com/pquerna/otp v1.4.0
@ -59,7 +59,7 @@ require (
github.com/spf13/cobra v1.7.0 github.com/spf13/cobra v1.7.0
github.com/spf13/viper v1.16.0 github.com/spf13/viper v1.16.0
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/studio-b12/gowebdav v0.0.0-20230203202212-3282f94193f2 github.com/studio-b12/gowebdav v0.9.0
github.com/subosito/gotenv v1.4.2 github.com/subosito/gotenv v1.4.2
github.com/unrolled/secure v1.13.0 github.com/unrolled/secure v1.13.0
github.com/wagslane/go-password-validator v0.3.0 github.com/wagslane/go-password-validator v0.3.0
@ -67,7 +67,7 @@ require (
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.7 go.etcd.io/bbolt v1.3.7
go.uber.org/automaxprocs v1.5.2 go.uber.org/automaxprocs v1.5.2
gocloud.dev v0.29.0 gocloud.dev v0.30.0
golang.org/x/crypto v0.10.0 golang.org/x/crypto v0.10.0
golang.org/x/net v0.11.0 golang.org/x/net v0.11.0
golang.org/x/oauth2 v0.9.0 golang.org/x/oauth2 v0.9.0
@ -79,10 +79,10 @@ require (
) )
require ( require (
cloud.google.com/go v0.110.2 // indirect cloud.google.com/go v0.110.3 // indirect
cloud.google.com/go/compute v1.20.0 // indirect cloud.google.com/go/compute v1.20.1 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/iam v1.1.0 // indirect cloud.google.com/go/iam v1.1.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // 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.4.10 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
@ -135,7 +135,7 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-isatty v0.0.19 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/miekg/dns v1.1.54 // indirect github.com/miekg/dns v1.1.55 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect
@ -164,7 +164,7 @@ require (
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/grpc v1.56.0 // indirect google.golang.org/grpc v1.56.1 // indirect
google.golang.org/protobuf v1.30.0 // indirect google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect

629
go.sum

File diff suppressed because it is too large Load diff

View file

@ -3490,7 +3490,7 @@ func doBuiltinKeyboardInteractiveAuth(user *User, client ssh.KeyboardInteractive
return 0, err return 0, err
} }
if len(answers) != 1 { if len(answers) != 1 {
return 0, fmt.Errorf("unexpected number of answers: %v", len(answers)) return 0, fmt.Errorf("unexpected number of answers: %d", len(answers))
} }
err = user.LoadAndApplyGroupSettings() err = user.LoadAndApplyGroupSettings()
if err != nil { if err != nil {
@ -3500,16 +3500,20 @@ func doBuiltinKeyboardInteractiveAuth(user *User, client ssh.KeyboardInteractive
if err != nil { if err != nil {
return 0, err return 0, err
} }
return checkKeyboardInteractiveSecondFactor(user, client, protocol)
}
func checkKeyboardInteractiveSecondFactor(user *User, client ssh.KeyboardInteractiveChallenge, protocol string) (int, error) {
if !user.Filters.TOTPConfig.Enabled || !util.Contains(user.Filters.TOTPConfig.Protocols, protocolSSH) { if !user.Filters.TOTPConfig.Enabled || !util.Contains(user.Filters.TOTPConfig.Protocols, protocolSSH) {
return 1, nil return 1, nil
} }
err = user.Filters.TOTPConfig.Secret.TryDecrypt() err := user.Filters.TOTPConfig.Secret.TryDecrypt()
if err != nil { if err != nil {
providerLog(logger.LevelError, "unable to decrypt TOTP secret for user %q, protocol %v, err: %v", providerLog(logger.LevelError, "unable to decrypt TOTP secret for user %q, protocol %v, err: %v",
user.Username, protocol, err) user.Username, protocol, err)
return 0, err return 0, err
} }
answers, err = client("", "", []string{"Authentication code: "}, []bool{false}) answers, err := client("", "", []string{"Authentication code: "}, []bool{false})
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -3742,6 +3746,9 @@ func doKeyboardInteractiveAuth(user *User, authHook string, client ssh.KeyboardI
var err error var err error
if plugin.Handler.HasAuthScope(plugin.AuthScopeKeyboardInteractive) { if plugin.Handler.HasAuthScope(plugin.AuthScopeKeyboardInteractive) {
authResult, err = executeKeyboardInteractivePlugin(user, client, ip, protocol) authResult, err = executeKeyboardInteractivePlugin(user, client, ip, protocol)
if authResult == 1 && err == nil {
authResult, err = checkKeyboardInteractiveSecondFactor(user, client, protocol)
}
} else if authHook != "" { } else if authHook != "" {
if strings.HasPrefix(authHook, "http") { if strings.HasPrefix(authHook, "http") {
authResult, err = executeKeyboardInteractiveHTTPHook(user, authHook, client, ip, protocol) authResult, err = executeKeyboardInteractiveHTTPHook(user, authHook, client, ip, protocol)