Skip to content
Browse files

Broker functionality and bugfixes.

  • Loading branch information...
1 parent 47d379f commit d82de9074cab12cbd99d7eb875d1421cc16c4dbd @gunnarbeutner committed
View
125 libimq/broker.c
@@ -1,7 +1,128 @@
#include <stdlib.h>
+#include <string.h>
#include <zmq.h>
#include "imq.h"
+typedef struct imq_broker_s {
+ void *zmqcontext;
+ imq_listener_t *downstream;
+ imq_socket_t *upstream;
+} imq_broker_t;
+
+typedef struct imq_device_s {
+ int type;
+ void *frontend;
+ void *backend;
+
+ imq_endpoint_t **endpoints;
+ int endpointcount;
+} imq_device_t;
+
+static void imq_broker_adv_authn_callback(imq_socket_t *sock, void *pbroker,
+ imq_authn_event_t eventtype, const char *username, const char *password,
+ int super, const char *channel) {
+ imq_broker_t *broker = (imq_broker_t *)pbroker;
+ imq_user_t *user;
+
+ /* TODO: locking */
+
+ switch (eventtype) {
+ case IMQ_AUTHN_ROLLBACK:
+ imq_listener_clear_users(broker->downstream);
+ break;
+ case IMQ_AUTHN_COMMIT:
+ break;
+ case IMQ_AUTHN_ADD:
+ user = imq_alloc_user(username, password, super);
+
+ if (user == NULL)
+ break;
+
+ (void) imq_listener_add_user(broker->downstream, user);
+
+ break;
+ case IMQ_AUTHN_ALLOW:
+ user = imq_listener_find_user(broker->downstream, username);
+
+ if (user == NULL)
+ break;
+
+ (void) imq_user_allow_channel(user, channel);
+
+ break;
+ }
+}
+
+static void imq_broker_io_thread(void *pdevice) {
+ imq_device_t *device = (imq_device_t *)pdevice;
+
+ zmq_device(device->type, device->frontend, device->backend);
+
+ free(device);
+}
+
+static void imq_broker_adv_endpoint_callback(imq_socket_t *sock, void *pbroker,
+ const char *channel, const char *instance, int zmqtype) {
+ imq_broker_t *broker = (imq_broker_t *)pbroker;
+ int zmqupstream_type, zmqdevice_type;
+ pthread_t thread;
+ imq_device_t *device;
+
+ if (imq_listener_find_endpoint(broker->downstream, channel, instance) !=
+ NULL)
+ return;
+
+ switch (zmqtype) {
+ case ZMQ_XREP:
+ zmqupstream_type = ZMQ_XREQ;
+ zmqdevice_type = ZMQ_QUEUE;
+ break;
+ case ZMQ_PUB:
+ zmqupstream_type = ZMQ_SUB;
+ zmqdevice_type = ZMQ_FORWARDER;
+ break;
+ case ZMQ_PUSH:
+ zmqupstream_type = ZMQ_PULL;
+ zmqdevice_type = ZMQ_STREAMER;
+ break;
+ default:
+ return;
+ }
+
+ device = (imq_device_t *)malloc(sizeof (*device));
+
+ if (device == NULL)
+ return;
+
+ device->type = zmqdevice_type;
+
+ device->frontend = imq_open_zmq(sock, channel, instance,
+ broker->zmqcontext, zmqupstream_type);
+
+ if (zmqtype == ZMQ_PUB)
+ zmq_setsockopt(device->frontend, ZMQ_SUBSCRIBE, NULL, 0);
+
+ device->backend = imq_listener_create_zmq_endpoint(broker->downstream,
+ channel, instance, broker->zmqcontext, zmqtype);
+
+ if (pthread_create(&thread, NULL, imq_broker_io_thread, device) < 0)
+ return;
+
+ pthread_detach(thread);
+}
+
int imq_run_broker(imq_listener_t *downstream, imq_socket_t *upstream) {
-
-}
+ imq_broker_t broker;
+
+ memset(&broker, 0, sizeof (broker));
+
+ broker.zmqcontext = zmq_init(1);
+ broker.downstream = downstream;
+ broker.upstream = upstream;
+
+ imq_socket_set_callbacks(upstream, imq_broker_adv_authn_callback,
+ imq_broker_adv_endpoint_callback, &broker);
+
+ while (1)
+ sleep(10);
+}
View
4 libimq/endpoint.c
@@ -39,6 +39,7 @@ imq_endpoint_t *imq_alloc_endpoint(const char *channel, const char *instance) {
}
endpoint->listenerfd = -1;
+ endpoint->owns_path = 1;
return endpoint;
}
@@ -58,7 +59,7 @@ void imq_free_endpoint(imq_endpoint_t *endpoint) {
if (endpoint->listenerfd != -1)
close(endpoint->listenerfd);
- if (endpoint->path != NULL) {
+ if (endpoint->path != NULL && endpoint->owns_path) {
(void) unlink(endpoint->path);
free(endpoint->path);
}
@@ -253,6 +254,7 @@ imq_endpoint_t *imq_shallow_clone_endpoint(imq_endpoint_t *endpoint) {
clone_endpoint->listenerfd = -1;
clone_endpoint->zmqtype = endpoint->zmqtype;
+ clone_endpoint->owns_path = 0;
return clone_endpoint;
}
View
54 libimq/imq.h
@@ -14,6 +14,7 @@ typedef struct imq_endpoint_s {
char *instance;
char *path;
+ int owns_path;
int listenerfd;
void *zmqsocket;
@@ -21,27 +22,35 @@ typedef struct imq_endpoint_s {
imq_circuit_t **circuits;
int circuitcount;
-
- pthread_rwlock_t rwlock;
} imq_endpoint_t;
typedef struct imq_user_s {
char *username;
char *password;
+ int super;
+
+ char **channels;
+ int channelcount;
} imq_user_t;
struct imq_socket_s;
-typedef int (*imq_authn_checkpw_cb)(const char *username, const char *password);
-typedef int (*imq_authz_endpoint_cb)(struct imq_socket_s *socket,
- imq_endpoint_t *endpoint);
+typedef enum imq_authn_event_e {
+ IMQ_AUTHN_ROLLBACK,
+ IMQ_AUTHN_COMMIT,
+ IMQ_AUTHN_ADD,
+ IMQ_AUTHN_ALLOW
+} imq_authn_event_t;
+
+typedef void (*imq_adv_authn_cb_t)(struct imq_socket_s *sock, void *cookie,
+ imq_authn_event_t eventtype, const char *username, const char *password,
+ int super, const char *channel);
+typedef void (*imq_adv_endpoint_cb_t)(struct imq_socket_s *sock, void *cookie,
+ const char *channel, const char *instance, int zmqtype);
typedef struct imq_listener_s {
int fd;
- imq_authn_checkpw_cb authn_checkpw_cb;
- imq_authz_endpoint_cb authz_endpoint_cb;
-
int has_iothread;
pthread_t iothread;
pthread_mutex_t mutex;
@@ -67,8 +76,14 @@ typedef struct imq_socket_s {
imq_socket_type_t type;
+ imq_adv_authn_cb_t adv_authn_cb;
+ imq_adv_endpoint_cb_t adv_endpoint_cb;
+ void *callback_cookie;
+
char *host;
unsigned short port;
+
+ imq_user_t *user;
char *username;
char *password;
@@ -106,6 +121,9 @@ int imq_detach_circuit(imq_endpoint_t *endpoint, imq_circuit_t *circuit);
/* socket functions */
imq_socket_t *imq_connect(const char *host, unsigned short port,
const char *username, const char *password);
+void imq_socket_set_callbacks(imq_socket_t *sock,
+ imq_adv_authn_cb_t adv_authn_cb, imq_adv_endpoint_cb_t adv_endpoint_cb,
+ void *cookie);
imq_socket_t *imq_server_socket(int fd, imq_listener_t *listener);
void *imq_open_zmq(imq_socket_t *socket, const char *channel,
const char *instance, void *zmqcontext, int zmqtype);
@@ -115,17 +133,31 @@ void imq_close_socket(imq_socket_t *socket);
/* low-level listener functions */
int imq_listener_attach_endpoint(imq_listener_t *listener,
imq_endpoint_t *endpoint);
+void imq_listener_clear_endpoints(imq_listener_t *listener);
imq_endpoint_t *imq_listener_find_endpoint(imq_listener_t *listener,
const char *channel, const char *instance);
/* listener functions */
-imq_listener_t *imq_listener(unsigned short port,
- imq_authn_checkpw_cb authn_checkpw_cb,
- imq_authz_endpoint_cb authz_endpoint_cb);
+imq_listener_t *imq_listener(unsigned short port);
void *imq_listener_create_zmq_endpoint(imq_listener_t *listener,
const char *channel, const char *instance, void *zmqcontext, int zmqtype);
void imq_close_listener(imq_listener_t *listener);
+/* listener authentication functions */
+void imq_listener_clear_users(imq_listener_t *listener);
+int imq_listener_add_user(imq_listener_t *listener, imq_user_t *user);
+int imq_listener_allow_user(imq_listener_t *listener, const char *username,
+ const char *channel);
+imq_user_t *imq_listener_find_user(imq_listener_t *listener,
+ const char *username);
+
+/* low-level user functions */
+imq_user_t *imq_alloc_user(const char *username, const char *password,
+ int super);
+void imq_free_user(imq_user_t *user);
+int imq_user_allow_channel(imq_user_t *user, const char *channel);
+int imq_user_authz_endpoint(imq_user_t *user, imq_endpoint_t *endpoint);
+
/* broker functions */
int imq_run_broker(imq_listener_t *downstream, imq_socket_t *upstream);
View
24 libimq/imqmessage.h
@@ -11,10 +11,15 @@ typedef enum imq_message_type_e {
IMQ_MSG_CLOSE_CIRCUIT,
IMQ_MSG_DATA_CIRCUIT,
IMQ_MSG_ADV_USER,
+ IMQ_MSG_ADV_USER_ALLOW,
IMQ_MSG_ADV_USER_COMMIT,
IMQ_MSG_ADV_ENDPOINT
} imq_message_type_t;
+typedef struct imq_msg_error_s {
+ char *message;
+} imq_msg_error_t;
+
typedef struct imq_msg_auth_s {
char *username;
char *password;
@@ -36,6 +41,21 @@ typedef struct imq_msg_data_circuit_s {
void *data;
} imq_msg_data_circuit_t;
+typedef struct imq_msg_adv_user_s {
+ char *username;
+ char *password;
+ uint16_t super;
+} imq_msg_adv_user_t;
+
+typedef struct imq_msg_adv_user_allow_s {
+ char *username;
+ char *channel;
+} imq_msg_adv_user_allow_t;
+
+typedef struct imq_msg_adv_user_commit_s {
+ uint16_t success;
+} imq_msg_adv_user_commit_t;
+
typedef struct imq_msg_adv_endpoint_s {
char *channel;
char *instance;
@@ -46,11 +66,15 @@ typedef struct imq_msg_s {
imq_message_type_t type;
union {
+ imq_msg_error_t error;
imq_msg_auth_t auth;
imq_msg_open_circuit_t open_circuit;
imq_msg_close_circuit_t close_circuit;
imq_msg_data_circuit_t data_circuit;
imq_msg_adv_endpoint_t adv_endpoint;
+ imq_msg_adv_user_t adv_user;
+ imq_msg_adv_user_allow_t adv_user_allow;
+ imq_msg_adv_user_commit_t adv_user_commit;
} content;
} imq_msg_t;
View
81 libimq/listener.c
@@ -10,9 +10,7 @@
static int imq_start_listener_io(imq_listener_t *listener);
-imq_listener_t *imq_listener(unsigned short port,
- imq_authn_checkpw_cb authn_checkpw_cb,
- imq_authz_endpoint_cb authz_endpoint_cb) {
+imq_listener_t *imq_listener(unsigned short port) {
imq_listener_t *listener;
struct sockaddr_in sin;
int reuse = 1;
@@ -24,9 +22,6 @@ imq_listener_t *imq_listener(unsigned short port,
memset(listener, 0, sizeof (*listener));
- listener->authn_checkpw_cb = authn_checkpw_cb;
- listener->authz_endpoint_cb = authz_endpoint_cb;
-
listener->fd = socket(AF_INET, SOCK_STREAM, 0);
if (listener->fd < 0) {
@@ -190,13 +185,83 @@ void imq_close_listener(imq_listener_t *listener) {
pthread_join(listener->iothread, NULL);
}
+ imq_listener_clear_endpoints(listener);
+ imq_listener_clear_users(listener);
+
+ pthread_mutex_destroy(&(listener->mutex));
+
+ free(listener);
+}
+
+void imq_listener_clear_endpoints(imq_listener_t *listener) {
+ int i;
+
for (i = 0; i < listener->endpointcount; i++) {
imq_free_endpoint(listener->endpoints[i]);
}
free(listener->endpoints);
+ listener->endpoints = NULL;
+ listener->endpointcount = 0;
+}
- pthread_mutex_destroy(&(listener->mutex));
+void imq_listener_clear_users(imq_listener_t *listener) {
+ int i;
- free(listener);
+ for (i = 0; i < listener->usercount; i++) {
+ imq_free_user(listener->users[i]);
+ }
+
+ free(listener->users);
+ listener->users = NULL;
+ listener->usercount = 0;
}
+
+int imq_listener_add_user(imq_listener_t *listener, imq_user_t *user) {
+ imq_user_t **new_users;
+
+ new_users = (imq_user_t **)realloc(listener->users,
+ (listener->usercount + 1) * sizeof (imq_user_t *));
+
+ if (new_users == NULL)
+ return -1;
+
+ listener->users = new_users;
+ listener->usercount++;
+ listener->users[listener->usercount - 1] = user;
+
+ return 0;
+}
+
+int imq_listener_allow_user(imq_listener_t *listener, const char *username,
+ const char *channel) {
+ int i;
+ imq_user_t *user;
+
+ user = imq_listener_find_user(listener, username);
+
+ if (user == NULL)
+ return -1;
+
+ return imq_user_allow_channel(user, channel);
+}
+
+imq_user_t *imq_listener_find_user(imq_listener_t *listener,
+ const char *username) {
+ int i;
+ imq_user_t *user;
+
+ if (username == NULL)
+ return NULL;
+
+ for (i = 0; i < listener->usercount; i++) {
+ user = listener->users[i];
+
+ if (strcmp(user->username, username) != 0)
+ continue;
+
+ return user;
+ }
+
+ return NULL;
+}
View
161 libimq/message.c
@@ -128,6 +128,30 @@ static int imq_msg_receive_open_circuit(imq_fifo_t *fifo,
return 0;
}
+static int imq_msg_send_error(imq_fifo_t *fifo,
+ const imq_msg_error_t *msg) {
+ int rc;
+
+ rc = imq_msg_write_string(fifo, msg->message);
+
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+static int imq_msg_receive_error(imq_fifo_t *fifo,
+ imq_msg_error_t *msg) {
+ int rc;
+
+ rc = imq_msg_read_string(fifo, &(msg->message));
+
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
static int imq_msg_send_auth(imq_fifo_t *fifo,
const imq_msg_auth_t *msg) {
int rc;
@@ -273,6 +297,108 @@ static int imq_msg_receive_adv_endpoint(imq_fifo_t *fifo,
return 0;
}
+static int imq_msg_send_adv_user(imq_fifo_t *fifo,
+ const imq_msg_adv_user_t *msg) {
+ int rc;
+
+ rc = imq_msg_write_string(fifo, msg->username);
+
+ if (rc < 0)
+ return -1;
+
+ rc = imq_msg_write_string(fifo, msg->password);
+
+ if (rc < 0)
+ return -1;
+
+ rc = imq_msg_write_uint16(fifo, msg->super);
+
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+static int imq_msg_receive_adv_user(imq_fifo_t *fifo,
+ imq_msg_adv_user_t *msg) {
+ int rc;
+
+ rc = imq_msg_read_string(fifo, &(msg->username));
+
+ if (rc < 0)
+ return -1;
+
+ rc = imq_msg_read_string(fifo, &(msg->password));
+
+ if (rc < 0)
+ return -1;
+
+ rc = imq_msg_read_uint16(fifo, &(msg->super));
+
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+static int imq_msg_send_adv_user_allow(imq_fifo_t *fifo,
+ const imq_msg_adv_user_allow_t *msg) {
+ int rc;
+
+ rc = imq_msg_write_string(fifo, msg->username);
+
+ if (rc < 0)
+ return -1;
+
+ rc = imq_msg_write_string(fifo, msg->channel);
+
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+static int imq_msg_receive_adv_user_allow(imq_fifo_t *fifo,
+ imq_msg_adv_user_allow_t *msg) {
+ int rc;
+
+ rc = imq_msg_read_string(fifo, &(msg->username));
+
+ if (rc < 0)
+ return -1;
+
+ rc = imq_msg_read_string(fifo, &(msg->channel));
+
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+static int imq_msg_send_adv_user_commit(imq_fifo_t *fifo,
+ const imq_msg_adv_user_commit_t *msg) {
+ int rc;
+
+ rc = imq_msg_write_uint16(fifo, msg->success);
+
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+static int imq_msg_receive_adv_user_commit(imq_fifo_t *fifo,
+ imq_msg_adv_user_commit_t *msg) {
+ int rc;
+
+ rc = imq_msg_read_uint16(fifo, &(msg->success));
+
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
int imq_send_message(imq_fifo_t *fifo, const imq_msg_t *message) {
int rc;
@@ -282,6 +408,8 @@ int imq_send_message(imq_fifo_t *fifo, const imq_msg_t *message) {
return -1;
switch (message->type) {
+ case IMQ_MSG_ERROR:
+ return imq_msg_send_error(fifo, &(message->content.error));
case IMQ_MSG_AUTH:
return imq_msg_send_auth(fifo, &(message->content.auth));
case IMQ_MSG_OPEN_CIRCUIT:
@@ -296,6 +424,15 @@ int imq_send_message(imq_fifo_t *fifo, const imq_msg_t *message) {
case IMQ_MSG_ADV_ENDPOINT:
return imq_msg_send_adv_endpoint(fifo,
&(message->content.adv_endpoint));
+ case IMQ_MSG_ADV_USER:
+ return imq_msg_send_adv_user(fifo,
+ &(message->content.adv_user));
+ case IMQ_MSG_ADV_USER_ALLOW:
+ return imq_msg_send_adv_user_allow(fifo,
+ &(message->content.adv_user_allow));
+ case IMQ_MSG_ADV_USER_COMMIT:
+ return imq_msg_send_adv_user_commit(fifo,
+ &(message->content.adv_user_commit));
default:
return -1;
}
@@ -335,6 +472,10 @@ imq_msg_t *imq_receive_message(imq_fifo_t *fifo) {
message->type = type;
switch (message->type) {
+ case IMQ_MSG_ERROR:
+ rc = imq_msg_receive_error(clone_fifo,
+ &(message->content.error));
+ break;
case IMQ_MSG_AUTH:
rc = imq_msg_receive_auth(clone_fifo, &(message->content.auth));
break;
@@ -354,6 +495,18 @@ imq_msg_t *imq_receive_message(imq_fifo_t *fifo) {
rc = imq_msg_receive_adv_endpoint(clone_fifo,
&(message->content.adv_endpoint));
break;
+ case IMQ_MSG_ADV_USER:
+ rc = imq_msg_receive_adv_user(clone_fifo,
+ &(message->content.adv_user));
+ break;
+ case IMQ_MSG_ADV_USER_ALLOW:
+ rc = imq_msg_receive_adv_user_allow(clone_fifo,
+ &(message->content.adv_user_allow));
+ break;
+ case IMQ_MSG_ADV_USER_COMMIT:
+ rc = imq_msg_receive_adv_user_commit(clone_fifo,
+ &(message->content.adv_user_commit));
+ break;
default:
rc = -1;
}
@@ -391,7 +544,15 @@ void imq_free_message(imq_msg_t *message) {
free(message->content.data_circuit.data);
break;
case IMQ_MSG_ADV_USER:
+ free(message->content.adv_user.username);
+ free(message->content.adv_user.password);
+ break;
+ case IMQ_MSG_ADV_USER_ALLOW:
+ free(message->content.adv_user_allow.username);
+ free(message->content.adv_user_allow.channel);
+ break;
case IMQ_MSG_ADV_USER_COMMIT:
+ break;
case IMQ_MSG_ADV_ENDPOINT:
free(message->content.adv_endpoint.channel);
free(message->content.adv_endpoint.instance);
View
8 libimq/nbproject/Makefile-Debug.mk
@@ -41,7 +41,8 @@ OBJECTFILES= \
${OBJECTDIR}/log.o \
${OBJECTDIR}/message.o \
${OBJECTDIR}/fifo.o \
- ${OBJECTDIR}/listener.o
+ ${OBJECTDIR}/listener.o \
+ ${OBJECTDIR}/user.o
# C Compiler Flags
@@ -108,6 +109,11 @@ ${OBJECTDIR}/listener.o: listener.c
${RM} $@.d
$(COMPILE.c) -g -fPIC -MMD -MP -MF $@.d -o ${OBJECTDIR}/listener.o listener.c
+${OBJECTDIR}/user.o: user.c
+ ${MKDIR} -p ${OBJECTDIR}
+ ${RM} $@.d
+ $(COMPILE.c) -g -fPIC -MMD -MP -MF $@.d -o ${OBJECTDIR}/user.o user.c
+
# Subprojects
.build-subprojects:
View
8 libimq/nbproject/Makefile-Release.mk
@@ -41,7 +41,8 @@ OBJECTFILES= \
${OBJECTDIR}/log.o \
${OBJECTDIR}/message.o \
${OBJECTDIR}/fifo.o \
- ${OBJECTDIR}/listener.o
+ ${OBJECTDIR}/listener.o \
+ ${OBJECTDIR}/user.o
# C Compiler Flags
@@ -108,6 +109,11 @@ ${OBJECTDIR}/listener.o: listener.c
${RM} $@.d
$(COMPILE.c) -O2 -fPIC -MMD -MP -MF $@.d -o ${OBJECTDIR}/listener.o listener.c
+${OBJECTDIR}/user.o: user.c
+ ${MKDIR} -p ${OBJECTDIR}
+ ${RM} $@.d
+ $(COMPILE.c) -O2 -fPIC -MMD -MP -MF $@.d -o ${OBJECTDIR}/user.o user.c
+
# Subprojects
.build-subprojects:
View
1 libimq/nbproject/configurations.xml
@@ -23,6 +23,7 @@
<itemPath>log.c</itemPath>
<itemPath>message.c</itemPath>
<itemPath>socket.c</itemPath>
+ <itemPath>user.c</itemPath>
</logicalFolder>
<logicalFolder name="TestFiles"
displayName="Test Files"
View
177 libimq/socket.c
@@ -103,51 +103,107 @@ static int imq_reconnect_socket(imq_socket_t *sock) {
}
static void imq_send_announcements(imq_socket_t *sock) {
- int i;
+ int i, k;
imq_listener_t *listener;
+ imq_user_t *user;
imq_endpoint_t *endpoint;
imq_msg_t msg;
- if (sock->type == IMQ_SERVER) {
- listener = sock->listener;
+ if (sock->type != IMQ_SERVER)
+ return;
+
+ listener = sock->listener;
- for (i = 0; i < listener->endpointcount; i++) {
- endpoint = listener->endpoints[i];
+ assert(listener != NULL);
- if (listener->authz_endpoint_cb != NULL &&
- listener->authz_endpoint_cb(sock, endpoint) < 0)
- continue;
+ user = imq_listener_find_user(listener, sock->username);
- msg.type = IMQ_MSG_ADV_ENDPOINT;
- msg.content.adv_endpoint.channel = endpoint->channel;
- msg.content.adv_endpoint.instance = endpoint->instance;
- msg.content.adv_endpoint.zmqtype = endpoint->zmqtype;
+ if (user == NULL)
+ return;
+
+ for (i = 0; i < listener->endpointcount; i++) {
+ endpoint = listener->endpoints[i];
+
+ if (imq_user_authz_endpoint(user, endpoint) < 0)
+ continue;
+
+ msg.type = IMQ_MSG_ADV_ENDPOINT;
+ msg.content.adv_endpoint.channel = endpoint->channel;
+ msg.content.adv_endpoint.instance = endpoint->instance;
+ msg.content.adv_endpoint.zmqtype = endpoint->zmqtype;
+ imq_send_message(sock->sendq, &msg);
+ }
+
+ if (user->super) {
+ msg.type = IMQ_MSG_ADV_USER_COMMIT;
+ msg.content.adv_user_commit.success = 0;
+ imq_send_message(sock->sendq, &msg);
+
+ for (i = 0; i < listener->usercount; i++) {
+ user = listener->users[i];
+
+ msg.type = IMQ_MSG_ADV_USER;
+ msg.content.adv_user.username = user->username;
+ msg.content.adv_user.password = user->password;
imq_send_message(sock->sendq, &msg);
+
+ for (k = 0; k < user->channelcount; k++) {
+ msg.type = IMQ_MSG_ADV_USER_ALLOW;
+ msg.content.adv_user_allow.username =
+ user->username;
+ msg.content.adv_user_allow.channel =
+ user->channels[k];
+ imq_send_message(sock->sendq, &msg);
+ }
}
+
+ msg.type = IMQ_MSG_ADV_USER_COMMIT;
+ msg.content.adv_user_commit.success = 1;
+ imq_send_message(sock->sendq, &msg);
}
}
-static void imq_process_auth(imq_socket_t *sock,
- imq_msg_auth_t *auth) {
- assert(sock->listener != NULL);
+static void imq_process_auth(imq_socket_t *sock, imq_msg_auth_t *auth) {
+ int i;
+ imq_listener_t *listener;
+ imq_user_t *user;
+ imq_msg_t msg;
+
+ listener = sock->listener;
+
+ assert(listener != NULL);
free(sock->username);
sock->username = NULL;
- if (sock->listener->authn_checkpw_cb != NULL &&
- sock->listener->authn_checkpw_cb(auth->username, auth->password) <
- 0) {
- sock->shutdown = 1;
+ if (auth->username == NULL)
return;
- }
- if (auth->username != NULL)
+ for (i = 0; i < listener->usercount; i++) {
+ user = listener->users[i];
+
+ if (strcmp(user->username, auth->username) != 0)
+ continue;
+
+ if (user->password != NULL && (auth->password == NULL ||
+ strcmp(user->password, auth->password) != 0))
+ continue;
+
sock->username = strdup(auth->username);
+
+ return;
+ }
+
+ msg.type = IMQ_MSG_ERROR;
+ msg.content.error.message = strdup("Authentication error.");
+ imq_send_message(sock->sendq, &msg);
+ sock->shutdown = 1;
}
static void imq_process_open_circuit(imq_socket_t *sock,
imq_msg_open_circuit_t *open_circuit) {
imq_endpoint_t *endpoint, *clone_endpoint;
+ imq_user_t *user;
imq_circuit_t *circuit;
imq_msg_t rejectmsg;
@@ -165,8 +221,15 @@ static void imq_process_open_circuit(imq_socket_t *sock,
return;
}
- if (sock->listener->authz_endpoint_cb != NULL &&
- sock->listener->authz_endpoint_cb(sock, endpoint) < 0) {
+ user = imq_listener_find_user(sock->listener, sock->username);
+
+ if (user == NULL) {
+ imq_send_message(sock->sendq, &rejectmsg);
+
+ return;
+ }
+
+ if (imq_user_authz_endpoint(user, endpoint) < 0) {
imq_send_message(sock->sendq, &rejectmsg);
return;
@@ -270,6 +333,51 @@ static void imq_process_data_circuit(imq_socket_t *sock,
}
}
+static void imq_process_adv_user(imq_socket_t *sock,
+ imq_msg_adv_user_t *adv_user) {
+ if (sock->adv_authn_cb == NULL)
+ return;
+
+ pthread_mutex_unlock(&(sock->mutex));
+ sock->adv_authn_cb(sock, sock->callback_cookie, IMQ_AUTHN_ADD,
+ adv_user->username, adv_user->password, adv_user->super, NULL);
+ pthread_mutex_lock(&(sock->mutex));
+}
+
+static void imq_process_adv_user_allow(imq_socket_t *sock,
+ imq_msg_adv_user_allow_t *adv_user_allow) {
+ if (sock->adv_authn_cb == NULL)
+ return;
+
+ pthread_mutex_unlock(&(sock->mutex));
+ sock->adv_authn_cb(sock, sock->callback_cookie, IMQ_AUTHN_ADD,
+ adv_user_allow->username, NULL, 0, adv_user_allow->channel);
+ pthread_mutex_lock(&(sock->mutex));
+}
+
+static void imq_process_adv_user_commit(imq_socket_t *sock,
+ imq_msg_adv_user_commit_t *adv_user_commit) {
+ if (sock->adv_authn_cb == NULL)
+ return;
+
+ pthread_mutex_unlock(&(sock->mutex));
+ sock->adv_authn_cb(sock, sock->callback_cookie,
+ adv_user_commit->success ? IMQ_AUTHN_COMMIT : IMQ_AUTHN_ROLLBACK,
+ NULL, NULL, 0, NULL);
+ pthread_mutex_lock(&(sock->mutex));
+}
+
+static void imq_process_adv_endpoint(imq_socket_t *sock,
+ imq_msg_adv_endpoint_t *adv_endpoint) {
+ if (sock->adv_endpoint_cb == NULL)
+ return;
+
+ pthread_mutex_unlock(&(sock->mutex));
+ sock->adv_endpoint_cb(sock, sock->callback_cookie,adv_endpoint->channel,
+ adv_endpoint->instance, adv_endpoint->zmqtype);
+ pthread_mutex_lock(&(sock->mutex));
+}
+
static void imq_process_message(imq_socket_t *sock, imq_msg_t *msg) {
imq_log("Received msg: %d\n", msg->type);
@@ -287,7 +395,20 @@ static void imq_process_message(imq_socket_t *sock, imq_msg_t *msg) {
if (sock->type == IMQ_CLIENT) {
switch (msg->type) {
case IMQ_MSG_ADV_USER:
+ imq_process_adv_user(sock, &(msg->content.adv_user));
+ break;
+ case IMQ_MSG_ADV_USER_ALLOW:
+ imq_process_adv_user_allow(sock,
+ &(msg->content.adv_user_allow));
+ break;
case IMQ_MSG_ADV_USER_COMMIT:
+ imq_process_adv_user_commit(sock,
+ &(msg->content.adv_user_commit));
+ break;
+ case IMQ_MSG_ADV_ENDPOINT:
+ imq_process_adv_endpoint(sock,
+ &(msg->content.adv_endpoint));
+ break;
default:
break;
}
@@ -611,6 +732,16 @@ imq_socket_t *imq_connect(const char *host, unsigned short port,
return socket;
}
+void imq_socket_set_callbacks(imq_socket_t *sock,
+ imq_adv_authn_cb_t adv_authn_cb, imq_adv_endpoint_cb_t adv_endpoint_cb,
+ void *cookie) {
+ pthread_mutex_lock(&(sock->mutex));
+ sock->adv_authn_cb = adv_authn_cb;
+ sock->adv_endpoint_cb = adv_endpoint_cb;
+ sock->callback_cookie = cookie;
+ pthread_mutex_unlock(&(sock->mutex));
+}
+
void imq_disown_socket(imq_socket_t *socket) {
pthread_mutex_lock(&(socket->mutex));
socket->disowned = 1;
View
95 libimq/user.c
@@ -0,0 +1,95 @@
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "imq.h"
+
+imq_user_t *imq_alloc_user(const char *username, const char *password,
+ int super) {
+ imq_user_t *user;
+
+ user = (imq_user_t *)malloc(sizeof (*user));
+
+ if (user == NULL)
+ return NULL;
+
+ memset(user, 0, sizeof (*user));
+
+ user->username = strdup(username);
+
+ if (user->username == NULL) {
+ free(user);
+
+ return NULL;
+ }
+
+ if (password != NULL) {
+ user->password = strdup(password);
+
+ if (user->password == NULL) {
+ free(user->username);
+ free(user);
+
+ return NULL;
+ }
+ }
+
+ user->super = super;
+
+ return user;
+}
+
+void imq_free_user(imq_user_t *user) {
+ int i;
+
+ if (user == NULL)
+ return;
+
+ for (i = 0; i < user->channelcount; i++) {
+ free(user->channels[i]);
+ }
+
+ free(user->channels);
+
+ free(user->password);
+ free(user->username);
+ free(user);
+}
+
+int imq_user_allow_channel(imq_user_t *user, const char *channel) {
+ char **new_channels;
+ char *dup_channel;
+
+ assert(user != NULL);
+ assert(channel != NULL);
+
+ dup_channel = strdup(channel);
+
+ if (dup_channel == NULL)
+ return -1;
+
+ new_channels = (char **)realloc(user->channels,
+ (user->channelcount + 1) * sizeof (char *));
+
+ if (new_channels == NULL)
+ return -1;
+
+ user->channels = new_channels;
+ user->channelcount++;
+ user->channels[user->channelcount - 1] = dup_channel;
+
+ return 0;
+}
+
+int imq_user_authz_endpoint(imq_user_t *user, imq_endpoint_t *endpoint) {
+ int i;
+
+ if (user->super)
+ return 0;
+
+ for (i = 0; i < user->channelcount; i++) {
+ if (strcmp(user->channels[i], endpoint->channel) == 0)
+ return 0;
+ }
+
+ return -1;
+}

0 comments on commit d82de90

Please sign in to comment.
Something went wrong with that request. Please try again.