transaction: Add an helper function to handle pam functions return status

All the pam functions return an integer with the status of the operation
so instead of duplicating the same code everywhere, that is quite error
prone, use an helper function.

It would have been nice to make this more dynamic, but cgo doesn't allow
us to do much magic here.

This is enough though.
This commit is contained in:
Marco Trevisan (Treviño)
2023-10-11 10:25:42 +02:00
parent a5f5ad6470
commit 3e4f7f5e4b

View File

@@ -22,6 +22,7 @@ package pam
import "C" import "C"
import ( import (
"errors"
"fmt" "fmt"
"runtime" "runtime"
"runtime/cgo" "runtime/cgo"
@@ -141,6 +142,15 @@ func transactionFinalizer(t *Transaction) {
t.c.Delete() t.c.Delete()
} }
// Allows to call pam functions managing return status
func (t *Transaction) handlePamStatus(cStatus C.int) error {
t.status = cStatus
if cStatus != success {
return t
}
return nil
}
// Start initiates a new PAM transaction. Service is treated identically to // Start initiates a new PAM transaction. Service is treated identically to
// how pam_start treats it internally. // how pam_start treats it internally.
// //
@@ -193,15 +203,16 @@ func start(service, user string, handler ConversationHandler, confDir string) (*
u = C.CString(user) u = C.CString(user)
defer C.free(unsafe.Pointer(u)) defer C.free(unsafe.Pointer(u))
} }
var err error
if confDir == "" { if confDir == "" {
t.status = C.pam_start(s, u, t.conv, &t.handle) err = t.handlePamStatus(C.pam_start(s, u, t.conv, &t.handle))
} else { } else {
c := C.CString(confDir) c := C.CString(confDir)
defer C.free(unsafe.Pointer(c)) defer C.free(unsafe.Pointer(c))
t.status = C.pam_start_confdir(s, u, t.conv, c, &t.handle) err = t.handlePamStatus(C.pam_start_confdir(s, u, t.conv, c, &t.handle))
} }
if t.status != success { if err != nil {
return nil, Error(t.status) return nil, errors.Join(Error(t.status), err)
} }
return t, nil return t, nil
} }
@@ -237,19 +248,15 @@ const (
func (t *Transaction) SetItem(i Item, item string) error { func (t *Transaction) SetItem(i Item, item string) error {
cs := unsafe.Pointer(C.CString(item)) cs := unsafe.Pointer(C.CString(item))
defer C.free(cs) defer C.free(cs)
t.status = C.pam_set_item(t.handle, C.int(i), cs) return t.handlePamStatus(C.pam_set_item(t.handle, C.int(i), cs))
if t.status != success {
return t
}
return nil
} }
// GetItem retrieves a PAM information item. // GetItem retrieves a PAM information item.
func (t *Transaction) GetItem(i Item) (string, error) { func (t *Transaction) GetItem(i Item) (string, error) {
var s unsafe.Pointer var s unsafe.Pointer
t.status = C.pam_get_item(t.handle, C.int(i), &s) err := t.handlePamStatus(C.pam_get_item(t.handle, C.int(i), &s))
if t.status != success { if err != nil {
return "", t return "", err
} }
return C.GoString((*C.char)(s)), nil return C.GoString((*C.char)(s)), nil
} }
@@ -286,11 +293,7 @@ const (
// //
// Valid flags: Silent, DisallowNullAuthtok // Valid flags: Silent, DisallowNullAuthtok
func (t *Transaction) Authenticate(f Flags) error { func (t *Transaction) Authenticate(f Flags) error {
t.status = C.pam_authenticate(t.handle, C.int(f)) return t.handlePamStatus(C.pam_authenticate(t.handle, C.int(f)))
if t.status != success {
return t
}
return nil
} }
// SetCred is used to establish, maintain and delete the credentials of a // SetCred is used to establish, maintain and delete the credentials of a
@@ -298,55 +301,35 @@ func (t *Transaction) Authenticate(f Flags) error {
// //
// Valid flags: EstablishCred, DeleteCred, ReinitializeCred, RefreshCred // Valid flags: EstablishCred, DeleteCred, ReinitializeCred, RefreshCred
func (t *Transaction) SetCred(f Flags) error { func (t *Transaction) SetCred(f Flags) error {
t.status = C.pam_setcred(t.handle, C.int(f)) return t.handlePamStatus(C.pam_setcred(t.handle, C.int(f)))
if t.status != success {
return t
}
return nil
} }
// AcctMgmt is used to determine if the user's account is valid. // AcctMgmt is used to determine if the user's account is valid.
// //
// Valid flags: Silent, DisallowNullAuthtok // Valid flags: Silent, DisallowNullAuthtok
func (t *Transaction) AcctMgmt(f Flags) error { func (t *Transaction) AcctMgmt(f Flags) error {
t.status = C.pam_acct_mgmt(t.handle, C.int(f)) return t.handlePamStatus(C.pam_acct_mgmt(t.handle, C.int(f)))
if t.status != success {
return t
}
return nil
} }
// ChangeAuthTok is used to change the authentication token. // ChangeAuthTok is used to change the authentication token.
// //
// Valid flags: Silent, ChangeExpiredAuthtok // Valid flags: Silent, ChangeExpiredAuthtok
func (t *Transaction) ChangeAuthTok(f Flags) error { func (t *Transaction) ChangeAuthTok(f Flags) error {
t.status = C.pam_chauthtok(t.handle, C.int(f)) return t.handlePamStatus(C.pam_chauthtok(t.handle, C.int(f)))
if t.status != success {
return t
}
return nil
} }
// OpenSession sets up a user session for an authenticated user. // OpenSession sets up a user session for an authenticated user.
// //
// Valid flags: Slient // Valid flags: Slient
func (t *Transaction) OpenSession(f Flags) error { func (t *Transaction) OpenSession(f Flags) error {
t.status = C.pam_open_session(t.handle, C.int(f)) return t.handlePamStatus(C.pam_open_session(t.handle, C.int(f)))
if t.status != success {
return t
}
return nil
} }
// CloseSession closes a previously opened session. // CloseSession closes a previously opened session.
// //
// Valid flags: Silent // Valid flags: Silent
func (t *Transaction) CloseSession(f Flags) error { func (t *Transaction) CloseSession(f Flags) error {
t.status = C.pam_close_session(t.handle, C.int(f)) return t.handlePamStatus(C.pam_close_session(t.handle, C.int(f)))
if t.status != success {
return t
}
return nil
} }
// PutEnv adds or changes the value of PAM environment variables. // PutEnv adds or changes the value of PAM environment variables.
@@ -357,11 +340,7 @@ func (t *Transaction) CloseSession(f Flags) error {
func (t *Transaction) PutEnv(nameval string) error { func (t *Transaction) PutEnv(nameval string) error {
cs := C.CString(nameval) cs := C.CString(nameval)
defer C.free(unsafe.Pointer(cs)) defer C.free(unsafe.Pointer(cs))
t.status = C.pam_putenv(t.handle, cs) return t.handlePamStatus(C.pam_putenv(t.handle, cs))
if t.status != success {
return t
}
return nil
} }
// GetEnv is used to retrieve a PAM environment variable. // GetEnv is used to retrieve a PAM environment variable.
@@ -384,8 +363,7 @@ func (t *Transaction) GetEnvList() (map[string]string, error) {
env := make(map[string]string) env := make(map[string]string)
p := C.pam_getenvlist(t.handle) p := C.pam_getenvlist(t.handle)
if p == nil { if p == nil {
t.status = C.int(ErrBuf) return nil, t.handlePamStatus(C.int(ErrBuf))
return nil, t
} }
for q := p; *q != nil; q = next(q) { for q := p; *q != nil; q = next(q) {
chunks := strings.SplitN(C.GoString(*q), "=", 2) chunks := strings.SplitN(C.GoString(*q), "=", 2)