Fix memory leaks
[platform/core/security/askuser.git] / src / agent / notification-daemon / AskUserTalker.cpp
1 /*
2  *  Copyright (c) 2016 Samsung Electronics Co.
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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
15  */
16 /**
17  * @file        src/notification-daemon/GuiRunner.h
18  * @author      Oskar Ĺšwitalski <o.switalski@samsung.com>
19  * @brief       Definition of AskUserTalker class
20  */
21
22 #include "AskUserTalker.h"
23
24 #include <iostream>
25 #include <string>
26
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>
37
38 #include <security-manager.h>
39 #include <privilegemgr/privilege_info.h>
40 #include <glib.h>
41
42 namespace AskUser {
43
44 namespace Notification {
45
46 namespace {
47
48 inline void throwOnSecurityPrivilegeError(std::string err, int ret)
49 {
50     if (ret != SECURITY_MANAGER_SUCCESS)
51         throw Exception(err + " : " + std::to_string(ret));
52 }
53
54 void setSecurityLevel(const std::string &app, const std::string &perm, const std::string &level)
55 {
56     int ret;
57
58     try {
59         if (level != "Allow" && level != "Deny")
60             throw std::invalid_argument("Not allowed security level <" + level + ">");
61
62         ALOGD("SecurityManager: Setting security level to " << level);
63
64         policy_update_req *policyUpdateRequest = nullptr;
65
66         ret = security_manager_policy_update_req_new(&policyUpdateRequest);
67         throwOnSecurityPrivilegeError("security_manager_policy_update_req_new", ret);
68
69         std::unique_ptr<policy_update_req, decltype(security_manager_policy_update_req_free)*>
70             policyUpdateRequestPtr(policyUpdateRequest, security_manager_policy_update_req_free);
71
72         char* privacy_name = nullptr;
73
74         ret = privilege_info_get_privacy_by_privilege(perm.c_str(), &privacy_name);
75         if (ret != PRVMGR_ERR_NONE || !privacy_name) {
76             ALOGE("Unable to get privacy group for privilege: <" << perm << ">, err: <" << ret << ">");
77             throw Exception("Can't get privacy group name for privilege " + perm);
78         }
79
80         GList *privilege_list = nullptr;
81
82         ret = privilege_info_get_privilege_list_by_privacy(privacy_name, &privilege_list);
83         free(privacy_name); // not needed anymore below this place
84
85         if (ret != PRVMGR_ERR_NONE || !privilege_list) {
86             ALOGE("Unable to get privacy group list of privileges; err: <" << ret <<  ">" );
87             throw Exception("Unable to get privacy list of privielges");
88         }
89
90         auto list_deleter = [](GList* l) { g_list_free_full(l, free); };
91         std::unique_ptr<GList,
92             decltype(list_deleter)> privilge_listPtr(privilege_list, list_deleter);
93         std::vector<std::unique_ptr<policy_entry,
94             decltype(security_manager_policy_entry_free)*>> policyEntries;
95
96         for (GList *l = privilege_list; l != NULL; l = l->next) {
97             char *privilege_name = static_cast<char*>(l->data);
98             policy_entry *policyEntry = nullptr;
99
100             ret = security_manager_policy_entry_new(&policyEntry);
101             throwOnSecurityPrivilegeError("security_manager_policy_entry_new", ret);
102
103             policyEntries.push_back(std::unique_ptr<policy_entry,
104                 decltype(security_manager_policy_entry_free)*>(policyEntry, security_manager_policy_entry_free));
105
106             char *pkg_name = nullptr;
107             char *app_name = nullptr;
108
109             ret = security_manager_identify_app_from_cynara_client(app.c_str(), &pkg_name, &app_name);
110             std::unique_ptr<char, decltype(free)*> pkg_name_p(pkg_name, free);
111             std::unique_ptr<char, decltype(free)*> app_name_p(app_name, free);
112             throwOnSecurityPrivilegeError("security_manager_identify_app_from_cynara_client", ret);
113
114             ret = security_manager_policy_entry_set_application(policyEntry, app_name);
115             throwOnSecurityPrivilegeError("security_manager_policy_entry_set_application", ret);
116
117             ret = security_manager_policy_entry_set_privilege(policyEntry, privilege_name);
118             throwOnSecurityPrivilegeError("security_manager_policy_entry_set_privilege", ret);
119
120             ret = security_manager_policy_entry_set_level(policyEntry, level.c_str());
121             throwOnSecurityPrivilegeError("security_manager_policy_entry_admin_set_level", ret);
122
123             ret = security_manager_policy_update_req_add_entry(policyUpdateRequest, policyEntry);
124             throwOnSecurityPrivilegeError("security_manager_policy_update_req_add_entry", ret);
125         }
126
127         ret = security_manager_policy_update_send(policyUpdateRequest);
128         throwOnSecurityPrivilegeError("security_manager_policy_update_send", ret);
129
130         ALOGD("SecurityManager: Setting level succeeded");
131     } catch (std::exception &e) {
132         ALOGE("SecurityManager: Failed <" << e.what() << ">");
133     }
134 }
135
136 } /* namespace */
137
138
139 AskUserTalker::AskUserTalker(GuiRunner *gui) : m_gui(gui) {
140     m_gui->setDropHandler([&](){return this->shouldDismiss();});
141 }
142
143 AskUserTalker::~AskUserTalker()
144 {
145     try {
146         Socket::close(sockfd);
147     } catch (const std::exception &e) {
148         ALOGE(std::string("~AskUserTalker") + e.what());
149     } catch (...) {
150         ALOGE("~AskUserTalker: Unknow error");
151     }
152 }
153
154 void AskUserTalker::run()
155 {
156     sockfd = Socket::connect(Path::getSocketPath());
157
158     while (!stopFlag) {
159         size_t size;
160         NotificationResponse response;
161
162         ALOGD("Waiting for request...");
163
164         if (!Socket::recv(sockfd, &size, sizeof(size))) {
165             ALOGI("Askuserd closed connection, closing...");
166             break;
167         }
168
169         Limits::checkSizeLimit(size);
170
171         std::unique_ptr<char[]> buf(new char[size]);
172
173         if (!Socket::recv(sockfd, buf.get(), size)) {
174             ALOGI("Askuserd closed connection, closing...");
175             break;
176         }
177
178         NotificationRequest request = Translator::Gui::dataToNotificationRequest(buf.get());
179         ALOGD("Recieved data " << request.data.client << " " << request.data.privilege);
180
181         response.response = m_gui->popupRun(request.data.client, request.data.privilege);
182         response.id = request.id;
183
184         if (response.response == NResponseType::None) {
185             continue;
186         }
187
188         if (!Socket::send(sockfd, &response, sizeof(response))) {
189             ALOGI("Askuserd closed connection, closing...");
190             break;
191         }
192
193         uint8_t ack = 0x00;
194         if (!Socket::recv(sockfd, &ack, sizeof(ack))) {
195             ALOGI("Askuserd closed connection, closing...");
196             break;
197         }
198
199         if (ack != Protocol::ackCode)
200             throw Exception("Incorrect ack");
201
202         switch (response.response) {
203         case NResponseType::Error:
204             throw Exception(m_gui->getErrorMsg());
205         case NResponseType::Allow:
206         case NResponseType::Never:
207             setSecurityLevel(request.data.client, request.data.privilege,
208                              Translator::Gui::responseToString(response.response));
209         default:
210             break;
211         }
212     }
213 }
214
215 void AskUserTalker::stop()
216 {
217     m_gui->stop();
218     Socket::close(sockfd);
219 }
220
221 bool AskUserTalker::shouldDismiss()
222 {
223     Socket::SelectRead select;
224     select.add(sockfd);
225     if (select.exec() == 0)
226         return false;
227
228     uint8_t a = 0x00;
229     Socket::recv(sockfd, &a, sizeof(a));
230
231     if (a != Protocol::dissmisCode)
232         throw Exception("Incorrect dismiss flag");
233
234     return true;
235 }
236
237 } /* namespace Notification */
238
239 } /* namespace AskUser */