[daemon-dev][daemon-fix] starting services by direct message (autostart) and some...
[platform/upstream/dbus.git] / dbus / dbus-transport-kdbus.c
index cf19608..6a33241 100644 (file)
@@ -33,8 +33,6 @@
 #include <sys/stat.h>
 #include <openssl/md5.h>
 
-//todo documentation need to be corrected
-
 #define KDBUS_PART_FOREACH(part, head, first)                          \
        for (part = (head)->first;                                      \
             (uint8_t *)(part) < (uint8_t *)(head) + (head)->size;      \
@@ -43,6 +41,7 @@
 #define MEMFD_SIZE_THRESHOLD (2 * 1024 * 1024LU) // over this memfd is used
 
 #define KDBUS_MSG_DECODE_DEBUG 0
+//#define DBUS_AUTHENTICATION
 
 #define ITER_APPEND_STR(string) \
 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &string))   \
@@ -171,7 +170,7 @@ static int reply_1_data(DBusMessage *message, int data_type, void* pData, DBusCo
     return -1;
 }
 
-/*todo uncomment if needed
+/*
 static int reply_ack(DBusMessage *message, DBusConnection* connection)
 {
        DBusMessage *reply;
@@ -394,7 +393,7 @@ static int kdbus_write_msg(DBusTransportSocket *transport, DBusMessage *message,
                item = KDBUS_PART_NEXT(item);
                item->type = KDBUS_MSG_DST_NAME;
                item->size = KDBUS_PART_HEADER_SIZE + strlen(name) + 1;
-               strcpy(item->str, name);
+               memcpy(item->str, name, item->size - KDBUS_PART_HEADER_SIZE);
        }
        else if (dst_id == KDBUS_DST_ID_BROADCAST)
        {
@@ -409,18 +408,21 @@ static int kdbus_write_msg(DBusTransportSocket *transport, DBusMessage *message,
        {
                if(errno == EINTR)
                        goto again;
-               if((errno == ESRCH) || (errno == ENXIO) || (errno = EADDRNOTAVAIL))  //when recipient is not available on the bus
+               else if(errno == ENXIO) //no such id on the bus
+               {
+            if(!reply_with_error(DBUS_ERROR_NAME_HAS_NO_OWNER, "Name \"%s\" does not exist", dbus_message_get_destination(message), message, transport->base.connection))
+                goto out;
+               }
+        else if((errno == ESRCH) || (errno = EADDRNOTAVAIL))  //when well known name is not available on the bus
                {
                        if(autostart)
                        {
-                               //todo start service here, otherwise
                                if(!reply_with_error(DBUS_ERROR_SERVICE_UNKNOWN, "The name %s was not provided by any .service files", dbus_message_get_destination(message), message, transport->base.connection))
                                        goto out;
                        }
                        else
-                               if(!reply_with_error(DBUS_ERROR_NAME_HAS_NO_OWNER, "Name \"%s\" does not exist", dbus_message_get_destination(message), message, transport->base.connection))
-                                       goto out;
-
+                   if(!reply_with_error(DBUS_ERROR_NAME_HAS_NO_OWNER, "Name \"%s\" does not exist", dbus_message_get_destination(message), message, transport->base.connection))
+                       goto out;
                }
                _dbus_verbose("kdbus error sending message: err %d (%m)\n", errno);
                ret_size = -1;
@@ -472,7 +474,7 @@ int kdbus_NameQuery(const char* name, DBusTransport* transport, struct nameInfo*
        item = msg->items;
        item->type = KDBUS_NAME_INFO_ITEM_NAME;
        item->size = item_size;
-       strcpy(item->str, name);
+       memcpy(item->str, name, strlen(name) + 1);
 
        again:
        ret = ioctl(((DBusTransportSocket*)transport)->fd, KDBUS_CMD_NAME_QUERY, msg);
@@ -496,13 +498,12 @@ int kdbus_NameQuery(const char* name, DBusTransport* transport, struct nameInfo*
                pInfo->uniqueId = msg->id;
                pInfo->userId = msg->creds.uid;
                pInfo->processId = msg->creds.pid;
-
                item = msg->items;
                while((uint8_t *)(item) < (uint8_t *)(msg) + msg->size)
                {
                        if(item->type == KDBUS_NAME_INFO_ITEM_SECLABEL)
                        {
-                               pInfo->sec_label_len = item->size - KDBUS_PART_HEADER_SIZE - 1;
+                           pInfo->sec_label_len = item->size - KDBUS_PART_HEADER_SIZE - 1;
                                if(pInfo->sec_label_len != 0)
                                {
                                        pInfo->sec_label = malloc(pInfo->sec_label_len);
@@ -511,7 +512,6 @@ int kdbus_NameQuery(const char* name, DBusTransport* transport, struct nameInfo*
                                        else
                                                memcpy(pInfo->sec_label, item->data, pInfo->sec_label_len);
                                }
-                                       
                                break;
                        }
                        item = KDBUS_PART_NEXT(item);
@@ -730,7 +730,7 @@ dbus_bool_t add_match_kdbus (DBusTransport* transport, __u64 id, const char *rul
                {
                        pItem->type = KDBUS_MATCH_SRC_NAME;
                        pItem->size = KDBUS_PART_HEADER_SIZE + name_size + 1;
-                       strcpy(pItem->str, pName);
+                       memcpy(pItem->str, pName, strlen(pName) + 1);
                        pItem = KDBUS_PART_NEXT(pItem);
                }
 
@@ -835,7 +835,7 @@ static int emulateOrgFreedesktopDBus(DBusTransport *transport, DBusMessage *mess
                ((DBusTransportSocket*)transport)->sender = sender;
 
                if(!reply_1_data(message, DBUS_TYPE_STRING, &name, transport->connection))
-                       return 0;  //todo why we cannot free name after sending reply?
+                       return 0;  //todo why we cannot free name after sending reply, shouldn't we?
                else
                        free(sender);
 
@@ -1067,13 +1067,13 @@ out:
                return ret_value;
        }
 #endif
-       else if(!strcmp(dbus_message_get_member(message), "GetAdtAuditSessionData"))  //todo to be implemented - now can not be simply passed to daemon
+/*     else if(!strcmp(dbus_message_get_member(message), "GetAdtAuditSessionData"))  //todo to be implemented if needed and possible
        {
                char* name = NULL;
 
                dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID);
                return reply_with_error(DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN, "Could not determine audit session data for '%s'", name, message, transport->connection);
-       }
+       }*/
 #ifdef DBUS_SERVICES_IN_LIB
        else if(!strcmp(dbus_message_get_member(message), "GetConnectionSELinuxSecurityContext"))
        {
@@ -1103,7 +1103,6 @@ out:
 #endif
        else
                return 1;  //send to daemon
-//             return reply_with_error(DBUS_ERROR_UNKNOWN_METHOD, NULL, (char*)dbus_message_get_member(message), message, transport->connection);
 
 #ifdef DBUS_SERVICES_IN_LIB
        if(info.sec_label)
@@ -1681,7 +1680,7 @@ check_write_watch (DBusTransport *transport)
   _dbus_transport_ref (transport);
 
 #ifdef DBUS_AUTHENTICATION
-  if (_dbus_transport_get_is_authenticated (transport))
+  if (_dbus_transport_try_to_authenticate (transport))
 #endif
     needed = _dbus_connection_has_messages_to_send_unlocked (transport->connection);
 #ifdef DBUS_AUTHENTICATION
@@ -1739,7 +1738,7 @@ check_read_watch (DBusTransport *transport)
   _dbus_transport_ref (transport);
 
 #ifdef DBUS_AUTHENTICATION
-  if (_dbus_transport_get_is_authenticated (transport))
+  if (_dbus_transport_try_to_authenticate (transport))
 #endif
     need_read_watch =
       (_dbus_counter_get_size_value (transport->live_messages) < transport->max_live_messages_size) &&
@@ -1800,12 +1799,13 @@ read_data_into_auth (DBusTransport *transport,
   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
   DBusString *buffer;
   int bytes_read;
+  int *fds, n_fds;
 
   *oom = FALSE;
 
   _dbus_auth_get_buffer (transport->auth, &buffer);
 
-  bytes_read = kdbus_read_message(socket_transport, buffer);
+  bytes_read = kdbus_read_message(socket_transport, buffer, fds, &n_fds);
 
   _dbus_auth_return_buffer (transport->auth, buffer,
                             bytes_read > 0 ? bytes_read : 0);
@@ -1845,11 +1845,38 @@ read_data_into_auth (DBusTransport *transport,
     }
 }
 
+static int kdbus_send_auth (DBusTransport *transport,  const DBusString *buffer)
+{
+       int len;
+       int bytes_written = -1;
+       struct kdbus_msg *msg;
+       struct kdbus_item *item;
+
+       len = _dbus_string_get_length (buffer);
+//     data = _dbus_string_get_const_data_len (buffer, 0, len);
+
+       msg = kdbus_init_msg(NULL, 1, 0, FALSE, 0, (DBusTransportSocket*)transport);
+       item = msg->items;
+       MSG_ITEM_BUILD_VEC(_dbus_string_get_const_data_len (buffer, 0, len), len);
+
+    again:
+    if(ioctl(((DBusTransportSocket*)transport)->fd, KDBUS_CMD_MSG_SEND, msg))
+    {
+        if(errno == EINTR)
+            goto again;
+        _dbus_verbose ("Error writing auth: %d, %m\n", errno);
+    }
+    else
+        bytes_written = len;
+
+       return bytes_written;
+}
+
 /* Return value is whether we successfully wrote any bytes */
 static dbus_bool_t
 write_data_from_auth (DBusTransport *transport)
 {
-  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
+//  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
   int bytes_written;
   const DBusString *buffer;
 
@@ -1857,9 +1884,7 @@ write_data_from_auth (DBusTransport *transport)
                                      &buffer))
     return FALSE;
 
-  bytes_written = _dbus_write_socket (socket_transport->fd,
-                                      buffer,
-                                      0, _dbus_string_get_length (buffer));
+  bytes_written = kdbus_send_auth (transport, buffer);
 
   if (bytes_written > 0)
     {
@@ -1955,7 +1980,7 @@ do_authentication (DBusTransport *transport,
 
   oom = FALSE;
 
-  orig_auth_state = _dbus_transport_get_is_authenticated (transport);
+  orig_auth_state = _dbus_transport_try_to_authenticate (transport);
 
   /* This is essential to avoid the check_write_watch() at the end,
    * we don't want to add a write watch in do_iteration before
@@ -1970,7 +1995,7 @@ do_authentication (DBusTransport *transport,
 
   _dbus_transport_ref (transport);
 
-  while (!_dbus_transport_get_is_authenticated (transport) &&
+   while (!_dbus_transport_try_to_authenticate (transport) &&
          _dbus_transport_get_is_connected (transport))
     {
       if (!exchange_credentials (transport, do_reading, do_writing))
@@ -2027,7 +2052,7 @@ do_authentication (DBusTransport *transport,
 
  out:
   if (auth_completed)
-    *auth_completed = (orig_auth_state != _dbus_transport_get_is_authenticated (transport));
+    *auth_completed = (orig_auth_state != _dbus_transport_try_to_authenticate (transport));
 
   check_read_watch (transport);
   check_write_watch (transport);
@@ -2049,7 +2074,7 @@ do_writing (DBusTransport *transport)
 
 #ifdef DBUS_AUTHENTICATION
        /* No messages without authentication! */
-       if (!_dbus_transport_get_is_authenticated (transport))
+       if (!_dbus_transport_try_to_authenticate (transport))
     {
                _dbus_verbose ("Not authenticated, not writing anything\n");
                return TRUE;
@@ -2081,9 +2106,12 @@ do_writing (DBusTransport *transport)
 
                message = _dbus_connection_get_message_to_send (transport->connection);
                _dbus_assert (message != NULL);
-               dbus_message_unlock(message);
-           dbus_message_set_sender(message, socket_transport->sender);
-               dbus_message_lock (message);
+               if(dbus_message_get_sender(message) == NULL)  //needed for daemon
+               {
+            dbus_message_unlock(message);
+            dbus_message_set_sender(message, socket_transport->sender);
+            dbus_message_lock (message);
+               }
                _dbus_message_get_network_data (message, &header, &body);
                total_bytes_to_write = _dbus_string_get_length(header) + _dbus_string_get_length(body);
                pDestination = dbus_message_get_destination(message);
@@ -2205,7 +2233,7 @@ do_reading (DBusTransport *transport)
 
 #ifdef DBUS_AUTHENTICATION
   /* No messages without authentication! */
-  if (!_dbus_transport_get_is_authenticated (transport))
+  if (!_dbus_transport_try_to_authenticate (transport))
     return TRUE;
 #endif
 
@@ -2448,7 +2476,7 @@ kdbus_connection_set (DBusTransport *transport)
 {
   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
 
-  dbus_connection_set_is_authenticated(transport->connection); //todo remove when authentication will work
+  dbus_connection_set_is_authenticated(transport->connection); //now we don't have authentication in kdbus
 
   _dbus_watch_set_handler (socket_transport->write_watch,
                            _dbus_connection_handle_watch,
@@ -2476,7 +2504,7 @@ kdbus_connection_set (DBusTransport *transport)
   return TRUE;
 }
 
-/**
+/**  original dbus copy-pasted
  * @todo We need to have a way to wake up the select sleep if
  * a new iteration request comes in with a flag (read/write) that
  * we're not currently serving. Otherwise a call that just reads
@@ -2510,7 +2538,7 @@ kdbus_do_iteration (DBusTransport *transport,
    poll_fd.fd = socket_transport->fd;
    poll_fd.events = 0;
 
-   if (_dbus_transport_peek_is_authenticated (transport))
+   if (_dbus_transport_try_to_authenticate (transport))
    {
       /* This is kind of a hack; if we have stuff to write, then try
        * to avoid the poll. This is probably about a 5% speedup on an