Implement new API for get GID and UID by cookie
authorPawel Polawski <p.polawski@partner.samsung.com>
Tue, 3 Sep 2013 15:23:38 +0000 (17:23 +0200)
committerBartlomiej Grzelewski <b.grzelewski@samsung.com>
Thu, 6 Feb 2014 16:13:22 +0000 (17:13 +0100)
[Issue#]        SSDWSSP-399
[Bug/Feature]   New API to security-server
[Cause]         Missing API to get UID and GID by cookie
[Solution]      New API added
[Verification]  Compile, run tests

Change-Id: Ie6f65378a31e65840b682b3a6dc2c9ab3f931ec2

12 files changed:
packaging/security-server.spec
src/include/security-server.h
src/server2/client/client-cookie.cpp
src/server2/common/protocols.cpp
src/server2/common/protocols.h
src/server2/service/cookie-jar.cpp
src/server2/service/cookie-jar.h
src/server2/service/cookie.cpp
src/server2/service/cookie.h
systemd/CMakeLists.txt
systemd/security-server-cookie-check-tmp.socket [new file with mode: 0644]
systemd/security-server.service

index bed2e2d..2502a42 100644 (file)
@@ -87,6 +87,7 @@ ln -s ../security-server-get-object-name.socket %{buildroot}/usr/lib/systemd/sys
 ln -s ../security-server-app-permissions.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/security-server-app-permissions.socket
 ln -s ../security-server-cookie-get.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/security-server-cookie-get.socket
 ln -s ../security-server-cookie-check.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/security-server-cookie-check.socket
+ln -s ../security-server-cookie-check-tmp.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/security-server-cookie-check-tmp.socket
 
 %clean
 rm -rf %{buildroot}
@@ -133,7 +134,8 @@ systemctl daemon-reload
 %attr(-,root,root) /usr/lib/systemd/system/security-server-cookie-get.socket
 %attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/security-server-cookie-check.socket
 %attr(-,root,root) /usr/lib/systemd/system/security-server-cookie-check.socket
-
+%attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/security-server-cookie-check-tmp.socket
+%attr(-,root,root) /usr/lib/systemd/system/security-server-cookie-check-tmp.socket
 
 %{_datadir}/license/%{name}
 
index 8561a8f..6ce0934 100644 (file)
@@ -986,6 +986,26 @@ int security_server_app_enable_permissions(const char *app_id, app_type_t app_ty
  */
 int security_server_app_disable_permissions(const char *app_id, app_type_t app_type, const char **perm_list);
 
+/*
+ * This function allows middleware to get UID assigned to cookie
+ *
+ * \param[in] Cookie
+ * \param[out] Handler to store UID
+ *
+ * \return SECURITY_SERVER_SUCCESS on success or error code on fail
+ */
+int security_server_get_uid_by_cookie(const char *cookie, uid_t *uid);
+
+/*
+ * This function allows middleware to get GID assigned to cookie
+ *
+ * \param[in] Cookie
+ * \param[out] Handler to store GID
+ *
+ * \return SECURITY_SERVER_SUCCESS on success or error code on fail
+ */
+int security_server_get_gid_by_cookie(const char *cookie, gid_t *gid);
+
 
 #ifdef __cplusplus
 }
index 0c72aa7..27f2201 100644 (file)
@@ -63,7 +63,7 @@ int security_server_request_cookie(char *cookie, size_t bufferSize)
         }
 
         //put data into buffer
-        Serialization::Serialize(send, (int)CookieGet::COOKIE);
+        Serialization::Serialize(send, (int)CookieCall::GET_COOKIE);
 
         //send buffer to server
         int retval = sendToServer(SERVICE_SOCKET_COOKIE_GET, send.Pop(), recv);
@@ -115,7 +115,7 @@ int security_server_get_cookie_pid(const char *cookie)
 
     try {
         //put data into buffer
-        Serialization::Serialize(send, (int)CookieGet::PID);
+        Serialization::Serialize(send, (int)CookieCall::CHECK_PID);
         Serialization::Serialize(send, key);
 
         //send buffer to server
@@ -162,7 +162,7 @@ char * security_server_get_smacklabel_cookie(const char *cookie)
 
     try {
         //put data into buffer
-        Serialization::Serialize(send, (int)CookieGet::SMACKLABEL);
+        Serialization::Serialize(send, (int)CookieCall::CHECK_SMACKLABEL);
         Serialization::Serialize(send, key);
 
         //send buffer to server
@@ -209,7 +209,7 @@ int security_server_check_privilege(const char *cookie, gid_t privilege)
 
     try {
         //put data into buffer
-        Serialization::Serialize(send, (int)CookieGet::PRIVILEGE_GID);
+        Serialization::Serialize(send, (int)CookieCall::CHECK_PRIVILEGE_GID);
         Serialization::Serialize(send, key);
         Serialization::Serialize(send, (int)privilege);
 
@@ -255,7 +255,7 @@ int security_server_check_privilege_by_cookie(const char *cookie, const char *ob
 
     try {
         //put data into buffer
-        Serialization::Serialize(send, (int)CookieGet::PRIVILEGE);
+        Serialization::Serialize(send, (int)CookieCall::CHECK_PRIVILEGE);
         Serialization::Serialize(send, key);
         Serialization::Serialize(send, obj);
         Serialization::Serialize(send, access);
@@ -281,3 +281,100 @@ int security_server_check_privilege_by_cookie(const char *cookie, const char *ob
 
     return SECURITY_SERVER_API_ERROR_UNKNOWN;
 }
+
+SECURITY_SERVER_API
+int security_server_get_uid_by_cookie(const char *cookie, uid_t *uid)
+{
+    using namespace SecurityServer;
+    SocketBuffer send, recv;
+    int retval = SECURITY_SERVER_API_ERROR_UNKNOWN;
+
+    LogDebug("security_server_get_uid_by_cookie() called");
+
+    if ((cookie == NULL) || (uid == NULL))
+        return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
+
+    //preprae cookie to send
+    std::vector<char> key(cookie, cookie + COOKIE_SIZE);
+
+    try {
+        //put data into buffer
+        Serialization::Serialize(send, (int)CookieCall::CHECK_UID);
+        Serialization::Serialize(send, key);
+
+        //send buffer to server
+        retval = sendToServer(SERVICE_SOCKET_COOKIE_CHECK, send.Pop(), recv);
+        if (retval != SECURITY_SERVER_API_SUCCESS) {
+            LogDebug("Error in sendToServer. Error code: " << retval);
+            return retval;
+        }
+
+        //receive response from server
+        Deserialization::Deserialize(recv, retval);
+        if (retval == SECURITY_SERVER_API_SUCCESS) {
+            int tmp;
+            Deserialization::Deserialize(recv, tmp);
+            *uid = static_cast<uid_t>(tmp);
+        }
+
+        return retval;
+
+    } catch (SocketBuffer::Exception::Base &e) {
+        LogDebug("SecurityServer::SocketBuffer::Exception " << e.DumpToString());
+    } catch (std::exception &e) {
+        LogDebug("STD exception " << e.what());
+    } catch (...) {
+        LogDebug("Unknown exception occured");
+    }
+
+    return SECURITY_SERVER_API_ERROR_UNKNOWN;
+}
+
+SECURITY_SERVER_API
+int security_server_get_gid_by_cookie(const char *cookie, gid_t *gid)
+{
+    using namespace SecurityServer;
+    SocketBuffer send, recv;
+    int retval = SECURITY_SERVER_API_ERROR_UNKNOWN;
+
+    LogDebug("security_server_get_uid_by_cookie() called");
+
+    if ((cookie == NULL) || (gid == NULL))
+        return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
+
+    //preprae cookie to send
+    std::vector<char> key(cookie, cookie + COOKIE_SIZE);
+
+    try {
+        //put data into buffer
+        Serialization::Serialize(send, (int)CookieCall::CHECK_GID);
+        Serialization::Serialize(send, key);
+
+        //send buffer to server
+        retval = sendToServer(SERVICE_SOCKET_COOKIE_CHECK, send.Pop(), recv);
+        if (retval != SECURITY_SERVER_API_SUCCESS) {
+            LogDebug("Error in sendToServer. Error code: " << retval);
+            return retval;
+        }
+
+        //receive response from server
+        Deserialization::Deserialize(recv, retval);
+        if (retval == SECURITY_SERVER_API_SUCCESS) {
+            int tmp;
+            Deserialization::Deserialize(recv, tmp);
+            *gid = static_cast<gid_t>(tmp);
+        }
+
+        return retval;
+
+    } catch (SocketBuffer::Exception::Base &e) {
+        LogDebug("SecurityServer::SocketBuffer::Exception " << e.DumpToString());
+    } catch (std::exception &e) {
+        LogDebug("STD exception " << e.what());
+    } catch (...) {
+        LogDebug("Unknown exception occured");
+    }
+
+    return SECURITY_SERVER_API_ERROR_UNKNOWN;
+}
+
index cc9ac5a..6978181 100644 (file)
@@ -45,6 +45,10 @@ char const * const SERVICE_SOCKET_COOKIE_GET =
     "/tmp/.security-server-api-cookie-get.sock";
 char const * const SERVICE_SOCKET_COOKIE_CHECK =
     "/tmp/.security-server-api-cookie-check.sock";
+//TODO: Merge bellow socket with the one above. This should be done
+//after security-server-api-cookie-check.sock will be protected by smack and has proper label
+char const * const SERVICE_SOCKET_COOKIE_CHECK_TMP =
+    "/tmp/.security-server-api-cookie-check-tmp.sock";
 
 const size_t COOKIE_SIZE = 20;
 
index 8eead85..29ee384 100644 (file)
@@ -38,17 +38,19 @@ extern char const * const SERVICE_SOCKET_GET_OBJECT_NAME;
 extern char const * const SERVICE_SOCKET_APP_PERMISSIONS;
 extern char const * const SERVICE_SOCKET_COOKIE_GET;
 extern char const * const SERVICE_SOCKET_COOKIE_CHECK;
+extern char const * const SERVICE_SOCKET_COOKIE_CHECK_TMP;
 
 enum class AppPermissionsAction { ENABLE, DISABLE };
 
-enum class CookieGet
+enum class CookieCall
 {
-    COOKIE_SIZE,
-    COOKIE,
-    PID,
-    SMACKLABEL,
-    PRIVILEGE_GID,
-    PRIVILEGE
+    GET_COOKIE,
+    CHECK_PID,
+    CHECK_SMACKLABEL,
+    CHECK_PRIVILEGE_GID,
+    CHECK_PRIVILEGE,
+    CHECK_GID,
+    CHECK_UID
 };
 
 extern const size_t COOKIE_SIZE;
index 5b1ff50..0c80aea 100644 (file)
@@ -108,30 +108,35 @@ const Cookie * CookieJar::GenerateCookie(int pid)
 
 
     //get GID list
-    const int LINE_LEN = 128;
     const int NAME_SIZE = 64;
-    char line[LINE_LEN]; //for storing parsed lines
     char filename[NAME_SIZE];
 
     snprintf(filename, NAME_SIZE, "/proc/%d/status", pid);
     std::ifstream status(filename, std::ifstream::binary);
-
-    while (status.getline(line, LINE_LEN)) {  //read line from file
-        if (strncmp(line, "Groups:", 7) == 0)
-            break;
-    }
-
-    char delim[] = ": ";    //separators for strtok: ' ' and ':'
-    char *token = strtok(line, delim);  //1st string is "Group:"
-    while ((token = strtok(NULL, delim))) {
-        int gid = atoi(token);
-        newCookie.permissions.push_back(gid);
+    std::string line;
+
+    while (std::getline(status, line)) {  //read line from file
+        const char *tmp = line.c_str();
+        if (strncmp(line.c_str(), "Uid:", 4) == 0)
+            newCookie.uid = atoi(&tmp[5]);
+        else if (strncmp(line.c_str(), "Gid:", 4) == 0)
+            newCookie.gid = atoi(&tmp[5]);
+        else if (strncmp(line.c_str(), "Groups:", 7) == 0) {
+            char delim[] = ": ";    //separators for strtok: ' ' and ':'
+            char *token = strtok(const_cast<char *>(tmp), delim);  //1st string is "Group:"
+            while ((token = strtok(NULL, delim))) {
+                int gid = atoi(token);
+                newCookie.permissions.push_back(gid);
+            }
+        }
     }
 
     //DEBUG ONLY
     //print info about cookie
     LogDebug("Cookie created");
     LogDebug("PID: " << newCookie.pid);
+    LogDebug("UID: " << newCookie.uid);
+    LogDebug("GID: " << newCookie.gid);
     LogDebug("PATH: " << newCookie.binaryPath);
     LogDebug("LABEL: " << newCookie.smackLabel);
     for (size_t k = 0; k < newCookie.permissions.size(); k++)
@@ -207,6 +212,12 @@ bool CookieJar::CompareCookies(const Cookie &c1, const Cookie &c2, CompareType c
                     return true;
         return false;
 
+    case CompareType::UID:
+        return (c1.uid == c2.uid);
+
+    case CompareType::GID:
+        return (c1.gid == c2.gid);
+
     default:
         LogDebug("Wrong function parameters");
         return false;
index 416b3d1..3921ff2 100644 (file)
@@ -41,7 +41,9 @@ enum class CompareType
     PID,
     PATH,
     SMACKLABEL,
-    PERMISSIONS
+    PERMISSIONS,
+    UID,
+    GID
 };
 
 
@@ -49,6 +51,8 @@ struct Cookie
 {
     std::vector<char> cookieId;     //ID key
     pid_t pid;                      //owner PID
+    uid_t uid;                      //owner UID
+    gid_t gid;                      //owner GID
     std::string binaryPath;         //path to owner binary
     std::string smackLabel;         //owner SMACK label
     std::vector<int> permissions;   //owner GIDs
index ac5d8fe..cadba47 100644 (file)
@@ -36,6 +36,7 @@
 //interfaces ID
 const int INTERFACE_GET = 0;
 const int INTERFACE_CHECK = 1;
+const int INTERFACE_CHECK_TMP = 3;
 
 namespace SecurityServer {
 
@@ -50,9 +51,15 @@ GenericSocketService::ServiceDescriptionVector CookieService::GetServiceDescript
         INTERFACE_CHECK,
         SERVICE_SOCKET_COOKIE_CHECK
     };
+    ServiceDescription sd3 = {
+        "security-server::api-cookie-check",
+        INTERFACE_CHECK_TMP,
+        SERVICE_SOCKET_COOKIE_CHECK_TMP
+    };
     ServiceDescriptionVector v;
     v.push_back(sd1);
     v.push_back(sd2);
+    v.push_back(sd3);
     return v;
 }
 
@@ -116,7 +123,7 @@ bool CookieService::readOne(const ConnectionID &conn, SocketBuffer &buffer, int
     //use received data
     if (interfaceID == INTERFACE_GET) {
         switch(msgType) {
-        case CookieGet::COOKIE:
+        case CookieCall::GET_COOKIE:
             LogDebug("Entering get-cookie server side handler");
             retval = cookieRequest(send, conn.sock);
             break;
@@ -128,22 +135,22 @@ bool CookieService::readOne(const ConnectionID &conn, SocketBuffer &buffer, int
         };
     } else if (interfaceID == INTERFACE_CHECK) {
         switch(msgType) {
-        case CookieGet::PID:
+        case CookieCall::CHECK_PID:
             LogDebug("Entering pid-by-cookie server side handler");
             retval = pidByCookieRequest(buffer, send);
             break;
 
-        case CookieGet::SMACKLABEL:
+        case CookieCall::CHECK_SMACKLABEL:
             LogDebug("Entering smacklabel-by-cookie server side handler");
             retval = smackLabelByCookieRequest(buffer, send);
             break;
 
-        case CookieGet::PRIVILEGE_GID:
+        case CookieCall::CHECK_PRIVILEGE_GID:
             LogDebug("Entering check-privilege-by-cookie-gid server side handler");
             retval = privilegeByCookieGidRequest(buffer, send);
             break;
 
-        case CookieGet::PRIVILEGE:
+        case CookieCall::CHECK_PRIVILEGE:
             LogDebug("Entering check-privilege-by-cookie side handler");
             retval = privilegeByCookieRequest(buffer, send);
             break;
@@ -153,6 +160,24 @@ bool CookieService::readOne(const ConnectionID &conn, SocketBuffer &buffer, int
             retval = false;
             break;
         };
+    } else if (interfaceID == INTERFACE_CHECK_TMP) {
+        //TODO: Merge this interface with INTERFACE_CHECK after INTERFACE_CHECK will be secured by smack 
+        switch(msgType) {
+        case CookieCall::CHECK_UID:
+            LogDebug("Entering get-uid-by-cookie side handler");
+            retval = uidByCookieRequest(buffer, send);
+            break;
+
+        case CookieCall::CHECK_GID:
+            LogDebug("Entering get-gid-by-cookie side handler");
+            retval = gidByCookieRequest(buffer, send);
+            break;
+
+        default:
+            LogDebug("Error, unknown function called by client");
+            retval = false;
+            break;
+        };
     } else {
         LogDebug("Error, wrong interface");
         retval = false;
@@ -208,7 +233,7 @@ bool CookieService::pidByCookieRequest(SocketBuffer &buffer, SocketBuffer &send)
 
     if (searchResult != NULL) {
         Serialization::Serialize(send, (int)SECURITY_SERVER_API_SUCCESS);
-        Serialization::Serialize(send, searchResult->pid);
+        Serialization::Serialize(send, (int)searchResult->pid);
     } else {
         Serialization::Serialize(send, (int)SECURITY_SERVER_API_ERROR_NO_SUCH_COOKIE);
     }
@@ -308,5 +333,57 @@ bool CookieService::privilegeByCookieRequest(SocketBuffer &buffer, SocketBuffer
     return true;
 }
 
+bool CookieService::uidByCookieRequest(SocketBuffer &buffer, SocketBuffer &send)
+{
+    std::vector<char> cookieKey;
+
+    Try {
+        Deserialization::Deserialize(buffer, cookieKey);
+    } Catch (SocketBuffer::Exception::Base) {
+        LogDebug("Broken protocol. Closing socket.");
+        return false;
+    }
+
+    Cookie searchPattern;
+    searchPattern.cookieId = cookieKey;
+
+    const Cookie *searchResult = m_cookieJar.SearchCookie(searchPattern, CompareType::COOKIE_ID);
+
+    if (searchResult != NULL) {
+        Serialization::Serialize(send, (int)SECURITY_SERVER_API_SUCCESS);
+        Serialization::Serialize(send, (int)searchResult->uid);
+    } else {
+        Serialization::Serialize(send, (int)SECURITY_SERVER_API_ERROR_NO_SUCH_COOKIE);
+    }
+
+    return true;
+}
+
+bool CookieService::gidByCookieRequest(SocketBuffer &buffer, SocketBuffer &send)
+{
+    std::vector<char> cookieKey;
+
+    Try {
+        Deserialization::Deserialize(buffer, cookieKey);
+    } Catch (SocketBuffer::Exception::Base) {
+        LogDebug("Broken protocol. Closing socket.");
+        return false;
+    }
+
+    Cookie searchPattern;
+    searchPattern.cookieId = cookieKey;
+
+    const Cookie *searchResult = m_cookieJar.SearchCookie(searchPattern, CompareType::COOKIE_ID);
+
+    if (searchResult != NULL) {
+        Serialization::Serialize(send, (int)SECURITY_SERVER_API_SUCCESS);
+        Serialization::Serialize(send, (int)searchResult->gid);
+    } else {
+        Serialization::Serialize(send, (int)SECURITY_SERVER_API_ERROR_NO_SUCH_COOKIE);
+    }
+
+    return true;
+}
+
 } // namespace SecurityServer
 
index 05507f2..78ee0fd 100644 (file)
@@ -71,6 +71,9 @@ private:
     bool privilegeByCookieGidRequest(SocketBuffer &buffer, SocketBuffer &send);
     bool privilegeByCookieRequest(SocketBuffer &buffer, SocketBuffer &send);
 
+    bool uidByCookieRequest(SocketBuffer &buffer, SocketBuffer &send);
+    bool gidByCookieRequest(SocketBuffer &buffer, SocketBuffer &send);
+
     CookieJar m_cookieJar;
 
     SocketInfoMap m_socketInfoMap;
index 006e4a3..f0151fc 100644 (file)
@@ -9,6 +9,7 @@ INSTALL(FILES
     ${CMAKE_SOURCE_DIR}/systemd/security-server-app-permissions.socket
     ${CMAKE_SOURCE_DIR}/systemd/security-server-cookie-get.socket
     ${CMAKE_SOURCE_DIR}/systemd/security-server-cookie-check.socket
+    ${CMAKE_SOURCE_DIR}/systemd/security-server-cookie-check-tmp.socket
     DESTINATION
     /usr/lib/systemd/system
 )
diff --git a/systemd/security-server-cookie-check-tmp.socket b/systemd/security-server-cookie-check-tmp.socket
new file mode 100644 (file)
index 0000000..803609b
--- /dev/null
@@ -0,0 +1,12 @@
+#This socket should be removed when security-server-api-cookie-check.sock
+#will be protected by smack and has proper label (at the moment it is '*')
+[Socket]
+ListenStream=/tmp/.security-server-api-cookie-check-tmp.sock
+SocketMode=0777
+SmackLabelIPIn=security-server::api-cookie-check
+SmackLabelIPOut=@
+
+Service=security-server.service
+
+[Install]
+WantedBy=sockets.target
index c36ed9d..610e6ff 100644 (file)
@@ -13,6 +13,7 @@ Sockets=security-server-get-object-name.socket
 Sockets=security-server-app-permissions.socket
 Sockets=security-server-cookie-get.socket
 Sockets=security-server-cookie-check.socket
+Sockets=security-server-cookie-check-tmp.socket
 
 [Install]
 WantedBy=multi-user.target