Add support for PAM authentication

This commit is contained in:
Simon Ser 2023-01-27 11:44:11 +01:00
parent ca2d666056
commit 24cae474db
7 changed files with 75 additions and 1 deletions

View File

@ -29,7 +29,8 @@ For end users, a `Makefile` is provided:
For development, you can use `go run ./cmd/soju` as usual.
To link with the system libsqlite3, set `GOFLAGS="-tags=libsqlite3"`. To disable
SQLite support, set `GOFLAGS="-tags=nosqlite"`.
SQLite support, set `GOFLAGS="-tags=nosqlite"`. To build with PAM authentication
support, set `GOFLAGS="-tags=pam"`.
To use an alternative SQLite library that does not require CGO, set `GOFLAGS="-tags=moderncsqlite"`.

View File

@ -23,6 +23,8 @@ func New(driver, source string) (Authenticator, error) {
return NewInternal(), nil
case "oauth2":
return newOAuth2(source)
case "pam":
return newPAM()
default:
return nil, fmt.Errorf("unknown auth driver %q", driver)
}

55
auth/pam.go Normal file
View File

@ -0,0 +1,55 @@
//go:build pam
package auth
import (
"context"
"fmt"
"github.com/msteinert/pam"
"git.sr.ht/~emersion/soju/database"
)
type pamAuth struct{}
var (
_ PlainAuthenticator = (*pamAuth)(nil)
)
func newPAM() (Authenticator, error) {
return pamAuth{}, nil
}
func (pamAuth) AuthPlain(ctx context.Context, db database.Database, username, password string) error {
t, err := pam.StartFunc("login", username, func(s pam.Style, msg string) (string, error) {
switch s {
case pam.PromptEchoOff:
return password, nil
case pam.PromptEchoOn, pam.ErrorMsg, pam.TextInfo:
return "", nil
default:
return "", fmt.Errorf("unsupported PAM conversation style: %v", s)
}
})
if err != nil {
return fmt.Errorf("failed to start PAM conversation: %v", err)
}
if err := t.Authenticate(0); err != nil {
return fmt.Errorf("PAM auth error: %v", err)
}
if err := t.AcctMgmt(0); err != nil {
return fmt.Errorf("PAM account unavailable: %v", err)
}
user, err := t.GetItem(pam.User)
if err != nil {
return fmt.Errorf("failed to get PAM user: %v", err)
} else if user != username {
return fmt.Errorf("PAM user doesn't match supplied username")
}
return nil
}

11
auth/pam_stub.go Normal file
View File

@ -0,0 +1,11 @@
//go:build !pam
package auth
import (
"errors"
)
func newPAM() (Authenticator, error) {
return nil, errors.New("PAM support is disabled")
}

View File

@ -201,6 +201,8 @@ The following directives are supported:
and password in the URL. The authorization server must support OAuth 2.0
Authorization Server Metadata (RFC 8414) and OAuth 2.0 Token
Introspection (RFC 7662).
*auth pam*
Use PAM authentication.
# IRC SERVICE

1
go.mod
View File

@ -11,6 +11,7 @@ require (
github.com/lib/pq v1.10.7
github.com/mattn/go-sqlite3 v1.14.16
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/msteinert/pam v1.1.0
github.com/pires/go-proxyproto v0.6.2
github.com/prometheus/client_golang v1.14.0
github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa // indirect

2
go.sum
View File

@ -212,6 +212,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/msteinert/pam v1.1.0 h1:VhLun/0n0kQYxiRBJJvVpC2jR6d21SWJFjpvUVj20Kc=
github.com/msteinert/pam v1.1.0/go.mod h1:M4FPeAW8g2ITO68W8gACDz13NDJyOQM9IQsQhrR6TOI=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=