Open fssrepository opened 9 months ago
I think you are supposed to just use mosquitto.h
, mosquitto_plugin.h
and perhaps the mosquitto_broker.h
.
It contains both definitions of callbacks and module functions to get what you are looking for, eg: mosquitto_client_username
to get the username or mosquitto_client_id
to get the client id. No need to dig around in the internal structures of mosquitto.
There are a variety of plugins out there that does auth different ways, like mosquitto-go-plugin, that does seem to have some kind of jwt validation or this url method you wanted.
What restrictions are you referring to with using cgo?
And what exactly is the unexpected behavior of mosquitto_pub -u
?
I have included three of them, but it was not enough. Cgo has lots of nasty restrictions, it's more like a wrapper around go to call back and forth between c and go. it's simply a hackaround. When you integrate you don't want to manage hundreds of components written in different languages. I made my plugin in mosquito, bypassing the hurdles. my project based on spring-boot, which has the jwt validation for Firebase. Most of the implementation in github becomes obsolete, and the Firebase one is not a simple jwt check, a whole infrastructure beneath the surface.
What was it that you needed, that you couldn't find in those 3 headers?
FFI will always be a great deal of boilerplate and naturally be either plugins or c library wrappers, if that's what you mean. Having written a few, personally I find CGO not that particularly hard to work with compared to many other languages.
Obviously, if you exhausted your options with open source plugins, you'll have to get your hands dirty.
Getting the username in the acl_check event shouldn't be more than
int evt_acl_callback(int event, void *event_data, void *user_data) {
struct mosquitto_evt_acl_check *evt = event_data;
const char* username = mosquitto_client_username(evt->client);
...
}
Username is probably supplied in the event data for the evt_basic_auth due to the fact that you are most likely going to want to use it, checking the username / password afterall.
int evt_basic_auth_callback(int event, void *event_data, void *user_data) {
struct mosquitto_evt_basic_auth *evt = event_data;
const char* username = evt->username;
...
}
mosquitto_client_username(client)
to get the username in the events that has the client field suppliedstruct mosquitto_evt_basic_auth *ed = event_data;
on acl check unless you registered the same callback with the acl_check event id (in which case you need to have a switch on it). Otherwise there is a high risk for crashing.userdata is simply a transparent user-defined (rather author-defined) passed through all the callbacks
int evt_basic_auth_callback(int event, void *event_data, void *user_data) {
struct mosquitto_evt_basic_auth *evt = event_data;
const char* username = evt->username;
// user_data is "hello world"
...
}
int mosquitto_plugin_init(msoquitto_plugin_id_t *id, ...) {
mosquitto_callback_register(id, MOSQ_EVT_BASIC_AUTH, evt_basic_auth_callback, NULL, "hello world");
...
}
as I understand it, the event_data field in the mosquitto_callback_register
is meant for arguments to the registration.
eg. the evt_control event takes a topic to trigger on;
int evt_control_test1_callback(int event, void *event_data, void *user_data) {
struct mosquitto_evt_control *evt = event_data;
const void *payoad = evt->payload
// Do something useful with payload
// user_data is "hello world"
...
}
int mosquitto_plugin_init(msoquitto_plugin_id_t *id, ...) {
mosquitto_callback_register(id, MOSQ_EVT_CONTROL, evt_control_test1_callback, "$CONTROL/test1", "hello world");
...
}
Hope things clear up.
v2.0.18
I'm dummy at C programming, but i'm trying to make an external_auth plugin, and when i'm making mosquitto_pub, in gdb variables are not filled in the correct way.
1) I had to use #include "lib/mosquitto_internal.h", as i need the username in acl_check also. the username is stored in the user_data->client->id, not in the user_data->client->username 2) if i'm making struct mosquitto_evt_basic_auth ed = event_data; on acl check, i'm getting the username field also, which is quite strange while it is accepting the struct mosquitto_evt_acl_check ed = event_data; also.
I think somehow there needs to be a cleanup in the header area. I'm not sure whether in real life it's working in this way, as you might establish the connection and subscribe later on. (you can't resemble the real life in this way in the development cycle)
I was able to remote debug to the docker container, just building with musl_libc inside, and move out the executable to my ubuntu and use the visual studio code C++ extension. It's strange that the gdbserver can be even outside of the container.
You have created a dynasec_auth plugin, but in real life, you need to look at a different db for acl_check and for auth maybe using firebase auth which has only go implementation. (cgo is not easy to use with many restriction)
I would advise some sort of plugin with a url config to be implemented inside the mosquitto code. In C it's very hard to do many extra thing, what you can do easily in java/go etc. (next to the mosquitto server, you can have a different one in the docker network what you can call)
In real life, you are using mqtt server next to other server components. Even if JWT token validation is missing, Firebase simply very hard to translate to C to do the job.