Add dbus helper API to fetch all credentials in one call
authorZofia Abramowska <z.abramowska@samsung.com>
Thu, 15 Dec 2022 22:39:53 +0000 (23:39 +0100)
committerTomasz Swierczek <t.swierczek@samsung.com>
Tue, 27 Dec 2022 06:01:58 +0000 (07:01 +0100)
Change-Id: I17653b94fe79065354bdb82c52c378d9126dab15

src/helpers/creds-dbus/CMakeLists.txt
src/helpers/creds-dbus/creds-dbus.cpp
src/include/cynara-creds-dbus.h

index 7f5da6c9bcb67b29d1b806dc43f88cf1bed3e470..09d6636ba645aeaf328030f7ba7c31881ee7676e 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2014-2020 Samsung Electronics Co., Ltd All Rights Reserved
+# Copyright (c) 2014-2022 Samsung Electronics Co., Ltd All Rights Reserved
 #
 # This file is licensed under the terms of MIT License or the Apache License
 # Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -27,9 +27,11 @@ SET(LIB_CREDS_DBUS_VERSION_MAJOR 0)
 SET(LIB_CREDS_DBUS_VERSION ${LIB_CREDS_DBUS_VERSION_MAJOR}.17.2)
 
 SET(LIB_CREDS_DBUS_PATH ${CYNARA_PATH}/helpers/creds-dbus)
+SET(LIB_CREDS_COMMONS_PATH ${CYNARA_PATH}/helpers/creds-commons)
 
 SET(LIB_CREDS_DBUS_SOURCES
     ${LIB_CREDS_DBUS_PATH}/creds-dbus.cpp
+    ${LIB_CREDS_COMMONS_PATH}/creds-inner.cpp
     )
 
 PKG_CHECK_MODULES(LIB_CREDS_DBUS_DEP
@@ -44,6 +46,7 @@ INCLUDE_DIRECTORIES(
 INCLUDE_DIRECTORIES(
     ${CYNARA_PATH}/include
     ${LIB_CREDS_DBUS_PATH}
+    ${LIB_CREDS_COMMONS_PATH}
     )
 
 ADD_LIBRARY(${TARGET_LIB_CREDS_DBUS} SHARED ${LIB_CREDS_DBUS_SOURCES})
index 9a266c84a5d1dd0dbeedc26b7d30e5f5d33503a7..81c1d3476b69a179d233fd192595ccbc157d5e88 100644 (file)
@@ -28,7 +28,6 @@
  * @brief       Implementation of external libcynara-creds-dbus API
  */
 
-
 #include <attributes/attributes.h>
 #include <string>
 #include <string.h>
@@ -38,6 +37,9 @@
 #include <cynara-error.h>
 #include <log/log.h>
 
+#include <Credentials.h>
+#include <creds-inner.h>
+
 namespace {
 
 const char dbusName[] = "org.freedesktop.DBus";
@@ -45,31 +47,30 @@ const char dbusObject[] = "/org/freedesktop/DBus";
 const char dbusInterface[] = "org.freedesktop.DBus";
 const char dbusMethod[] = "GetConnectionCredentials";
 
-struct Credentials
-{
-    Credentials() : m_pid(0), m_isPidSet(false), m_uid(0), m_isUidSet(false),
-                    m_securityLabel(nullptr), m_isSecuritySet(false) {
+class DBusCredentials : public Credentials {
+public:
+    DBusCredentials() : m_pid(0), m_uid(0), m_securityLabel(nullptr) {}
 
-    }
     int init(DBusConnection *connection, const char *uniqueId) {
         DBusMessageIter args_iter, arr_iter, pair_iter, var_iter;
 
-        m_message = dbus_message_new_method_call(dbusName, dbusObject, dbusInterface, dbusMethod);
-        if (m_message == nullptr)
+        LOGW("Attempting to initialize DBusCredentials");
+        DBusMessage *message = dbus_message_new_method_call(dbusName, dbusObject, dbusInterface, dbusMethod);
+        if (message == nullptr)
             return CYNARA_API_OUT_OF_MEMORY;
 
-        if (!dbus_message_append_args(m_message, DBUS_TYPE_STRING, &uniqueId, DBUS_TYPE_INVALID))
+        if (!dbus_message_append_args(message, DBUS_TYPE_STRING, &uniqueId, DBUS_TYPE_INVALID))
             return CYNARA_API_UNKNOWN_ERROR;
 
 
         LOGW("Calling %s on %s", dbusMethod, dbusName);
-        m_reply = dbus_connection_send_with_reply_and_block(connection, m_message,
-                                                            DBUS_TIMEOUT_USE_DEFAULT, nullptr);
+        DBusMessage *reply = dbus_connection_send_with_reply_and_block(connection, message,
+                                   DBUS_TIMEOUT_USE_DEFAULT, nullptr);
         LOGW("%s returned", dbusMethod);
-        if (m_reply == nullptr)
+        if (reply == nullptr)
             return CYNARA_API_UNKNOWN_ERROR;
 
-        if (!dbus_message_iter_init(m_reply, &args_iter) ||
+        if (!dbus_message_iter_init(reply, &args_iter) ||
             dbus_message_iter_get_arg_type(&args_iter) != DBUS_TYPE_ARRAY ||
             dbus_message_iter_get_element_type(&args_iter) != DBUS_TYPE_DICT_ENTRY)
             return CYNARA_API_UNKNOWN_ERROR;
@@ -124,122 +125,97 @@ struct Credentials
             }
             dbus_message_iter_next(&arr_iter);
         }
+
+        dbus_message_unref(message);
+        dbus_message_unref(reply);
+
         return CYNARA_API_SUCCESS;
     }
-    ~Credentials() {
+    virtual ~DBusCredentials() {
         free(m_securityLabel);
-        dbus_message_unref(m_message);
-        dbus_message_unref(m_reply);
     }
 
-    bool isPidSet(void) const { return m_isPidSet; }
-    bool isUidSet(void) const { return m_isUidSet; }
-    bool isSecurityLabelSet(void) const { return m_isSecuritySet; }
+    pid_t getPid(void) const { return m_pid; }
+    char *getPidStr(void) const {
+        return strdup(std::to_string(m_pid).c_str());
+    }
+    char *getUidStr(void) const {
+        return strdup(std::to_string(m_uid).c_str());
+    }
+    char *getSecurityLabel(void) const {
+        return strdup(m_securityLabel);
+    }
 
+private:
     dbus_uint32_t m_pid;
-    bool m_isPidSet;
     dbus_uint32_t m_uid;
-    bool m_isUidSet;
     char *m_securityLabel;
-    bool m_isSecuritySet;
 
-private:
-    DBusMessage *m_message = nullptr;
-    DBusMessage *m_reply = nullptr;
 };
 } // namespace anonymous
 
 CYNARA_API
-int cynara_creds_dbus_get_client(DBusConnection *connection, const char *uniqueName,
-                                 enum cynara_client_creds method, char **client) {
-    int ret;
-
-    if (connection == nullptr || uniqueName == nullptr || client == nullptr)
+int cynara_creds_dbus_get(DBusConnection *connection, const char *uniqueName,
+                          const enum cynara_client_creds *pClientMethod, char **client,
+                          const enum cynara_user_creds *pUserMethod, char **user,
+                          pid_t *pid) {
+    if (connection == nullptr || uniqueName == nullptr) {
         return CYNARA_API_INVALID_PARAM;
-
-    if (method == cynara_client_creds::CLIENT_METHOD_DEFAULT) {
-        ret = cynara_creds_get_default_client_method(&method);
-        if (ret != CYNARA_API_SUCCESS)
-            return ret;
     }
 
-    Credentials credentials;
-    LOGW("Attempting to initialize Credentials");
-    ret = credentials.init(connection, uniqueName);
-    if (ret != CYNARA_API_SUCCESS)
+    DBusCredentials credentials;
+    int ret = credentials.init(connection, uniqueName);
+    if (ret != CYNARA_API_SUCCESS) {
         return ret;
-
-    switch (method) {
-        case cynara_client_creds::CLIENT_METHOD_SMACK:
-            if (!credentials.isSecurityLabelSet())
-                return CYNARA_API_UNKNOWN_ERROR;
-            *client = strdup(credentials.m_securityLabel);
-            if (*client == nullptr)
-                return CYNARA_API_OUT_OF_MEMORY;
-            break;
-        case cynara_client_creds::CLIENT_METHOD_PID:
-            if (!credentials.isPidSet())
-                return CYNARA_API_UNKNOWN_ERROR;
-            *client = strdup(std::to_string(credentials.m_pid).c_str());
-            if (*client == nullptr)
-                return CYNARA_API_OUT_OF_MEMORY;
-            break;
-        default:
-            return CYNARA_API_METHOD_NOT_SUPPORTED;
     }
-    LOGW("cynara_creds_dbus_get_client returns %d", ret);
+
+    ret = cynara_creds_inner_get(credentials, pClientMethod, client,
+                                 pUserMethod, user, pid);
+
+    LOGW("cynara_creds_dbus_get returns %d", ret);
     return ret;
 }
 
 CYNARA_API
-int cynara_creds_dbus_get_user(DBusConnection *connection, const char *uniqueName,
-                               enum cynara_user_creds method, char **user) {
-    int ret;
-
-    if (connection == nullptr || uniqueName == nullptr || user == nullptr)
+int cynara_creds_dbus_get_default(DBusConnection *connection, const char *uniqueName,
+                                  char **client, char **user, pid_t *pid) {
+    if (connection == nullptr || uniqueName == nullptr) {
         return CYNARA_API_INVALID_PARAM;
-
-    if (method == cynara_user_creds::USER_METHOD_DEFAULT) {
-        ret = cynara_creds_get_default_user_method(&method);
-        if (ret != CYNARA_API_SUCCESS)
-            return ret;
     }
 
-    Credentials credentials;
-    ret = credentials.init(connection, uniqueName);
-    if (ret != CYNARA_API_SUCCESS)
+    DBusCredentials credentials;
+    int ret = credentials.init(connection, uniqueName);
+    if (ret != CYNARA_API_SUCCESS) {
         return ret;
-
-    switch (method) {
-        case cynara_user_creds::USER_METHOD_UID:
-            if (!credentials.isUidSet())
-                return CYNARA_API_UNKNOWN_ERROR;
-            *user = strdup(std::to_string(credentials.m_uid).c_str());
-            if (*user == nullptr)
-                return CYNARA_API_OUT_OF_MEMORY;
-            break;
-        case cynara_user_creds::USER_METHOD_GID:
-            return CYNARA_API_METHOD_NOT_SUPPORTED;
-        default:
-            return CYNARA_API_METHOD_NOT_SUPPORTED;
     }
+
+    ret = cynara_creds_inner_get_default(credentials, client, user, pid);
+    LOGW("cynara_creds_dbus_get_default returns %d", ret);
     return ret;
 }
 
 CYNARA_API
-int cynara_creds_dbus_get_pid(DBusConnection *connection, const char *uniqueName, pid_t *pid) {
-    if (connection == nullptr || uniqueName == nullptr || pid == nullptr)
-        return CYNARA_API_INVALID_PARAM;
-
-    Credentials credentials;
-    int ret = credentials.init(connection, uniqueName);
-    if (ret != CYNARA_API_SUCCESS)
-        return ret;
-
-    if (!credentials.isPidSet())
-        return CYNARA_API_UNKNOWN_ERROR;
+int cynara_creds_dbus_get_client(DBusConnection *connection, const char *uniqueName,
+                                 enum cynara_client_creds method, char **client) {
+    int ret = cynara_creds_dbus_get(connection, uniqueName, &method, client, nullptr,
+                                    nullptr, nullptr);
+    LOGW("cynara_creds_dbus_get_client returns %d", ret);
+    return ret;
+}
 
-    *pid = credentials.m_pid;
+CYNARA_API
+int cynara_creds_dbus_get_user(DBusConnection *connection, const char *uniqueName,
+                               enum cynara_user_creds method, char **user) {
+    int ret = cynara_creds_dbus_get(connection, uniqueName, nullptr, nullptr, &method,
+                                     user, nullptr);
+    LOGW("cynara_creds_dbus_get_user returns %d", ret);
+    return ret;
+}
 
+CYNARA_API
+int cynara_creds_dbus_get_pid(DBusConnection *connection, const char *uniqueName, pid_t *pid) {
+    int ret = cynara_creds_dbus_get(connection, uniqueName, nullptr, nullptr, nullptr,
+                                     nullptr, pid);
+    LOGW("cynara_creds_dbus_get_pid returns %d", ret);
     return ret;
 }
index b9cbea2ba64b8253699dc442d4b7018a26ab8ce5..633f2d990662e6f88b6098245927381de10634c0 100644 (file)
 extern "C" {
 #endif
 
+/**
+ * \par Description:
+ * Creates a client identification string, user identification string with default methods
+ * from Cynara configuration file, or PID identification. Client is a process identified
+ * by the unique name at the other side of the dbus connection. User is an executor of
+ * process at the other side of the socket. User can fetch any of the three, function will fail
+*  only when none of the client, user or pid are requested.
+ *
+ * \par Purpose:
+ * Client and user identification strings are required for cynara_check() and
+ * cynara_async_create_request() functions. PID may be used for client_session creation with
+ * cynara_helper_session_from_pid() function from libcynara-helper-session library.
+ * Client_session is needed for cynara_check() and cynara_async_create_request() functions.
+ *
+ * \par Typical use case:
+ * The function is called before the call of cynara_check() or cynara_async_create_request()
+ * function. Returned PID may be used to create client_session using function
+ * cynara_helper_session_from_pid(). Returned strings are used as client, user and pid parameters
+ * in cynara_check() or cynara_async_create_request() function.
+ * Strings are released with g_free() function when they are no longer needed.
+ *
+ * \par Method of function operation:
+ * The function generates client string, user string and PID by calling a method from
+ * DBus Interface ("org.freedesktop.DBus") which is placed on system bus ("org.freedesktop.DBus").
+ *
+ * \par Sync (or) Async:
+ * This is a synchronous API.
+ *
+ * \par Thread safety:
+ * This function is NOT thread-safe. If functions from described API are called by multithreaded
+ * application from different threads, they must be put into mutex protected critical section.
+ *
+ * \par Important notes:
+ * Memory for returned all strings should be freed with g_free().
+ * Allocated strings are returned only, when function succeeds.
+ *
+ * \param[in] connection DBus connection to a bus. It manages incomming and outgoing messages
+ * \param[in] uniqueName DBus identifier of the client
+ * \param[out] client Placeholder for allocated string containing client id
+ * \param[out] user Placeholder for allocated string containing client id
+ * \param[out] pid Placeholder for PID returned by function
+ *
+ * \return CYNARA_API_SUCCESS on success
+ * \return CYNARA_API_INVALID_PARAM when all client, user and pid are NULL or uniqueName
+ *                                  and connection have wrong value (i.e NULL or non-existing)
+ *                                  or given method is NULL for identifier thas is not.
+ * \return CYNARA_API_CONFIGURATION_ERROR if the configuration file can not be opened or
+ *                                        there are errors in configuration file
+ * \return CYNARA_API_METHOD_NOT_SUPPORTED when requested method is not supported
+ */
+int cynara_creds_dbus_get_default(DBusConnection *connection, const char *uniqueName,
+                                  char **client, char **user, pid_t *pid);
+
+/**
+ * \par Description:
+ * Creates a client identification string with given method, user identification string with
+ * given method, or PID identification. Client is a process identified by the unique name
+ * at the other side of the dbus connection. User is an executor of process at the other side
+ * of socket. User can fetch any of the three, function will fail only when none of the client,
+ * user or pid are requested.
+ *
+ * \par Purpose:
+ * Client and user identification strings are required for cynara_check() and
+ * cynara_async_create_request() functions. PID may be used for client_session creation with
+ * cynara_helper_session_from_pid() function from libcynara-helper-session library.
+ * Client_session is needed for cynara_check() and cynara_async_create_request() functions.
+ *
+ * \par Typical use case:
+ * The function is called before the call of cynara_check() or cynara_async_create_request()
+ * function. Returned PID may be used to create client_session using function
+ * cynara_helper_session_from_pid(). Returned strings are used as client, user and pid
+ * parameters in cynara_check() or cynara_async_create_request() function.
+ * Strings are released with g_free() function when they are no longer needed.
+ *
+ * \par Method of function operation:
+ * The function generates client string, user string and PID by calling a method from
+ * DBus Interface ("org.freedesktop.DBus") which is placed on system bus ("org.freedesktop.DBus").
+ *
+ * \par Sync (or) Async:
+ * This is a synchronous API.
+ *
+ * \par Thread safety:
+ * This function is NOT thread-safe. If functions from described API are called by multithreaded
+ * application from different threads, they must be put into mutex protected critical section.
+ *
+ * \par Important notes:
+ * Memory for returned all strings should be freed with g_free().
+ * Allocated strings are returned only, when function succeeds.
+ * If methods are CLIENT_METHOD_DEFAULT or USER_METHOD_DEFAULT, then it will be chosen based on
+ * Cynara configuration file.
+ *
+ * \param[in] connection DBus connection to a bus. It manages incomming and outgoing messages
+ * \param[in] uniqueName DBus identifier of the client
+ * \param[in] pClientMethod Pointer to method of client identifier creation
+ * \param[out] client Placeholder for allocated string containing client id
+ * \param[in] pUserMethod Pointer to method of user identifier creation
+ * \param[out] user Placeholder for allocated string containing client id
+ * \param[out] pid Placeholder for PID returned by function
+ *
+ * \return CYNARA_API_SUCCESS on success
+ * \return CYNARA_API_INVALID_PARAM when all client, user and pid are NULL or uniqueName
+ *                                  and connection have wrong value (i.e NULL or non-existing)
+ *                                  or given method is NULL for identifier thas is not.
+ * \return CYNARA_API_CONFIGURATION_ERROR if the configuration file can not be opened or
+ *                                        there are errors in configuration file
+ * \return CYNARA_API_METHOD_NOT_SUPPORTED when requested method is not supported
+ */
+int cynara_creds_dbus_get(DBusConnection *connection, const char *uniqueName,
+                          const enum cynara_client_creds *pClientMethod, char **client,
+                          const enum cynara_user_creds *pUserMethod, char **user,
+                          pid_t *pid);
+
 /**
  * \par Description:
  * Creates a client identification string with given method. Client is a process identified by the