diff --git a/transaction.go b/transaction.go index ae052c8..9dba072 100644 --- a/transaction.go +++ b/transaction.go @@ -4,21 +4,7 @@ package pam //#cgo CFLAGS: -Wall -std=c99 //#cgo LDFLAGS: -lpam // -//#include -//#include -//#include -// -//#ifdef PAM_BINARY_PROMPT -//#define BINARY_PROMPT_IS_SUPPORTED 1 -//#else -//#include -//#define PAM_BINARY_PROMPT INT_MAX -//#define BINARY_PROMPT_IS_SUPPORTED 0 -//#endif -// -//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 check_pam_start_confdir(void); +//#include "transaction.h" import "C" import ( @@ -89,16 +75,24 @@ func (f ConversationFunc) RespondPAM(s Style, msg string) (string, error) { return f(s, msg) } -// cbPAMConv is a wrapper for the conversation callback function. +// _go_pam_conv_handler is a C wrapper for the conversation callback function. // -//export cbPAMConv -func cbPAMConv(s C.int, msg *C.char, c C.uintptr_t) (*C.char, C.int) { +//export _go_pam_conv_handler +func _go_pam_conv_handler(msg *C.struct_pam_message, c C.uintptr_t, outMsg **C.char) C.int { + convHandler, ok := cgo.Handle(c).Value().(ConversationHandler) + if !ok || convHandler == nil { + return C.int(ErrConv) + } + replyMsg, r := pamConvHandler(Style(msg.msg_style), msg.msg, convHandler) + *outMsg = replyMsg + return r +} + +// pamConvHandler is a Go wrapper for the conversation callback function. +func pamConvHandler(style Style, msg *C.char, handler ConversationHandler) (*C.char, C.int) { var r string var err error - v := cgo.Handle(c).Value() - style := Style(s) - var handler ConversationHandler - switch cb := v.(type) { + switch cb := handler.(type) { case BinaryConversationHandler: if style == BinaryPrompt { bytes, err := cb.RespondPAMBinary(BinaryPointer(msg)) @@ -116,8 +110,7 @@ func cbPAMConv(s C.int, msg *C.char, c C.uintptr_t) (*C.char, C.int) { return nil, C.int(ErrConv) } handler = cb - } - if handler == nil { + default: return nil, C.int(ErrConv) } r, err = handler.RespondPAM(style, C.GoString(msg)) diff --git a/transaction.c b/transaction.h similarity index 62% rename from transaction.c rename to transaction.h index 8abed03..88d2766 100644 --- a/transaction.c +++ b/transaction.h @@ -1,15 +1,25 @@ -#include "_cgo_export.h" #include #include +#include #include +#ifdef PAM_BINARY_PROMPT +#define BINARY_PROMPT_IS_SUPPORTED 1 +#else +#include +#define PAM_BINARY_PROMPT INT_MAX +#define BINARY_PROMPT_IS_SUPPORTED 0 +#endif + #ifdef __sun #define PAM_CONST #else #define PAM_CONST const #endif -int cb_pam_conv(int num_msg, PAM_CONST struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) +extern int _go_pam_conv_handler(struct pam_message *, uintptr_t, char **reply); + +static inline int cb_pam_conv(int num_msg, PAM_CONST struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { if (num_msg <= 0 || num_msg > PAM_MAX_NUM_MSG) return PAM_CONV_ERR; @@ -19,11 +29,9 @@ int cb_pam_conv(int num_msg, PAM_CONST struct pam_message **msg, struct pam_resp return PAM_BUF_ERR; for (size_t i = 0; i < num_msg; ++i) { - struct cbPAMConv_return result = cbPAMConv(msg[i]->msg_style, (char *)msg[i]->msg, (uintptr_t)appdata_ptr); - if (result.r1 != PAM_SUCCESS) + int result = _go_pam_conv_handler((struct pam_message *)msg[i], (uintptr_t)appdata_ptr, &(*resp)[i].resp); + if (result != PAM_SUCCESS) goto error; - - (*resp)[i].resp = result.r0; } return PAM_SUCCESS; @@ -41,7 +49,7 @@ error: return PAM_CONV_ERR; } -void init_pam_conv(struct pam_conv *conv, uintptr_t appdata) +static inline void init_pam_conv(struct pam_conv *conv, uintptr_t appdata) { conv->conv = cb_pam_conv; conv->appdata_ptr = (void *)appdata; @@ -52,7 +60,7 @@ void init_pam_conv(struct pam_conv *conv, uintptr_t appdata) 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) +static inline int check_pam_start_confdir(void) { if (pam_start_confdir == NULL) return 1;