Merge pull request #8 from 3v1n0/simpler-callbacks
transaction: Use cgo.Handle to pass callback data to PAM
This commit is contained in:
39
callback.go
39
callback.go
@@ -1,39 +0,0 @@
|
|||||||
package pam
|
|
||||||
|
|
||||||
import "sync"
|
|
||||||
|
|
||||||
var cb struct {
|
|
||||||
sync.Mutex
|
|
||||||
m map[int]interface{}
|
|
||||||
c int
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cb.m = make(map[int]interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func cbAdd(v interface{}) int {
|
|
||||||
cb.Lock()
|
|
||||||
defer cb.Unlock()
|
|
||||||
cb.c++
|
|
||||||
cb.m[cb.c] = v
|
|
||||||
return cb.c
|
|
||||||
}
|
|
||||||
|
|
||||||
func cbGet(c int) interface{} {
|
|
||||||
cb.Lock()
|
|
||||||
defer cb.Unlock()
|
|
||||||
if v, ok := cb.m[c]; ok {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
panic("Callback pointer not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
func cbDelete(c int) {
|
|
||||||
cb.Lock()
|
|
||||||
defer cb.Unlock()
|
|
||||||
if _, ok := cb.m[c]; !ok {
|
|
||||||
panic("Callback pointer not found")
|
|
||||||
}
|
|
||||||
delete(cb.m, c)
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package pam
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCallback_001(t *testing.T) {
|
|
||||||
c := cbAdd(TestCallback_001)
|
|
||||||
v := cbGet(c)
|
|
||||||
if reflect.TypeOf(v) != reflect.TypeOf(TestCallback_001) {
|
|
||||||
t.Error("Received unexpected value")
|
|
||||||
}
|
|
||||||
cbDelete(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCallback_002(t *testing.T) {
|
|
||||||
defer func() {
|
|
||||||
recover()
|
|
||||||
}()
|
|
||||||
c := cbAdd(TestCallback_002)
|
|
||||||
cbGet(c + 1)
|
|
||||||
t.Error("Expected a panic")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCallback_003(t *testing.T) {
|
|
||||||
defer func() {
|
|
||||||
recover()
|
|
||||||
}()
|
|
||||||
c := cbAdd(TestCallback_003)
|
|
||||||
cbDelete(c + 1)
|
|
||||||
t.Error("Expected a panic")
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "_cgo_export.h"
|
#include "_cgo_export.h"
|
||||||
#include <security/pam_appl.h>
|
#include <security/pam_appl.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef __sun
|
#ifdef __sun
|
||||||
@@ -25,7 +26,7 @@ int cb_pam_conv(
|
|||||||
struct cbPAMConv_return result = cbPAMConv(
|
struct cbPAMConv_return result = cbPAMConv(
|
||||||
msg[i]->msg_style,
|
msg[i]->msg_style,
|
||||||
(char *)msg[i]->msg,
|
(char *)msg[i]->msg,
|
||||||
(long)appdata_ptr);
|
(uintptr_t)appdata_ptr);
|
||||||
if (result.r1 != PAM_SUCCESS) {
|
if (result.r1 != PAM_SUCCESS) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -45,10 +46,10 @@ error:
|
|||||||
return PAM_CONV_ERR;
|
return PAM_CONV_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_pam_conv(struct pam_conv *conv, long c)
|
void init_pam_conv(struct pam_conv *conv, uintptr_t appdata)
|
||||||
{
|
{
|
||||||
conv->conv = cb_pam_conv;
|
conv->conv = cb_pam_conv;
|
||||||
conv->appdata_ptr = (void *)c;
|
conv->appdata_ptr = (void *)appdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pam_start_confdir is a recent PAM api to declare a confdir (mostly for tests)
|
// pam_start_confdir is a recent PAM api to declare a confdir (mostly for tests)
|
||||||
|
|||||||
@@ -3,9 +3,10 @@ package pam
|
|||||||
|
|
||||||
//#include <security/pam_appl.h>
|
//#include <security/pam_appl.h>
|
||||||
//#include <stdlib.h>
|
//#include <stdlib.h>
|
||||||
|
//#include <stdint.h>
|
||||||
//#cgo CFLAGS: -Wall -std=c99
|
//#cgo CFLAGS: -Wall -std=c99
|
||||||
//#cgo LDFLAGS: -lpam
|
//#cgo LDFLAGS: -lpam
|
||||||
//void init_pam_conv(struct pam_conv *conv, long c);
|
//void init_pam_conv(struct pam_conv *conv, uintptr_t);
|
||||||
//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 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);
|
//int check_pam_start_confdir(void);
|
||||||
import "C"
|
import "C"
|
||||||
@@ -13,6 +14,7 @@ import "C"
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"runtime/cgo"
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@@ -56,10 +58,10 @@ func (f ConversationFunc) RespondPAM(s Style, msg string) (string, error) {
|
|||||||
|
|
||||||
// cbPAMConv is a wrapper for the conversation callback function.
|
// cbPAMConv is a wrapper for the conversation callback function.
|
||||||
//export cbPAMConv
|
//export cbPAMConv
|
||||||
func cbPAMConv(s C.int, msg *C.char, c int) (*C.char, C.int) {
|
func cbPAMConv(s C.int, msg *C.char, c C.uintptr_t) (*C.char, C.int) {
|
||||||
var r string
|
var r string
|
||||||
var err error
|
var err error
|
||||||
v := cbGet(c)
|
v := cgo.Handle(c).Value()
|
||||||
switch cb := v.(type) {
|
switch cb := v.(type) {
|
||||||
case ConversationHandler:
|
case ConversationHandler:
|
||||||
r, err = cb.RespondPAM(Style(s), C.GoString(msg))
|
r, err = cb.RespondPAM(Style(s), C.GoString(msg))
|
||||||
@@ -75,14 +77,14 @@ type Transaction struct {
|
|||||||
handle *C.pam_handle_t
|
handle *C.pam_handle_t
|
||||||
conv *C.struct_pam_conv
|
conv *C.struct_pam_conv
|
||||||
status C.int
|
status C.int
|
||||||
c int
|
c cgo.Handle
|
||||||
}
|
}
|
||||||
|
|
||||||
// transactionFinalizer cleans up the PAM handle and deletes the callback
|
// transactionFinalizer cleans up the PAM handle and deletes the callback
|
||||||
// function.
|
// function.
|
||||||
func transactionFinalizer(t *Transaction) {
|
func transactionFinalizer(t *Transaction) {
|
||||||
C.pam_end(t.handle, t.status)
|
C.pam_end(t.handle, t.status)
|
||||||
cbDelete(t.c)
|
t.c.Delete()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start initiates a new PAM transaction. Service is treated identically to
|
// Start initiates a new PAM transaction. Service is treated identically to
|
||||||
@@ -117,9 +119,9 @@ func StartConfDir(service, user string, handler ConversationHandler, confDir str
|
|||||||
func start(service, user string, handler ConversationHandler, confDir string) (*Transaction, error) {
|
func start(service, user string, handler ConversationHandler, confDir string) (*Transaction, error) {
|
||||||
t := &Transaction{
|
t := &Transaction{
|
||||||
conv: &C.struct_pam_conv{},
|
conv: &C.struct_pam_conv{},
|
||||||
c: cbAdd(handler),
|
c: cgo.NewHandle(handler),
|
||||||
}
|
}
|
||||||
C.init_pam_conv(t.conv, C.long(t.c))
|
C.init_pam_conv(t.conv, C.uintptr_t(t.c))
|
||||||
runtime.SetFinalizer(t, transactionFinalizer)
|
runtime.SetFinalizer(t, transactionFinalizer)
|
||||||
s := C.CString(service)
|
s := C.CString(service)
|
||||||
defer C.free(unsafe.Pointer(s))
|
defer C.free(unsafe.Pointer(s))
|
||||||
|
|||||||
Reference in New Issue
Block a user