hostauth

package
v0.9.2 Latest Latest
Warning

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

Go to latest
Published: Jun 22, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package hostauth verifies the host OS's own credentials. The application stores no passwords — every authentication goes through the OS subsystem (Open Directory on macOS, the unix_chkpwd/shadow pair on Linux, SAM on Windows) so the same password that unlocks the machine is what unlocks remote superadmin. The Linux path is deliberately cgo-free so the cross-compiled (CGO_ENABLED=0) release binary authenticates correctly — see hostauth_linux.go.

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidCredentials = errors.New("invalid credentials")

ErrInvalidCredentials is returned when the OS rejects the supplied username/password pair.

View Source
var ErrNotImplemented = errors.New("host auth not implemented on this OS")

ErrNotImplemented is reserved for any future OS that lacks a credential authenticator. All currently-supported platforms (macOS, Linux, Windows) have real implementations, so no live path returns this today.

Functions

func BareUsername added in v0.5.4

func BareUsername(s string) string

BareUsername strips platform qualifiers from an account name so the same human-typed username works against every OS:

  • "MACHINE\alice" / "DOMAIN\alice" (Windows down-level) → "alice"
  • "alice@example.com" (Windows UPN) → "alice"
  • "alice" (Unix / bare) → "alice"

Unix account names cannot contain '\' or '@' (useradd and macOS both forbid them), and Windows SAM account names forbid both characters too, so stripping at the last '\' / first '@' is unambiguous: any qualifier present is exactly one of the two Windows forms.

func CurrentDisplayName

func CurrentDisplayName() string

CurrentDisplayName returns the GECOS / "full name" of the agent's OS user (e.g. "Alice Smith"). May be empty on stripped-down systems; the portal falls back to the username in that case.

func CurrentUser

func CurrentUser() (string, error)

CurrentUser returns the agent process's own username — used as the canonical "this host's account". The matrix-agent runs as a user-level service, so this is the account the in-process shell will inherit.

func SameUser added in v0.5.4

func SameUser(submitted, canonical string) bool

SameUser reports whether a submitted username refers to the same account as the canonical one, accepting either the exact local form or the bare (unqualified) form, case-insensitively. This is the single equality rule for the "submitted user must be the agent's own OS user" gates (/auth and the SSH PasswordCallback).

On Windows, Go's user.Current().Username is the SAM-compatible "MACHINE\user" — demanding that exact string from an SSH client is hostile (quoting a backslash plus a space), so "user" alone must match too. The match only widens the *comparison*: callers still authenticate the canonical name, so the password remains the gate.

Types

type Authenticator

type Authenticator interface {
	Authenticate(username, password string) error
}

Authenticator verifies a username/password pair against the host OS. Implementations live in per-OS files (hostauth_<goos>.go).

func DefaultAuthenticator

func DefaultAuthenticator() Authenticator

DefaultAuthenticator on Linux verifies the OS password WITHOUT cgo or libpam. It shells out to the setuid unix_chkpwd PAM helper and, if that rejects a valid password, falls back to reading /etc/shadow directly and verifying the stored crypt(3) hash in pure Go.

Why not cgo PAM (the previous implementation)? Outpost release binaries are cross-compiled with CGO_ENABLED=0 (scripts/build-all.sh), so the cgo PAM authenticator never linked in practice — the host fell through to the no-cgo stub that returned ErrNotImplemented and rejected *every* password, which is why a freshly-paired Linux host could not be connected to at all. A pure-Go implementation means the standard cross-compiled binary authenticates correctly with no libpam-dev build dependency.

Why the /etc/shadow fallback? Ubuntu 26.04 ships PAM 1.7.0 with a unix_chkpwd helper that rejects otherwise-valid passwords; reading the shadow hash ourselves sidesteps it. The fallback requires the outpost process to be able to read /etc/shadow (shadow-group membership, or running as root) — when it can't, only the unix_chkpwd path is available.

type StubAuth

type StubAuth struct {
	Want map[string]string // username → expected password
}

StubAuth always returns the configured result. Tests inject this so we don't shell out to dscl during unit/integration tests.

func (StubAuth) Authenticate

func (s StubAuth) Authenticate(user, pass string) error

Jump to

Keyboard shortcuts

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