2 * Copyright (c) 2016 Samsung Electronics Co.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
17 * @file src/notification-daemon/GuiRunner.h
18 * @author Oskar Ĺwitalski <o.switalski@samsung.com>
19 * @brief Definition of AskUserTalker class
22 #include "AskUserTalker.h"
27 #include <socket/Socket.h>
28 #include <socket/SelectRead.h>
29 #include <types/NotificationResponse.h>
30 #include <types/Protocol.h>
31 #include <types/NotificationRequest.h>
32 #include <exception/ErrnoException.h>
33 #include <exception/Exception.h>
34 #include <translator/Translator.h>
35 #include <config/Path.h>
36 #include <config/Limits.h>
38 #include <security-manager.h>
39 #include <privilegemgr/privilege_info.h>
44 namespace Notification {
48 inline void throwOnSecurityPrivilegeError(std::string err, int ret)
50 if (ret != SECURITY_MANAGER_SUCCESS)
51 throw Exception(err + " : " + std::to_string(ret));
54 inline const char *dropPrefix(const char* app)
56 constexpr char prefix[] = "User::App::";
57 constexpr size_t prefixSize = sizeof(prefix) - 1;
58 return strncmp(app, prefix, prefixSize) ? app : app + prefixSize;
61 void setSecurityLevel(const std::string &app, const std::string &perm, const std::string &level)
66 if (level != "Allow" && level != "Deny")
67 throw std::invalid_argument("Not allowed security level <" + level + ">");
69 ALOGD("SecurityManager: Setting security level to " << level);
71 policy_update_req *policyUpdateRequest = nullptr;
73 ret = security_manager_policy_update_req_new(&policyUpdateRequest);
74 throwOnSecurityPrivilegeError("security_manager_policy_update_req_new", ret);
76 std::unique_ptr<policy_update_req, decltype(security_manager_policy_update_req_free)*>
77 policyUpdateRequestPtr(policyUpdateRequest, security_manager_policy_update_req_free);
79 char* privacy_name = nullptr;
81 ret = privilege_info_get_privacy_by_privilege(perm.c_str(), &privacy_name);
82 if (ret != PRVMGR_ERR_NONE || !privacy_name) {
83 ALOGE("Unable to get privacy group for privilege: <" << perm << ">, err: <" << ret << ">");
84 throw Exception("Can't get privacy group name for privilege " + perm);
87 GList *privilege_list = nullptr;
89 ret = privilege_info_get_privilege_list_by_privacy(privacy_name, &privilege_list);
90 free(privacy_name); // not needed anymore below this place
92 if (ret != PRVMGR_ERR_NONE || !privilege_list) {
93 ALOGE("Unable to get privacy group list of privileges; err: <" << ret << ">" );
94 throw Exception("Unable to get privacy list of privielges");
97 auto list_deleter = [](GList* l) { g_list_free_full(l, free); };
98 std::unique_ptr<GList,
99 decltype(list_deleter)> privilge_listPtr(privilege_list, list_deleter);
100 std::vector<std::unique_ptr<policy_entry,
101 decltype(security_manager_policy_entry_free)*>> policyEntries;
103 for (GList *l = privilege_list; l != NULL; l = l->next) {
104 char *privilege_name = static_cast<char*>(l->data);
105 policy_entry *policyEntry = nullptr;
107 ret = security_manager_policy_entry_new(&policyEntry);
108 throwOnSecurityPrivilegeError("security_manager_policy_entry_new", ret);
110 policyEntries.push_back(std::unique_ptr<policy_entry,
111 decltype(security_manager_policy_entry_free)*>(policyEntry, security_manager_policy_entry_free));
113 ret = security_manager_policy_entry_set_application(policyEntry,
114 dropPrefix(app.c_str()));
115 throwOnSecurityPrivilegeError("security_manager_policy_entry_set_application", ret);
117 ret = security_manager_policy_entry_set_privilege(policyEntry, privilege_name);
118 throwOnSecurityPrivilegeError("security_manager_policy_entry_set_privilege", ret);
120 ret = security_manager_policy_entry_set_level(policyEntry, level.c_str());
121 throwOnSecurityPrivilegeError("security_manager_policy_entry_admin_set_level", ret);
123 ret = security_manager_policy_update_req_add_entry(policyUpdateRequest, policyEntry);
124 throwOnSecurityPrivilegeError("security_manager_policy_update_req_add_entry", ret);
127 ret = security_manager_policy_update_send(policyUpdateRequest);
128 throwOnSecurityPrivilegeError("security_manager_policy_update_send", ret);
130 ALOGD("SecurityManager: Setting level succeeded");
131 } catch (std::exception &e) {
132 ALOGE("SecurityManager: Failed <" << e.what() << ">");
139 AskUserTalker::AskUserTalker(GuiRunner *gui) : m_gui(gui) {
140 m_gui->setDropHandler([&](){return this->shouldDismiss();});
143 AskUserTalker::~AskUserTalker()
146 Socket::close(sockfd);
147 } catch (const std::exception &e) {
148 ALOGE(std::string("~AskUserTalker") + e.what());
150 ALOGE("~AskUserTalker: Unknow error");
154 void AskUserTalker::run()
156 sockfd = Socket::connect(Path::getSocketPath());
161 NotificationResponse response;
163 ALOGD("Waiting for request...");
165 if (!Socket::recv(sockfd, &size, sizeof(size))) {
166 ALOGI("Askuserd closed connection, closing...");
170 Limits::checkSizeLimit(size);
172 buf = new char[size];
174 if (!Socket::recv(sockfd, buf, size)) {
175 ALOGI("Askuserd closed connection, closing...");
179 NotificationRequest request = Translator::Gui::dataToNotificationRequest(buf);
181 ALOGD("Recieved data " << request.data.client << " " << request.data.privilege);
183 response.response = m_gui->popupRun(request.data.client, request.data.privilege);
184 response.id = request.id;
186 if (response.response == NResponseType::None) {
190 if (!Socket::send(sockfd, &response, sizeof(response))) {
191 ALOGI("Askuserd closed connection, closing...");
196 if (!Socket::recv(sockfd, &ack, sizeof(ack))) {
197 ALOGI("Askuserd closed connection, closing...");
201 if (ack != Protocol::ackCode)
202 throw Exception("Incorrect ack");
204 switch (response.response) {
205 case NResponseType::Error:
206 throw Exception(m_gui->getErrorMsg());
207 case NResponseType::Allow:
208 case NResponseType::Never:
209 setSecurityLevel(request.data.client, request.data.privilege,
210 Translator::Gui::responseToString(response.response));
217 void AskUserTalker::stop()
220 Socket::close(sockfd);
223 bool AskUserTalker::shouldDismiss()
225 Socket::SelectRead select;
227 if (select.exec() == 0)
231 Socket::recv(sockfd, &a, sizeof(a));
233 if (a != Protocol::dissmisCode)
234 throw Exception("Incorrect dismiss flag");
239 } /* namespace Notification */
241 } /* namespace AskUser */