<label name="security-server::daemon" />
<label name="security-server::db" />
<label name="security-server::api-app-permissions" />
+ <label name="security-server::api-app-privilege-by-name" />
<label name="security-server::api-cookie-check" />
<label name="security-server::api-cookie-get" />
<label name="security-server::api-data-share" />
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
+ln -s ../security-server-app-privilege-by-name.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/security-server-app-privilege-by-name.socket
%clean
rm -rf %{buildroot}
%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
+%attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/security-server-app-privilege-by-name.socket
+%attr(-,root,root) /usr/lib/systemd/system/security-server-app-privilege-by-name.socket
%attr(-,root,root) /etc/security/security-server-audit.conf
%{_datadir}/license/%{name}
/*! \brief indicating password retry timeout is not occurred yet */
#define SECURITY_SERVER_API_ERROR_PASSWORD_REUSED -20
+/*! \brief indicating getting smack label from socket failed */
+#define SECURITY_SERVER_API_ERROR_GETTING_SOCKET_LABEL_FAILED -21
+
/*! \brief indicating the error with unknown reason */
#define SECURITY_SERVER_API_ERROR_UNKNOWN -255
/** @}*/
int security_server_get_uid_by_cookie(const char *cookie, uid_t *uid);
/*
+ * 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_SUCCESS on success or error code on fail
+ *
+ * Access to this function requires SMACK rule: "<app_label> 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);
+
+/*
+ * This function allows middleware to check if caller app has the specified privilege
+ * enabled. Security Server gets caller app smack label from the IPC socket.
+ *
+ * \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_SUCCESS on success or error code on fail
+ *
+ * Access to this function requires SMACK rule: "<app_label> security-server::api-app-privilege-by-name w"
+ */
+int security_server_app_caller_has_privilege(app_type_t app_type,
+ const char *privilege_name,
+ int *result);
+
+/*
* This function allows middleware to get GID assigned to cookie
*
* \param[in] Cookie
return SECURITY_SERVER_API_ERROR_UNKNOWN;
}
+
+
+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<int>(app_type));
+ LogDebug("privilege_name: " << privilege_name);
+
+ //put data into buffer
+ Serialization::Serialize(send, static_cast<int>(PrivilegeCheckCall::CHECK_GIVEN_APP));
+ Serialization::Serialize(send, std::string(app_id));
+ Serialization::Serialize(send, static_cast<int>(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;
+}
+
+
+SECURITY_SERVER_API
+int security_server_app_caller_has_privilege(app_type_t app_type,
+ const char *privilege_name,
+ int *result)
+{
+ using namespace SecurityServer;
+ MessageBuffer send, recv;
+
+ LogDebug("security_server_app_caller_has_privilege() called");
+
+ try {
+ 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_type: " << static_cast<int>(app_type));
+ LogDebug("privilege_name: " << privilege_name);
+
+ //put data into buffer
+ Serialization::Serialize(send, static_cast<int>(PrivilegeCheckCall::CHECK_CALLER_APP));
+ Serialization::Serialize(send, static_cast<int>(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;
+}
"/tmp/.security-server-api-get-object-name.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 =
"/tmp/.security-server-api-cookie-get.sock";
char const * const SERVICE_SOCKET_COOKIE_CHECK =
extern char const * const SERVICE_SOCKET_PRIVILEGE_BY_PID;
extern char const * const SERVICE_SOCKET_GET_OBJECT_NAME;
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;
extern char const * const SERVICE_SOCKET_COOKIE_CHECK_TMP;
CHECK_UID
};
+enum class PrivilegeCheckCall
+{
+ CHECK_GIVEN_APP,
+ CHECK_CALLER_APP
+};
+
extern const size_t COOKIE_SIZE;
} // namespace SecuritySever
#include <memory>
#include <dpl/log/log.h>
#include <dpl/serialization.h>
+#include <privilege-control.h>
+
+#include <sys/smack.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <app-permissions.h>
#include <protocols.h>
#include <security-server.h>
-#include <privilege-control.h>
#include <security-server-common.h>
-#include <app-permissions.h>
+
namespace {
namespace SecurityServer {
GenericSocketService::ServiceDescriptionVector AppPermissionsService::GetServiceDescription() {
- return ServiceDescriptionVector
- {{SERVICE_SOCKET_APP_PERMISSIONS, "security-server::api-app-permissions" }};
+ return ServiceDescriptionVector {
+ { SERVICE_SOCKET_APP_PERMISSIONS,
+ "security-server::api-app-permissions",
+ static_cast<int>(InterfaceType::CHANGE_APP_PERMISSIONS) },
+ { SERVICE_SOCKET_APP_PRIVILEGE_BY_NAME,
+ "security-server::api-app-privilege-by-name",
+ static_cast<int>(InterfaceType::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_socketInfoMap[event.connectionID.counter];
+ info.interfaceID = static_cast<InterfaceType>(event.interfaceID);
}
void AppPermissionsService::write(const WriteEvent &event) {
void AppPermissionsService::process(const ReadEvent &event) {
LogDebug("Read event for counter: " << event.connectionID.counter);
- auto &buffer = m_messageBufferMap[event.connectionID.counter];
- buffer.Push(event.rawBuffer);
+ auto &info = m_socketInfoMap[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, buffer));
+ while(processOne(event.connectionID, info.buffer, info.interfaceID));
}
void AppPermissionsService::close(const CloseEvent &event) {
LogDebug("CloseEvent. ConnectionID: " << event.connectionID.sock);
- m_messageBufferMap.erase(event.connectionID.counter);
+ m_socketInfoMap.erase(event.connectionID.counter);
}
-bool AppPermissionsService::processOne(const ConnectionID &conn, MessageBuffer &buffer)
+bool AppPermissionsService::processOne(const ConnectionID &conn,
+ MessageBuffer &buffer,
+ InterfaceType interfaceID)
{
LogDebug("Iteration begin");
- MessageBuffer send, recv;
+
+ //waiting for all data
+ if (!buffer.Ready()) {
+ return false;
+ }
+
+ LogDebug("Entering app_permissions server side handler");
+
+ switch(interfaceID) {
+ case InterfaceType::CHANGE_APP_PERMISSIONS:
+ return processPermissionsChange(conn, buffer);
+
+ case InterfaceType::CHECK_APP_PRIVILEGE:
+ return processCheckAppPrivilege(conn, buffer);
+
+ default:
+ LogDebug("Unknown interfaceId. Closing socket.");
+ m_serviceManager->Close(conn);
+ return false;
+ }
+}
+
+bool AppPermissionsService::processPermissionsChange(const ConnectionID &conn, MessageBuffer &buffer)
+{
+ MessageBuffer send;
std::vector<std::string> permissions_list;
std::string app_id;
int persistent;
app_type_t app_type;
AppPermissionsAction appPermAction;
- //waiting for all data
- if (!buffer.Ready()) {
- return false;
- }
-
- LogDebug("Entering app_permissions server side handler");
+ LogDebug("Processing permissions change request");
//receive data from buffer and check MSG_ID
Try {
//use received data
if (appPermAction == AppPermissionsAction::ENABLE) {
- LogDebug("Calling app_enable_permiossions()");
+ LogDebug("Calling perm_app_enable_permissions()");
result = perm_app_enable_permissions(app_id.c_str(), app_type, perm_list.get(), persistent);
- LogDebug("app_enable_permissions() returned: " << result);
+ LogDebug("perm_app_enable_permissions() returned: " << result);
} else {
- LogDebug("Calling app_disable_permiossions()");
+ LogDebug("Calling perm_app_disable_permissions()");
result = perm_app_disable_permissions(app_id.c_str(), app_type, perm_list.get());
- LogDebug("app_disable_permissions() returned: " << result);
+ LogDebug("perm_app_disable_permissions() returned: " << result);
}
//send response
return true;
}
-} // namespace SecurityServer
+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;
+ PrivilegeCheckCall checkType = PrivilegeCheckCall::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<PrivilegeCheckCall>(temp);
+ LogDebug("App privilege check call type: "
+ << (checkType == PrivilegeCheckCall::CHECK_GIVEN_APP ?
+ "CHECK_GIVEN_APP":"CHECK_CALLER_APP"));
+ if (checkType == PrivilegeCheckCall::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<app_type_t>(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 == PrivilegeCheckCall::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<int>(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<int>(has_permission));
+ m_serviceManager->Write(conn, send.Pop());
+ return true;
+}
+
+} // namespace SecurityServer
, public SecurityServer::ServiceThread<AppPermissionsService>
{
public:
- typedef std::map<int, MessageBuffer> MessageBufferMap;
+ enum class InterfaceType {
+ CHANGE_APP_PERMISSIONS,
+ CHECK_APP_PRIVILEGE,
+ };
+
+ struct SocketInfo {
+ InterfaceType interfaceID;
+ MessageBuffer buffer;
+ };
+
+ typedef std::map<int, SocketInfo> SocketInfoMap;
ServiceDescriptionVector GetServiceDescription();
void close(const CloseEvent &event);
private:
- bool processOne(const ConnectionID &conn, MessageBuffer &buffer);
+ bool processOne(const ConnectionID &conn, MessageBuffer &buffer, InterfaceType interfaceID);
+
+ bool processPermissionsChange(const ConnectionID &conn, MessageBuffer &buffer);
+ bool processCheckAppPrivilege(const ConnectionID &conn, MessageBuffer &buffer);
- MessageBufferMap m_messageBufferMap;
+ SocketInfoMap m_socketInfoMap;
};
} // namespace SecurityServer
${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
${CMAKE_SOURCE_DIR}/systemd/security-server-cookie-check-tmp.socket
DESTINATION
/usr/lib/systemd/system
--- /dev/null
+[Socket]
+ListenStream=/tmp/.security-server-api-app-privilege-by-name.sock
+SocketMode=0777
+SmackLabelIPIn=security-server::api-app-privilege-by-name
+SmackLabelIPOut=@
+
+Service=security-server.service
+
+[Install]
+WantedBy=sockets.target
Sockets=security-server-exec-path.socket
Sockets=security-server-get-object-name.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
Sockets=security-server-cookie-check-tmp.socket