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>
28 #include <tzplatform_config.h>
30 #include <unordered_set>
31 #include <sys/types.h>
32 #include <sys/socket.h>
38 #include "protocols.h"
39 #include "security-manager.h"
40 #include "smack-common.h"
41 #include "smack-rules.h"
42 #include "smack-labels.h"
43 #include "privilege_db.h"
45 namespace SecurityManager {
47 const InterfaceID IFACE = 1;
49 static inline bool isGlobalUser(uid_t uid) {
50 static uid_t uidGlobalApp = 0;
52 // As long as the recorded global user id is root, recheck.
53 uid_t id = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
57 return uidGlobalApp == uid || !uid; // FIXME: is root authorized?
64 GenericSocketService::ServiceDescriptionVector Service::GetServiceDescription()
66 return ServiceDescriptionVector {
67 {SERVICE_SOCKET, "security-manager", IFACE},
71 void Service::accept(const AcceptEvent &event)
73 LogDebug("Accept event. ConnectionID.sock: " << event.connectionID.sock <<
74 " ConnectionID.counter: " << event.connectionID.counter <<
75 " ServiceID: " << event.interfaceID);
77 auto &info = m_connectionInfoMap[event.connectionID.counter];
78 info.interfaceID = event.interfaceID;
81 void Service::write(const WriteEvent &event)
83 LogDebug("WriteEvent. ConnectionID: " << event.connectionID.sock <<
84 " Size: " << event.size <<
85 " Left: " << event.left);
88 m_serviceManager->Close(event.connectionID);
91 void Service::process(const ReadEvent &event)
93 LogDebug("Read event for counter: " << event.connectionID.counter);
94 auto &info = m_connectionInfoMap[event.connectionID.counter];
95 info.buffer.Push(event.rawBuffer);
97 // We can get several requests in one package.
98 // Extract and process them all
99 while (processOne(event.connectionID, info.buffer, info.interfaceID));
102 void Service::close(const CloseEvent &event)
104 LogDebug("CloseEvent. ConnectionID: " << event.connectionID.sock);
105 m_connectionInfoMap.erase(event.connectionID.counter);
108 static bool getPeerID(int sock, uid_t &uid, pid_t &pid) {
110 socklen_t len = sizeof(cr);
112 if (!getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &cr, &len)) {
121 bool Service::processOne(const ConnectionID &conn, MessageBuffer &buffer,
122 InterfaceID interfaceID)
124 LogDebug("Iteration begin. Interface = " << interfaceID);
126 //waiting for all data
127 if (!buffer.Ready()) {
137 if(!getPeerID(conn.sock, uid, pid)) {
138 LogError("Closing socket because of error: unable to get peer's uid and pid");
139 m_serviceManager->Close(conn);
143 if (IFACE == interfaceID) {
145 // deserialize API call type
147 Deserialization::Deserialize(buffer, call_type_int);
148 SecurityModuleCall call_type = static_cast<SecurityModuleCall>(call_type_int);
151 case SecurityModuleCall::APP_INSTALL:
152 LogDebug("call_type: SecurityModuleCall::APP_INSTALL");
153 processAppInstall(buffer, send, uid);
155 case SecurityModuleCall::APP_UNINSTALL:
156 LogDebug("call_type: SecurityModuleCall::APP_UNINSTALL");
157 processAppUninstall(buffer, send, uid);
159 case SecurityModuleCall::APP_GET_PKGID:
160 processGetPkgId(buffer, send);
162 case SecurityModuleCall::APP_GET_GROUPS:
163 processGetAppGroups(buffer, send, uid, pid);
166 LogError("Invalid call: " << call_type_int);
167 Throw(ServiceException::InvalidAction);
169 // if we reach this point, the protocol is OK
171 } Catch (MessageBuffer::Exception::Base) {
172 LogError("Broken protocol.");
173 } Catch (ServiceException::Base) {
174 LogError("Broken protocol.");
175 } catch (std::exception &e) {
176 LogError("STD exception " << e.what());
178 LogError("Unknown exception");
182 LogError("Wrong interface");
187 m_serviceManager->Write(conn, send.Pop());
189 LogError("Closing socket because of error");
190 m_serviceManager->Close(conn);
196 static inline bool isSubDir(const char *parent, const char *subdir)
198 while (*parent && *subdir)
199 if (*parent++ != *subdir++)
202 return (*subdir == '/');
205 static inline bool installRequestAuthCheck(const app_inst_req &req, uid_t uid)
214 if (!pwd && errno != EINTR) {
215 LogError("getpwuid failed with '" << uid
216 << "' as paramter: " << strerror(errno));
221 std::unique_ptr<char, std::function<void(void*)>> home(
222 realpath(pwd->pw_dir, NULL), free);
224 LogError("realpath failed with '" << pwd->pw_dir
225 << "' as paramter: " << strerror(errno));
229 for (const auto &appPath : req.appPaths) {
230 std::unique_ptr<char, std::function<void(void*)>> real_path(
231 realpath(appPath.first.c_str(), NULL), free);
232 if (!real_path.get()) {
233 LogError("realpath failed with '" << appPath.first.c_str()
234 << "' as paramter: " << strerror(errno));
237 LogDebug("Requested path is '" << appPath.first.c_str()
238 << "'. User's HOME is '" << pwd->pw_dir << "'");
239 if (!isSubDir(home.get(), real_path.get())) {
240 LogWarning("User's apps may have registered folders only in user's home dir");
244 app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
245 if (pathType == SECURITY_MANAGER_PATH_PUBLIC) {
246 LogWarning("Only root can register SECURITY_MANAGER_PATH_PUBLIC path");
253 bool Service::processAppInstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid)
255 bool pkgIdIsNew = false;
256 std::vector<std::string> addedPermissions;
257 std::vector<std::string> removedPermissions;
259 // deserialize request data
261 Deserialization::Deserialize(buffer, req.appId);
262 Deserialization::Deserialize(buffer, req.pkgId);
263 Deserialization::Deserialize(buffer, req.privileges);
264 Deserialization::Deserialize(buffer, req.appPaths);
266 if(!installRequestAuthCheck(req, uid)) {
267 LogError("Request from uid " << uid << " for app installation denied");
268 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED);
272 std::string smackLabel;
273 if (!generateAppLabel(req.pkgId, smackLabel)) {
274 LogError("Cannot generate Smack label for package: " << req.pkgId);
275 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
279 LogDebug("Install parameters: appId: " << req.appId << ", pkgId: " << req.pkgId
280 << ", generated smack label: " << smackLabel);
282 // create null terminated array of strings for permissions
283 std::unique_ptr<const char *[]> pp_permissions(new const char* [req.privileges.size() + 1]);
284 for (size_t i = 0; i < req.privileges.size(); ++i) {
285 LogDebug(" Permission = " << req.privileges[i]);
286 pp_permissions[i] = req.privileges[i].c_str();
288 pp_permissions[req.privileges.size()] = nullptr;
291 std::vector<std::string> oldPkgPrivileges, newPkgPrivileges;
292 std::string uidstr = isGlobalUser(uid) ? CYNARA_ADMIN_WILDCARD
293 : std::to_string(static_cast<unsigned int>(uid));
295 LogDebug("Install parameters: appId: " << req.appId << ", pkgId: " << req.pkgId
296 << ", uidstr " << uidstr << ", generated smack label: " << smackLabel);
298 m_privilegeDb.BeginTransaction();
299 m_privilegeDb.GetPkgPrivileges(req.pkgId, uid, oldPkgPrivileges);
300 m_privilegeDb.AddApplication(req.appId, req.pkgId, uid, pkgIdIsNew);
301 m_privilegeDb.UpdateAppPrivileges(req.appId, uid, req.privileges);
302 m_privilegeDb.GetPkgPrivileges(req.pkgId, uid, newPkgPrivileges);
303 CynaraAdmin::UpdatePackagePolicy(smackLabel, uidstr, oldPkgPrivileges,
305 m_privilegeDb.CommitTransaction();
306 LogDebug("Application installation commited to database");
307 } catch (const PrivilegeDb::Exception::InternalError &e) {
308 m_privilegeDb.RollbackTransaction();
309 LogError("Error while saving application info to database: " << e.DumpToString());
311 } catch (const CynaraException::Base &e) {
312 m_privilegeDb.RollbackTransaction();
313 LogError("Error while setting Cynara rules for application: " << e.DumpToString());
315 } catch (const std::bad_alloc &e) {
316 m_privilegeDb.RollbackTransaction();
317 LogError("Memory allocation while setting Cynara rules for application: " << e.what());
322 for (const auto &appPath : req.appPaths) {
323 const std::string &path = appPath.first;
324 app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
325 int result = setupPath(req.pkgId, path, pathType);
328 LogError("setupPath() failed");
334 LogDebug("Adding Smack rules for new pkgId " << req.pkgId);
335 if (!SmackRules::installPackageRules(req.pkgId)) {
336 LogError("Failed to apply package-specific smack rules");
342 Serialization::Serialize(send, SECURITY_MANAGER_API_SUCCESS);
346 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
350 bool Service::processAppUninstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid)
352 // deserialize request data
355 std::string smackLabel;
356 bool appExists = true;
357 bool removePkg = false;
359 Deserialization::Deserialize(buffer, appId);
362 std::vector<std::string> oldPkgPrivileges, newPkgPrivileges;
364 m_privilegeDb.BeginTransaction();
365 if (!m_privilegeDb.GetAppPkgId(appId, pkgId)) {
366 LogWarning("Application " << appId <<
367 " not found in database while uninstalling");
368 m_privilegeDb.RollbackTransaction();
371 if (!generateAppLabel(pkgId, smackLabel)) {
372 LogError("Cannot generate Smack label for package: " << pkgId);
376 std::string uidstr = isGlobalUser(uid) ? CYNARA_ADMIN_WILDCARD
377 : std::to_string(static_cast<unsigned int>(uid));
379 LogDebug("Uninstall parameters: appId: " << appId << ", pkgId: " << pkgId
380 << ", uidstr " << uidstr << ", generated smack label: " << smackLabel);
382 m_privilegeDb.GetPkgPrivileges(pkgId, uid, oldPkgPrivileges);
383 m_privilegeDb.UpdateAppPrivileges(appId, uid, std::vector<std::string>());
384 m_privilegeDb.RemoveApplication(appId, uid, removePkg);
385 m_privilegeDb.GetPkgPrivileges(pkgId, uid, newPkgPrivileges);
386 CynaraAdmin::UpdatePackagePolicy(smackLabel, uidstr, oldPkgPrivileges,
388 m_privilegeDb.CommitTransaction();
389 LogDebug("Application uninstallation commited to database");
391 } catch (const PrivilegeDb::Exception::InternalError &e) {
392 m_privilegeDb.RollbackTransaction();
393 LogError("Error while removing application info from database: " << e.DumpToString());
395 } catch (const CynaraException::Base &e) {
396 m_privilegeDb.RollbackTransaction();
397 LogError("Error while setting Cynara rules for application: " << e.DumpToString());
399 } catch (const std::bad_alloc &e) {
400 m_privilegeDb.RollbackTransaction();
401 LogError("Memory allocation while setting Cynara rules for application: " << e.what());
408 LogDebug("Removing Smack rules for deleted pkgId " << pkgId);
409 if (!SmackRules::uninstallPackageRules(pkgId)) {
410 LogError("Error on uninstallation of package-specific smack rules");
417 Serialization::Serialize(send, SECURITY_MANAGER_API_SUCCESS);
421 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
425 bool Service::processGetPkgId(MessageBuffer &buffer, MessageBuffer &send)
427 // deserialize request data
431 Deserialization::Deserialize(buffer, appId);
432 LogDebug("appId: " << appId);
435 if (!m_privilegeDb.GetAppPkgId(appId, pkgId)) {
436 LogWarning("Application " << appId << " not found in database");
437 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT);
440 LogDebug("pkgId: " << pkgId);
442 } catch (const PrivilegeDb::Exception::InternalError &e) {
443 LogError("Error while getting pkgId from database: " << e.DumpToString());
444 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
449 Serialization::Serialize(send, SECURITY_MANAGER_API_SUCCESS);
450 Serialization::Serialize(send, pkgId);
454 bool Service::processGetAppGroups(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid)
456 std::unordered_set<gid_t> gids;
461 std::string smackLabel;
462 std::string uidStr = std::to_string(uid);
463 std::string pidStr = std::to_string(pid);
465 Deserialization::Deserialize(buffer, appId);
466 LogDebug("appId: " << appId);
468 if (!m_privilegeDb.GetAppPkgId(appId, pkgId)) {
469 LogWarning("Application " << appId << " not found in database");
470 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT);
473 LogDebug("pkgId: " << pkgId);
475 if (!generateAppLabel(pkgId, smackLabel)) {
476 LogError("Cannot generate Smack label for package: " << pkgId);
477 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT);
480 LogDebug("smack label: " << smackLabel);
482 std::vector<std::string> privileges;
483 m_privilegeDb.GetPkgPrivileges(pkgId, uid, privileges);
484 for (const auto &privilege : privileges) {
485 std::vector<gid_t> gidsTmp;
486 m_privilegeDb.GetPrivilegeGids(privilege, gidsTmp);
487 if (!gidsTmp.empty()) {
488 LogDebug("Considering privilege " << privilege << " with " <<
489 gidsTmp.size() << " groups assigned");
490 if (m_cynara.check(smackLabel, privilege, uidStr, pidStr)) {
491 gids.insert(gidsTmp.begin(), gidsTmp.end());
492 LogDebug("Cynara allowed, adding groups");
494 LogDebug("Cynara denied, not adding groups");
497 } catch (const PrivilegeDb::Exception::InternalError &e) {
498 LogError("Database error: " << e.DumpToString());
499 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
501 } catch (const CynaraException::Base &e) {
502 LogError("Error while querying Cynara for permissions: " << e.DumpToString());
503 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
505 } catch (const std::bad_alloc &e) {
506 LogError("Memory allocation failed: " << e.what());
507 Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY);
512 Serialization::Serialize(send, SECURITY_MANAGER_API_SUCCESS);
513 Serialization::Serialize(send, static_cast<int>(gids.size()));
514 for (const auto &gid : gids) {
515 Serialization::Serialize(send, gid);
521 } // namespace SecurityManager