module-transaction: Add support for setting/getting module data
Module data is data associated with a module handle that is available for the whole module loading time so it can be used also during different operations. We use cgo handles to preserve the life of the go objects so any value can be associated with a pam transaction.
This commit is contained in:
@@ -6,6 +6,7 @@ package pam
|
||||
#cgo CFLAGS: -Wall -std=c99
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <security/pam_modules.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
@@ -19,6 +20,7 @@ import (
|
||||
|
||||
type mockModuleTransactionExpectations struct {
|
||||
UserPrompt string
|
||||
DataKey string
|
||||
}
|
||||
|
||||
type mockModuleTransactionReturnedData struct {
|
||||
@@ -33,14 +35,19 @@ type mockModuleTransaction struct {
|
||||
Expectations mockModuleTransactionExpectations
|
||||
RetData mockModuleTransactionReturnedData
|
||||
ConversationHandler ConversationHandler
|
||||
moduleData map[string]uintptr
|
||||
allocatedData []unsafe.Pointer
|
||||
}
|
||||
|
||||
func newMockModuleTransaction(m *mockModuleTransaction) *mockModuleTransaction {
|
||||
m.moduleData = make(map[string]uintptr)
|
||||
runtime.SetFinalizer(m, func(m *mockModuleTransaction) {
|
||||
for _, ptr := range m.allocatedData {
|
||||
C.free(ptr)
|
||||
}
|
||||
for _, handle := range m.moduleData {
|
||||
_go_pam_data_cleanup(nil, C.uintptr_t(handle), C.PAM_DATA_SILENT)
|
||||
}
|
||||
})
|
||||
return m
|
||||
}
|
||||
@@ -76,6 +83,33 @@ func (m *mockModuleTransaction) getUser(outUser **C.char, prompt *C.char) C.int
|
||||
return C.int(m.RetData.Status)
|
||||
}
|
||||
|
||||
func (m *mockModuleTransaction) getData(key *C.char, outHandle *C.uintptr_t) C.int {
|
||||
goKey := C.GoString(key)
|
||||
if m.Expectations.DataKey != "" && goKey != m.Expectations.DataKey {
|
||||
m.T.Fatalf("data key mismatch: %#v vs %#v", goKey, m.Expectations.DataKey)
|
||||
}
|
||||
if handle, ok := m.moduleData[goKey]; ok {
|
||||
*outHandle = C.uintptr_t(handle)
|
||||
} else {
|
||||
*outHandle = 0
|
||||
}
|
||||
return C.int(m.RetData.Status)
|
||||
}
|
||||
|
||||
func (m *mockModuleTransaction) setData(key *C.char, handle C.uintptr_t) C.int {
|
||||
goKey := C.GoString(key)
|
||||
if m.Expectations.DataKey != "" && goKey != m.Expectations.DataKey {
|
||||
m.T.Fatalf("data key mismatch: %#v vs %#v", goKey, m.Expectations.DataKey)
|
||||
}
|
||||
if oldHandle, ok := m.moduleData[goKey]; ok {
|
||||
_go_pam_data_cleanup(nil, C.uintptr_t(oldHandle), C.PAM_DATA_REPLACE)
|
||||
}
|
||||
if handle != 0 {
|
||||
m.moduleData[goKey] = uintptr(handle)
|
||||
}
|
||||
return C.int(m.RetData.Status)
|
||||
}
|
||||
|
||||
type mockConversationHandler struct {
|
||||
User string
|
||||
ExpectedMessage string
|
||||
|
||||
Reference in New Issue
Block a user