pam

package
v0.60.0 Latest Latest
Warning

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

Go to latest
Published: Nov 12, 2026 License: MIT Imports: 26 Imported by: 0

Documentation

Overview

Package pam is the Linux operating-system sign-in provider: a person signs in to filex with the login they use on the machine filex runs on, and PAM — the same door SSH and su use — judges the password.

How it asks PAM (and why not another way)

filex is not root and has no cgo. It runs a command the administrator has set up: by default

sudo -n /usr/bin/pamtester filex <user> authenticate acct_mgmt

with the password on STANDARD INPUT. `authenticate` checks the password; `acct_mgmt` checks the account (expired, locked, not permitted to log in). pamtester was chosen over a checkpassword-style helper because sudo closes every file descriptor above 2 — a password handed over on fd 3 never arrives.

⚠⚠ The argv is BUILT here, never composed from a template string and never through a shell: the user name is one argv element, checked to be a plain login name that does not start with a dash; the command path and the PAM service name are configuration, checked to be plain too. There is no place an administrator's or a visitor's text can become a shell command. The password is written to the pipe and nowhere else — not argv (visible in `ps`), not the environment, not a log line.

Three answers, kept apart

  • yes — PAM accepted the password and the account;
  • no — PAM refused (wrong password, unknown user, locked or expired account): auth.ErrUnauthorized;
  • could not decide — pamtester is missing, sudo wants a password, PAM itself is failing, the command timed out: an error that is NOT ErrUnauthorized (auth.ErrUndecided), so the operator's log shows it and a misconfigured server never looks like a wrong password.

Setup is checked before the provider may be switched on (probe.go) and again every time filex starts.

Index

Constants

View Source
const (
	DefaultPamtester     = "/usr/bin/pamtester"
	DefaultService       = "filex"
	DefaultSudo          = "/usr/bin/sudo"
	DefaultTimeout       = 10 * time.Second
	DefaultMaxConcurrent = 4
)

Defaults.

View Source
const AuditOSAdminGranted = "auth.os_admin_granted"

AuditOSAdminGranted is the audit action of the test account becoming a super administrator.

View Source
const AuditProviderUnavailable = "auth.provider_unavailable"

AuditProviderUnavailable is the audit action written when the provider's setup is found broken at start-up and it is left out of the running set.

View Source
const Name = "pam"

Name is the provider's name.

Variables

This section is empty.

Functions

func SwapForTest

func SwapForTest(run func(argv []string, stdin string) (exit int, stdout, stderr string, err error), dir string) (restore func())

SwapForTest replaces the process runner (every command the provider would run) and the directory PAM service files are looked up in, and returns the function that puts both back. It exists so tests of the layers above — the identity-providers handler, the provider set — can drive this provider without a real PAM, sudo or pamtester. Never call it outside a test.

Types

type Driver

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

Driver is the PAM sign-in provider.

func New

func New(store db.Store) *Driver

New constructs an empty driver — Init must be called.

func (*Driver) Authenticate

func (d *Driver) Authenticate(_ *http.Request) (*model.User, error)

Authenticate is a no-op, as the LDAP driver's: the session cookie is resolved by the local driver.

func (*Driver) Capabilities

func (d *Driver) Capabilities() auth.Capabilities

Capabilities implements auth.Driver.

func (*Driver) GrantTestAccount

func (d *Driver) GrantTestAccount(ctx context.Context, store any, cfg map[string]any, username string) error

GrantTestAccount implements auth.TestAccountGranter: the account the setup test signed in with becomes a super administrator of this filex — created when it has no account, raised when it has one. It is the ONE place this provider makes an administrator, and it does so only for the account whose password just passed a real PAM sign-in in the same request.

func (*Driver) Init

func (d *Driver) Init(ctx context.Context, cfg map[string]any) error

Init configures the driver AND re-checks the machine's setup (steps 1-4 of the provider test). A setup that has broken since it was switched on — the package was removed, sudoers was edited — keeps THIS provider out of the running set, with the reason in the error, the log and an audit row; every other sign-in path is unaffected.

func (*Driver) Login

func (d *Driver) Login(ctx context.Context, identifier, password string) (*model.User, string, error)

Login verifies the credentials and mints a browser session.

func (*Driver) Logout

func (d *Driver) Logout(ctx context.Context, token string) error

Logout revokes a session minted by Login.

func (*Driver) Name

func (d *Driver) Name() string

Name implements auth.Driver.

func (*Driver) Probe

func (d *Driver) Probe(ctx context.Context, cfg map[string]any, _ *http.Request) []auth.ProbeCheck

Probe tests a configuration the way a sign-in would use it, stopping at the first step that fails. Every failing step carries a `reason` and a `hint`: the sentence, in the administrator's language, that names the fix — with the command to run.

config        the settings are well-formed
first_login…  what happens to a person with no account (auth.FirstLoginCheck)
pamtester     the tool is installed and runnable
pam_service   /etc/pam.d/<service> exists
sudo          sudo may run that one command without a password (no
              requiretty); skipped when use_sudo is off
unknown_user  a login that does not exist is a clean "no" — not an error,
              and not a "yes"
test_account  the account the administrator named signs in for real

⚠ This is the gate the provider cannot be switched on without (StrictProbe): no `confirm_failed_test`. The last step needs `test_account` on the request (auth.TestAccountFrom) — its password is used for this one call and goes nowhere else.

func (*Driver) StrictProbe

func (d *Driver) StrictProbe() bool

StrictProbe implements auth.StrictProber: this provider cannot be switched on past a failing test.

func (*Driver) VerifyPassword

func (d *Driver) VerifyPassword(ctx context.Context, identifier, password string) (*model.User, error)

VerifyPassword is the sign-in — name checks, PAM, groups, then the account — and the protocol path (WebDAV, SFTP, FTPS, S3): the password is judged, no session is minted. The resolver hands over either the typed login name or the account's e-mail.

Jump to

Keyboard shortcuts

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