module-transaction: Add GetUser() method that prompts an user if non-set

We can now finally test this properly both using a mock and through the
interactive module that will do the request for us in various conditions.
This commit is contained in:
Marco Trevisan (Treviño)
2023-09-29 15:13:43 +02:00
parent c1b7ee1623
commit 449b2672b9
6 changed files with 348 additions and 4 deletions

View File

@@ -1,11 +1,20 @@
// Package pam provides a wrapper for the PAM application API.
package pam
/*
#cgo CFLAGS: -Wall -std=c99
#cgo LDFLAGS: -lpam
#include <security/pam_modules.h>
#include <stdlib.h>
#include <stdint.h>
*/
import "C"
import (
"errors"
"fmt"
"unsafe"
)
// ModuleTransaction is an interface that a pam module transaction
@@ -16,6 +25,7 @@ type ModuleTransaction interface {
PutEnv(nameVal string) error
GetEnv(name string) string
GetEnvList() (map[string]string, error)
GetUser(prompt string) (string, error)
}
// ModuleHandlerFunc is a function type used by the ModuleHandler.
@@ -89,3 +99,31 @@ func (m *moduleTransaction) InvokeHandler(handler ModuleHandlerFunc,
m.lastStatus.Store(status)
return err
}
type moduleTransactionIface interface {
getUser(outUser **C.char, prompt *C.char) C.int
}
func (m *moduleTransaction) getUser(outUser **C.char, prompt *C.char) C.int {
return C.pam_get_user(m.handle, outUser, prompt)
}
// getUserImpl is the default implementation for GetUser, but kept as private so
// that can be used to test the pam package
func (m *moduleTransaction) getUserImpl(iface moduleTransactionIface,
prompt string) (string, error) {
var user *C.char
var cPrompt = C.CString(prompt)
defer C.free(unsafe.Pointer(cPrompt))
err := m.handlePamStatus(iface.getUser(&user, cPrompt))
if err != nil {
return "", err
}
return C.GoString(user), nil
}
// GetUser is similar to GetItem(User), but it would start a conversation if
// no user is currently set in PAM.
func (m *moduleTransaction) GetUser(prompt string) (string, error) {
return m.getUserImpl(m, prompt)
}