157 lines
4.5 KiB
Go
157 lines
4.5 KiB
Go
package main
|
|
|
|
/*
|
|
#include <mosquitto.h>
|
|
#include <mosquitto_plugin.h>
|
|
typedef struct mosquitto mosquitto;
|
|
typedef const struct mosquitto_acl_msg const_mosquitto_acl_msg;
|
|
typedef const char const_char;
|
|
*/
|
|
import "C"
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"unsafe"
|
|
)
|
|
|
|
var (
|
|
logger *log.Logger
|
|
file *os.File = nil
|
|
)
|
|
|
|
//export mosquitto_auth_plugin_version
|
|
/*
|
|
* Returns the value of MOSQ_AUTH_PLUGIN_VERSION defined in the mosquitto header file that the plugin was compiled
|
|
* against.
|
|
*/
|
|
func mosquitto_auth_plugin_version() C.int {
|
|
return C.MOSQ_AUTH_PLUGIN_VERSION
|
|
}
|
|
|
|
//export mosquitto_auth_plugin_init
|
|
/*
|
|
* Initialises the plugin.
|
|
*/
|
|
func mosquitto_auth_plugin_init(cUserData *unsafe.Pointer, cOpts *C.struct_mosquitto_opt, cOptCount C.int) C.int {
|
|
var err error
|
|
// copy opts from the C world into Go
|
|
optMap := extractOptions(cOpts, cOptCount)
|
|
|
|
// initialise logger
|
|
if logger, file, err = initialiseLogger(optMap[optLogDest]); err != nil {
|
|
fmt.Printf("error initialising logger, %s", err)
|
|
return C.MOSQ_ERR_AUTH
|
|
}
|
|
logger.Println("plugin initializing")
|
|
|
|
// initialise the user data that will be used in subsequent plugin calls
|
|
userData, err := initialiseUserData(optMap)
|
|
if err != nil {
|
|
logger.Println("initialiseUserData failed with err:", err)
|
|
return C.MOSQ_ERR_AUTH
|
|
}
|
|
*cUserData = unsafe.Pointer(&userData)
|
|
|
|
return C.MOSQ_ERR_SUCCESS
|
|
}
|
|
|
|
//export mosquitto_auth_plugin_cleanup
|
|
/*
|
|
* Cleans up the plugin before the server shuts down.
|
|
*/
|
|
func mosquitto_auth_plugin_cleanup(cUserData unsafe.Pointer, cOpts *C.struct_mosquitto_opt, cOptCount C.int) C.int {
|
|
//logger.Println("enter - plugin cleanup")
|
|
// close logfile
|
|
if file != nil {
|
|
file.Sync()
|
|
file.Close()
|
|
file = nil
|
|
}
|
|
// set the client cache to nil so it can be garage collected
|
|
clearUserData((*userData)(cUserData))
|
|
|
|
//logger.Println("leave - plugin cleanup")
|
|
logger = nil
|
|
return C.MOSQ_ERR_SUCCESS
|
|
}
|
|
|
|
//export mosquitto_auth_acl_check
|
|
/*
|
|
* Checks whether a client is authorised to read from or write to a topic.
|
|
*/
|
|
func mosquitto_auth_acl_check(cUserData unsafe.Pointer, cAccess C.int, cClient *C.mosquitto, cMsg *C.const_mosquitto_acl_msg) C.int {
|
|
if cUserData == nil {
|
|
logger.Printf("auth_acl_check[%p]: missing user data", cClient)
|
|
return C.MOSQ_ERR_AUTH
|
|
}
|
|
|
|
access := access(cAccess)
|
|
allow, err := authorise(http.DefaultClient, (*userData)(cUserData), access, unsafe.Pointer(cClient),
|
|
C.GoString(cMsg.topic))
|
|
if err != nil {
|
|
logger.Printf("auth_acl_check[%p]: error: %v", cClient, err)
|
|
return C.MOSQ_ERR_AUTH
|
|
}
|
|
if !allow {
|
|
logger.Printf("auth_acl_check[%p]: acl %q denied", cClient, access)
|
|
return C.MOSQ_ERR_PLUGIN_DEFER
|
|
}
|
|
logger.Printf("auth_acl_check[%p]: acl %q granted", cClient, access)
|
|
return C.MOSQ_ERR_SUCCESS
|
|
}
|
|
|
|
//export mosquitto_auth_unpwd_check
|
|
/*
|
|
* Authenticates the client by checking the supplied username and password.
|
|
*/
|
|
func mosquitto_auth_unpwd_check(cUserData unsafe.Pointer, cClient *C.mosquitto, cUsername, cPassword *C.const_char) C.int {
|
|
if cUsername == nil || cPassword == nil {
|
|
return C.MOSQ_ERR_AUTH
|
|
}
|
|
|
|
username := goStringFromConstant(cUsername)
|
|
password := goStringFromConstant(cPassword)
|
|
//logger.Printf("u: %s, p: %s\n", username, password)
|
|
|
|
authorised, err := authenticate((*userData)(cUserData), unsafe.Pointer(cClient), username, password)
|
|
if err != nil {
|
|
logger.Printf("auth_unpwd_check[%p]: user %q error: %v", cClient, username, err)
|
|
return C.MOSQ_ERR_AUTH
|
|
}
|
|
|
|
if !authorised {
|
|
logger.Printf("auth_unpwd_check[%p]: user %q unauthorized", cClient, username)
|
|
return C.MOSQ_ERR_PLUGIN_DEFER
|
|
}
|
|
logger.Printf("auth_unpwd_check[%p]: user %q authorized", cClient, username)
|
|
return C.MOSQ_ERR_SUCCESS
|
|
}
|
|
|
|
//export mosquitto_auth_security_init
|
|
/*
|
|
* No-op function. Included to satisfy the plugin contract to Mosquitto.
|
|
*/
|
|
func mosquitto_auth_security_init(cUserData unsafe.Pointer, cOpts *C.struct_mosquitto_opt, cOptCount C.int, cReload C.bool) C.int {
|
|
return C.MOSQ_ERR_SUCCESS
|
|
}
|
|
|
|
//export mosquitto_auth_security_cleanup
|
|
/*
|
|
* No-op function. Included to satisfy the plugin contract to Mosquitto.
|
|
*/
|
|
func mosquitto_auth_security_cleanup(cUserData unsafe.Pointer, cOpts *C.struct_mosquitto_opt, cOptCount C.int, cReload C.bool) C.int {
|
|
return C.MOSQ_ERR_SUCCESS
|
|
}
|
|
|
|
//export mosquitto_auth_psk_key_get
|
|
/*
|
|
* No-op function. Included to satisfy the plugin contract to Mosquitto.
|
|
*/
|
|
func mosquitto_auth_psk_key_get(cUserData unsafe.Pointer, cClient *C.mosquitto, cHint, cIdentity *C.const_char, cKey *C.char, cMaxKeyLen C.int) C.int {
|
|
return C.MOSQ_ERR_SUCCESS
|
|
}
|
|
|
|
func main() {}
|