123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- package pam
- import "C"
- import (
- "runtime"
- "strings"
- "unsafe"
- )
- type Style int
- const (
-
-
- PromptEchoOff Style = C.PAM_PROMPT_ECHO_OFF
-
-
- PromptEchoOn = C.PAM_PROMPT_ECHO_ON
-
-
- ErrorMsg = C.PAM_ERROR_MSG
-
-
- TextInfo = C.PAM_TEXT_INFO
- )
- type ConversationHandler interface {
-
-
-
- RespondPAM(Style, string) (string, error)
- }
- type ConversationFunc func(Style, string) (string, error)
- func (f ConversationFunc) RespondPAM(s Style, msg string) (string, error) {
- return f(s, msg)
- }
- func cbPAMConv(s C.int, msg *C.char, c int) (*C.char, C.int) {
- var r string
- var err error
- v := cbGet(c)
- switch cb := v.(type) {
- case ConversationHandler:
- r, err = cb.RespondPAM(Style(s), C.GoString(msg))
- }
- if err != nil {
- return nil, C.PAM_CONV_ERR
- }
- return C.CString(r), C.PAM_SUCCESS
- }
- type Transaction struct {
- handle *C.pam_handle_t
- conv *C.struct_pam_conv
- status C.int
- c int
- }
- func transactionFinalizer(t *Transaction) {
- C.pam_end(t.handle, t.status)
- cbDelete(t.c)
- }
- func Start(service, user string, handler ConversationHandler) (*Transaction, error) {
- t := &Transaction{
- conv: &C.struct_pam_conv{},
- c: cbAdd(handler),
- }
- C.init_pam_conv(t.conv, C.long(t.c))
- runtime.SetFinalizer(t, transactionFinalizer)
- s := C.CString(service)
- defer C.free(unsafe.Pointer(s))
- var u *C.char
- if len(user) != 0 {
- u = C.CString(user)
- defer C.free(unsafe.Pointer(u))
- }
- t.status = C.pam_start(s, u, t.conv, &t.handle)
- if t.status != C.PAM_SUCCESS {
- return nil, t
- }
- return t, nil
- }
- func StartFunc(service, user string, handler func(Style, string) (string, error)) (*Transaction, error) {
- return Start(service, user, ConversationFunc(handler))
- }
- func (t *Transaction) Error() string {
- return C.GoString(C.pam_strerror(t.handle, C.int(t.status)))
- }
- type Item int
- const (
-
- Service Item = C.PAM_SERVICE
-
- User = C.PAM_USER
-
- Tty = C.PAM_TTY
-
- Rhost = C.PAM_RHOST
-
- Authtok = C.PAM_AUTHTOK
-
- Oldauthtok = C.PAM_OLDAUTHTOK
-
- Ruser = C.PAM_RUSER
-
- UserPrompt = C.PAM_USER_PROMPT
- )
- func (t *Transaction) SetItem(i Item, item string) error {
- cs := unsafe.Pointer(C.CString(item))
- defer C.free(cs)
- t.status = C.pam_set_item(t.handle, C.int(i), cs)
- if t.status != C.PAM_SUCCESS {
- return t
- }
- return nil
- }
- func (t *Transaction) GetItem(i Item) (string, error) {
- var s unsafe.Pointer
- t.status = C.pam_get_item(t.handle, C.int(i), &s)
- if t.status != C.PAM_SUCCESS {
- return "", t
- }
- return C.GoString((*C.char)(s)), nil
- }
- type Flags int
- const (
-
- Silent Flags = C.PAM_SILENT
-
-
- DisallowNullAuthtok = C.PAM_DISALLOW_NULL_AUTHTOK
-
-
- EstablishCred = C.PAM_ESTABLISH_CRED
-
- DeleteCred = C.PAM_DELETE_CRED
-
-
- ReinitializeCred = C.PAM_REINITIALIZE_CRED
-
-
- RefreshCred = C.PAM_REFRESH_CRED
-
-
- ChangeExpiredAuthtok = C.PAM_CHANGE_EXPIRED_AUTHTOK
- )
- func (t *Transaction) Authenticate(f Flags) error {
- t.status = C.pam_authenticate(t.handle, C.int(f))
- if t.status != C.PAM_SUCCESS {
- return t
- }
- return nil
- }
- func (t *Transaction) SetCred(f Flags) error {
- t.status = C.pam_setcred(t.handle, C.int(f))
- if t.status != C.PAM_SUCCESS {
- return t
- }
- return nil
- }
- func (t *Transaction) AcctMgmt(f Flags) error {
- t.status = C.pam_acct_mgmt(t.handle, C.int(f))
- if t.status != C.PAM_SUCCESS {
- return t
- }
- return nil
- }
- func (t *Transaction) ChangeAuthTok(f Flags) error {
- t.status = C.pam_chauthtok(t.handle, C.int(f))
- if t.status != C.PAM_SUCCESS {
- return t
- }
- return nil
- }
- func (t *Transaction) OpenSession(f Flags) error {
- t.status = C.pam_open_session(t.handle, C.int(f))
- if t.status != C.PAM_SUCCESS {
- return t
- }
- return nil
- }
- func (t *Transaction) CloseSession(f Flags) error {
- t.status = C.pam_close_session(t.handle, C.int(f))
- if t.status != C.PAM_SUCCESS {
- return t
- }
- return nil
- }
- func (t *Transaction) PutEnv(nameval string) error {
- cs := C.CString(nameval)
- defer C.free(unsafe.Pointer(cs))
- t.status = C.pam_putenv(t.handle, cs)
- if t.status != C.PAM_SUCCESS {
- return t
- }
- return nil
- }
- 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)
- }
- func next(p **C.char) **C.char {
- return (**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(p)))
- }
- func (t *Transaction) GetEnvList() (map[string]string, error) {
- env := make(map[string]string)
- p := C.pam_getenvlist(t.handle)
- if p == nil {
- t.status = C.PAM_BUF_ERR
- return nil, t
- }
- for q := p; *q != nil; q = next(q) {
- chunks := strings.SplitN(C.GoString(*q), "=", 2)
- if len(chunks) == 2 {
- env[chunks[0]] = chunks[1]
- }
- C.free(unsafe.Pointer(*q))
- }
- C.free(unsafe.Pointer(p))
- return env, nil
- }
|