server

package
v1.5.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 22, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package server implements the Doomsday SFTP server mode.

The server uses golang.org/x/crypto/ssh for SSH transport and github.com/pkg/sftp RequestServer for SFTP protocol handling. Each authenticated client is jailed to its own data directory with quota enforcement and an append-only whitelist of allowed operations.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrClientExists is returned when adding a client that already exists.
	ErrClientExists = errors.New("server: client already exists")

	// ErrClientNotFound is returned when operating on a client that does not exist.
	ErrClientNotFound = errors.New("server: client not found")
)

Functions

func Start

func Start(ctx context.Context, config Config) error

Start creates and runs the SFTP server. It blocks until ctx is cancelled or an unrecoverable error occurs. On context cancellation it stops accepting new connections and waits for existing connections to drain.

Types

type ClientConfig

type ClientConfig struct {
	// Name is the unique client identifier. Also used as the subdirectory name.
	Name string

	// PublicKey is the parsed SSH public key for authentication.
	PublicKey ssh.PublicKey

	// QuotaBytes is the maximum number of bytes this client may store (0 = unlimited).
	QuotaBytes int64

	// AppendOnly restricts the client to append-only operations (no overwrite/truncate/delete).
	AppendOnly bool
}

ClientConfig describes an authorized client.

type ClientManager

type ClientManager struct {
	// contains filtered or unexported fields
}

ClientManager handles client lookup at runtime. Clients are loaded from server.yaml at startup; this is an in-memory index.

func NewClientManager

func NewClientManager(dataDir string, clients []ClientConfig) (*ClientManager, error)

NewClientManager creates a ClientManager from the given client configs. It creates jail directories for each client under dataDir.

func (*ClientManager) FindByKey

func (cm *ClientManager) FindByKey(key ssh.PublicKey) (ClientConfig, bool)

FindByKey looks up a client by their SSH public key.

func (*ClientManager) Get

func (cm *ClientManager) Get(name string) (ClientConfig, bool)

Get returns a copy of the ClientConfig for the named client.

func (*ClientManager) List

func (cm *ClientManager) List() []ClientConfig

List returns all registered clients.

func (*ClientManager) Replace

func (cm *ClientManager) Replace(clients []ClientConfig) error

Replace atomically swaps the client set. New jail directories are created; removed clients keep their data on disk but are no longer authorized.

type Config

type Config struct {
	// ListenAddr is the address to listen on (default ":8420").
	ListenAddr string

	// HostKeyPEM is the SSH host private key in PEM format.
	HostKeyPEM []byte

	// DataDir is the root data directory. Each client gets a subdirectory.
	DataDir string

	// Clients is the set of authorized clients (from server.yaml).
	Clients []ClientConfig

	// Listener is an optional pre-created listener (e.g. from tsnet).
	// When set, ListenAddr is ignored and this listener is used directly.
	Listener net.Listener

	// ReloadClients, if non-nil, is called periodically to get an updated client
	// list. The server hot-swaps the client set without restarting. The function
	// should return (nil, nil) if the config hasn't changed.
	ReloadClients func() ([]ClientConfig, error)
}

Config holds the server configuration.

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler implements the pkg/sftp request handler interfaces with a strict whitelist approach:

  • FileReader (Fileread) -- allowed: read files
  • FileWriter (Filewrite) -- allowed: create new files only (no overwrite/truncate)
  • FileLister (Filelist) -- allowed: list directories, stat files
  • FileCmder (Filecmd) -- allowed: Mkdir, Remove (files only), Rename (no overwrite)

All paths are jailed to the client's data directory. Symlinks are resolved and verified to remain within the jail.

func NewHandler

func NewHandler(jailDir string, quotaBytes int64, appendOnly bool, logger *log.Logger) *Handler

NewHandler creates a new jailed SFTP handler. jailDir should be an absolute path. It will be resolved through EvalSymlinks to ensure consistent path comparisons (e.g. on macOS /var -> /private/var). quotaBytes of 0 means unlimited. When appendOnly is true, clients cannot overwrite, truncate, or delete existing files.

func (*Handler) Filecmd

func (h *Handler) Filecmd(r *sftp.Request) error

Filecmd handles file commands. Allowed: Mkdir, Rename (no overwrite), Remove (files only). Rejected: Rmdir, Setstat, Link, Symlink. Implements sftp.FileCmder.

func (*Handler) Filelist

func (h *Handler) Filelist(r *sftp.Request) (sftp.ListerAt, error)

Filelist returns a ListerAt for directory listing and stat operations. Implements sftp.FileLister.

func (*Handler) Fileread

func (h *Handler) Fileread(r *sftp.Request) (io.ReaderAt, error)

Fileread opens a file for reading. Implements sftp.FileReader.

func (*Handler) Filewrite

func (h *Handler) Filewrite(r *sftp.Request) (io.WriterAt, error)

Filewrite opens a file for writing. Only new file creation is allowed. Overwriting or truncating existing files is rejected. Implements sftp.FileWriter.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is the Doomsday SFTP server.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL