msteinert-go-pam/transaction.go

198 lines
6.2 KiB
Go
Raw Normal View History

2015-12-04 16:05:44 +00:00
// Package pam provides a wrapper for the PAM application API.
2015-03-27 23:59:29 +00:00
package pam
//#cgo CFLAGS: -Wall -std=c99
//#cgo LDFLAGS: -lpam
//
//#include "transaction.h"
2015-03-27 23:59:29 +00:00
import "C"
import (
"strings"
"sync/atomic"
2015-03-27 23:59:29 +00:00
"unsafe"
)
// success indicates a successful function return.
const success = C.PAM_SUCCESS
2015-04-10 20:04:52 +00:00
// Style is the type of message that the conversation handler should display.
2015-03-27 23:59:29 +00:00
type Style int
2015-04-10 20:04:52 +00:00
// Coversation handler style types.
2015-03-27 23:59:29 +00:00
const (
2015-04-10 20:04:52 +00:00
// PromptEchoOff indicates the conversation handler should obtain a
// string without echoing any text.
2015-03-27 23:59:29 +00:00
PromptEchoOff Style = C.PAM_PROMPT_ECHO_OFF
2015-04-10 20:04:52 +00:00
// PromptEchoOn indicates the conversation handler should obtain a
// string while echoing text.
PromptEchoOn Style = C.PAM_PROMPT_ECHO_ON
2015-04-10 20:04:52 +00:00
// ErrorMsg indicates the conversation handler should display an
// error message.
ErrorMsg Style = C.PAM_ERROR_MSG
2015-04-10 20:04:52 +00:00
// TextInfo indicates the conversation handler should display some
// text.
TextInfo Style = C.PAM_TEXT_INFO
// BinaryPrompt indicates the conversation handler that should implement
// the private binary protocol
BinaryPrompt Style = C.PAM_BINARY_PROMPT
2015-03-27 23:59:29 +00: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
// NativeHandle is the type of the native PAM handle for a transaction so that
// it can be exported
type NativeHandle = *C.pam_handle_t
// transactionBase is a handler for a PAM transaction that can be used to
// group the operations that can be performed both by the application and the
// module side
type transactionBase struct {
handle NativeHandle
lastStatus atomic.Int32
}
// Allows to call pam functions managing return status
func (t *transactionBase) handlePamStatus(cStatus C.int) error {
t.lastStatus.Store(int32(cStatus))
if status := Error(cStatus); status != success {
return status
}
return nil
}
2015-04-10 20:04:52 +00:00
// Item is a an PAM information type.
2015-03-27 23:59:29 +00:00
type Item int
2015-04-10 20:04:52 +00:00
// PAM Item types.
2015-03-27 23:59:29 +00:00
const (
2015-04-10 20:04:52 +00:00
// Service is the name which identifies the PAM stack.
Service Item = C.PAM_SERVICE
// User identifies the username identity used by a service.
User Item = C.PAM_USER
2015-04-10 20:04:52 +00:00
// Tty is the terminal name.
Tty Item = C.PAM_TTY
2015-04-10 20:04:52 +00:00
// Rhost is the requesting host name.
Rhost Item = C.PAM_RHOST
2015-04-10 20:04:52 +00:00
// Authtok is the currently active authentication token.
Authtok Item = C.PAM_AUTHTOK
2015-04-10 20:04:52 +00:00
// Oldauthtok is the old authentication token.
Oldauthtok Item = C.PAM_OLDAUTHTOK
2015-04-10 20:04:52 +00:00
// Ruser is the requesting user name.
Ruser Item = C.PAM_RUSER
2015-04-10 20:04:52 +00:00
// UserPrompt is the string use to prompt for a username.
UserPrompt Item = C.PAM_USER_PROMPT
// FailDelay is the app supplied function to override failure delays.
FailDelay Item = C.PAM_FAIL_DELAY
// Xdisplay is the X display name
Xdisplay Item = C.PAM_XDISPLAY
// Xauthdata is the X server authentication data.
Xauthdata Item = C.PAM_XAUTHDATA
// AuthtokType is the type for pam_get_authtok
AuthtokType Item = C.PAM_AUTHTOK_TYPE
2015-03-27 23:59:29 +00:00
)
2015-04-10 20:04:52 +00:00
// SetItem sets a PAM information item.
func (t *transactionBase) SetItem(i Item, item string) error {
2015-03-27 23:59:29 +00:00
cs := unsafe.Pointer(C.CString(item))
defer C.free(cs)
return t.handlePamStatus(C.pam_set_item(t.handle, C.int(i), cs))
2015-03-27 23:59:29 +00:00
}
2015-04-10 20:04:52 +00:00
// GetItem retrieves a PAM information item.
func (t *transactionBase) GetItem(i Item) (string, error) {
2015-03-27 23:59:29 +00:00
var s unsafe.Pointer
err := t.handlePamStatus(C.pam_get_item(t.handle, C.int(i), &s))
if err != nil {
return "", err
2015-03-27 23:59:29 +00:00
}
return C.GoString((*C.char)(s)), nil
}
2015-04-10 20:04:52 +00: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 23:59:29 +00:00
type Flags int
2015-04-10 20:04:52 +00:00
// PAM Flag types.
2015-03-27 23:59:29 +00:00
const (
2015-04-10 20:04:52 +00: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.
DisallowNullAuthtok Flags = C.PAM_DISALLOW_NULL_AUTHTOK
2015-04-10 20:04:52 +00:00
// EstablishCred indicates that credentials should be established
// for the user.
EstablishCred Flags = C.PAM_ESTABLISH_CRED
2023-11-20 20:15:43 +00:00
// DeleteCred indicates that credentials should be deleted.
DeleteCred Flags = C.PAM_DELETE_CRED
2015-04-10 20:04:52 +00:00
// ReinitializeCred indicates that credentials should be fully
// reinitialized.
ReinitializeCred Flags = C.PAM_REINITIALIZE_CRED
2015-04-10 20:04:52 +00:00
// RefreshCred indicates that the lifetime of existing credentials
// should be extended.
RefreshCred Flags = C.PAM_REFRESH_CRED
2015-04-10 20:04:52 +00:00
// ChangeExpiredAuthtok indicates that the authentication token
// should be changed if it has expired.
ChangeExpiredAuthtok Flags = C.PAM_CHANGE_EXPIRED_AUTHTOK
2015-03-27 23:59:29 +00:00
)
2015-04-10 20:04:52 +00: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.
func (t *transactionBase) PutEnv(nameval string) error {
2015-03-27 23:59:29 +00:00
cs := C.CString(nameval)
defer C.free(unsafe.Pointer(cs))
return t.handlePamStatus(C.pam_putenv(t.handle, cs))
2015-03-27 23:59:29 +00:00
}
2015-04-10 20:04:52 +00:00
// GetEnv is used to retrieve a PAM environment variable.
func (t *transactionBase) GetEnv(name string) string {
2015-03-27 23:59:29 +00:00
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 23:20:09 +00:00
func next(p **C.char) **C.char {
return (**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(p)))
}
2015-04-10 20:04:52 +00:00
// GetEnvList returns a copy of the PAM environment as a map.
func (t *transactionBase) GetEnvList() (map[string]string, error) {
2015-03-27 23:59:29 +00:00
env := make(map[string]string)
p := C.pam_getenvlist(t.handle)
if p == nil {
t.lastStatus.Store(int32(ErrBuf))
return nil, ErrBuf
2015-03-27 23:59:29 +00:00
}
t.lastStatus.Store(success)
2015-03-30 23:20:09 +00:00
for q := p; *q != nil; q = next(q) {
2015-03-30 23:13:10 +00:00
chunks := strings.SplitN(C.GoString(*q), "=", 2)
2015-03-27 23:59:29 +00:00
if len(chunks) == 2 {
env[chunks[0]] = chunks[1]
}
2015-03-30 23:13:10 +00:00
C.free(unsafe.Pointer(*q))
2015-03-27 23:59:29 +00:00
}
C.free(unsafe.Pointer(p))
2015-03-27 23:59:29 +00:00
return env, nil
}
// CheckPamHasStartConfdir return if pam on system supports pam_system_confdir
func CheckPamHasStartConfdir() bool {
return C.check_pam_start_confdir() == 0
}
// CheckPamHasBinaryProtocol return if pam on system supports PAM_BINARY_PROMPT
func CheckPamHasBinaryProtocol() bool {
return C.BINARY_PROMPT_IS_SUPPORTED != 0
}