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 security-manager service.
26 #include <dpl/log/log.h>
27 #include <dpl/serialization.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
36 #include "protocols.h"
37 #include "security-manager.h"
38 #include "smack-common.h"
39 #include "smack-rules.h"
40 #include "smack-labels.h"
41 #include "privilege_db.h"
44 namespace SecurityManager {
46 const InterfaceID IFACE = 1;
53 GenericSocketService::ServiceDescriptionVector Service::GetServiceDescription()
55 return ServiceDescriptionVector {
56 {SERVICE_SOCKET, "security-manager", IFACE},
60 void Service::accept(const AcceptEvent &event)
62 LogDebug("Accept event. ConnectionID.sock: " << event.connectionID.sock <<
63 " ConnectionID.counter: " << event.connectionID.counter <<
64 " ServiceID: " << event.interfaceID);
66 auto &info = m_connectionInfoMap[event.connectionID.counter];
67 info.interfaceID = event.interfaceID;
70 void Service::write(const WriteEvent &event)
72 LogDebug("WriteEvent. ConnectionID: " << event.connectionID.sock <<
73 " Size: " << event.size <<
74 " Left: " << event.left);
77 m_serviceManager->Close(event.connectionID);
80 void Service::process(const ReadEvent &event)
82 LogDebug("Read event for counter: " << event.connectionID.counter);
83 auto &info = m_connectionInfoMap[event.connectionID.counter];
84 info.buffer.Push(event.rawBuffer);
86 // We can get several requests in one package.
87 // Extract and process them all
88 while (processOne(event.connectionID, info.buffer, info.interfaceID));
91 void Service::close(const CloseEvent &event)
93 LogDebug("CloseEvent. ConnectionID: " << event.connectionID.sock);
94 m_connectionInfoMap.erase(event.connectionID.counter);
97 static bool getPeerUserID(int sock, uid_t *uid) {
99 socklen_t len = sizeof (cr);
103 if (!getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &cr, &len)) {
110 bool Service::processOne(const ConnectionID &conn, MessageBuffer &buffer,
111 InterfaceID interfaceID)
113 LogDebug("Iteration begin. Interface = " << interfaceID);
115 //waiting for all data
116 if (!buffer.Ready()) {
125 if(!getPeerUserID(conn.sock, &uid)) {
126 LogError("Closing socket because of error: unable to get peer's uid");
127 m_serviceManager->Close(conn);
131 if (IFACE == interfaceID) {
133 // deserialize API call type
135 Deserialization::Deserialize(buffer, call_type_int);
136 SecurityModuleCall call_type = static_cast<SecurityModuleCall>(call_type_int);
139 case SecurityModuleCall::APP_INSTALL:
140 LogDebug("call_type: SecurityModuleCall::APP_INSTALL");
141 processAppInstall(buffer, send, uid);
143 case SecurityModuleCall::APP_UNINSTALL:
144 LogDebug("call_type: SecurityModuleCall::APP_UNINSTALL");
145 processAppUninstall(buffer, send, uid);
147 case SecurityModuleCall::APP_GET_PKGID:
148 processGetPkgId(buffer, send);
151 LogError("Invalid call: " << call_type_int);
152 Throw(ServiceException::InvalidAction);
154 // if we reach this point, the protocol is OK
156 } Catch (MessageBuffer::Exception::Base) {
157 LogError("Broken protocol.");
158 } Catch (ServiceException::Base) {
159 LogError("Broken protocol.");
160 } catch (std::exception &e) {
161 LogError("STD exception " << e.what());
163 LogError("Unknown exception");
167 LogError("Wrong interface");
172 m_serviceManager->Write(conn, send.Pop());
174 LogError("Closing socket because of error");
175 m_serviceManager->Close(conn);
181 static inline bool isSubDir(const char *parent, const char *subdir)
183 while (*parent && *subdir)
184 if (*parent++ != *subdir++)
187 return (*subdir == '/');
190 static inline bool installRequestAuthCheck(const app_inst_req &req, uid_t uid)
199 if (!pwd && errno != EINTR) {
200 LogError("getpwuid failed with '" << uid
201 << "' as paramter: " << strerror(errno));
206 std::unique_ptr<char, std::function<void(void*)>> home(
207 realpath(pwd->pw_dir, NULL), free);
209 LogError("realpath failed with '" << pwd->pw_dir
210 << "' as paramter: " << strerror(errno));
214 for (const auto &appPath : req.appPaths) {
215 std::unique_ptr<char, std::function<void(void*)>> real_path(
216 realpath(appPath.first.c_str(), NULL), free);
217 if (!real_path.get()) {
218 LogError("realpath failed with '" << appPath.first.c_str()
219 << "' as paramter: " << strerror(errno));
222 LogDebug("Requested path is '" << appPath.first.c_str()
223 << "'. User's HOME is '" << pwd->pw_dir << "'");
224 if (!isSubDir(home.get(), real_path.get())) {
225 LogWarning("User's apps may have registered folders only in user's home dir");
229 app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
230 if (pathType == SECURITY_MANAGER_PATH_PUBLIC) {
231 LogWarning("Only root can register SECURITY_MANAGER_PATH_PUBLIC path");
238 bool Service::processAppInstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid)
240 bool pkgIdIsNew = false;
241 std::vector<std::string> addedPermissions;
242 std::vector<std::string> removedPermissions;
244 // deserialize request data
246 Deserialization::Deserialize(buffer, req.appId);
247 Deserialization::Deserialize(buffer, req.pkgId);
248 Deserialization::Deserialize(buffer, req.privileges);
249 Deserialization::Deserialize(buffer, req.appPaths);
251 if(!installRequestAuthCheck(req, uid)) {
252 LogError("Request from uid " << uid << " for app installation denied");
253 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED);
257 std::string smackLabel;
258 if (!generateAppLabel(req.pkgId, smackLabel)) {
259 LogError("Cannot generate Smack label for package: " << req.pkgId);
260 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
264 LogDebug("Install parameters: appId: " << req.appId << ", pkgId: " << req.pkgId
265 << ", generated smack label: " << smackLabel);
267 // create null terminated array of strings for permissions
268 std::unique_ptr<const char *[]> pp_permissions(new const char* [req.privileges.size() + 1]);
269 for (size_t i = 0; i < req.privileges.size(); ++i) {
270 LogDebug(" Permission = " << req.privileges[i]);
271 pp_permissions[i] = req.privileges[i].c_str();
273 pp_permissions[req.privileges.size()] = nullptr;
276 std::vector<std::string> oldPkgPrivileges, newPkgPrivileges;
277 std::string uidstr = uid ? std::to_string(static_cast<unsigned int>(uid))
278 : CYNARA_ADMIN_WILDCARD;
280 LogDebug("Install parameters: appId: " << req.appId << ", pkgId: " << req.pkgId
281 << ", uidstr " << uidstr << ", generated smack label: " << smackLabel);
283 m_privilegeDb.BeginTransaction();
284 m_privilegeDb.GetPkgPrivileges(req.pkgId, uid, oldPkgPrivileges);
285 m_privilegeDb.AddApplication(req.appId, req.pkgId, uid, pkgIdIsNew);
286 m_privilegeDb.UpdateAppPrivileges(req.appId, uid, req.privileges);
287 m_privilegeDb.GetPkgPrivileges(req.pkgId, uid, newPkgPrivileges);
288 CynaraAdmin::UpdatePackagePolicy(smackLabel, uidstr, oldPkgPrivileges,
290 m_privilegeDb.CommitTransaction();
291 LogDebug("Application installation commited to database");
292 } catch (const PrivilegeDb::Exception::InternalError &e) {
293 m_privilegeDb.RollbackTransaction();
294 LogError("Error while saving application info to database: " << e.DumpToString());
296 } catch (const CynaraException::Base &e) {
297 m_privilegeDb.RollbackTransaction();
298 LogError("Error while setting Cynara rules for application: " << e.DumpToString());
300 } catch (const std::bad_alloc &e) {
301 m_privilegeDb.RollbackTransaction();
302 LogError("Memory allocation while setting Cynara rules for application: " << e.what());
307 for (const auto &appPath : req.appPaths) {
308 const std::string &path = appPath.first;
309 app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
310 int result = setupPath(req.pkgId, path, pathType);
313 LogError("setupPath() failed");
319 LogDebug("Adding Smack rules for new pkgId " << req.pkgId);
320 if (!SmackRules::installPackageRules(req.pkgId)) {
321 LogError("Failed to apply package-specific smack rules");
327 Serialization::Serialize(send, SECURITY_MANAGER_API_SUCCESS);
331 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
335 bool Service::processAppUninstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid)
337 // deserialize request data
340 std::string smackLabel;
341 bool appExists = true;
342 bool removePkg = false;
344 Deserialization::Deserialize(buffer, appId);
347 std::vector<std::string> oldPkgPrivileges, newPkgPrivileges;
349 m_privilegeDb.BeginTransaction();
350 if (!m_privilegeDb.GetAppPkgId(appId, pkgId)) {
351 LogWarning("Application " << appId <<
352 " not found in database while uninstalling");
353 m_privilegeDb.RollbackTransaction();
356 if (!generateAppLabel(pkgId, smackLabel)) {
357 LogError("Cannot generate Smack label for package: " << pkgId);
361 std::string uidstr = uid ? std::to_string(static_cast<unsigned int>(uid))
362 : CYNARA_ADMIN_WILDCARD;
364 LogDebug("Uninstall parameters: appId: " << appId << ", pkgId: " << pkgId
365 << ", uidstr " << uidstr << ", generated smack label: " << smackLabel);
367 m_privilegeDb.GetPkgPrivileges(pkgId, uid, oldPkgPrivileges);
368 m_privilegeDb.UpdateAppPrivileges(appId, uid, std::vector<std::string>());
369 m_privilegeDb.RemoveApplication(appId, uid, removePkg);
370 m_privilegeDb.GetPkgPrivileges(pkgId, uid, newPkgPrivileges);
371 CynaraAdmin::UpdatePackagePolicy(smackLabel, uidstr, oldPkgPrivileges,
373 m_privilegeDb.CommitTransaction();
374 LogDebug("Application uninstallation commited to database");
376 } catch (const PrivilegeDb::Exception::InternalError &e) {
377 m_privilegeDb.RollbackTransaction();
378 LogError("Error while removing application info from database: " << e.DumpToString());
380 } catch (const CynaraException::Base &e) {
381 m_privilegeDb.RollbackTransaction();
382 LogError("Error while setting Cynara rules for application: " << e.DumpToString());
384 } catch (const std::bad_alloc &e) {
385 m_privilegeDb.RollbackTransaction();
386 LogError("Memory allocation while setting Cynara rules for application: " << e.what());
393 LogDebug("Removing Smack rules for deleted pkgId " << pkgId);
394 if (!SmackRules::uninstallPackageRules(pkgId)) {
395 LogError("Error on uninstallation of package-specific smack rules");
402 Serialization::Serialize(send, SECURITY_MANAGER_API_SUCCESS);
406 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
410 bool Service::processGetPkgId(MessageBuffer &buffer, MessageBuffer &send)
412 // deserialize request data
416 Deserialization::Deserialize(buffer, appId);
417 LogDebug("appId: " << appId);
420 if (!m_privilegeDb.GetAppPkgId(appId, pkgId)) {
421 LogWarning("Application " << appId << " not found in database");
422 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT);
425 LogDebug("pkgId: " << pkgId);
427 } catch (const PrivilegeDb::Exception::InternalError &e) {
428 LogError("Error while getting pkgId from database: " << e.DumpToString());
429 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
434 Serialization::Serialize(send, SECURITY_MANAGER_API_SUCCESS);
435 Serialization::Serialize(send, pkgId);
439 } // namespace SecurityManager