From b9e5027857ee64ae3c9c6ceb85d8dd5ceb736ff5 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Thu, 8 May 2014 21:23:43 +0200 Subject: [PATCH] Bring back part of app-permissions service [Cause] security_server_app_has_permission function is needed for temporary cynara (bootstrap) version [Solution] roll back part of commit ed1815535d0383bc343bb92062fe934b44f4e53d [Verification] compile and install security-server Change-Id: I3a51ee09a554a5561d559f0a30dc25f9b74e2d76 Signed-off-by: Lukasz Wojciechowski --- build/security-server/security-server.pc.in | 4 +- packaging/security-server.spec | 3 + src/CMakeLists.txt | 2 + src/include/security-server.h | 20 ++- src/server/client/client-app-permissions.cpp | 95 ++++++++++++ src/server/common/protocols.cpp | 2 + src/server/common/protocols.h | 6 + src/server/main/server2-main.cpp | 2 + src/server/service/app-permissions.cpp | 194 +++++++++++++++++++++++++ src/server/service/app-permissions.h | 64 ++++++++ systemd/CMakeLists.txt | 1 + systemd/security-server-app-permissions.socket | 14 ++ systemd/security-server.service | 1 + 13 files changed, 405 insertions(+), 3 deletions(-) create mode 100644 src/server/client/client-app-permissions.cpp create mode 100644 src/server/service/app-permissions.cpp create mode 100644 src/server/service/app-permissions.h create mode 100644 systemd/security-server-app-permissions.socket diff --git a/build/security-server/security-server.pc.in b/build/security-server/security-server.pc.in index 608cb2d..a865f8a 100644 --- a/build/security-server/security-server.pc.in +++ b/build/security-server/security-server.pc.in @@ -6,6 +6,6 @@ includedir=${prefix}/include Name: security-server Description: Security Server Package Version: 1.0.1 -Requires: openssl libsmack -Libs: -L${libdir} -lsecurity-server-client -lsmack +Requires: openssl libsmack libprivilege-control +Libs: -L${libdir} -lsecurity-server-client Cflags: -I${includedir}/security-server diff --git a/packaging/security-server.spec b/packaging/security-server.spec index a0f15f1..5d7a9fb 100644 --- a/packaging/security-server.spec +++ b/packaging/security-server.spec @@ -111,6 +111,7 @@ ln -s ../security-server.service %{buildroot}/usr/lib/systemd/system/multi-user. ln -s ../security-server-data-share.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/security-server-data-share.socket ln -s ../security-server-get-gid.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/security-server-get-gid.socket ln -s ../security-server-privilege-by-pid.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/security-server-privilege-by-pid.socket +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-app-privilege-by-name.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/security-server-app-privilege-by-name.socket @@ -168,6 +169,8 @@ fi %attr(-,root,root) /usr/lib/systemd/system/security-server-get-gid.socket %attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/security-server-privilege-by-pid.socket %attr(-,root,root) /usr/lib/systemd/system/security-server-privilege-by-pid.socket +%attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/security-server-app-permissions.socket +%attr(-,root,root) /usr/lib/systemd/system/security-server-app-permissions.socket %attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/security-server-cookie-get.socket %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 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b4ea4ea..fc9c23b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,6 +17,7 @@ SET(SECURITY_SERVER_SOURCES ${SERVER2_PATH}/main/server2-main.cpp ${SERVER2_PATH}/service/data-share.cpp ${SERVER2_PATH}/service/get-gid.cpp + ${SERVER2_PATH}/service/app-permissions.cpp ${SERVER2_PATH}/service/cookie.cpp ${SERVER2_PATH}/service/cookie-jar.cpp ${SERVER2_PATH}/service/cookie-common.cpp @@ -71,6 +72,7 @@ SET(SECURITY_CLIENT_SOURCES ${SERVER2_PATH}/client/client-common.cpp ${SERVER2_PATH}/client/client-shared-memory.cpp ${SERVER2_PATH}/client/client-get-gid.cpp + ${SERVER2_PATH}/client/client-app-permissions.cpp ${SERVER2_PATH}/client/client-cookie.cpp ${SERVER2_PATH}/client/client-privilege-by-pid.cpp ${SERVER2_PATH}/client/client-socket-privilege.cpp diff --git a/src/include/security-server.h b/src/include/security-server.h index a69a7e1..2114fcb 100644 --- a/src/include/security-server.h +++ b/src/include/security-server.h @@ -23,7 +23,7 @@ #define SECURITY_SERVER_H #include - +#include /** * @file security-server.h @@ -970,6 +970,24 @@ int security_server_check_privilege_by_sockfd(int sockfd, const char *object, const char *access_rights); +/* + * This function allows middleware to check if an app has the specified privilege + * enabled. + * + * \param[in] Application ID + * \param[in] Application type + * \param[in] Privilege name + * \param[out] Handler to store the result. It is set to 1 (true) if privilege is enabled, 0 (false) otherwise + * + * \return SECURITY_SERVER_API_SUCCESS on success or error code on fail + * + * Access to this function requires SMACK rule: " security-server::api-app-privilege-by-name w" + */ +int security_server_app_has_privilege(const char *app_id, + app_type_t app_type, + const char *privilege_name, + int *result); + #ifdef __cplusplus } #endif diff --git a/src/server/client/client-app-permissions.cpp b/src/server/client/client-app-permissions.cpp new file mode 100644 index 0000000..c1b7b9a --- /dev/null +++ b/src/server/client/client-app-permissions.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Bartlomiej Grzelewski + * + * 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 client-app-permissions.cpp + * @author Pawel Polawski (pawel.polawski@partner.samsung.com) + * @version 1.0 + * @brief This file contains implementation of + * security_server_app_has_privilege function + */ + + +#include +#include + +#include +#include +#include + +#include +#include + +SECURITY_SERVER_API +int security_server_app_has_privilege(const char *app_id, + app_type_t app_type, + const char *privilege_name, + int *result) +{ + using namespace SecurityServer; + MessageBuffer send, recv; + + LogDebug("security_server_app_has_privilege() called"); + + try { + if ((NULL == app_id) || (strlen(app_id) == 0)) { + LogError("app_id is NULL or empty"); + return SECURITY_SERVER_API_ERROR_INPUT_PARAM; + } + if ((NULL == privilege_name) || (strlen(privilege_name) == 0)) { + LogError("privilege_name is NULL or empty"); + return SECURITY_SERVER_API_ERROR_INPUT_PARAM; + } + if (NULL == result) { + LogError("result is NULL"); + return SECURITY_SERVER_API_ERROR_INPUT_PARAM; + } + + LogDebug("app_id: " << app_id); + LogDebug("app_type: " << static_cast(app_type)); + LogDebug("privilege_name: " << privilege_name); + + //put data into buffer + Serialization::Serialize(send, static_cast(PrivilegeCheckHdrs::CHECK_GIVEN_APP)); + Serialization::Serialize(send, std::string(app_id)); + Serialization::Serialize(send, static_cast(app_type)); + Serialization::Serialize(send, std::string(privilege_name)); + + //send buffer to server + int apiResult = sendToServer(SERVICE_SOCKET_APP_PRIVILEGE_BY_NAME, send.Pop(), recv); + if (apiResult != SECURITY_SERVER_API_SUCCESS) { + LogError("Error in sendToServer. Error code: " << apiResult); + return apiResult; + } + + //receive response from server + Deserialization::Deserialize(recv, apiResult); + if (apiResult == SECURITY_SERVER_API_SUCCESS) { + Deserialization::Deserialize(recv, *result); + } + return apiResult; + + } catch (MessageBuffer::Exception::Base &e) { + LogError("SecurityServer::MessageBuffer::Exception " << e.DumpToString()); + } catch (std::exception &e) { + LogError("STD exception " << e.what()); + } catch (...) { + LogError("Unknown exception occured"); + } + + return SECURITY_SERVER_API_ERROR_UNKNOWN; +} diff --git a/src/server/common/protocols.cpp b/src/server/common/protocols.cpp index 6862d4a..2bfb1bb 100644 --- a/src/server/common/protocols.cpp +++ b/src/server/common/protocols.cpp @@ -33,6 +33,8 @@ char const * const SERVICE_SOCKET_GET_GID = "/tmp/.security-server-api-get-gid.sock"; char const * const SERVICE_SOCKET_PRIVILEGE_BY_PID = "/tmp/.security-server-api-privilege-by-pid.sock"; +char const * const SERVICE_SOCKET_APP_PERMISSIONS = + "/tmp/.security-server-api-app-permissions.sock"; char const * const SERVICE_SOCKET_APP_PRIVILEGE_BY_NAME = "/tmp/.security-server-api-app-privilege-by-name.sock"; char const * const SERVICE_SOCKET_COOKIE_GET = diff --git a/src/server/common/protocols.h b/src/server/common/protocols.h index 3d17dca..1294d9f 100644 --- a/src/server/common/protocols.h +++ b/src/server/common/protocols.h @@ -44,6 +44,7 @@ namespace SecurityServer { extern char const * const SERVICE_SOCKET_SHARED_MEMORY; extern char const * const SERVICE_SOCKET_GET_GID; extern char const * const SERVICE_SOCKET_PRIVILEGE_BY_PID; +extern char const * const SERVICE_SOCKET_APP_PERMISSIONS; extern char const * const SERVICE_SOCKET_APP_PRIVILEGE_BY_NAME; extern char const * const SERVICE_SOCKET_COOKIE_GET; extern char const * const SERVICE_SOCKET_COOKIE_CHECK; @@ -65,6 +66,11 @@ enum class CookieCall CHECK_UID }; +enum class PrivilegeCheckHdrs +{ + CHECK_GIVEN_APP, + CHECK_CALLER_APP +}; extern const size_t COOKIE_SIZE; enum class PasswordHdrs diff --git a/src/server/main/server2-main.cpp b/src/server/main/server2-main.cpp index 26fff65..60e6f8c 100644 --- a/src/server/main/server2-main.cpp +++ b/src/server/main/server2-main.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -97,6 +98,7 @@ int main(void) { REGISTER_SOCKET_SERVICE(manager, SecurityServer::SharedMemoryService); REGISTER_SOCKET_SERVICE(manager, SecurityServer::GetGidService); REGISTER_SOCKET_SERVICE(manager, SecurityServer::PrivilegeByPidService); + REGISTER_SOCKET_SERVICE(manager, SecurityServer::AppPermissionsService); REGISTER_SOCKET_SERVICE(manager, SecurityServer::PasswordService); REGISTER_SOCKET_SERVICE(manager, SecurityServer::InstallerService); diff --git a/src/server/service/app-permissions.cpp b/src/server/service/app-permissions.cpp new file mode 100644 index 0000000..9d63f4e --- /dev/null +++ b/src/server/service/app-permissions.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Bartlomiej Grzelewski + * + * 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 app-permissions.cpp + * @author Pawel Polawski (pawel.polawski@partner.samsung.com) + * @version 1.0 + * @brief This file contains implementation of security_server_app_has_permission + * on server side + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace { + +int privilegeToSecurityServerError(int error) { + switch (error) { + case PC_OPERATION_SUCCESS: return SECURITY_SERVER_API_SUCCESS; + case PC_ERR_FILE_OPERATION: return SECURITY_SERVER_API_ERROR_UNKNOWN; + case PC_ERR_MEM_OPERATION: return SECURITY_SERVER_API_ERROR_OUT_OF_MEMORY; + case PC_ERR_NOT_PERMITTED: return SECURITY_SERVER_API_ERROR_ACCESS_DENIED; + case PC_ERR_INVALID_PARAM: return SECURITY_SERVER_API_ERROR_INPUT_PARAM; + case PC_ERR_INVALID_OPERATION: + case PC_ERR_DB_OPERATION: + default: + ; + } + return SECURITY_SERVER_API_ERROR_UNKNOWN; +} + +// interface ids +const SecurityServer::InterfaceID CHANGE_APP_PERMISSIONS = 0; +const SecurityServer::InterfaceID CHECK_APP_PRIVILEGE = 1; + +} // namespace anonymous + +namespace SecurityServer { + +GenericSocketService::ServiceDescriptionVector AppPermissionsService::GetServiceDescription() { + return ServiceDescriptionVector { + { SERVICE_SOCKET_APP_PERMISSIONS, + "security-server::api-app-permissions", + CHANGE_APP_PERMISSIONS }, + { SERVICE_SOCKET_APP_PRIVILEGE_BY_NAME, + "security-server::api-app-privilege-by-name", + CHECK_APP_PRIVILEGE } + }; +} + +void AppPermissionsService::accept(const AcceptEvent &event) { + LogDebug("Accept event. ConnectionID.sock: " << event.connectionID.sock + << " ConnectionID.counter: " << event.connectionID.counter + << " ServiceID: " << event.interfaceID); + auto &info = m_connectionInfoMap[event.connectionID.counter]; + info.interfaceID = event.interfaceID; +} + +void AppPermissionsService::write(const WriteEvent &event) { + LogDebug("WriteEvent. ConnectionID: " << event.connectionID.sock << + " Size: " << event.size << " Left: " << event.left); + if (event.left == 0) + m_serviceManager->Close(event.connectionID); +} + +void AppPermissionsService::process(const ReadEvent &event) { + LogDebug("Read event for counter: " << event.connectionID.counter); + auto &info = m_connectionInfoMap[event.connectionID.counter]; + info.buffer.Push(event.rawBuffer); + + // We can get several requests in one package. + // Extract and process them all + while(processOne(event.connectionID, info.buffer, info.interfaceID)); +} + +void AppPermissionsService::close(const CloseEvent &event) { + LogDebug("CloseEvent. ConnectionID: " << event.connectionID.sock); + m_connectionInfoMap.erase(event.connectionID.counter); +} + +bool AppPermissionsService::processOne(const ConnectionID &conn, + MessageBuffer &buffer, + InterfaceID interfaceID) +{ + LogDebug("Begin of an iteration"); + + //waiting for all data + if (!buffer.Ready()) { + return false; + } + + LogDebug("Entering app_permissions server side handler"); + + switch(interfaceID) { + + case CHECK_APP_PRIVILEGE: + return processCheckAppPrivilege(conn, buffer); + + default: + LogDebug("Unknown interfaceId. Closing socket."); + m_serviceManager->Close(conn); + return false; + } +} + +bool AppPermissionsService::processCheckAppPrivilege(const ConnectionID &conn, MessageBuffer &buffer) +{ + MessageBuffer send; + std::string privilege_name; + std::string app_id; + int result = SECURITY_SERVER_API_ERROR_SERVER_ERROR; + app_type_t app_type; + bool has_permission = false; + PrivilegeCheckHdrs checkType = PrivilegeCheckHdrs::CHECK_GIVEN_APP; + + LogDebug("Processing app privilege check request"); + + //receive data from buffer + Try { + int temp; + Deserialization::Deserialize(buffer, temp); // call type + checkType = static_cast(temp); + LogDebug("App privilege check call type: " + << (checkType == PrivilegeCheckHdrs::CHECK_GIVEN_APP ? + "CHECK_GIVEN_APP":"CHECK_CALLER_APP")); + if (checkType == PrivilegeCheckHdrs::CHECK_GIVEN_APP) { //app_id present only in this case + Deserialization::Deserialize(buffer, app_id); //get app id + } + Deserialization::Deserialize(buffer, temp); //get app type + app_type = static_cast(temp); + + Deserialization::Deserialize(buffer, privilege_name); //get privilege name + } Catch (MessageBuffer::Exception::Base) { + LogDebug("Broken protocol. Closing socket."); + m_serviceManager->Close(conn); + return false; + } + + if (checkType == PrivilegeCheckHdrs::CHECK_CALLER_APP) { //get sender app_id in this case + char *label = NULL; + if (smack_new_label_from_socket(conn.sock, &label) < 0) { + LogDebug("Error in smack_new_label_from_socket(): " + "client label is unknown. Sending error response."); + Serialization::Serialize(send, SECURITY_SERVER_API_ERROR_GETTING_SOCKET_LABEL_FAILED); + m_serviceManager->Write(conn, send.Pop()); + return false; + } else { + app_id = label; + free(label); + } + } //end if + + //print received data + LogDebug("app_id: " << app_id); + LogDebug("app_type: " << static_cast(app_type)); + LogDebug("privilege_name: " << privilege_name); + + LogDebug("Calling perm_app_has_permission()"); + result = perm_app_has_permission(app_id.c_str(), app_type, privilege_name.c_str(), &has_permission); + LogDebug("perm_app_has_permission() returned: " << result << " , permission enabled: " << has_permission); + + //send response + Serialization::Serialize(send, privilegeToSecurityServerError(result)); + Serialization::Serialize(send, static_cast(has_permission)); + m_serviceManager->Write(conn, send.Pop()); + return true; +} + +} // namespace SecurityServer diff --git a/src/server/service/app-permissions.h b/src/server/service/app-permissions.h new file mode 100644 index 0000000..ccf5780 --- /dev/null +++ b/src/server/service/app-permissions.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Bartlomiej Grzelewski + * + * 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 app-permissions.h + * @author Pawel Polawski (p.polawski@partner.samsung.com) + * @version 1.0 + * @brief This function contains header for implementation of + * security_server_app_has_permissions on server side + */ + +#ifndef _SECURITY_SERVER_APP_PERMISSIONS_ +#define _SECURITY_SERVER_APP_PERMISSIONS_ + +#include +#include +#include +#include +#include + +namespace SecurityServer { + +class AppPermissionsService : + public SecurityServer::GenericSocketService + , public SecurityServer::ServiceThread +{ +public: + ServiceDescriptionVector GetServiceDescription(); + + DECLARE_THREAD_EVENT(AcceptEvent, accept) + DECLARE_THREAD_EVENT(WriteEvent, write) + DECLARE_THREAD_EVENT(ReadEvent, process) + DECLARE_THREAD_EVENT(CloseEvent, close) + + void accept(const AcceptEvent &event); + void write(const WriteEvent &event); + void process(const ReadEvent &event); + void close(const CloseEvent &event); + +private: + bool processOne(const ConnectionID &conn, MessageBuffer &buffer, InterfaceID interfaceID); + + bool processCheckAppPrivilege(const ConnectionID &conn, MessageBuffer &buffer); + + ConnectionInfoMap m_connectionInfoMap; +}; + +} // namespace SecurityServer + +#endif // _SECURITY_SERVER_APP_ENABLE_PERMISSIONS_ diff --git a/systemd/CMakeLists.txt b/systemd/CMakeLists.txt index e2ebc7a..8049250 100644 --- a/systemd/CMakeLists.txt +++ b/systemd/CMakeLists.txt @@ -4,6 +4,7 @@ INSTALL(FILES ${CMAKE_SOURCE_DIR}/systemd/security-server-data-share.socket ${CMAKE_SOURCE_DIR}/systemd/security-server-get-gid.socket ${CMAKE_SOURCE_DIR}/systemd/security-server-privilege-by-pid.socket + ${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-app-privilege-by-name.socket diff --git a/systemd/security-server-app-permissions.socket b/systemd/security-server-app-permissions.socket new file mode 100644 index 0000000..7271ff2 --- /dev/null +++ b/systemd/security-server-app-permissions.socket @@ -0,0 +1,14 @@ +[Socket] +ListenStream=/tmp/.security-server-api-app-permissions.sock +SocketMode=0777 +SmackLabelIPIn=* +SmackLabelIPOut=@ + +Service=security-server.service + +[Unit] +Wants=security-server.target +Before=security-server.target + +[Install] +WantedBy=sockets.target diff --git a/systemd/security-server.service b/systemd/security-server.service index 6c74174..51fa5d6 100644 --- a/systemd/security-server.service +++ b/systemd/security-server.service @@ -7,6 +7,7 @@ ExecStart=/usr/bin/security-server Sockets=security-server-data-share.socket Sockets=security-server-get-gid.socket Sockets=security-server-privilege-by-pid.socket +Sockets=security-server-app-permissions.socket Sockets=security-server-app-privilege-by-name.socket Sockets=security-server-cookie-get.socket Sockets=security-server-cookie-check.socket -- 2.7.4