PageRenderTime 23ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://gitlab.com/admin-github-cloud/cynara
C++ | 196 lines | 125 code | 42 blank | 29 comment | 36 complexity | 78265becb00fb64fc1e7c2c312995eed MD5 | raw file
  1. /*
  2. * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License
  15. */
  16. /**
  17. * @file src/helpers/creds-dbus/creds-dbus-inner.cpp
  18. * @author Radoslaw Bartosiak <r.bartosiak@samsung.com>
  19. * @author Aleksander Zdyb <a.zdyb@samsung.com>
  20. * @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
  21. * @version 1.0
  22. * @brief Implementation of internal libcynara-creds-dbus functions
  23. */
  24. #include <attributes/attributes.h>
  25. #include <string>
  26. #include <string.h>
  27. #include <cynara-error.h>
  28. #include "creds-dbus-inner.h"
  29. // TODO: Move this class somewhere else
  30. // TODO: Find a better name for this class
  31. // TODO: Introduce std::exception instead of throwing ints
  32. // TODO: Make this class more general
  33. // TODO: Write tests for this class
  34. class DBusMethod {
  35. public:
  36. typedef int ArgType;
  37. DBusMethod(DBusConnection *connection, const std::string &method) : m_connection(connection) {
  38. if (connection == nullptr)
  39. throw CYNARA_API_INVALID_PARAM;
  40. m_message = dbus_message_new_method_call(m_dbusName, m_dbusObject,
  41. m_dbusInterface, method.c_str());
  42. if (m_message == nullptr)
  43. throw CYNARA_API_OUT_OF_MEMORY;
  44. }
  45. ~DBusMethod() {
  46. if (m_message != nullptr)
  47. dbus_message_unref(m_message);
  48. delete m_argsIter;
  49. }
  50. void appendArg(ArgType type, void *value) {
  51. if (dbus_message_append_args(m_message, type, value, DBUS_TYPE_INVALID) == FALSE)
  52. throw CYNARA_API_UNKNOWN_ERROR;
  53. }
  54. void getArgPtr(ArgType type, void *value) {
  55. if (m_argsIter == nullptr)
  56. throw CYNARA_API_UNKNOWN_ERROR;
  57. if (dbus_message_iter_get_arg_type(m_argsIter) != type)
  58. throw CYNARA_API_UNKNOWN_ERROR;
  59. dbus_message_iter_get_basic(m_argsIter, value);
  60. dbus_message_iter_next(m_argsIter);
  61. }
  62. DBusMethod send(void) {
  63. DBusPendingCall *reply = nullptr;
  64. auto ret = dbus_connection_send_with_reply(m_connection, m_message, &reply,
  65. DBUS_TIMEOUT_USE_DEFAULT);
  66. if (ret == FALSE)
  67. throw CYNARA_API_OUT_OF_MEMORY;
  68. if (reply == nullptr)
  69. throw CYNARA_API_INVALID_PARAM;
  70. dbus_connection_flush(m_connection);
  71. dbus_pending_call_block(reply);
  72. DBusMessage *replyMsg = dbus_pending_call_steal_reply(reply);
  73. if (replyMsg == nullptr)
  74. throw CYNARA_API_UNKNOWN_ERROR;
  75. return { m_connection, replyMsg };
  76. }
  77. private:
  78. DBusMethod(DBusConnection *connection, DBusMessage *message)
  79. : m_connection(connection), m_message(message), m_argsIter(new DBusMessageIter()) {
  80. if (dbus_message_iter_init(m_message, m_argsIter) == FALSE)
  81. throw CYNARA_API_UNKNOWN_ERROR;
  82. }
  83. DBusConnection *m_connection = nullptr;
  84. DBusMessage *m_message = nullptr;
  85. DBusMessageIter *m_argsIter = nullptr;
  86. static const char m_dbusName[];
  87. static const char m_dbusObject[];
  88. static const char m_dbusInterface[];
  89. };
  90. const char DBusMethod::m_dbusName[] = "org.freedesktop.DBus";
  91. const char DBusMethod::m_dbusObject[] = "/org/freedesktop/DBus";
  92. const char DBusMethod::m_dbusInterface[] = "org.freedesktop.DBus";
  93. int getIdFromConnection(DBusConnection *connection, const char *uniqueName,
  94. const std::string &dbusMethod, unsigned int *id) {
  95. if (uniqueName == nullptr)
  96. return CYNARA_API_INVALID_PARAM;
  97. if (dbusMethod != "GetConnectionUnixUser" && dbusMethod != "GetConnectionUnixProcessID")
  98. return CYNARA_API_INVALID_PARAM;
  99. try {
  100. DBusMethod call(connection, dbusMethod);
  101. call.appendArg(DBUS_TYPE_STRING, &uniqueName);
  102. auto reply = call.send();
  103. reply.getArgPtr(DBUS_TYPE_UINT32, id);
  104. } catch (int apiError) {
  105. return apiError;
  106. }
  107. return CYNARA_API_SUCCESS;
  108. }
  109. int getClientSmackLabel(DBusConnection *connection, const char *uniqueName, char **client) {
  110. if (uniqueName == nullptr)
  111. return CYNARA_API_INVALID_PARAM;
  112. try {
  113. DBusMethod call(connection, "GetConnectionSmackContext");
  114. call.appendArg(DBUS_TYPE_STRING, &uniqueName);
  115. auto reply = call.send();
  116. char *label;
  117. reply.getArgPtr(DBUS_TYPE_STRING, &label);
  118. *client = strdup(label);
  119. if (*client == nullptr)
  120. return CYNARA_API_OUT_OF_MEMORY;
  121. } catch (int apiError) {
  122. return apiError;
  123. }
  124. return CYNARA_API_SUCCESS;
  125. }
  126. int getUint32(DBusConnection *connection, const char *uniqueName, const char *method,
  127. char **value) {
  128. unsigned int dbusValue;
  129. int ret = getIdFromConnection(connection, uniqueName, method, &dbusValue);
  130. if (ret != CYNARA_API_SUCCESS)
  131. return ret;
  132. *value = strdup(std::to_string(dbusValue).c_str());
  133. if (*value == nullptr)
  134. return CYNARA_API_OUT_OF_MEMORY;
  135. return CYNARA_API_SUCCESS;
  136. }
  137. int getClientPid(DBusConnection *connection, const char *uniqueName, char **client) {
  138. return getUint32(connection, uniqueName, "GetConnectionUnixProcessID", client);
  139. }
  140. int getUserId(DBusConnection *connection, const char *uniqueName, char **user) {
  141. return getUint32(connection, uniqueName, "GetConnectionUnixUser", user);
  142. }
  143. int getUserGid(DBusConnection *connection UNUSED, const char *uniqueName UNUSED,
  144. char **user UNUSED) {
  145. //todo
  146. return CYNARA_API_METHOD_NOT_SUPPORTED;
  147. }
  148. int getPid(DBusConnection *connection, const char *uniqueName, pid_t *pid) {
  149. unsigned int _pid;
  150. auto ret = getIdFromConnection(connection, uniqueName, "GetConnectionUnixProcessID", &_pid);
  151. if (ret == CYNARA_API_SUCCESS)
  152. *pid = _pid;
  153. return ret;
  154. }