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. For development, you can use `go run ./cmd/soju` as usual.
To link with the system libsqlite3, set `GOFLAGS="-tags=libsqlite3"`. To disable 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"`. 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 return NewInternal(), nil
case "oauth2": case "oauth2":
return newOAuth2(source) return newOAuth2(source)
case "pam":
return newPAM()
default: default:
return nil, fmt.Errorf("unknown auth driver %q", driver) 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 and password in the URL. The authorization server must support OAuth 2.0
Authorization Server Metadata (RFC 8414) and OAuth 2.0 Token Authorization Server Metadata (RFC 8414) and OAuth 2.0 Token
Introspection (RFC 7662). Introspection (RFC 7662).
*auth pam*
Use PAM authentication.
# IRC SERVICE # IRC SERVICE

1
go.mod
View File

@ -11,6 +11,7 @@ require (
github.com/lib/pq v1.10.7 github.com/lib/pq v1.10.7
github.com/mattn/go-sqlite3 v1.14.16 github.com/mattn/go-sqlite3 v1.14.16
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect 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/pires/go-proxyproto v0.6.2
github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_golang v1.14.0
github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa // indirect 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.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 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/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-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/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= github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=