Pass char* to Go and convert with C.GoString, avoiding unsafe use
Using the char* passed by Mosquitto in a GoString struct is unsafe. The memory it points to is managed by Mosquitto, but Go will keep the pointer around for an indefinite duration, even when Mosquitto might free the memory. By passing the actual char* to Go, we can use C.GoString to convert it, which copies the bytes into a buffer managed by Go. That way we can use it safely at any time in the future.
This commit is contained in:
parent
807e8f25e3
commit
d74392c365
|
@ -38,15 +38,13 @@ int mosquitto_auth_plugin_init(void **user_data, struct mosquitto_auth_opt *auth
|
|||
|
||||
GoInt32 opts_count = auth_opt_count;
|
||||
|
||||
GoString keys[auth_opt_count];
|
||||
GoString values[auth_opt_count];
|
||||
char *keys[auth_opt_count];
|
||||
char *values[auth_opt_count];
|
||||
int i;
|
||||
struct mosquitto_auth_opt *o;
|
||||
for (i = 0, o = auth_opts; i < auth_opt_count; i++, o++) {
|
||||
GoString opt_key = {o->key, strlen(o->key)};
|
||||
GoString opt_value = {o->value, strlen(o->value)};
|
||||
keys[i] = opt_key;
|
||||
values[i] = opt_value;
|
||||
keys[i] = o->key;
|
||||
values[i] = o->value;
|
||||
}
|
||||
|
||||
GoSlice keysSlice = {keys, auth_opt_count, auth_opt_count};
|
||||
|
@ -55,9 +53,8 @@ int mosquitto_auth_plugin_init(void **user_data, struct mosquitto_auth_opt *auth
|
|||
char versionArray[10];
|
||||
sprintf(versionArray, "%i.%i.%i", LIBMOSQUITTO_MAJOR, LIBMOSQUITTO_MINOR, LIBMOSQUITTO_REVISION);
|
||||
|
||||
GoString version = {versionArray, strlen(versionArray)};
|
||||
|
||||
AuthPluginInit(keysSlice, valuesSlice, opts_count, version);
|
||||
AuthPluginInit(keysSlice, valuesSlice, opts_count, versionArray);
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -93,11 +90,7 @@ int mosquitto_auth_unpwd_check(void *userdata, const char *username, const char
|
|||
return MOSQ_ERR_AUTH;
|
||||
}
|
||||
|
||||
GoString go_username = {username, strlen(username)};
|
||||
GoString go_password = {password, strlen(password)};
|
||||
GoString go_clientid = {clientid, strlen(clientid)};
|
||||
|
||||
GoUint8 ret = AuthUnpwdCheck(go_username, go_password, go_clientid);
|
||||
GoUint8 ret = AuthUnpwdCheck((char *)username, (char *)password, (char *)clientid);
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
|
@ -135,12 +128,7 @@ int mosquitto_auth_acl_check(void *userdata, const char *clientid, const char *u
|
|||
return MOSQ_ERR_ACL_DENIED;
|
||||
}
|
||||
|
||||
GoString go_clientid = {clientid, strlen(clientid)};
|
||||
GoString go_username = {username, strlen(username)};
|
||||
GoString go_topic = {topic, strlen(topic)};
|
||||
GoInt32 go_access = access;
|
||||
|
||||
GoUint8 ret = AuthAclCheck(go_clientid, go_username, go_topic, go_access);
|
||||
GoUint8 ret = AuthAclCheck((char *)clientid, (char *)username, (char *)topic, access);
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
|
|
14
go-auth.go
14
go-auth.go
|
@ -38,7 +38,7 @@ var authOpts map[string]string //Options passed by mosquitto.
|
|||
var authPlugin AuthPlugin //General struct with options and conf.
|
||||
|
||||
//export AuthPluginInit
|
||||
func AuthPluginInit(keys []string, values []string, authOptsNum int, version string) {
|
||||
func AuthPluginInit(keys []*C.char, values []*C.char, authOptsNum int, version *C.char) {
|
||||
log.SetFormatter(&log.TextFormatter{
|
||||
FullTimestamp: true,
|
||||
})
|
||||
|
@ -51,7 +51,7 @@ func AuthPluginInit(keys []string, values []string, authOptsNum int, version str
|
|||
|
||||
authOpts = make(map[string]string)
|
||||
for i := 0; i < authOptsNum; i++ {
|
||||
authOpts[keys[i]] = values[i]
|
||||
authOpts[C.GoString(keys[i])] = C.GoString(values[i])
|
||||
}
|
||||
|
||||
if retryCount, ok := authOpts["retry_count"]; ok {
|
||||
|
@ -104,7 +104,7 @@ func AuthPluginInit(keys []string, values []string, authOptsNum int, version str
|
|||
|
||||
var err error
|
||||
|
||||
authPlugin.backends, err = bes.Initialize(authOpts, authPlugin.logLevel, version)
|
||||
authPlugin.backends, err = bes.Initialize(authOpts, authPlugin.logLevel, C.GoString(version))
|
||||
if err != nil {
|
||||
log.Fatalf("error initializing backends: %s", err)
|
||||
}
|
||||
|
@ -276,12 +276,12 @@ func setCache(authOpts map[string]string) {
|
|||
}
|
||||
|
||||
//export AuthUnpwdCheck
|
||||
func AuthUnpwdCheck(username, password, clientid string) uint8 {
|
||||
func AuthUnpwdCheck(username, password, clientid *C.char) uint8 {
|
||||
var ok bool
|
||||
var err error
|
||||
|
||||
for try := 0; try <= authPlugin.retryCount; try++ {
|
||||
ok, err = authUnpwdCheck(username, password, clientid)
|
||||
ok, err = authUnpwdCheck(C.GoString(username), C.GoString(password), C.GoString(clientid))
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
|
@ -330,12 +330,12 @@ func authUnpwdCheck(username, password, clientid string) (bool, error) {
|
|||
}
|
||||
|
||||
//export AuthAclCheck
|
||||
func AuthAclCheck(clientid, username, topic string, acc int) uint8 {
|
||||
func AuthAclCheck(clientid, username, topic *C.char, acc C.int) uint8 {
|
||||
var ok bool
|
||||
var err error
|
||||
|
||||
for try := 0; try <= authPlugin.retryCount; try++ {
|
||||
ok, err = authAclCheck(clientid, username, topic, acc)
|
||||
ok, err = authAclCheck(C.GoString(clientid), C.GoString(username), C.GoString(topic), int(acc))
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue