Implement cynara-creds-dbus library 88/26988/6
authorAleksander Zdyb <a.zdyb@partner.samsung.com>
Thu, 4 Sep 2014 13:31:31 +0000 (15:31 +0200)
committerAleksander Zdyb <a.zdyb@partner.samsung.com>
Thu, 4 Sep 2014 13:31:31 +0000 (15:31 +0200)
Signed-off-by: Radoslaw Bartosiak <r.bartosiak@samsung.com>
Signed-off-by: Aleksander Zdyb <a.zdyb@partner.samsung.com>
Change-Id: Iccf9cb0acb1016746d8af7a4ee85714e74f4664e

src/helpers/creds-dbus/creds-dbus-inner.cpp

index f72f073..dbbfb0d 100644 (file)
  */
 
 #include <attributes/attributes.h>
+#include <string>
+#include <string.h>
 
 #include <cynara-client-error.h>
 
 #include "creds-dbus-inner.h"
 
-int getClientSmackLabel(DBusConnection *connection UNUSED, const char *uniqueName UNUSED,
-                   char **client UNUSED) {
-    //todo
-    return CYNARA_API_METHOD_NOT_SUPPORTED;
+// TODO: Move this class somewhere else
+// TODO: Find a better name for this class
+// TODO: Introduce std::exception instead of throwing ints
+// TODO: Make this class more general
+// TODO: Write tests for this class
+class DBusMethod {
+public:
+    typedef int ArgType;
+    DBusMethod(DBusConnection *connection, const std::string &method) : m_connection(connection) {
+        if (connection == nullptr)
+            throw CYNARA_API_INVALID_PARAM;
+
+        m_message = dbus_message_new_method_call(m_dbusName.c_str(), m_dbusObject.c_str(),
+                                                 m_dbusInterface.c_str(), method.c_str());
+
+        if (m_message == nullptr)
+            throw CYNARA_API_OUT_OF_MEMORY;
+    }
+
+    ~DBusMethod() {
+        if (m_message != nullptr)
+            dbus_message_unref(m_message);
+
+        delete m_argsIter;
+    }
+
+    void appendArg(ArgType type, void *value) {
+        if (dbus_message_append_args(m_message, type, value, DBUS_TYPE_INVALID) == FALSE)
+            throw CYNARA_API_UNKNOWN_ERROR;
+    }
+
+    void getArgPtr(ArgType type, void *value) {
+        if (m_argsIter == nullptr)
+            throw CYNARA_API_UNKNOWN_ERROR;
+
+        if (dbus_message_iter_get_arg_type(m_argsIter) != type)
+            throw CYNARA_API_UNKNOWN_ERROR;
+
+        dbus_message_iter_get_basic(m_argsIter, value);
+        dbus_message_iter_next(m_argsIter);
+    }
+
+    DBusMethod send(void) {
+        DBusPendingCall *reply = nullptr;
+        auto ret = dbus_connection_send_with_reply(m_connection, m_message, &reply,
+                                                   DBUS_TIMEOUT_USE_DEFAULT);
+        if (ret == FALSE)
+            throw CYNARA_API_OUT_OF_MEMORY;
+
+        if (reply == nullptr)
+            throw CYNARA_API_INVALID_PARAM;
+
+        dbus_connection_flush(m_connection);
+        dbus_pending_call_block(reply);
+
+        DBusMessage *replyMsg = dbus_pending_call_steal_reply(reply);
+        if (replyMsg == nullptr)
+            throw CYNARA_API_UNKNOWN_ERROR;
+
+        return { m_connection, replyMsg };
+    }
+
+private:
+    DBusMethod(DBusConnection *connection, DBusMessage *message)
+        : m_connection(connection), m_message(message), m_argsIter(new DBusMessageIter()) {
+
+        if (dbus_message_iter_init(m_message, m_argsIter) == FALSE)
+            throw CYNARA_API_UNKNOWN_ERROR;
+    }
+
+    DBusConnection *m_connection = nullptr;
+    DBusMessage *m_message = nullptr;
+    DBusMessageIter *m_argsIter = nullptr;
+
+    static const std::string m_dbusName;
+    static const std::string m_dbusObject;
+    static const std::string m_dbusInterface;
+};
+
+const std::string DBusMethod::m_dbusName = "org.freedesktop.DBus";
+const std::string DBusMethod::m_dbusObject = "/org/freedesktop/DBus";
+const std::string DBusMethod::m_dbusInterface = "org.freedesktop.DBus";
+
+
+int getIdFromConnection(DBusConnection *connection, const char *uniqueName,
+                        const std::string &dbusMethod, unsigned int *id) {
+
+    if (uniqueName == nullptr)
+        return CYNARA_API_INVALID_PARAM;
+
+    if (dbusMethod != "GetConnectionUnixUser" && dbusMethod != "GetConnectionUnixProcessID")
+        return CYNARA_API_INVALID_PARAM;
+
+    try {
+        DBusMethod call(connection, dbusMethod);
+        call.appendArg(DBUS_TYPE_STRING, &uniqueName);
+        auto reply = call.send();
+        reply.getArgPtr(DBUS_TYPE_UINT32, id);
+    } catch (int apiError) {
+        return apiError;
+    }
+
+    return CYNARA_API_SUCCESS;
 }
 
-int getClientPid(DBusConnection *connection UNUSED, const char *uniqueName UNUSED,
-                 char **client UNUSED) {
-    //todo
-    return CYNARA_API_METHOD_NOT_SUPPORTED;
+int getClientSmackLabel(DBusConnection *connection, const char *uniqueName, char **client) {
+    if (uniqueName == nullptr)
+        return CYNARA_API_INVALID_PARAM;
+
+    try {
+        DBusMethod call(connection, "GetConnectionSmackContext");
+        call.appendArg(DBUS_TYPE_STRING, &uniqueName);
+        auto reply = call.send();
+        char *label;
+        reply.getArgPtr(DBUS_TYPE_STRING, &label);
+        *client = strdup(label);
+        if (*client == nullptr)
+          return CYNARA_API_OUT_OF_MEMORY;
+    } catch (int apiError) {
+        return apiError;
+    }
+
+    return CYNARA_API_SUCCESS;
 }
 
-int getUserId(DBusConnection *connection UNUSED, const char *uniqueName UNUSED,
-               char **user UNUSED) {
-    //todo
-    return CYNARA_API_METHOD_NOT_SUPPORTED;
+int getUint32(DBusConnection *connection, const char *uniqueName, const char *method,
+              char **value) {
+    unsigned int dbusValue;
+    int ret = getIdFromConnection(connection, uniqueName, method, &dbusValue);
+
+    if (ret != CYNARA_API_SUCCESS)
+        return ret;
+
+    *value = strdup(std::to_string(dbusValue).c_str());
+
+    if (*value == nullptr)
+      return CYNARA_API_OUT_OF_MEMORY;
+
+    return CYNARA_API_SUCCESS;
+}
+
+int getClientPid(DBusConnection *connection, const char *uniqueName, char **client) {
+    return getUint32(connection, uniqueName, "GetConnectionUnixProcessID", client);
+}
+
+int getUserId(DBusConnection *connection, const char *uniqueName, char **user) {
+    return getUint32(connection, uniqueName, "GetConnectionUnixUser", user);
 }
 
 int getUserGid(DBusConnection *connection UNUSED, const char *uniqueName UNUSED,
@@ -52,7 +185,12 @@ int getUserGid(DBusConnection *connection UNUSED, const char *uniqueName UNUSED,
     return CYNARA_API_METHOD_NOT_SUPPORTED;
 }
 
-int getPid(DBusConnection *connection UNUSED, const char *uniqueName UNUSED, pid_t *pid UNUSED) {
-    //todo
-    return CYNARA_API_METHOD_NOT_SUPPORTED;
+int getPid(DBusConnection *connection, const char *uniqueName, pid_t *pid) {
+    unsigned int _pid;
+    auto ret = getIdFromConnection(connection, uniqueName, "GetConnectionUnixProcessID", &_pid);
+
+    if (ret == CYNARA_API_SUCCESS)
+        *pid = _pid;
+
+    return ret;
 }