aboutsummaryrefslogtreecommitdiff
path: root/weed/sftpd/auth/publickey.go
blob: 83c5092a1705c0ee033d74988417a40d8d4a814d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package auth

import (
	"crypto/subtle"
	"fmt"

	"github.com/seaweedfs/seaweedfs/weed/sftpd/user"
	"golang.org/x/crypto/ssh"
)

// PublicKeyAuthenticator handles public key-based authentication
type PublicKeyAuthenticator struct {
	userStore user.Store
	enabled   bool
}

// NewPublicKeyAuthenticator creates a new public key authenticator
func NewPublicKeyAuthenticator(userStore user.Store, enabled bool) *PublicKeyAuthenticator {
	return &PublicKeyAuthenticator{
		userStore: userStore,
		enabled:   enabled,
	}
}

// Enabled returns whether public key authentication is enabled
func (a *PublicKeyAuthenticator) Enabled() bool {
	return a.enabled
}

// Authenticate validates a public key for a user
func (a *PublicKeyAuthenticator) Authenticate(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
	username := conn.User()

	// Check if public key auth is enabled
	if !a.enabled {
		return nil, fmt.Errorf("public key authentication disabled")
	}

	// Convert key to string format for comparison
	keyData := string(key.Marshal())

	// Validate public key
	if ValidatePublicKey(a.userStore, username, keyData) {
		return &ssh.Permissions{
			Extensions: map[string]string{
				"username": username,
			},
		}, nil
	}

	return nil, fmt.Errorf("authentication failed")
}

// ValidatePublicKey checks if the provided public key is valid for the user
func ValidatePublicKey(store user.Store, username string, keyData string) bool {
	user, err := store.GetUser(username)
	if err != nil {
		return false
	}

	for _, key := range user.PublicKeys {
		if subtle.ConstantTimeCompare([]byte(key), []byte(keyData)) == 1 {
			return true
		}
	}

	return false
}