BusRegistry *registry;
BusService *service;
DBusMessage *reply;
+#ifdef ENABLE_KDBUS_TRANSPORT
+ char unique_name[(unsigned int)(snprintf((char*)base_name, 0, "%llu", ULLONG_MAX) + sizeof(":1."))];
+#endif
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
{
int ret;
struct nameInfo info;
- char unique_name[(unsigned int)(snprintf((char*)base_name, 0, "%llu", ULLONG_MAX) + sizeof(":1."))];
ret = kdbus_NameQuery(text, dbus_connection_get_transport(connection), &info);
if(ret == 0) //unique id of the name
#ifdef ENABLE_KDBUS_TRANSPORT
if(bus_context_is_kdbus(bus_transaction_get_context (transaction)))
{
- if(!kdbus_get_connection_unix_user(connection, message, &uid, error))
+ const char* name;
+
+ if(!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID))
+ goto failed;
+ if(!kdbus_get_connection_unix_user(connection, name, &uid, error))
goto failed;
}
else
reply = dbus_message_new_method_return (message);
if (reply == NULL)
goto oom;
-
#ifdef ENABLE_KDBUS_TRANSPORT
if(bus_context_is_kdbus(bus_transaction_get_context (transaction)))
- {
- if(!kdbus_get_connection_unix_process_id(connection, message, &pid, error))
- goto failed;
- }
- else
+ {
+ const char* name;
+
+ if(!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID))
+ goto failed;
+ if(!kdbus_get_connection_unix_process_id(connection, name, &pid, error))
+ goto failed;
+ }
+ else
#endif
{
- conn = bus_driver_get_conn_helper (connection, message, "PID", &service,
- error);
-
- if (conn == NULL)
- goto failed;
-
-
+ conn = bus_driver_get_conn_helper (connection, message, "PID", &service,
+ error);
+ if (conn == NULL)
+ goto failed;
- if (!dbus_connection_get_unix_process_id (conn, &pid))
- {
- dbus_set_error (error,
- DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
- "Could not determine PID for '%s'", service);
- goto failed;
- }
+ if (!dbus_connection_get_unix_process_id (conn, &pid))
+ {
+ dbus_set_error (error,
+ DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
+ "Could not determine PID for '%s'", service);
+ goto failed;
+ }
}
pid32 = pid;
}
else
{
- if(kdbus_get_connection_unix_process_id(connection, message, &ulong_val, error))
+ const char* name;
+
+ if(!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID))
+ goto failed;
+ if(kdbus_get_connection_unix_process_id(connection, name, &ulong_val, error))
{
if (!_dbus_asv_add_uint32 (&array_iter, "ProcessID", ulong_val))
goto oom;
else
goto failed;
- if(kdbus_get_connection_unix_user(connection, message, &ulong_val, error))
+ if(kdbus_get_connection_unix_user(connection, name, &ulong_val, error))
{
if (!_dbus_asv_add_uint32 (&array_iter, "UnixUserID", ulong_val))
goto oom;
return release_kdbus_name(fd, _dbus_string_get_const_data(service_name), sender_id);
}
+/*
+ * Asks kdbus for well-known names registered on the bus
+ */
dbus_bool_t kdbus_list_services (DBusConnection* connection, char ***listp, int *array_len)
{
int fd;
+ struct kdbus_cmd_names* pCmd;
+ __u64 cmd_size;
+ dbus_bool_t ret_val = FALSE;
+ char** list;
+ int list_len = 0;
+ int i = 0;
+ int j;
+
+ cmd_size = sizeof(struct kdbus_cmd_names) + KDBUS_ITEM_SIZE(1);
+ pCmd = malloc(cmd_size);
+ if(pCmd == NULL)
+ goto out;
+ pCmd->size = cmd_size;
_dbus_transport_get_socket_fd(dbus_connection_get_transport(connection), &fd);
- return list_kdbus_names(fd, listp, array_len);
+again:
+ cmd_size = 0;
+ if(ioctl(fd, KDBUS_CMD_NAME_LIST, pCmd))
+ {
+ if(errno == EINTR)
+ goto again;
+ if(errno == ENOBUFS) //buffer to small to put all names into it
+ cmd_size = pCmd->size; //here kernel tells how much memory it needs
+ else
+ {
+ _dbus_verbose("kdbus error asking for name list: err %d (%m)\n",errno);
+ goto out;
+ }
+ }
+ if(cmd_size) //kernel needs more memory
+ {
+ pCmd = realloc(pCmd, cmd_size); //prepare memory
+ if(pCmd == NULL)
+ return FALSE;
+ goto again; //and try again
+ }
+ else
+ {
+ struct kdbus_cmd_name* pCmd_name;
+
+ for (pCmd_name = pCmd->names; (uint8_t *)(pCmd_name) < (uint8_t *)(pCmd) + pCmd->size; pCmd_name = KDBUS_PART_NEXT(pCmd_name))
+ list_len++;
+
+ list = malloc(sizeof(char*) * (list_len + 1));
+ if(list == NULL)
+ goto out;
+
+ for (pCmd_name = pCmd->names; (uint8_t *)(pCmd_name) < (uint8_t *)(pCmd) + pCmd->size; pCmd_name = KDBUS_PART_NEXT(pCmd_name))
+ {
+ list[i] = strdup(pCmd_name->name);
+ if(list[i] == NULL)
+ {
+ for(j=0; j<i; j++)
+ free(list[j]);
+ free(list);
+ goto out;
+ }
+ _dbus_verbose ("Name %d: %s\n", i, list[i]);
+ ++i;
+ }
+ list[i] = NULL;
+ }
+
+ *array_len = list_len;
+ *listp = list;
+ ret_val = TRUE;
+
+out:
+ if(pCmd)
+ free(pCmd);
+ return ret_val;
}
/*
return TRUE;
}
+int kdbus_get_name_owner(DBusConnection* connection, const char* name, char* owner)
+{
+ int ret;
+ struct nameInfo info;
+
+ ret = kdbus_NameQuery(name, dbus_connection_get_transport(connection), &info);
+ if(ret == 0) //unique id of the name
+ {
+ sprintf(owner, ":1.%llu", (unsigned long long int)info.uniqueId);
+ _dbus_verbose("Unique name discovered:%s\n", owner);
+ }
+ else if(ret != -ENOENT)
+ _dbus_verbose("kdbus error sending name query: err %d (%m)\n", errno);
+
+ return ret;
+}
+
/*
* Asks kdbus for uid of the owner of the name given in the message
*/
-dbus_bool_t kdbus_get_connection_unix_user(DBusConnection* connection, DBusMessage* message, unsigned long* uid, DBusError* error)
+dbus_bool_t kdbus_get_connection_unix_user(DBusConnection* connection, const char* name, unsigned long* uid, DBusError* error)
{
- char* name = NULL;
struct nameInfo info;
int inter_ret;
dbus_bool_t ret = FALSE;
- dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID);
inter_ret = kdbus_NameQuery(name, dbus_connection_get_transport(connection), &info);
if(inter_ret == 0) //name found
{
/*
* Asks kdbus for pid of the owner of the name given in the message
*/
-dbus_bool_t kdbus_get_connection_unix_process_id(DBusConnection* connection, DBusMessage* message, unsigned long* pid, DBusError* error)
+dbus_bool_t kdbus_get_connection_unix_process_id(DBusConnection* connection, const char* name, unsigned long* pid, DBusError* error)
{
- char* name = NULL;
struct nameInfo info;
int inter_ret;
dbus_bool_t ret = FALSE;
- dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID);
inter_ret = kdbus_NameQuery(name, dbus_connection_get_transport(connection), &info);
if(inter_ret == 0) //name found
{
return ret;
}
+/**
+ * Gets the UNIX user ID of the connection from kdbus, if known. Returns #TRUE if
+ * the uid is filled in. Always returns #FALSE on non-UNIX platforms
+ * for now., though in theory someone could hook Windows to NIS or
+ * something. Always returns #FALSE prior to authenticating the
+ * connection.
+ *
+ * The UID of is only read by bus daemon from kdbus. You can not
+ * call this function from client side of the connection.
+ *
+ * You can ask the bus to tell you the UID of another connection though
+ * if you like; this is done with dbus_bus_get_unix_user().
+ *
+ * @param connection the connection
+ * @param uid return location for the user ID
+ * @returns #TRUE if uid is filled in with a valid user ID
+ */
+dbus_bool_t
+dbus_connection_get_unix_user (DBusConnection *connection,
+ unsigned long *uid)
+{
+ _dbus_return_val_if_fail (connection != NULL, FALSE);
+ _dbus_return_val_if_fail (uid != NULL, FALSE);
+
+ return kdbus_get_connection_unix_user(connection, bus_connection_get_name(connection), uid, NULL);
+}
+
+/**
+ * Gets the process ID of the connection if any.
+ * Returns #TRUE if the pid is filled in.
+ *
+ * @param connection the connection
+ * @param pid return location for the process ID
+ * @returns #TRUE if uid is filled in with a valid process ID
+ */
+dbus_bool_t
+dbus_connection_get_unix_process_id (DBusConnection *connection,
+ unsigned long *pid)
+{
+ _dbus_return_val_if_fail (connection != NULL, FALSE);
+ _dbus_return_val_if_fail (pid != NULL, FALSE);
+
+ return kdbus_get_connection_unix_process_id(connection, bus_connection_get_name(connection), pid, NULL);
+}
+
/*
* Create connection structure for given name. It is needed to control starters - activatable services
* and for ListQueued method (as long as kdbus is not supporting it). This connections don't have it's own
}
/*
-static dbus_bool_t remove_conn_if_name_match (DBusConnection *connection, void *data)
-{
- if(!strcmp(bus_connection_get_name(connection), (char*)data))
- {
- bus_connection_disconnected(connection);
- return FALSE; //this is to break foreach function
- }
- return TRUE;
-}*/
-
-/*
* Analyzes system broadcasts about id and name changes.
* Basing on this it sends NameAcquired and NameLost signals and clear phantom connections.
*/
__u64 sender_name_to_id(const char* name, DBusError* error);
char* make_kdbus_bus(DBusBusType type, DBusError *error);
DBusServer* empty_server_init(char* address);
-DBusConnection* daemon_as_client(DBusBusType type, char* address, DBusError *error);
-dbus_bool_t register_daemon_name(DBusConnection* connection);
+
dbus_bool_t kdbus_register_policy (const DBusString *service_name, DBusConnection* connection);
dbus_uint32_t kdbus_request_name(DBusConnection* connection, const DBusString *service_name, dbus_uint32_t flags, __u64 sender_id);
dbus_uint32_t kdbus_release_name(DBusConnection* connection, const DBusString *service_name, __u64 sender_id);
dbus_bool_t kdbus_list_services (DBusConnection* connection, char ***listp, int *array_len);
dbus_bool_t kdbus_add_match_rule (DBusConnection* connection, DBusMessage* message, const char* text, DBusError* error);
dbus_bool_t kdbus_remove_match (DBusConnection* connection, DBusMessage* message, DBusError* error);
-dbus_bool_t kdbus_get_connection_unix_user(DBusConnection* connection, DBusMessage* message, unsigned long* uid, DBusError* error);
-dbus_bool_t kdbus_get_connection_unix_process_id(DBusConnection* connection, DBusMessage* message, unsigned long* pid, DBusError* error);
+
+int kdbus_get_name_owner(DBusConnection* connection, const char* name, char* owner);
+dbus_bool_t kdbus_get_connection_unix_user(DBusConnection* connection, const char* name, unsigned long* uid, DBusError* error);
+dbus_bool_t kdbus_get_connection_unix_process_id(DBusConnection* connection, const char* name, unsigned long* pid, DBusError* error);
dbus_bool_t kdbus_get_connection_unix_selinux_security_context(DBusConnection* connection, DBusMessage* message, DBusMessage* reply, DBusError* error);
+dbus_bool_t dbus_connection_get_unix_user (DBusConnection *connection, unsigned long *uid);
+dbus_bool_t dbus_connection_get_unix_process_id (DBusConnection *connection, unsigned long *pid);
+
+DBusConnection* daemon_as_client(DBusBusType type, char* address, DBusError *error);
+dbus_bool_t register_daemon_name(DBusConnection* connection);
DBusConnection* create_phantom_connection(DBusConnection* connection, const char* unique_name, DBusError* error);
dbus_bool_t register_kdbus_starters(DBusConnection* connection);
dbus_bool_t update_kdbus_starters(DBusConnection* connection);
+
void handleNameOwnerChanged(DBusMessage *msg, BusTransaction *transaction, DBusConnection *connection);
#endif /* KDBUS_H_ */
#include <dbus/dbus-list.h>
#include <dbus/dbus-mempool.h>
#include <dbus/dbus-marshal-validate.h>
-#ifdef ENABLE_KDBUS_TRANSPORT
-#include <linux/types.h>
-#include <errno.h>
-#include <stdlib.h>
-#endif
-
#include "driver.h"
#include "services.h"
#include "connection.h"
#include "policy.h"
#include "bus.h"
#include "selinux.h"
+
#ifdef ENABLE_KDBUS_TRANSPORT
+#include <linux/types.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+
#include "kdbus-d.h"
#include "dbus/kdbus.h"
#endif
dbus_uint32_t flags;
__u64 sender_id;
dbus_bool_t rm_owner_daemon = FALSE;
+ const char* conn_unique_name;
if (!dbus_message_get_args (message, error,
DBUS_TYPE_STRING, &name,
goto out;
}
+ conn_unique_name = dbus_message_get_sender(message);
+
if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
{
dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
"Connection \"%s\" is not allowed to own the service \"%s\"because "
"it is reserved for D-Bus' use only",
- bus_connection_is_active (connection) ?
- bus_connection_get_name (connection) :
- "(inactive)",
- DBUS_SERVICE_DBUS);
+ conn_unique_name, DBUS_SERVICE_DBUS);
goto out;
}
+ if (!bus_client_policy_check_can_own (bus_connection_get_policy (connection), service_name))
+ {
+ dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+ "Connection \"%s\" is not allowed to own the service \"%s\" due "
+ "to security policies in the configuration file",
+ conn_unique_name, _dbus_string_get_const_data (service_name));
+ goto out;
+ }
+
service = bus_registry_lookup (registry, service_name);
if (service == NULL)
{
if(!kdbus_register_policy(service_name, connection))
{
dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
- "Connection is not allowed to own the service \"%s\" due to security policies in the configuration file",
- _dbus_string_get_const_data (service_name));
+ "Kdbus error when setting policy for connection \"%s\" and service name \"%s\"",
+ conn_unique_name, _dbus_string_get_const_data (service_name));
goto failed;
}
}
- sender_id = sender_name_to_id(dbus_message_get_sender(message), error);
+ sender_id = sender_name_to_id(conn_unique_name, error);
if(dbus_error_is_set(error))
goto failed;
if(*result == -EPERM)
{
dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
- "Connection is not allowed to own the service \"%s\" due to security policies in the configuration file",
+ "Kdbus not allowed to own the service \"%s\"",
_dbus_string_get_const_data (service_name));
goto failed;
}
bus_service_get_primary_owners_connection (BusService *service)
{
BusOwner *owner;
+#ifdef ENABLE_KDBUS_TRANSPORT
+ char unique_name[(unsigned int)(snprintf((char*)NULL, 0, "%llu", ULLONG_MAX) + sizeof(":1."))];
+#endif
owner = bus_service_get_primary_owner (service);
+#ifdef ENABLE_KDBUS_TRANSPORT
+ if(kdbus_get_name_owner(owner->conn, bus_service_get_name(service), unique_name) < 0)
+ return NULL;
+ return _bus_service_find_owner_connection(service, unique_name); //bus_connections_find_conn_by_name would be safer? but slower
+#else
if (owner != NULL)
return owner->conn;
else
return NULL;
+#endif
}
BusOwner*
return retval;
}
-
+#ifndef ENABLE_KDBUS_TRANSPORT
/**
* Gets the UNIX user ID of the connection if known. Returns #TRUE if
* the uid is filled in. Always returns #FALSE on non-UNIX platforms
return result;
}
+#endif
/**
* Gets the ADT audit data of the connection if any.
pInfo->sec_label_len = 0;
pInfo->sec_label = NULL;
- item_size = KDBUS_PART_HEADER_SIZE + strlen(name) + 1;
+ item_size = KDBUS_PART_HEADER_SIZE + strlen(name) + 1;
item_size = (item_size < 56) ? 56 : item_size; //at least 56 bytes are needed by kernel to place info about name, otherwise error
- size = sizeof(struct kdbus_cmd_name_info) + item_size;
+ size = sizeof(struct kdbus_cmd_name_info) + item_size;
msg = malloc(size);
if (!msg)
*/
#include "kdbus.h"
#include "kdbus-common.h"
+#include "dbus-transport-kdbus.h"
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
return TRUE;
}
-/*
- * Asks kdbus for well-known names registered on the bus
- */
-dbus_bool_t list_kdbus_names(int fd, char ***listp, int *array_len)
-{
- struct kdbus_cmd_names* pCmd;
- __u64 cmd_size;
- dbus_bool_t ret_val = FALSE;
- char** list;
- int list_len = 0;
- int i = 0;
- int j;
-
- cmd_size = sizeof(struct kdbus_cmd_names) + KDBUS_ITEM_SIZE(1);
- pCmd = malloc(cmd_size);
- if(pCmd == NULL)
- goto out;
- pCmd->size = cmd_size;
-
-again:
- cmd_size = 0;
- if(ioctl(fd, KDBUS_CMD_NAME_LIST, pCmd))
- {
- if(errno == EINTR)
- goto again;
- if(errno == ENOBUFS) //buffer to small to put all names into it
- cmd_size = pCmd->size; //here kernel tells how much memory it needs
- else
- {
- _dbus_verbose("kdbus error asking for name list: err %d (%m)\n",errno);
- goto out;
- }
- }
- if(cmd_size) //kernel needs more memory
- {
- pCmd = realloc(pCmd, cmd_size); //prepare memory
- if(pCmd == NULL)
- return FALSE;
- goto again; //and try again
- }
- else
- {
- struct kdbus_cmd_name* pCmd_name;
-
- for (pCmd_name = pCmd->names; (uint8_t *)(pCmd_name) < (uint8_t *)(pCmd) + pCmd->size; pCmd_name = KDBUS_PART_NEXT(pCmd_name))
- list_len++;
-
- list = malloc(sizeof(char*) * (list_len + 1));
- if(list == NULL)
- goto out;
-
- for (pCmd_name = pCmd->names; (uint8_t *)(pCmd_name) < (uint8_t *)(pCmd) + pCmd->size; pCmd_name = KDBUS_PART_NEXT(pCmd_name))
- {
- list[i] = strdup(pCmd_name->name);
- if(list[i] == NULL)
- {
- for(j=0; j<i; j++)
- free(list[j]);
- free(list);
- goto out;
- }
- _dbus_verbose ("Name %d: %s\n", i, list[i]);
- ++i;
- }
- list[i] = NULL;
- }
-
- *array_len = list_len;
- *listp = list;
- ret_val = TRUE;
-
-out:
- if(pCmd)
- free(pCmd);
- return ret_val;
-}
-
/**
*
* Asks the bus to assign the given name to the connection.
(typeof(part))(((uint8_t *)part) + KDBUS_ALIGN8((part)->size))
#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_PART_HEADER_SIZE)
-/*struct kdbus_policy *make_policy_name(const char *name);
-struct kdbus_policy *make_policy_access(__u64 type, __u64 bits, __u64 id);
-void append_policy(struct kdbus_cmd_policy *cmd_policy, struct kdbus_policy *policy, __u64 max_size);*/
dbus_bool_t register_kdbus_policy(const char* name, int fd);
-dbus_bool_t list_kdbus_names(int fd, char ***listp, int *array_len);
int request_kdbus_name(int fd, const char *name, const __u64 flags, __u64 id);
int release_kdbus_name(int fd, const char *name, __u64 id);