2015-12-04 10:05:44 -06:00
|
|
|
// Package pam provides a wrapper for the PAM application API.
|
2015-03-27 18:59:29 -05:00
|
|
|
package pam
|
|
|
|
|
|
2023-09-19 20:51:45 +02:00
|
|
|
//#cgo CFLAGS: -Wall -std=c99
|
|
|
|
|
//#cgo LDFLAGS: -lpam
|
|
|
|
|
//
|
2015-03-27 18:59:29 -05:00
|
|
|
//#include <security/pam_appl.h>
|
|
|
|
|
//#include <stdlib.h>
|
2023-09-19 20:04:06 +02:00
|
|
|
//#include <stdint.h>
|
2023-09-19 20:51:45 +02:00
|
|
|
//
|
|
|
|
|
//#ifdef PAM_BINARY_PROMPT
|
|
|
|
|
//#define BINARY_PROMPT_IS_SUPPORTED 1
|
|
|
|
|
//#else
|
|
|
|
|
//#include <limits.h>
|
|
|
|
|
//#define PAM_BINARY_PROMPT INT_MAX
|
|
|
|
|
//#define BINARY_PROMPT_IS_SUPPORTED 0
|
|
|
|
|
//#endif
|
|
|
|
|
//
|
2023-09-19 20:04:06 +02:00
|
|
|
//void init_pam_conv(struct pam_conv *conv, uintptr_t);
|
2022-09-16 08:09:26 +02:00
|
|
|
//int pam_start_confdir(const char *service_name, const char *user, const struct pam_conv *pam_conversation, const char *confdir, pam_handle_t **pamh) __attribute__ ((weak));
|
|
|
|
|
//int check_pam_start_confdir(void);
|
2015-03-27 18:59:29 -05:00
|
|
|
import "C"
|
|
|
|
|
|
|
|
|
|
import (
|
2023-09-25 13:44:45 +02:00
|
|
|
"fmt"
|
2023-09-19 20:04:06 +02:00
|
|
|
"runtime/cgo"
|
2015-03-27 18:59:29 -05:00
|
|
|
"strings"
|
2023-09-29 23:01:50 +02:00
|
|
|
"sync/atomic"
|
2015-03-27 18:59:29 -05:00
|
|
|
"unsafe"
|
|
|
|
|
)
|
|
|
|
|
|
2023-09-22 16:59:03 +02:00
|
|
|
// success indicates a successful function return.
|
|
|
|
|
const success = C.PAM_SUCCESS
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// Style is the type of message that the conversation handler should display.
|
2015-03-27 18:59:29 -05:00
|
|
|
type Style int
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// Coversation handler style types.
|
2015-03-27 18:59:29 -05:00
|
|
|
const (
|
2015-04-10 15:04:52 -05:00
|
|
|
// PromptEchoOff indicates the conversation handler should obtain a
|
|
|
|
|
// string without echoing any text.
|
2015-03-27 18:59:29 -05:00
|
|
|
PromptEchoOff Style = C.PAM_PROMPT_ECHO_OFF
|
2015-04-10 15:04:52 -05:00
|
|
|
// PromptEchoOn indicates the conversation handler should obtain a
|
|
|
|
|
// string while echoing text.
|
2023-10-10 11:45:12 +02:00
|
|
|
PromptEchoOn Style = C.PAM_PROMPT_ECHO_ON
|
2015-04-10 15:04:52 -05:00
|
|
|
// ErrorMsg indicates the conversation handler should display an
|
|
|
|
|
// error message.
|
2023-10-10 11:45:12 +02:00
|
|
|
ErrorMsg Style = C.PAM_ERROR_MSG
|
2015-04-10 15:04:52 -05:00
|
|
|
// TextInfo indicates the conversation handler should display some
|
|
|
|
|
// text.
|
2023-10-10 11:45:12 +02:00
|
|
|
TextInfo Style = C.PAM_TEXT_INFO
|
2023-09-19 20:51:45 +02:00
|
|
|
// BinaryPrompt indicates the conversation handler that should implement
|
|
|
|
|
// the private binary protocol
|
2023-10-10 11:45:12 +02:00
|
|
|
BinaryPrompt Style = C.PAM_BINARY_PROMPT
|
2015-03-27 18:59:29 -05:00
|
|
|
)
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// ConversationHandler is an interface for objects that can be used as
|
|
|
|
|
// conversation callbacks during PAM authentication.
|
2015-03-27 18:59:29 -05:00
|
|
|
type ConversationHandler interface {
|
2015-04-10 15:04:52 -05:00
|
|
|
// RespondPAM receives a message style and a message string. If the
|
|
|
|
|
// message Style is PromptEchoOff or PromptEchoOn then the function
|
|
|
|
|
// should return a response string.
|
2015-03-27 18:59:29 -05:00
|
|
|
RespondPAM(Style, string) (string, error)
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-19 20:51:45 +02:00
|
|
|
// BinaryPointer exposes the type used for the data in a binary conversation
|
|
|
|
|
// it represents a pointer to data that is produced by the module and that
|
|
|
|
|
// must be parsed depending on the protocol in use
|
|
|
|
|
type BinaryPointer unsafe.Pointer
|
|
|
|
|
|
|
|
|
|
// BinaryConversationHandler is an interface for objects that can be used as
|
|
|
|
|
// conversation callbacks during PAM authentication if binary protocol is going
|
|
|
|
|
// to be supported.
|
|
|
|
|
type BinaryConversationHandler interface {
|
|
|
|
|
ConversationHandler
|
|
|
|
|
// RespondPAMBinary receives a pointer to the binary message. It's up to
|
|
|
|
|
// the receiver to parse it according to the protocol specifications.
|
|
|
|
|
// The function can return a byte array that will passed as pointer back
|
|
|
|
|
// to the module.
|
|
|
|
|
RespondPAMBinary(BinaryPointer) ([]byte, error)
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-30 14:53:16 -05:00
|
|
|
// ConversationFunc is an adapter to allow the use of ordinary functions as
|
|
|
|
|
// conversation callbacks.
|
2015-03-27 18:59:29 -05:00
|
|
|
type ConversationFunc func(Style, string) (string, error)
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// RespondPAM is a conversation callback adapter.
|
2015-03-27 18:59:29 -05:00
|
|
|
func (f ConversationFunc) RespondPAM(s Style, msg string) (string, error) {
|
|
|
|
|
return f(s, msg)
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-04 09:21:38 -06:00
|
|
|
// cbPAMConv is a wrapper for the conversation callback function.
|
2023-09-19 20:51:45 +02:00
|
|
|
//
|
2015-03-27 18:59:29 -05:00
|
|
|
//export cbPAMConv
|
2023-09-19 20:04:06 +02:00
|
|
|
func cbPAMConv(s C.int, msg *C.char, c C.uintptr_t) (*C.char, C.int) {
|
2015-12-03 14:59:51 -06:00
|
|
|
var r string
|
2015-12-04 09:46:42 -06:00
|
|
|
var err error
|
2023-09-19 20:04:06 +02:00
|
|
|
v := cgo.Handle(c).Value()
|
2023-09-19 20:51:45 +02:00
|
|
|
style := Style(s)
|
2023-11-07 11:51:27 +02:00
|
|
|
var handler ConversationHandler
|
2015-12-03 14:59:51 -06:00
|
|
|
switch cb := v.(type) {
|
2023-09-19 20:51:45 +02:00
|
|
|
case BinaryConversationHandler:
|
|
|
|
|
if style == BinaryPrompt {
|
|
|
|
|
bytes, err := cb.RespondPAMBinary(BinaryPointer(msg))
|
|
|
|
|
if err != nil {
|
2023-09-22 16:59:03 +02:00
|
|
|
return nil, C.int(ErrConv)
|
2023-09-19 20:51:45 +02:00
|
|
|
}
|
2023-09-22 16:59:03 +02:00
|
|
|
return (*C.char)(C.CBytes(bytes)), success
|
2023-09-19 20:51:45 +02:00
|
|
|
}
|
2023-11-07 11:51:27 +02:00
|
|
|
handler = cb
|
2015-12-03 14:59:51 -06:00
|
|
|
case ConversationHandler:
|
2023-09-19 20:51:45 +02:00
|
|
|
if style == BinaryPrompt {
|
2023-09-22 16:59:03 +02:00
|
|
|
return nil, C.int(ErrConv)
|
2023-09-19 20:51:45 +02:00
|
|
|
}
|
2023-11-07 11:51:27 +02:00
|
|
|
handler = cb
|
2015-12-03 14:59:51 -06:00
|
|
|
}
|
2023-11-07 11:51:27 +02:00
|
|
|
if handler == nil {
|
2023-09-22 16:59:03 +02:00
|
|
|
return nil, C.int(ErrConv)
|
2023-11-07 11:51:27 +02:00
|
|
|
}
|
|
|
|
|
r, err = handler.RespondPAM(style, C.GoString(msg))
|
2015-03-27 18:59:29 -05:00
|
|
|
if err != nil {
|
2023-09-22 16:59:03 +02:00
|
|
|
return nil, C.int(ErrConv)
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
2023-09-22 16:59:03 +02:00
|
|
|
return C.CString(r), success
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
|
|
|
|
|
2015-03-30 14:53:16 -05:00
|
|
|
// Transaction is the application's handle for a PAM transaction.
|
2015-03-27 18:59:29 -05:00
|
|
|
type Transaction struct {
|
2023-09-29 23:01:50 +02:00
|
|
|
handle *C.pam_handle_t
|
|
|
|
|
conv *C.struct_pam_conv
|
|
|
|
|
lastStatus atomic.Int32
|
|
|
|
|
c cgo.Handle
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
|
|
|
|
|
2023-10-11 22:36:28 +02:00
|
|
|
// End cleans up the PAM handle and deletes the callback function.
|
|
|
|
|
// It must be called when done with the transaction.
|
|
|
|
|
func (t *Transaction) End() error {
|
|
|
|
|
handle := atomic.SwapPointer((*unsafe.Pointer)(unsafe.Pointer(&t.handle)), nil)
|
|
|
|
|
if handle == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
defer t.c.Delete()
|
|
|
|
|
return t.handlePamStatus(C.pam_end((*C.pam_handle_t)(handle),
|
|
|
|
|
C.int(t.lastStatus.Load())))
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
|
|
|
|
|
2023-10-11 10:25:42 +02:00
|
|
|
// Allows to call pam functions managing return status
|
|
|
|
|
func (t *Transaction) handlePamStatus(cStatus C.int) error {
|
2023-09-29 23:01:50 +02:00
|
|
|
t.lastStatus.Store(int32(cStatus))
|
2023-10-11 12:16:59 +02:00
|
|
|
if status := Error(cStatus); status != success {
|
|
|
|
|
return status
|
2023-10-11 10:25:42 +02:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// Start initiates a new PAM transaction. Service is treated identically to
|
|
|
|
|
// how pam_start treats it internally.
|
2015-03-27 18:59:29 -05:00
|
|
|
//
|
2022-09-16 08:09:26 +02:00
|
|
|
// All application calls to PAM begin with Start*. The returned
|
2015-04-10 15:04:52 -05:00
|
|
|
// transaction provides an interface to the remainder of the API.
|
2023-10-11 22:36:28 +02:00
|
|
|
//
|
|
|
|
|
// It's responsibility of the Transaction owner to release all the resources
|
|
|
|
|
// allocated underneath by PAM by calling End() once done.
|
|
|
|
|
//
|
|
|
|
|
// It's not advised to End the transaction using a runtime.SetFinalizer unless
|
|
|
|
|
// you're absolutely sure that your stack is multi-thread friendly (normally it
|
|
|
|
|
// is not!) and using a LockOSThread/UnlockOSThread pair.
|
2015-03-27 18:59:29 -05:00
|
|
|
func Start(service, user string, handler ConversationHandler) (*Transaction, error) {
|
2022-09-16 08:09:26 +02:00
|
|
|
return start(service, user, handler, "")
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-11 22:36:28 +02:00
|
|
|
// StartFunc registers the handler func as a conversation handler and starts
|
|
|
|
|
// the transaction (see Start() documentation).
|
2022-09-16 08:09:26 +02:00
|
|
|
func StartFunc(service, user string, handler func(Style, string) (string, error)) (*Transaction, error) {
|
2023-10-11 23:09:04 +02:00
|
|
|
return start(service, user, ConversationFunc(handler), "")
|
2022-09-16 08:09:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// StartConfDir initiates a new PAM transaction. Service is treated identically to
|
|
|
|
|
// how pam_start treats it internally.
|
|
|
|
|
// confdir allows to define where all pam services are defined. This is used to provide
|
|
|
|
|
// custom paths for tests.
|
|
|
|
|
//
|
|
|
|
|
// All application calls to PAM begin with Start*. The returned
|
|
|
|
|
// transaction provides an interface to the remainder of the API.
|
2023-10-11 22:36:28 +02:00
|
|
|
//
|
|
|
|
|
// It's responsibility of the Transaction owner to release all the resources
|
|
|
|
|
// allocated underneath by PAM by calling End() once done.
|
|
|
|
|
//
|
|
|
|
|
// It's not advised to End the transaction using a runtime.SetFinalizer unless
|
|
|
|
|
// you're absolutely sure that your stack is multi-thread friendly (normally it
|
|
|
|
|
// is not!) and using a LockOSThread/UnlockOSThread pair.
|
2022-09-16 08:09:26 +02:00
|
|
|
func StartConfDir(service, user string, handler ConversationHandler, confDir string) (*Transaction, error) {
|
|
|
|
|
if !CheckPamHasStartConfdir() {
|
2023-09-25 13:44:45 +02:00
|
|
|
return nil, fmt.Errorf(
|
|
|
|
|
"%w: StartConfDir was used, but the pam version on the system is not recent enough",
|
|
|
|
|
ErrSystem)
|
2022-09-16 08:09:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return start(service, user, handler, confDir)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func start(service, user string, handler ConversationHandler, confDir string) (*Transaction, error) {
|
2023-09-19 20:51:45 +02:00
|
|
|
switch handler.(type) {
|
|
|
|
|
case BinaryConversationHandler:
|
|
|
|
|
if !CheckPamHasBinaryProtocol() {
|
2023-09-25 13:44:45 +02:00
|
|
|
return nil, fmt.Errorf("%w: BinaryConversationHandler was used, but it is not supported by this platform",
|
|
|
|
|
ErrSystem)
|
2023-09-19 20:51:45 +02:00
|
|
|
}
|
|
|
|
|
}
|
2015-12-04 09:21:38 -06:00
|
|
|
t := &Transaction{
|
|
|
|
|
conv: &C.struct_pam_conv{},
|
2023-09-19 20:04:06 +02:00
|
|
|
c: cgo.NewHandle(handler),
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
2023-10-11 23:09:04 +02:00
|
|
|
|
2023-09-19 20:04:06 +02:00
|
|
|
C.init_pam_conv(t.conv, C.uintptr_t(t.c))
|
2015-03-27 18:59:29 -05:00
|
|
|
s := C.CString(service)
|
|
|
|
|
defer C.free(unsafe.Pointer(s))
|
|
|
|
|
var u *C.char
|
|
|
|
|
if len(user) != 0 {
|
|
|
|
|
u = C.CString(user)
|
2015-03-29 11:25:00 -05:00
|
|
|
defer C.free(unsafe.Pointer(u))
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
2023-10-11 10:25:42 +02:00
|
|
|
var err error
|
2022-09-16 08:09:26 +02:00
|
|
|
if confDir == "" {
|
2023-10-11 10:25:42 +02:00
|
|
|
err = t.handlePamStatus(C.pam_start(s, u, t.conv, &t.handle))
|
2022-09-16 08:09:26 +02:00
|
|
|
} else {
|
|
|
|
|
c := C.CString(confDir)
|
|
|
|
|
defer C.free(unsafe.Pointer(c))
|
2023-10-11 10:25:42 +02:00
|
|
|
err = t.handlePamStatus(C.pam_start_confdir(s, u, t.conv, c, &t.handle))
|
2022-09-16 08:09:26 +02:00
|
|
|
}
|
2023-10-11 10:25:42 +02:00
|
|
|
if err != nil {
|
2023-10-11 22:36:28 +02:00
|
|
|
var _ = t.End()
|
2023-10-11 12:16:59 +02:00
|
|
|
return nil, err
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
|
|
|
|
return t, nil
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// Item is a an PAM information type.
|
2015-03-27 18:59:29 -05:00
|
|
|
type Item int
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// PAM Item types.
|
2015-03-27 18:59:29 -05:00
|
|
|
const (
|
2015-04-10 15:04:52 -05:00
|
|
|
// Service is the name which identifies the PAM stack.
|
|
|
|
|
Service Item = C.PAM_SERVICE
|
|
|
|
|
// User identifies the username identity used by a service.
|
2023-10-10 11:45:12 +02:00
|
|
|
User Item = C.PAM_USER
|
2015-04-10 15:04:52 -05:00
|
|
|
// Tty is the terminal name.
|
2023-10-10 11:45:12 +02:00
|
|
|
Tty Item = C.PAM_TTY
|
2015-04-10 15:04:52 -05:00
|
|
|
// Rhost is the requesting host name.
|
2023-10-10 11:45:12 +02:00
|
|
|
Rhost Item = C.PAM_RHOST
|
2015-04-10 15:04:52 -05:00
|
|
|
// Authtok is the currently active authentication token.
|
2023-10-10 11:45:12 +02:00
|
|
|
Authtok Item = C.PAM_AUTHTOK
|
2015-04-10 15:04:52 -05:00
|
|
|
// Oldauthtok is the old authentication token.
|
2023-10-10 11:45:12 +02:00
|
|
|
Oldauthtok Item = C.PAM_OLDAUTHTOK
|
2015-04-10 15:04:52 -05:00
|
|
|
// Ruser is the requesting user name.
|
2023-10-10 11:45:12 +02:00
|
|
|
Ruser Item = C.PAM_RUSER
|
2015-04-10 15:04:52 -05:00
|
|
|
// UserPrompt is the string use to prompt for a username.
|
2023-10-10 11:45:12 +02:00
|
|
|
UserPrompt Item = C.PAM_USER_PROMPT
|
2015-03-27 18:59:29 -05:00
|
|
|
)
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// SetItem sets a PAM information item.
|
2015-03-27 18:59:29 -05:00
|
|
|
func (t *Transaction) SetItem(i Item, item string) error {
|
|
|
|
|
cs := unsafe.Pointer(C.CString(item))
|
|
|
|
|
defer C.free(cs)
|
2023-10-11 10:25:42 +02:00
|
|
|
return t.handlePamStatus(C.pam_set_item(t.handle, C.int(i), cs))
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// GetItem retrieves a PAM information item.
|
2015-03-27 18:59:29 -05:00
|
|
|
func (t *Transaction) GetItem(i Item) (string, error) {
|
|
|
|
|
var s unsafe.Pointer
|
2023-10-11 10:25:42 +02:00
|
|
|
err := t.handlePamStatus(C.pam_get_item(t.handle, C.int(i), &s))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
|
|
|
|
return C.GoString((*C.char)(s)), nil
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// Flags are inputs to various PAM functions than be combined with a bitwise
|
|
|
|
|
// or. Refer to the official PAM documentation for which flags are accepted
|
|
|
|
|
// by which functions.
|
2015-03-27 18:59:29 -05:00
|
|
|
type Flags int
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// PAM Flag types.
|
2015-03-27 18:59:29 -05:00
|
|
|
const (
|
2015-04-10 15:04:52 -05:00
|
|
|
// Silent indicates that no messages should be emitted.
|
|
|
|
|
Silent Flags = C.PAM_SILENT
|
|
|
|
|
// DisallowNullAuthtok indicates that authorization should fail
|
|
|
|
|
// if the user does not have a registered authentication token.
|
2023-10-10 11:45:12 +02:00
|
|
|
DisallowNullAuthtok Flags = C.PAM_DISALLOW_NULL_AUTHTOK
|
2015-04-10 15:04:52 -05:00
|
|
|
// EstablishCred indicates that credentials should be established
|
|
|
|
|
// for the user.
|
2023-10-10 11:45:12 +02:00
|
|
|
EstablishCred Flags = C.PAM_ESTABLISH_CRED
|
2015-04-10 15:04:52 -05:00
|
|
|
// DeleteCred inidicates that credentials should be deleted.
|
2023-10-10 11:45:12 +02:00
|
|
|
DeleteCred Flags = C.PAM_DELETE_CRED
|
2015-04-10 15:04:52 -05:00
|
|
|
// ReinitializeCred indicates that credentials should be fully
|
|
|
|
|
// reinitialized.
|
2023-10-10 11:45:12 +02:00
|
|
|
ReinitializeCred Flags = C.PAM_REINITIALIZE_CRED
|
2015-04-10 15:04:52 -05:00
|
|
|
// RefreshCred indicates that the lifetime of existing credentials
|
|
|
|
|
// should be extended.
|
2023-10-10 11:45:12 +02:00
|
|
|
RefreshCred Flags = C.PAM_REFRESH_CRED
|
2015-04-10 15:04:52 -05:00
|
|
|
// ChangeExpiredAuthtok indicates that the authentication token
|
|
|
|
|
// should be changed if it has expired.
|
2023-10-10 11:45:12 +02:00
|
|
|
ChangeExpiredAuthtok Flags = C.PAM_CHANGE_EXPIRED_AUTHTOK
|
2015-03-27 18:59:29 -05:00
|
|
|
)
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// Authenticate is used to authenticate the user.
|
|
|
|
|
//
|
|
|
|
|
// Valid flags: Silent, DisallowNullAuthtok
|
2015-03-27 18:59:29 -05:00
|
|
|
func (t *Transaction) Authenticate(f Flags) error {
|
2023-10-11 10:25:42 +02:00
|
|
|
return t.handlePamStatus(C.pam_authenticate(t.handle, C.int(f)))
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// SetCred is used to establish, maintain and delete the credentials of a
|
|
|
|
|
// user.
|
|
|
|
|
//
|
|
|
|
|
// Valid flags: EstablishCred, DeleteCred, ReinitializeCred, RefreshCred
|
2015-03-27 18:59:29 -05:00
|
|
|
func (t *Transaction) SetCred(f Flags) error {
|
2023-10-11 10:25:42 +02:00
|
|
|
return t.handlePamStatus(C.pam_setcred(t.handle, C.int(f)))
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// AcctMgmt is used to determine if the user's account is valid.
|
|
|
|
|
//
|
|
|
|
|
// Valid flags: Silent, DisallowNullAuthtok
|
2015-03-27 18:59:29 -05:00
|
|
|
func (t *Transaction) AcctMgmt(f Flags) error {
|
2023-10-11 10:25:42 +02:00
|
|
|
return t.handlePamStatus(C.pam_acct_mgmt(t.handle, C.int(f)))
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// ChangeAuthTok is used to change the authentication token.
|
|
|
|
|
//
|
|
|
|
|
// Valid flags: Silent, ChangeExpiredAuthtok
|
2015-03-27 18:59:29 -05:00
|
|
|
func (t *Transaction) ChangeAuthTok(f Flags) error {
|
2023-10-11 10:25:42 +02:00
|
|
|
return t.handlePamStatus(C.pam_chauthtok(t.handle, C.int(f)))
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// OpenSession sets up a user session for an authenticated user.
|
|
|
|
|
//
|
|
|
|
|
// Valid flags: Slient
|
2015-03-27 18:59:29 -05:00
|
|
|
func (t *Transaction) OpenSession(f Flags) error {
|
2023-10-11 10:25:42 +02:00
|
|
|
return t.handlePamStatus(C.pam_open_session(t.handle, C.int(f)))
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// CloseSession closes a previously opened session.
|
|
|
|
|
//
|
|
|
|
|
// Valid flags: Silent
|
2015-03-27 18:59:29 -05:00
|
|
|
func (t *Transaction) CloseSession(f Flags) error {
|
2023-10-11 10:25:42 +02:00
|
|
|
return t.handlePamStatus(C.pam_close_session(t.handle, C.int(f)))
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// PutEnv adds or changes the value of PAM environment variables.
|
|
|
|
|
//
|
|
|
|
|
// NAME=value will set a variable to a value.
|
|
|
|
|
// NAME= will set a variable to an empty value.
|
|
|
|
|
// NAME (without an "=") will delete a variable.
|
2015-03-27 18:59:29 -05:00
|
|
|
func (t *Transaction) PutEnv(nameval string) error {
|
|
|
|
|
cs := C.CString(nameval)
|
|
|
|
|
defer C.free(unsafe.Pointer(cs))
|
2023-10-11 10:25:42 +02:00
|
|
|
return t.handlePamStatus(C.pam_putenv(t.handle, cs))
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// GetEnv is used to retrieve a PAM environment variable.
|
2015-03-27 18:59:29 -05:00
|
|
|
func (t *Transaction) GetEnv(name string) string {
|
|
|
|
|
cs := C.CString(name)
|
|
|
|
|
defer C.free(unsafe.Pointer(cs))
|
|
|
|
|
value := C.pam_getenv(t.handle, cs)
|
|
|
|
|
if value == nil {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return C.GoString(value)
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-30 18:20:09 -05:00
|
|
|
func next(p **C.char) **C.char {
|
|
|
|
|
return (**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(p)))
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-10 15:04:52 -05:00
|
|
|
// GetEnvList returns a copy of the PAM environment as a map.
|
2015-03-27 18:59:29 -05:00
|
|
|
func (t *Transaction) GetEnvList() (map[string]string, error) {
|
|
|
|
|
env := make(map[string]string)
|
|
|
|
|
p := C.pam_getenvlist(t.handle)
|
|
|
|
|
if p == nil {
|
2023-09-29 23:01:50 +02:00
|
|
|
t.lastStatus.Store(int32(ErrBuf))
|
2023-10-11 12:16:59 +02:00
|
|
|
return nil, ErrBuf
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
2023-09-29 23:01:50 +02:00
|
|
|
t.lastStatus.Store(success)
|
2015-03-30 18:20:09 -05:00
|
|
|
for q := p; *q != nil; q = next(q) {
|
2015-03-30 18:13:10 -05:00
|
|
|
chunks := strings.SplitN(C.GoString(*q), "=", 2)
|
2015-03-27 18:59:29 -05:00
|
|
|
if len(chunks) == 2 {
|
|
|
|
|
env[chunks[0]] = chunks[1]
|
|
|
|
|
}
|
2015-03-30 18:13:10 -05:00
|
|
|
C.free(unsafe.Pointer(*q))
|
2015-03-27 18:59:29 -05:00
|
|
|
}
|
2015-03-30 14:53:16 -05:00
|
|
|
C.free(unsafe.Pointer(p))
|
2015-03-27 18:59:29 -05:00
|
|
|
return env, nil
|
|
|
|
|
}
|
2022-09-16 08:09:26 +02:00
|
|
|
|
|
|
|
|
// CheckPamHasStartConfdir return if pam on system supports pam_system_confdir
|
|
|
|
|
func CheckPamHasStartConfdir() bool {
|
|
|
|
|
return C.check_pam_start_confdir() == 0
|
|
|
|
|
}
|
2023-09-19 20:51:45 +02:00
|
|
|
|
|
|
|
|
// CheckPamHasBinaryProtocol return if pam on system supports PAM_BINARY_PROMPT
|
|
|
|
|
func CheckPamHasBinaryProtocol() bool {
|
|
|
|
|
return C.BINARY_PROMPT_IS_SUPPORTED != 0
|
|
|
|
|
}
|