You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
3.2 KiB
111 lines
3.2 KiB
// Package user provides user management functionality for the SFTP server
|
|
package user
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"path/filepath"
|
|
)
|
|
|
|
// User represents an SFTP user with authentication and permission details
|
|
type User struct {
|
|
Username string // Username for authentication
|
|
Password string // Plaintext password
|
|
PublicKeys []string // Authorized public keys
|
|
HomeDir string // User's home directory
|
|
Permissions map[string][]string // path -> permissions (read, write, list, etc.)
|
|
Uid uint32 // User ID for file ownership
|
|
Gid uint32 // Group ID for file ownership
|
|
}
|
|
|
|
// Store defines the interface for user storage and retrieval
|
|
type Store interface {
|
|
// GetUser retrieves a user by username
|
|
GetUser(username string) (*User, error)
|
|
|
|
// ValidatePassword checks if the password is valid for the user
|
|
ValidatePassword(username string, password []byte) bool
|
|
|
|
// ValidatePublicKey checks if the public key is valid for the user
|
|
ValidatePublicKey(username string, keyData string) bool
|
|
|
|
// GetUserPermissions returns the permissions for a user on a path
|
|
GetUserPermissions(username string, path string) []string
|
|
|
|
// SaveUser saves or updates a user
|
|
SaveUser(user *User) error
|
|
|
|
// DeleteUser removes a user
|
|
DeleteUser(username string) error
|
|
|
|
// ListUsers returns all usernames
|
|
ListUsers() ([]string, error)
|
|
}
|
|
|
|
// UserNotFoundError is returned when a user is not found
|
|
type UserNotFoundError struct {
|
|
Username string
|
|
}
|
|
|
|
func (e *UserNotFoundError) Error() string {
|
|
return fmt.Sprintf("user not found: %s", e.Username)
|
|
}
|
|
|
|
// NewUser creates a new user with default settings
|
|
func NewUser(username string) *User {
|
|
// Generate a random UID/GID between 1000 and 60000
|
|
// This range is typically safe for regular users in most systems
|
|
// 0-999 are often reserved for system users
|
|
randomId := 1000 + rand.Intn(59000)
|
|
|
|
return &User{
|
|
Username: username,
|
|
Permissions: make(map[string][]string),
|
|
HomeDir: filepath.Join("/home", username),
|
|
Uid: uint32(randomId),
|
|
Gid: uint32(randomId),
|
|
}
|
|
}
|
|
|
|
// SetPassword sets a plaintext password for the user
|
|
func (u *User) SetPassword(password string) {
|
|
u.Password = password
|
|
}
|
|
|
|
// AddPublicKey adds a public key to the user
|
|
func (u *User) AddPublicKey(key string) {
|
|
// Check if key already exists
|
|
for _, existingKey := range u.PublicKeys {
|
|
if existingKey == key {
|
|
return
|
|
}
|
|
}
|
|
u.PublicKeys = append(u.PublicKeys, key)
|
|
}
|
|
|
|
// RemovePublicKey removes a public key from the user
|
|
func (u *User) RemovePublicKey(key string) bool {
|
|
for i, existingKey := range u.PublicKeys {
|
|
if existingKey == key {
|
|
// Remove the key by replacing it with the last element and truncating
|
|
u.PublicKeys[i] = u.PublicKeys[len(u.PublicKeys)-1]
|
|
u.PublicKeys = u.PublicKeys[:len(u.PublicKeys)-1]
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// SetPermission sets permissions for a specific path
|
|
func (u *User) SetPermission(path string, permissions []string) {
|
|
u.Permissions[path] = permissions
|
|
}
|
|
|
|
// RemovePermission removes permissions for a specific path
|
|
func (u *User) RemovePermission(path string) bool {
|
|
if _, exists := u.Permissions[path]; exists {
|
|
delete(u.Permissions, path)
|
|
return true
|
|
}
|
|
return false
|
|
}
|