2 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Rafal Krypa <r.krypa@samsung.com>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License
20 * @author Michal Witanowski <m.witanowski@samsung.com>
21 * @author Jacek Bukarewicz <j.bukarewicz@samsung.com>
22 * @author Rafal Krypa <r.krypa@samsung.com>
23 * @brief Implementation of installer service.
26 #include <dpl/log/log.h>
27 #include <dpl/serialization.h>
29 #include <privilege-control.h>
31 #include "installer.h"
32 #include "protocols.h"
33 #include "security-manager.h"
34 #include "smack-common.h"
35 #include "smack-rules.h"
36 #include "smack-labels.h"
37 #include "privilege_db.h"
39 namespace SecurityManager {
41 const InterfaceID INSTALLER_IFACE = 0;
44 InstallerService::InstallerService()
48 GenericSocketService::ServiceDescriptionVector InstallerService::GetServiceDescription()
50 return ServiceDescriptionVector {
51 {SERVICE_SOCKET_INSTALLER, "security-manager::installer", INSTALLER_IFACE},
55 void InstallerService::accept(const AcceptEvent &event)
57 LogDebug("Accept event. ConnectionID.sock: " << event.connectionID.sock <<
58 " ConnectionID.counter: " << event.connectionID.counter <<
59 " ServiceID: " << event.interfaceID);
61 auto &info = m_connectionInfoMap[event.connectionID.counter];
62 info.interfaceID = event.interfaceID;
65 void InstallerService::write(const WriteEvent &event)
67 LogDebug("WriteEvent. ConnectionID: " << event.connectionID.sock <<
68 " Size: " << event.size <<
69 " Left: " << event.left);
72 m_serviceManager->Close(event.connectionID);
75 void InstallerService::process(const ReadEvent &event)
77 LogDebug("Read event for counter: " << event.connectionID.counter);
78 auto &info = m_connectionInfoMap[event.connectionID.counter];
79 info.buffer.Push(event.rawBuffer);
81 // We can get several requests in one package.
82 // Extract and process them all
83 while (processOne(event.connectionID, info.buffer, info.interfaceID));
86 void InstallerService::close(const CloseEvent &event)
88 LogDebug("CloseEvent. ConnectionID: " << event.connectionID.sock);
89 m_connectionInfoMap.erase(event.connectionID.counter);
92 bool InstallerService::processOne(const ConnectionID &conn, MessageBuffer &buffer,
93 InterfaceID interfaceID)
95 LogDebug("Iteration begin. Interface = " << interfaceID);
97 //waiting for all data
98 if (!buffer.Ready()) {
105 if (INSTALLER_IFACE == interfaceID) {
107 // deserialize API call type
109 Deserialization::Deserialize(buffer, call_type_int);
110 SecurityModuleCall call_type = static_cast<SecurityModuleCall>(call_type_int);
113 case SecurityModuleCall::APP_INSTALL:
114 processAppInstall(buffer, send);
116 case SecurityModuleCall::APP_UNINSTALL:
117 processAppUninstall(buffer, send);
119 case SecurityModuleCall::APP_GET_PKGID:
120 processGetPkgId(buffer, send);
123 LogError("Invalid call: " << call_type_int);
124 Throw(InstallerException::InvalidAction);
126 // if we reach this point, the protocol is OK
128 } Catch (MessageBuffer::Exception::Base) {
129 LogError("Broken protocol.");
130 } Catch (InstallerException::Base) {
131 LogError("Broken protocol.");
132 } catch (std::exception &e) {
133 LogError("STD exception " << e.what());
135 LogError("Unknown exception");
139 LogError("Wrong interface");
144 m_serviceManager->Write(conn, send.Pop());
146 LogError("Closing socket because of error");
147 m_serviceManager->Close(conn);
153 bool InstallerService::processAppInstall(MessageBuffer &buffer, MessageBuffer &send)
155 bool pkgIdIsNew = false;
156 std::vector<std::string> addedPermissions;
157 std::vector<std::string> removedPermissions;
159 // deserialize request data
161 Deserialization::Deserialize(buffer, req.appId);
162 Deserialization::Deserialize(buffer, req.pkgId);
163 Deserialization::Deserialize(buffer, req.privileges);
164 Deserialization::Deserialize(buffer, req.appPaths);
166 LogDebug("appId: " << req.appId);
167 LogDebug("pkgId: " << req.pkgId);
169 std::string smackLabel;
170 if (!generateAppLabel(req.pkgId, smackLabel)) {
171 LogError("Cannot generate Smack label for package");
172 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
175 LogDebug("Smack label: " << smackLabel);
177 // create null terminated array of strigns for permissions
178 std::unique_ptr<const char *[]> pp_permissions(new const char* [req.privileges.size() + 1]);
179 for (size_t i = 0; i < req.privileges.size(); ++i) {
180 LogDebug("Permission = " << req.privileges[i]);
181 pp_permissions[i] = req.privileges[i].c_str();
183 pp_permissions[req.privileges.size()] = nullptr;
185 // start database transaction
186 int result = perm_begin();
187 LogDebug("perm_begin() returned " << result);
188 if (PC_OPERATION_SUCCESS != result) {
189 // libprivilege is locked
190 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
194 result = perm_app_install(smackLabel.c_str());
195 LogDebug("perm_app_install() returned " << result);
196 if (PC_OPERATION_SUCCESS != result) {
197 // libprivilege error
201 result = perm_app_enable_permissions(smackLabel.c_str(), APP_TYPE_WGT,
202 pp_permissions.get(), true);
203 LogDebug("perm_app_enable_permissions() returned " << result);
204 if (PC_OPERATION_SUCCESS != result) {
205 // libprivilege error
210 std::vector<std::string> oldPkgPrivileges, newPkgPrivileges;
212 m_privilegeDb.BeginTransaction();
213 m_privilegeDb.GetPkgPrivileges(req.pkgId, oldPkgPrivileges);
214 m_privilegeDb.AddApplication(req.appId, req.pkgId, pkgIdIsNew);
215 m_privilegeDb.UpdateAppPrivileges(req.appId, req.privileges);
216 m_privilegeDb.GetPkgPrivileges(req.pkgId, newPkgPrivileges);
217 // TODO: configure Cynara rules based on oldPkgPrivileges and newPkgPrivileges
218 m_privilegeDb.CommitTransaction();
219 LogDebug("Application installation commited to database");
220 } catch (const PrivilegeDb::Exception::InternalError &e) {
221 m_privilegeDb.RollbackTransaction();
222 LogError("Error while saving application info to database: " << e.DumpToString());
227 for (const auto &appPath : req.appPaths) {
228 const std::string &path = appPath.first;
229 app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
230 result = setupPath(req.pkgId, path, pathType);
233 LogDebug("setupPath() failed ");
239 LogDebug("Adding Smack rules for new pkgId " << req.pkgId);
240 if (!SmackRules::installPackageRules(req.pkgId)) {
241 LogError("Failed to apply package-specific smack rules");
246 // finish database transaction
248 LogDebug("perm_end() returned " << result);
249 if (PC_OPERATION_SUCCESS != result) {
251 if (!SmackRules::uninstallPackageRules(req.pkgId))
252 LogWarning("Failed to rollback package-specific smack rules");
254 // error in libprivilege-control
255 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
260 Serialization::Serialize(send, SECURITY_MANAGER_API_SUCCESS);
264 // rollback failed transaction before exiting
265 result = perm_rollback();
266 LogDebug("perm_rollback() returned " << result);
267 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
271 bool InstallerService::processAppUninstall(MessageBuffer &buffer, MessageBuffer &send)
273 // deserialize request data
276 std::string smackLabel;
277 bool appExists = true;
278 bool removePkg = false;
280 Deserialization::Deserialize(buffer, appId);
281 LogDebug("appId: " << appId);
283 int result = perm_begin();
284 LogDebug("perm_begin() returned " << result);
285 if (PC_OPERATION_SUCCESS != result) {
286 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
291 std::vector<std::string> oldPkgPrivileges, newPkgPrivileges;
293 m_privilegeDb.BeginTransaction();
294 if (!m_privilegeDb.GetAppPkgId(appId, pkgId)) {
295 LogWarning("Application " << appId <<
296 " not found in database while uninstalling");
297 m_privilegeDb.RollbackTransaction();
300 LogDebug("pkgId: " << pkgId);
302 if (!generateAppLabel(pkgId, smackLabel)) {
303 LogError("Cannot generate Smack label for package");
306 LogDebug("Smack label: " << smackLabel);
308 m_privilegeDb.GetPkgPrivileges(pkgId, oldPkgPrivileges);
309 m_privilegeDb.UpdateAppPrivileges(appId, std::vector<std::string>());
310 m_privilegeDb.RemoveApplication(appId, removePkg);
311 m_privilegeDb.GetPkgPrivileges(pkgId, newPkgPrivileges);
312 // TODO: configure Cynara rules based on oldPkgPrivileges and newPkgPrivileges
313 m_privilegeDb.CommitTransaction();
314 LogDebug("Application uninstallation commited to database");
316 } catch (const PrivilegeDb::Exception::InternalError &e) {
317 m_privilegeDb.RollbackTransaction();
318 LogError("Error while removing application info from database: " << e.DumpToString());
323 result = perm_app_uninstall(smackLabel.c_str());
324 LogDebug("perm_app_uninstall() returned " << result);
325 if (PC_OPERATION_SUCCESS != result) {
326 // error in libprivilege-control
331 LogDebug("Removing Smack rules for deleted pkgId " << pkgId);
332 if (!SmackRules::uninstallPackageRules(pkgId)) {
333 LogError("Error on uninstallation of package-specific smack rules");
339 // finish database transaction
341 LogDebug("perm_end() returned " << result);
342 if (PC_OPERATION_SUCCESS != result) {
343 // error in libprivilege-control
344 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
349 Serialization::Serialize(send, SECURITY_MANAGER_API_SUCCESS);
353 // rollback failed transaction before exiting
354 result = perm_rollback();
355 LogDebug("perm_rollback() returned " << result);
356 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
360 bool InstallerService::processGetPkgId(MessageBuffer &buffer, MessageBuffer &send)
362 // deserialize request data
366 Deserialization::Deserialize(buffer, appId);
367 LogDebug("appId: " << appId);
370 if (!m_privilegeDb.GetAppPkgId(appId, pkgId)) {
371 LogWarning("Application " << appId << " not found in database");
372 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT);
375 LogDebug("pkgId: " << pkgId);
377 } catch (const PrivilegeDb::Exception::InternalError &e) {
378 LogError("Error while getting pkgId from database: " << e.DumpToString());
379 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
384 Serialization::Serialize(send, SECURITY_MANAGER_API_SUCCESS);
385 Serialization::Serialize(send, pkgId);
389 } // namespace SecurityManager