From ac07692583601db96dc0a655158e78a1cbbbfcfd Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Thu, 6 Feb 2014 20:12:38 +0100 Subject: [PATCH] frontend: Send connection-related log messages to the client. This is done by registering a logging callback which will send all messages originating from a thread currently handling a connection to the respective client. For this, the connection object is stored in a thread-specific data segment. --- src/frontend/connection.c | 88 ++++++++++++++++++++++++++++++- src/include/frontend/connection.h | 14 +++++ src/include/frontend/proto.h | 4 +- src/tools/sysdbd/main.c | 3 ++ 4 files changed, 107 insertions(+), 2 deletions(-) diff --git a/src/frontend/connection.c b/src/frontend/connection.c index 24735de..4ba12dc 100644 --- a/src/frontend/connection.c +++ b/src/frontend/connection.c @@ -27,6 +27,7 @@ #include "sysdb.h" #include "core/object.h" +#include "core/plugin.h" #include "frontend/connection-private.h" #include "utils/error.h" #include "utils/strbuf.h" @@ -38,10 +39,20 @@ #include #include +#include #include +#include + +/* + * private variables + */ + +static pthread_key_t conn_ctx_key; +static _Bool conn_ctx_key_initialized = 0; + /* - * private data types + * private types */ /* name of connection objects */ @@ -145,10 +156,74 @@ static sdb_type_t connection_type = { /* destroy = */ connection_destroy, }; +/* + * private helper functions + */ + +static void +sdb_conn_ctx_destructor(void *c) +{ + sdb_object_t *conn = c; + + if (! conn) + return; + sdb_object_deref(conn); +} /* sdb_conn_ctx_destructor */ + +static void +sdb_conn_ctx_init(void) +{ + if (conn_ctx_key_initialized) + return; + + pthread_key_create(&conn_ctx_key, sdb_conn_ctx_destructor); + conn_ctx_key_initialized = 1; +} /* sdb_conn_ctx_init */ + +static void +sdb_conn_set_ctx(sdb_conn_t *conn) +{ + sdb_conn_ctx_init(); + if (conn) + sdb_object_ref(SDB_OBJ(conn)); + pthread_setspecific(conn_ctx_key, conn); +} /* sdb_conn_set_ctx */ + +static sdb_conn_t * +sdb_conn_get_ctx(void) +{ + if (! conn_ctx_key_initialized) + return NULL; + return pthread_getspecific(conn_ctx_key); +} /* sdb_conn_get_ctx */ + /* * connection handler functions */ +/* + * connection_log: + * Send a log message originating from the current thread to the client. + */ +static int +connection_log(int __attribute__((unused)) prio, const char *msg, + sdb_object_t __attribute__((unused)) *user_data) +{ + sdb_conn_t *conn; + + conn = sdb_conn_get_ctx(); + /* no connection associated to this thread + * or user not authenticated yet => don't leak any information */ + if ((! conn) || (! conn->username)) + return 0; + + /* TODO: Use CONNECTION_LOG_? */ + if (sdb_connection_send(conn, CONNECTION_LOG, + (uint32_t)strlen(msg), msg) < 0) + return -1; + return 0; +} /* connection_log */ + static uint32_t connection_get_int32(sdb_conn_t *conn, size_t offset) { @@ -303,6 +378,13 @@ connection_read(sdb_conn_t *conn) * public API */ +int +sdb_connection_enable_logging(void) +{ + return sdb_plugin_register_log("connection-logger", connection_log, + /* user_data = */ NULL); +} /* sdb_connection_enable_logging */ + sdb_conn_t * sdb_connection_accept(int fd) { @@ -326,6 +408,8 @@ sdb_connection_read(sdb_conn_t *conn) { ssize_t n = 0; + sdb_conn_set_ctx(conn); + while (42) { ssize_t status = connection_read(conn); @@ -341,6 +425,8 @@ sdb_connection_read(sdb_conn_t *conn) n += status; } + + sdb_conn_set_ctx(NULL); return n; } /* sdb_connection_read */ diff --git a/src/include/frontend/connection.h b/src/include/frontend/connection.h index 45d377e..dc93db6 100644 --- a/src/include/frontend/connection.h +++ b/src/include/frontend/connection.h @@ -52,6 +52,20 @@ typedef struct { } sdb_conn_node_t; #define SDB_CONN_NODE(obj) ((sdb_conn_node_t *)(obj)) +/* + * sdb_connection_enable_logging: + * Enable logging of connection-related messages to the current client + * connection. After this function has been called all log messages + * originating from the thread handling the current client connection will + * also be sent to the client. + * + * Returns: + * - 0 on success + * - a negative value else + */ +int +sdb_connection_enable_logging(void); + /* * sdb_connection_accpet: * Accept a new connection on the specified file-descriptor 'fd' and return a diff --git a/src/include/frontend/proto.h b/src/include/frontend/proto.h index fd78c26..af336d5 100644 --- a/src/include/frontend/proto.h +++ b/src/include/frontend/proto.h @@ -35,7 +35,9 @@ extern "C" { /* status codes returned to a client */ typedef enum { CONNECTION_OK = 0, - CONNECTION_ERROR + CONNECTION_ERROR, + + CONNECTION_LOG, } sdb_conn_status_t; /* accepted commands / state of the connection */ diff --git a/src/tools/sysdbd/main.c b/src/tools/sysdbd/main.c index 2e35c16..ca1c50d 100644 --- a/src/tools/sysdbd/main.c +++ b/src/tools/sysdbd/main.c @@ -34,6 +34,7 @@ #include "core/store.h" #include "utils/error.h" +#include "frontend/connection.h" #include "frontend/sock.h" #include "tools/sysdbd/configfile.h" @@ -278,6 +279,8 @@ main(int argc, char **argv) if (sdb_fe_sock_add_listener(sock, listen_addresses[i])) break; + sdb_connection_enable_logging(); + /* break on error */ if (i >= listen_addresses_num) sdb_fe_sock_listen_and_serve(sock, &frontend_main_loop); -- 2.30.2