summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Trevisan (Treviño) <[email protected]>2023-10-11 23:09:04 +0200
committerMarco Trevisan (Treviño) <[email protected]>2023-11-30 02:49:29 +0100
commitc7ecbf20dcee2221ba50c5b07144f3684121e886 (patch)
tree0978f53813cd42b437b25ea1b70fb90cb8f70ada
parentc635cfc38a6067d5902215db16c417801e2fe993 (diff)
transaction: Add a test finalizer checking if transaction has ended
Check if a transaction is ended in in tests.
-rw-r--r--transaction.go3
-rw-r--r--transaction_test.go50
2 files changed, 52 insertions, 1 deletions
diff --git a/transaction.go b/transaction.go
index 52ad1be..148e786 100644
--- a/transaction.go
+++ b/transaction.go
@@ -173,7 +173,7 @@ func Start(service, user string, handler ConversationHandler) (*Transaction, err
// StartFunc registers the handler func as a conversation handler and starts
// the transaction (see Start() documentation).
func StartFunc(service, user string, handler func(Style, string) (string, error)) (*Transaction, error) {
- return Start(service, user, ConversationFunc(handler))
+ return start(service, user, ConversationFunc(handler), "")
}
// StartConfDir initiates a new PAM transaction. Service is treated identically to
@@ -212,6 +212,7 @@ func start(service, user string, handler ConversationHandler, confDir string) (*
conv: &C.struct_pam_conv{},
c: cgo.NewHandle(handler),
}
+
C.init_pam_conv(t.conv, C.uintptr_t(t.c))
s := C.CString(service)
defer C.free(unsafe.Pointer(s))
diff --git a/transaction_test.go b/transaction_test.go
index 2f620a2..e5da07b 100644
--- a/transaction_test.go
+++ b/transaction_test.go
@@ -6,7 +6,11 @@ import (
"os"
"os/user"
"path/filepath"
+ "runtime"
+ "sync/atomic"
"testing"
+ "time"
+ "unsafe"
)
func maybeEndTransaction(t *testing.T, tx *Transaction) {
@@ -21,6 +25,19 @@ func maybeEndTransaction(t *testing.T, tx *Transaction) {
}
}
+func ensureTransactionEnds(t *testing.T, tx *Transaction) {
+ t.Helper()
+
+ runtime.SetFinalizer(tx, func(tx *Transaction) {
+ // #nosec:G103 - the pointer conversion is checked.
+ handle := atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&tx.handle)))
+ if handle == nil {
+ return
+ }
+ t.Fatalf("transaction has not been finalized")
+ })
+}
+
func TestPAM_001(t *testing.T) {
u, _ := user.Current()
if u.Uid != "0" {
@@ -30,6 +47,7 @@ func TestPAM_001(t *testing.T) {
tx, err := StartFunc("", "test", func(s Style, msg string) (string, error) {
return p, nil
})
+ ensureTransactionEnds(t, tx)
defer maybeEndTransaction(t, tx)
if err != nil {
t.Fatalf("start #error: %v", err)
@@ -62,6 +80,7 @@ func TestPAM_002(t *testing.T) {
}
return "", errors.New("unexpected")
})
+ ensureTransactionEnds(t, tx)
defer maybeEndTransaction(t, tx)
if err != nil {
t.Fatalf("start #error: %v", err)
@@ -97,6 +116,7 @@ func TestPAM_003(t *testing.T) {
Password: "secret",
}
tx, err := Start("", "", c)
+ ensureTransactionEnds(t, tx)
defer maybeEndTransaction(t, tx)
if err != nil {
t.Fatalf("start #error: %v", err)
@@ -116,6 +136,7 @@ func TestPAM_004(t *testing.T) {
Password: "secret",
}
tx, err := Start("", "test", c)
+ ensureTransactionEnds(t, tx)
defer maybeEndTransaction(t, tx)
if err != nil {
t.Fatalf("start #error: %v", err)
@@ -134,6 +155,7 @@ func TestPAM_005(t *testing.T) {
tx, err := StartFunc("passwd", "test", func(s Style, msg string) (string, error) {
return "secret", nil
})
+ ensureTransactionEnds(t, tx)
defer maybeEndTransaction(t, tx)
if err != nil {
t.Fatalf("start #error: %v", err)
@@ -152,6 +174,7 @@ func TestPAM_006(t *testing.T) {
tx, err := StartFunc("passwd", u.Username, func(s Style, msg string) (string, error) {
return "secret", nil
})
+ ensureTransactionEnds(t, tx)
defer maybeEndTransaction(t, tx)
if err != nil {
t.Fatalf("start #error: %v", err)
@@ -174,6 +197,7 @@ func TestPAM_007(t *testing.T) {
tx, err := StartFunc("", "test", func(s Style, msg string) (string, error) {
return "", errors.New("Sorry, it didn't work")
})
+ ensureTransactionEnds(t, tx)
defer maybeEndTransaction(t, tx)
if err != nil {
t.Fatalf("start #error: %v", err)
@@ -256,6 +280,7 @@ func TestPAM_ConfDir_InfoMessage(t *testing.T) {
}
return "", errors.New("unexpected")
}), "test-services")
+ ensureTransactionEnds(t, tx)
defer maybeEndTransaction(t, tx)
if err != nil {
t.Fatalf("start #error: %v", err)
@@ -272,6 +297,7 @@ func TestPAM_ConfDir_InfoMessage(t *testing.T) {
func TestPAM_ConfDir_Deny(t *testing.T) {
u, _ := user.Current()
tx, err := StartConfDir("deny-service", u.Username, Credentials{}, "test-services")
+ ensureTransactionEnds(t, tx)
defer maybeEndTransaction(t, tx)
if err != nil {
t.Fatalf("start #error: %v", err)
@@ -296,6 +322,7 @@ func TestPAM_ConfDir_PromptForUserName(t *testing.T) {
Password: "wrongsecret",
}
tx, err := StartConfDir("succeed-if-user-test", "", c, "test-services")
+ ensureTransactionEnds(t, tx)
defer maybeEndTransaction(t, tx)
if !CheckPamHasStartConfdir() {
if err == nil {
@@ -319,6 +346,7 @@ func TestPAM_ConfDir_WrongUserName(t *testing.T) {
Password: "wrongsecret",
}
tx, err := StartConfDir("succeed-if-user-test", "", c, "test-services")
+ ensureTransactionEnds(t, tx)
defer maybeEndTransaction(t, tx)
if !CheckPamHasStartConfdir() {
if err == nil {
@@ -344,6 +372,7 @@ func TestItem(t *testing.T) {
tx, err := StartFunc("passwd", "test", func(s Style, msg string) (string, error) {
return "", nil
})
+ ensureTransactionEnds(t, tx)
defer maybeEndTransaction(t, tx)
if err != nil {
t.Fatalf("start #error: %v", err)
@@ -382,6 +411,7 @@ func TestEnv(t *testing.T) {
tx, err := StartFunc("", "", func(s Style, msg string) (string, error) {
return "", nil
})
+ ensureTransactionEnds(t, tx)
defer maybeEndTransaction(t, tx)
if err != nil {
t.Fatalf("start #error: %v", err)
@@ -525,6 +555,7 @@ func Test_Error(t *testing.T) {
}
tx, err := StartConfDir(serviceName, "user", c, servicePath)
+ ensureTransactionEnds(t, tx)
defer maybeEndTransaction(t, tx)
if err != nil {
t.Fatalf("start #error: %v", err)
@@ -558,6 +589,25 @@ func Test_Error(t *testing.T) {
}
}
+func Test_Finalizer(t *testing.T) {
+ if !CheckPamHasStartConfdir() {
+ t.Skip("this requires PAM with Conf dir support")
+ }
+
+ func() {
+ tx, err := StartConfDir("permit-service", "", nil, "test-services")
+ ensureTransactionEnds(t, tx)
+ defer maybeEndTransaction(t, tx)
+ if err != nil {
+ t.Fatalf("start #error: %v", err)
+ }
+ }()
+
+ runtime.GC()
+ // sleep to switch to finalizer goroutine
+ time.Sleep(5 * time.Millisecond)
+}
+
func TestFailure_001(t *testing.T) {
tx := Transaction{}
_, err := tx.GetEnvList()