Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unexpected mosquitto_pub -u behavior #2946

Open
fssrepository opened this issue Nov 8, 2023 · 3 comments
Open

unexpected mosquitto_pub -u behavior #2946

fssrepository opened this issue Nov 8, 2023 · 3 comments

Comments

@fssrepository
Copy link

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.

@Daedaluz
Copy link
Contributor

Daedaluz commented Nov 8, 2023

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?

@fssrepository
Copy link
Author

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.

@Daedaluz
Copy link
Contributor

Daedaluz commented Dec 6, 2023

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;
  ...
}
  1. use the mosquitto_client_username(client) to get the username in the events that has the client field supplied
  2. You do not get the user name field also if you do struct 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants