From: Pawel Polawski Date: Tue, 3 Sep 2013 15:23:38 +0000 (+0200) Subject: Implement new API for get GID and UID by cookie X-Git-Tag: submit/tizen/20140307.131547~75 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=43b6d1b615b4b027048663f232fce6f8a247c1bc;p=platform%2Fcore%2Fsecurity%2Fsecurity-server.git Implement new API for get GID and UID by cookie [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 --- diff --git a/packaging/security-server.spec b/packaging/security-server.spec index bed2e2d..2502a42 100644 --- a/packaging/security-server.spec +++ b/packaging/security-server.spec @@ -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} diff --git a/src/include/security-server.h b/src/include/security-server.h index 8561a8f..6ce0934 100644 --- a/src/include/security-server.h +++ b/src/include/security-server.h @@ -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 } diff --git a/src/server2/client/client-cookie.cpp b/src/server2/client/client-cookie.cpp index 0c72aa7..27f2201 100644 --- a/src/server2/client/client-cookie.cpp +++ b/src/server2/client/client-cookie.cpp @@ -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 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(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 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(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; +} + diff --git a/src/server2/common/protocols.cpp b/src/server2/common/protocols.cpp index cc9ac5a..6978181 100644 --- a/src/server2/common/protocols.cpp +++ b/src/server2/common/protocols.cpp @@ -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; diff --git a/src/server2/common/protocols.h b/src/server2/common/protocols.h index 8eead85..29ee384 100644 --- a/src/server2/common/protocols.h +++ b/src/server2/common/protocols.h @@ -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; diff --git a/src/server2/service/cookie-jar.cpp b/src/server2/service/cookie-jar.cpp index 5b1ff50..0c80aea 100644 --- a/src/server2/service/cookie-jar.cpp +++ b/src/server2/service/cookie-jar.cpp @@ -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(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; diff --git a/src/server2/service/cookie-jar.h b/src/server2/service/cookie-jar.h index 416b3d1..3921ff2 100644 --- a/src/server2/service/cookie-jar.h +++ b/src/server2/service/cookie-jar.h @@ -41,7 +41,9 @@ enum class CompareType PID, PATH, SMACKLABEL, - PERMISSIONS + PERMISSIONS, + UID, + GID }; @@ -49,6 +51,8 @@ struct Cookie { std::vector 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 permissions; //owner GIDs diff --git a/src/server2/service/cookie.cpp b/src/server2/service/cookie.cpp index ac5d8fe..cadba47 100644 --- a/src/server2/service/cookie.cpp +++ b/src/server2/service/cookie.cpp @@ -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,26 +135,44 @@ 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; + default: + LogDebug("Error, unknown function called by client"); + 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; @@ -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 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 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 diff --git a/src/server2/service/cookie.h b/src/server2/service/cookie.h index 05507f2..78ee0fd 100644 --- a/src/server2/service/cookie.h +++ b/src/server2/service/cookie.h @@ -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; diff --git a/systemd/CMakeLists.txt b/systemd/CMakeLists.txt index 006e4a3..f0151fc 100644 --- a/systemd/CMakeLists.txt +++ b/systemd/CMakeLists.txt @@ -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 index 0000000..803609b --- /dev/null +++ b/systemd/security-server-cookie-check-tmp.socket @@ -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 diff --git a/systemd/security-server.service b/systemd/security-server.service index c36ed9d..610e6ff 100644 --- a/systemd/security-server.service +++ b/systemd/security-server.service @@ -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