X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bus%2Fservices.c;h=90a2f5f18cd556c9e695b06a093ee075c47d8fe7;hb=c1a77d2c58c78abc606f1cb7918704596ebf2bfe;hp=e88ca107ed68c2ffb7bd17e149635d0c82ff027c;hpb=492a317ae9fb1e1bc5ff500fd14536bf11f1d6bd;p=platform%2Fupstream%2Fdbus.git diff --git a/bus/services.c b/bus/services.c index e88ca10..90a2f5f 100644 --- a/bus/services.c +++ b/bus/services.c @@ -3,6 +3,7 @@ * * Copyright (C) 2003 Red Hat, Inc. * Copyright (C) 2003 CodeFactory AB + * Copyright (C) 2013 Samsung Electronics * * Licensed under the Academic Free License version 2.1 * @@ -27,11 +28,6 @@ #include #include #include -#include -#include -#include - - #include "driver.h" #include "services.h" #include "connection.h" @@ -40,7 +36,18 @@ #include "policy.h" #include "bus.h" #include "selinux.h" + +#ifdef ENABLE_KDBUS_TRANSPORT +#include +#include +#include +#include +#include + #include "kdbus-d.h" +#include "dbus/kdbus.h" +#include "dbus/kdbus-common.h" +#endif struct BusService { @@ -60,6 +67,9 @@ struct BusOwner unsigned int allow_replacement : 1; unsigned int do_not_queue : 1; +#ifdef ENABLE_KDBUS_TRANSPORT + unsigned int is_kdbus_starter : 1; +#endif }; struct BusRegistry @@ -177,6 +187,30 @@ _bus_service_find_owner_link (BusService *service, return link; } +#ifdef ENABLE_KDBUS_TRANSPORT +static DBusConnection * +_bus_service_find_owner_connection (BusService *service, + const char* unique_name) +{ + DBusList *link; + + link = _dbus_list_get_first_link (&service->owners); + + while (link != NULL) + { + BusOwner *bus_owner; + + bus_owner = (BusOwner *) link->data; + if(!strcmp(bus_connection_get_name(bus_owner->conn), unique_name)) + return bus_owner->conn; + + link = _dbus_list_get_next_link (&service->owners, link); + } + + return NULL; +} +#endif + static void bus_owner_set_flags (BusOwner *owner, dbus_uint32_t flags) @@ -186,6 +220,11 @@ bus_owner_set_flags (BusOwner *owner, owner->do_not_queue = (flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) != FALSE; + +#ifdef ENABLE_KDBUS_TRANSPORT + owner->is_kdbus_starter = + (flags & KDBUS_NAME_STARTER_NAME) != FALSE; +#endif } static BusOwner * @@ -600,6 +639,7 @@ bus_registry_acquire_service (BusRegistry *registry, return retval; } +#ifdef ENABLE_KDBUS_TRANSPORT dbus_bool_t bus_registry_acquire_kdbus_service (BusRegistry *registry, DBusConnection *connection, @@ -611,12 +651,14 @@ bus_registry_acquire_kdbus_service (BusRegistry *registry, dbus_bool_t retval; BusService *service; BusActivation *activation; - DBusString service_name_real; const DBusString *service_name = &service_name_real; char* name; dbus_uint32_t flags; __u64 sender_id; + const char* conn_unique_name; + DBusConnection* phantom; + unsigned long int uid; if (!dbus_message_get_args (message, error, DBUS_TYPE_STRING, &name, @@ -632,97 +674,117 @@ bus_registry_acquire_kdbus_service (BusRegistry *registry, _dbus_string_get_length (service_name))) { dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, - "Requested bus name \"%s\" is not valid", - _dbus_string_get_const_data (service_name)); + "Requested bus name \"%s\" is not valid", name); _dbus_verbose ("Attempt to acquire invalid service name\n"); - goto out; + return FALSE; } if (_dbus_string_get_byte (service_name, 0) == ':') { /* Not allowed; only base services can start with ':' */ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, - "Cannot acquire a service starting with ':' such as \"%s\"", - _dbus_string_get_const_data (service_name)); + "Cannot acquire a service starting with ':' such as \"%s\"", name); - _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"", - _dbus_string_get_const_data (service_name)); + _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"", name); - goto out; + return FALSE; } + 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); - goto out; + conn_unique_name, DBUS_SERVICE_DBUS); + return FALSE; } - service = bus_registry_lookup (registry, service_name); - if (service == NULL) - { - service = bus_registry_ensure (registry, service_name, connection, flags, - transaction, error); //adds daemon to service owners list - must be removed after right owner is set - if (service == NULL) - goto out; + sender_id = sender_name_to_id(conn_unique_name, error); + if(dbus_error_is_set(error)) + return FALSE; - 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)); - goto out; - } - } + phantom = bus_connections_find_conn_by_name(bus_connection_get_connections(connection), conn_unique_name); + if(phantom == NULL) + { + phantom = create_phantom_connection(connection, conn_unique_name, error); + if(phantom == NULL) + return FALSE; + } - sender_id = sender_name_to_id(dbus_message_get_sender(message), error); - if(dbus_error_is_set(error)) - return FALSE; + if (!bus_client_policy_check_can_own (bus_connection_get_policy (phantom), 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, name); + goto failed; + } - *result = kdbus_request_name(connection, service_name, flags, sender_id); - 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", - _dbus_string_get_const_data (service_name)); - goto out; - } - else if(*result < 0) - { - dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be acquired", name); - goto out; - } + if (!kdbus_connection_get_unix_user(phantom, conn_unique_name, &uid, NULL)) + goto failed; - if((*result == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) || (*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)) - { - DBusConnection* phantom; - - phantom = create_phantom_connection(connection, dbus_message_get_sender(message)); - if(phantom == NULL) - goto out; - if (!bus_service_add_owner (service, phantom, flags, transaction, error)) - goto out; /* todo FIXME what to do with phantom connection? look into create_phantom_connection for a clue*/ - if(*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) - if (!bus_service_remove_owner (service, connection, transaction, error)) - goto out; /* todo FIXME what to do with phantom connection? look into create_phantom_connection for a clue*/ - } +#ifdef POLICY_TO_KDBUS + if (!register_kdbus_policy(name, dbus_connection_get_transport(phantom), uid)) + { + dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, + "Kdbus error when setting policy for connection \"%s\" and service name \"%s\"", + conn_unique_name, name); + goto failed; + } +#endif + + *result = kdbus_request_name(connection, service_name, flags, sender_id); + if(*result == -EPERM) + { + dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, + "Kdbus not allowed %s to own the service \"%s\"", + conn_unique_name, _dbus_string_get_const_data (service_name)); + goto failed; + } + else if(*result < 0) + { + dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be acquired", name); + goto failed; + } + + if((*result == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) || (*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)) + { + service = bus_registry_lookup (registry, service_name); + if (service == NULL) + { + service = bus_registry_ensure (registry, service_name, phantom, flags, + transaction, error); + if (service == NULL) + goto failed2; + } + else + { + if (!bus_service_add_owner (service, phantom, flags, transaction, error)) + goto failed2; + } + + activation = bus_context_get_activation (registry->context); + retval = bus_activation_send_pending_auto_activation_messages (activation, + service, + transaction, + error); + } + else + retval = TRUE; - activation = bus_context_get_activation (registry->context); - retval = bus_activation_send_pending_auto_activation_messages (activation, - service, - transaction, - error); - - out: return retval; + +failed2: + kdbus_release_name(phantom, service_name, sender_id); +failed: + bus_connection_disconnected(phantom); + + return FALSE; } +#endif dbus_bool_t bus_registry_release_service (BusRegistry *registry, @@ -775,44 +837,120 @@ bus_registry_release_service (BusRegistry *registry, goto out; } - if(bus_context_is_kdbus(bus_transaction_get_context (transaction))) //todo kdbus incl - { - __u64 sender_id; - - sender_id = sender_name_to_id(dbus_message_get_sender((DBusMessage*)registry), error); - if(dbus_error_is_set(error)) - return FALSE; + service = bus_registry_lookup (registry, service_name); - *result = kdbus_release_name(connection, service_name, sender_id); - } + if (service == NULL) + { + *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT; + } + else if (!bus_service_has_owner (service, connection)) + { + *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER; + } else - { - service = bus_registry_lookup (registry, service_name); + { + if (!bus_service_remove_owner (service, connection, + transaction, error)) + goto out; - if (service == NULL) - { - *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT; - } - else if (!bus_service_has_owner (service, connection)) - { - *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER; - } - else - { - if (!bus_service_remove_owner (service, connection, - transaction, error)) - goto out; + _dbus_assert (!bus_service_has_owner (service, connection)); + *result = DBUS_RELEASE_NAME_REPLY_RELEASED; + } - _dbus_assert (!bus_service_has_owner (service, connection)); - *result = DBUS_RELEASE_NAME_REPLY_RELEASED; - } - } + retval = TRUE; + + out: + return retval; +} + +#ifdef ENABLE_KDBUS_TRANSPORT +dbus_bool_t +bus_registry_release_service_kdbus (const char* sender_name, + DBusConnection *connection, + const DBusString *service_name, + dbus_uint32_t *result, + BusTransaction *transaction, + DBusError *error) +{ + dbus_bool_t retval = FALSE; + __u64 sender_id; + + if (!_dbus_validate_bus_name (service_name, 0, + _dbus_string_get_length (service_name))) + { + dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, + "Given bus name \"%s\" is not valid", + _dbus_string_get_const_data (service_name)); + + _dbus_verbose ("Attempt to release invalid service name\n"); + + goto out; + } + + if (_dbus_string_get_byte (service_name, 0) == ':') + { + /* Not allowed; the base service name cannot be created or released */ + dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, + "Cannot release a service starting with ':' such as \"%s\"", + _dbus_string_get_const_data (service_name)); + + _dbus_verbose ("Attempt to release invalid base service name \"%s\"", + _dbus_string_get_const_data (service_name)); + + goto out; + } + + if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS)) + { + /* Not allowed; the base service name cannot be created or released */ + dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, + "Cannot release the %s service because it is owned by the bus", + DBUS_SERVICE_DBUS); + + _dbus_verbose ("Attempt to release service name \"%s\"", + DBUS_SERVICE_DBUS); + + goto out; + } + + sender_id = sender_name_to_id(sender_name, error); + if(dbus_error_is_set(error)) + return FALSE; + + *result = kdbus_release_name(connection, service_name, sender_id); + + if(*result == DBUS_RELEASE_NAME_REPLY_RELEASED) + { + BusRegistry* registry; + BusService *service; + + registry = bus_connection_get_registry (connection); + service = bus_registry_lookup (registry, service_name); + if(service) + { + DBusConnection* phantom; + + phantom = _bus_service_find_owner_connection(service, sender_name); + if(phantom) + { + bus_service_remove_owner (service, phantom, transaction, NULL); + /* todo we could remove phantom if he doesn't own any name + * to do this we should write function in connection.c to check if + * _dbus_list_get_last (&d->services_owned) returns not NULL + * or we can leave phantom - he will be removed when he disconnects from the bus + */ + } + else + _dbus_verbose ("Didn't find phantom connection for released name!\n"); + } + } retval = TRUE; out: return retval; } +#endif dbus_bool_t bus_registry_set_service_context_table (BusRegistry *registry, @@ -1362,13 +1500,29 @@ DBusConnection * 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(!owner) + return NULL; + if(bus_context_is_kdbus(service->registry->context)) + { + 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 + return owner->conn; +#else if (owner != NULL) return owner->conn; else return NULL; +#endif } BusOwner* @@ -1397,6 +1551,22 @@ bus_service_get_allow_replacement (BusService *service) return owner->allow_replacement; } +#ifdef ENABLE_KDBUS_TRANSPORT +dbus_bool_t +bus_service_get_is_kdbus_starter (BusService *service) +{ + BusOwner *owner; + DBusList *link; + + _dbus_assert (service->owners != NULL); + + link = _dbus_list_get_first_link (&service->owners); + owner = (BusOwner *) link->data; + + return owner->is_kdbus_starter; +} +#endif + dbus_bool_t bus_service_has_owner (BusService *service, DBusConnection *connection) @@ -1431,8 +1601,11 @@ bus_service_list_queued_owners (BusService *service, owner = (BusOwner *) link->data; uname = bus_connection_get_name (owner->conn); - if (!_dbus_list_append (return_list, (char *)uname)) - goto oom; +#ifdef ENABLE_KDBUS_TRANSPORT + if(!owner->is_kdbus_starter) +#endif + if (!_dbus_list_append (return_list, (char *)uname)) + goto oom; link = _dbus_list_get_next_link (&service->owners, link); }