Implement cynara_creds_get_[client|user]_method 06/27306/19
authorRadoslaw Bartosiak <r.bartosiak@samsung.com>
Wed, 10 Sep 2014 13:04:17 +0000 (15:04 +0200)
committerRadoslaw Bartosiak <r.bartosiak@samsung.com>
Fri, 24 Oct 2014 11:38:55 +0000 (13:38 +0200)
The functions enable obtaining system default identification method
for [process|user] by reading a configuration file (default
/etc/cynara/creds.conf).

Change-Id: I662a7681abbaa130a3d628352a13ff950a7affd3
Signed-off-by: Radoslaw Bartosiak <r.bartosiak@samsung.com>
src/helpers/creds-commons/CMakeLists.txt
src/helpers/creds-commons/CredsCommonsInner.cpp [new file with mode: 0644]
src/helpers/creds-commons/CredsCommonsInner.h [new file with mode: 0644]
src/helpers/creds-commons/creds-commons.cpp
src/include/cynara-creds-commons.h
src/include/cynara-error.h

index 8cca765..5dd5007 100644 (file)
@@ -25,6 +25,7 @@ SET(LIB_CREDS_COMMONS_PATH ${CYNARA_PATH}/helpers/creds-commons)
 
 SET(LIB_CREDS_COMMONS_SOURCES
     ${LIB_CREDS_COMMONS_PATH}/creds-commons.cpp
+    ${LIB_CREDS_COMMONS_PATH}/CredsCommonsInner.cpp
     )
 
 INCLUDE_DIRECTORIES(
diff --git a/src/helpers/creds-commons/CredsCommonsInner.cpp b/src/helpers/creds-commons/CredsCommonsInner.cpp
new file mode 100644 (file)
index 0000000..c9f0538
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+ /**
+ * @file        src/helpers/creds-commons/CredsCommonsInner.cpp
+ * @author      Radoslaw Bartosiak <r.bartosiak@samsung.com>
+ * @version     1.0
+ * @brief       Implementation of internal credential commons functions
+ */
+
+#include <algorithm>
+#include <cctype>
+#include <fstream>
+#include <functional>
+#include <sstream>
+#include <string>
+
+#include <log/log.h>
+
+#include <cynara-creds-commons.h>
+#include <cynara-error.h>
+
+#include <CredsCommonsInner.h>
+
+namespace Cynara {
+
+std::string CredsCommonsInnerBackend::credsConfigurationFile(void) {
+    std::string confFile("/etc/cynara/creds.conf");
+#ifdef CYNARA_CONFIGURATION_DIR
+    confFile = std::string(CYNARA_CONFIGURATION_DIR) + std::string("/creds.conf");
+#else
+    LOGW("Cynara compiled without CYNARA_CONFIGURATION_DIR flag."
+         " Using default configuration directory.");
+#endif
+    return confFile;
+}
+// parses stream with configuration skipping comments (from # till the end of line)
+// untill a line of form <non empty key>=<empty or no empty value>
+// is found. Returns true when key and value FOUND, false when no more lines
+bool CredsCommonsInnerBackend::getKeyAndValue(std::istream &f, const std::locale &loc,
+                                              std::string &key, std::string &value) {
+    std::string rawLine;
+    while (std::getline(f, rawLine)) {
+        std::istringstream rawLineStream(rawLine);
+        std::string uncommentedLine;
+        if (std::getline(rawLineStream, uncommentedLine, '#')) {
+            size_t found = uncommentedLine.find_first_of("=");
+            if (found != std::string::npos) {
+                std::string tempKey = uncommentedLine.substr(0, found);
+                std::string tempValue = uncommentedLine.substr(found + 1);
+                if (!tempKey.empty()) {
+                    key = normalizeString(tempKey, loc);
+                    value = normalizeString(tempValue, loc);
+                    return true;
+                }
+            }
+       }
+   }
+   return false;
+}
+
+bool CredsCommonsInnerBackend::interpretValue(const CredentialsMap &methodCodeMap, int &method,
+                                              const std::string &value, bool &occurred) {
+    if (occurred) //two entries in conf file are treated as error
+        return false;
+    occurred = true;
+    auto it = methodCodeMap.find(value);
+    if (it == methodCodeMap.end()) //value is not valid
+        return false;
+
+    method = it->second;
+    return true;
+}
+
+int CredsCommonsInnerBackend::getMethodFromConfigurationFile(const CredentialsMap &methodCodeMap,
+                                                             const std::string &methodName,
+                                                             int &method) {
+    std::ifstream f(credsConfigurationFile());
+    if (!f.is_open())
+        return CYNARA_API_CONFIGURATION_ERROR;
+
+    std::locale loc = f.getloc();
+    bool occurred = false;
+    std::string key, value;
+    int tmpMethod;
+    while (getKeyAndValue(f, loc, key, value))
+        if (key == methodName && !interpretValue(methodCodeMap, tmpMethod, value, occurred))
+            return CYNARA_API_CONFIGURATION_ERROR;
+    if (occurred) {
+        method = tmpMethod;
+        return CYNARA_API_SUCCESS;
+    }
+    return CYNARA_API_CONFIGURATION_ERROR;
+}
+
+// trim from the start
+inline std::string &CredsCommonsInnerBackend::ltrim(std::string &s, const std::locale &loc) {
+    s.erase(s.begin(), std::find_if(s.begin(), s.end(),
+                                    [&loc](char c) { return not(std::isspace(c, loc)); }));
+    return s;
+}
+
+// trim from the end
+inline std::string &CredsCommonsInnerBackend::rtrim(std::string &s, const std::locale &loc) {
+    s.erase(std::find_if(s.rbegin(), s.rend(),
+                         [&loc](char c) { return not(std::isspace(c, loc)); }).base(),
+                         s.end());
+    return s;
+}
+
+inline std::string &CredsCommonsInnerBackend::toLower(std::string &s, const std::locale &loc) {
+    std::transform(s.begin(), s.end(), s.begin(), [&loc](char c) { return std::tolower(c, loc); });
+    return s;
+}
+
+inline std::string &CredsCommonsInnerBackend::normalizeString(std::string &s,
+                                                              const std::locale &loc) {
+    return toLower(ltrim(rtrim(s, loc), loc), loc);
+}
+
+} // namespace Cynara
diff --git a/src/helpers/creds-commons/CredsCommonsInner.h b/src/helpers/creds-commons/CredsCommonsInner.h
new file mode 100644 (file)
index 0000000..afa3b0b
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/**
+ * @file        src/helpers/creds-commons/CredsCommonsInner.h
+ * @author      Radoslaw Bartosiak <r.bartosiak@samsung.com>
+ * @version     1.0
+ * @brief       Declaration of internal credential commons functions
+ */
+
+#ifndef SRC_HELPERS_CREDS_COMMONS_CREDSCOMMONSINNER_H_
+#define SRC_HELPERS_CREDS_COMMONS_CREDSCOMMONSINNER_H_
+
+#include <map>
+#include <string>
+
+namespace Cynara {
+
+typedef std::map<std::string, int> CredentialsMap;
+
+class CredsCommonsInnerBackend {
+    public:
+        static std::string credsConfigurationFile(void);
+        static bool getKeyAndValue(std::istream &f, const std::locale &loc, std::string &key,
+                                   std::string &value);
+        static bool interpretValue(const CredentialsMap &methodCodeMap, int &method,
+                                   const std::string &value, bool &occurred);
+        static int getMethodFromConfigurationFile(const CredentialsMap &methodCodeMap,
+                                                  const std::string &methodName, int &method);
+    private:
+        // trim from the start
+        static std::string &ltrim(std::string &s, const std::locale &loc);
+        // trim from the end
+        static std::string &rtrim(std::string &s, const std::locale &loc);
+        static std::string &toLower(std::string &s, const std::locale &loc);
+        static std::string &normalizeString(std::string &s, const std::locale &loc);
+};
+
+} //namespace Cynara
+
+#endif /* SRC_HELPERS_CREDS_COMMONS_CREDSCOMMONSINNER_H_ */
index 35d2ac7..973f278 100644 (file)
  */
 
 #include <attributes/attributes.h>
+#include <exceptions/TryCatch.h>
 
 #include <cynara-creds-commons.h>
 #include <cynara-error.h>
 
+#include "CredsCommonsInner.h"
+
 CYNARA_API
 int cynara_creds_get_default_client_method(enum cynara_client_creds *method) {
-    //todo read from proper file and parse
+    return Cynara::tryCatch([&] () {
+        int methodCode, ret;
+        static const Cynara::CredentialsMap clientCredsMap{{"smack", CLIENT_METHOD_SMACK},
+                                                           {"pid", CLIENT_METHOD_PID}};
+
+        if ((ret = Cynara::CredsCommonsInnerBackend::
+                           getMethodFromConfigurationFile(clientCredsMap,
+                                                          "client_default",
+                                                          methodCode))
+            != CYNARA_API_SUCCESS)
+            return ret;
 
-    *method = CLIENT_METHOD_SMACK;
-    return CYNARA_API_SUCCESS;
+        *method = static_cast<enum cynara_client_creds>(methodCode);
+        return CYNARA_API_SUCCESS;
+    });
 }
 
 CYNARA_API
 int cynara_creds_get_default_user_method(enum cynara_user_creds *method) {
-    //todo read from proper file and parse
+     return Cynara::tryCatch([&] () {
+        int methodCode, ret;
+        static const Cynara::CredentialsMap userCredsMap{{"uid", USER_METHOD_UID},
+                                                         {"gid", USER_METHOD_GID}};
+        if ((ret = Cynara::CredsCommonsInnerBackend::
+                           getMethodFromConfigurationFile(userCredsMap,
+                                                          "user_default",
+                                                          methodCode))
+            != CYNARA_API_SUCCESS)
+            return ret;
 
-    *method = USER_METHOD_UID;
-    return CYNARA_API_SUCCESS;
+        *method = static_cast<enum cynara_user_creds>(methodCode);
+        return CYNARA_API_SUCCESS;
+    });
 }
index 75e4366..813c1b9 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef CYNARA_CREDS_COMMONS_H
 #define CYNARA_CREDS_COMMONS_H
 
+#include <attributes/attributes.h>
 #include <cynara-error.h>
 
 enum cynara_client_creds {
@@ -53,12 +54,13 @@ extern "C" {
  * for this parameter.
  *
  * \par Typical use case:
- * The function might be called before cynara_creds_dbus_get_client() and cynara_creds_socket_get_client(),
- * when functions shall be invoked with system default value of method parameter.
+ * The function might be called before cynara_creds_dbus_get_client()
+ * and cynara_creds_socket_get_client(), when functions shall be invoked with system default
+ * value of method parameter.
  *
  * \par Method of function operation:
- * Now the function is mocked up. It sets method to CLIENT_METHOD_SMACK and returns CYNARA_API_SUCCESS.
- * In the future the function will probably read the value from /etc/cynara/cynara_client_creds file.
+ * The function will read and return the value of parameter client_default set
+ * in /etc/cynara/creds.conf file (the path is determined by CYNARA_CONFIGURATION_DIR).
  *
  * \par Sync (or) Async:
  * This is a synchronous API.
@@ -69,8 +71,14 @@ extern "C" {
  * \param[out] method Placeholder for system default client feature
  *                     (like CLIENT_METHOD_SMACK, CLIENT_METHOD_PID)
  *
- * \return CYNARA_API_SUCCESS on success, negative error code on error
+ * \return CYNARA_API_SUCCESS on success
+ *         CYNARA_API_CONFIGURATION_ERROR if the configuration file can not be opened or
+ *                                        there are errors in configuration file.
+ *         CYNARA_API_OUT_OF_MEMORY if there is error in memory allocation.
+ *         CYNARA_API_UNKNOWN_ERROR if there is other error.
+ *
  */
+CYNARA_API
 int cynara_creds_get_default_client_method(enum cynara_client_creds *method);
 
 /**
@@ -84,14 +92,13 @@ int cynara_creds_get_default_client_method(enum cynara_client_creds *method);
  * for this parameter.
  *
  * \par Typical use case:
- * The function might be called before cynara_creds_dbus_get_user() and cynara_creds_socket_get_user(),
- * when functions shall be invoked with system default value of method parameter.
+ * The function might be called before cynara_creds_dbus_get_user()
+ * and cynara_creds_socket_get_user() when functions shall be invoked with system default
+ * value of method parameter.
  *
  * \par Method of function operation:
- *
- * The function reads the value from /etc/cynara/cynara_user_creds file.
- * Now the function is mocked up. It sets method to USER_METHOD_UID and returns CYNARA_API_SUCCESS.
- * In the future the function will probably read the value from /etc/cynara/cynara_user_creds file.
+ * The function will read and return the value of parameter user_default set
+ * in /etc/cynara/creds.conf file (the path is determined by CYNARA_CONFIGURATION_DIR).
  *
  * \par Sync (or) Async:
  * This is a synchronous API.
@@ -99,10 +106,16 @@ int cynara_creds_get_default_client_method(enum cynara_client_creds *method);
  * \par Thread safety:
  * This function is thread-safe.
  *
- * \param[out] method Placeholder for system default user feature (like USER_METHOD_UID, USER_METHOD_GID)
+ * \param[out] method Placeholder for system default user feature
+ * (like USER_METHOD_UID, USER_METHOD_GID)
  *
- * \return CYNARA_API_SUCCESS on success, negative error code on error
+ * \return CYNARA_API_SUCCESS on success
+ *         CYNARA_API_CONFIGURATION_ERROR if the configuration file can not be opened or
+ *                                        there are errors in configuration file.
+ *         CYNARA_API_OUT_OF_MEMORY if there is error in memory allocation.
+ *         CYNARA_API_UNKNOWN_ERROR if there is other error.
  */
+CYNARA_API
 int cynara_creds_get_default_user_method(enum cynara_user_creds *method);
 
 #ifdef __cplusplus
index 728fc2a..8ac7de1 100644 (file)
@@ -17,6 +17,7 @@
  * @file        src/include/cynara-error.h
  * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
  * @author      Zofia Abramowska <z.abramowska@samsung.com>
+ * @author      Radoslaw Bartosiak <r.bartosiak@samsung.com>
  * @version     1.0
  * @brief       This file contains error codes returned by APIs of Cynara.
  */
@@ -70,6 +71,8 @@
 /*! \brief   indicating an unknown error */
 #define CYNARA_API_UNKNOWN_ERROR         -10
 
+/*! \brief   indicating configuration error */
+#define CYNARA_API_CONFIGURATION_ERROR   -11
 /** @}*/
 
 #endif /* CYNARA_ERROR_H */