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
18 * Security Manager library header
21 * @file client-security-manager.cpp
22 * @author Pawel Polawski <p.polawski@samsung.com>
23 * @author Rafal Krypa <r.krypa@samsung.com>
25 * @brief This file contain client side implementation of security-manager API
34 #include <sys/types.h>
36 #include <sys/xattr.h>
37 #include <sys/smack.h>
38 #include <sys/capability.h>
40 #include <dpl/log/log.h>
41 #include <dpl/exception.h>
43 #include <message-buffer.h>
44 #include <client-common.h>
45 #include <protocols.h>
46 #include <smack-common.h>
48 #include <security-manager.h>
53 int security_manager_app_inst_req_new(app_inst_req **pp_req)
56 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
59 *pp_req = new app_inst_req;
60 } catch (std::bad_alloc& ex) {
61 return SECURITY_MANAGER_ERROR_MEMORY;
65 return SECURITY_MANAGER_SUCCESS;
69 void security_manager_app_inst_req_free(app_inst_req *p_req)
75 int security_manager_app_inst_req_set_uid(app_inst_req *p_req,
79 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
83 return SECURITY_MANAGER_SUCCESS;
87 int security_manager_app_inst_req_set_app_id(app_inst_req *p_req, const char *app_id)
89 if (!p_req || !app_id)
90 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
92 p_req->appId = app_id;
94 return SECURITY_MANAGER_SUCCESS;
98 int security_manager_app_inst_req_set_pkg_id(app_inst_req *p_req, const char *pkg_id)
100 if (!p_req || !pkg_id)
101 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
103 p_req->pkgId = pkg_id;
105 return SECURITY_MANAGER_SUCCESS;
109 int security_manager_app_inst_req_add_privilege(app_inst_req *p_req, const char *privilege)
111 if (!p_req || !privilege)
112 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
114 p_req->privileges.push_back(privilege);
116 return SECURITY_MANAGER_SUCCESS;
120 int security_manager_app_inst_req_add_path(app_inst_req *p_req, const char *path, const int path_type)
122 if (!p_req || !path || (path_type < 0) || (path_type >= SECURITY_MANAGER_ENUM_END))
123 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
125 p_req->appPaths.push_back(std::make_pair(path, path_type));
127 return SECURITY_MANAGER_SUCCESS;
131 int security_manager_app_install(const app_inst_req *p_req)
133 using namespace SecurityManager;
134 MessageBuffer send, recv;
136 return try_catch([&] {
137 //checking parameters
139 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
140 if (p_req->appId.empty() || p_req->pkgId.empty())
141 return SECURITY_MANAGER_ERROR_REQ_NOT_COMPLETE;
143 //put data into buffer
144 Serialization::Serialize(send, (int)SecurityModuleCall::APP_INSTALL);
145 Serialization::Serialize(send, p_req->appId);
146 Serialization::Serialize(send, p_req->pkgId);
147 Serialization::Serialize(send, p_req->privileges);
148 Serialization::Serialize(send, p_req->appPaths);
149 Serialization::Serialize(send, p_req->uid);
151 //send buffer to server
152 int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
153 if (retval != SECURITY_MANAGER_API_SUCCESS) {
154 LogError("Error in sendToServer. Error code: " << retval);
155 return SECURITY_MANAGER_ERROR_UNKNOWN;
158 //receive response from server
159 Deserialization::Deserialize(recv, retval);
161 case SECURITY_MANAGER_API_SUCCESS:
162 return SECURITY_MANAGER_SUCCESS;
163 case SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED:
164 return SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED;
166 return SECURITY_MANAGER_ERROR_UNKNOWN;
173 int security_manager_app_uninstall(const app_inst_req *p_req)
175 using namespace SecurityManager;
176 MessageBuffer send, recv;
178 return try_catch([&] {
179 //checking parameters
181 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
182 if (p_req->appId.empty())
183 return SECURITY_MANAGER_ERROR_REQ_NOT_COMPLETE;
185 //put data into buffer
186 Serialization::Serialize(send, (int)SecurityModuleCall::APP_UNINSTALL);
187 Serialization::Serialize(send, p_req->appId);
189 //send buffer to server
190 int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
191 if (retval != SECURITY_MANAGER_API_SUCCESS) {
192 LogError("Error in sendToServer. Error code: " << retval);
193 return SECURITY_MANAGER_ERROR_UNKNOWN;
196 //receive response from server
197 Deserialization::Deserialize(recv, retval);
198 if (retval != SECURITY_MANAGER_API_SUCCESS)
199 return SECURITY_MANAGER_ERROR_UNKNOWN;
201 return SECURITY_MANAGER_SUCCESS;;
206 int security_manager_get_app_pkgid(char **pkg_id, const char *app_id)
208 using namespace SecurityManager;
209 MessageBuffer send, recv;
211 LogDebug("security_manager_get_app_pkgid() called");
213 return try_catch([&] {
214 //checking parameters
216 if (app_id == NULL) {
217 LogError("security_manager_app_get_pkgid: app_id is NULL");
218 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
221 if (pkg_id == NULL) {
222 LogError("security_manager_app_get_pkgid: pkg_id is NULL");
223 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
226 //put data into buffer
227 Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::APP_GET_PKGID));
228 Serialization::Serialize(send, std::string(app_id));
230 //send buffer to server
231 int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
232 if (retval != SECURITY_MANAGER_API_SUCCESS) {
233 LogDebug("Error in sendToServer. Error code: " << retval);
234 return SECURITY_MANAGER_ERROR_UNKNOWN;
237 //receive response from server
238 Deserialization::Deserialize(recv, retval);
239 if (retval != SECURITY_MANAGER_API_SUCCESS)
240 return SECURITY_MANAGER_ERROR_UNKNOWN;
242 std::string pkgIdString;
243 Deserialization::Deserialize(recv, pkgIdString);
244 if (pkgIdString.empty()) {
245 LogError("Unexpected empty pkgId");
246 return SECURITY_MANAGER_ERROR_UNKNOWN;
249 *pkg_id = strdup(pkgIdString.c_str());
250 if (*pkg_id == NULL) {
251 LogError("Failed to allocate memory for pkgId");
252 return SECURITY_MANAGER_ERROR_MEMORY;
255 return SECURITY_MANAGER_SUCCESS;
259 static bool setup_smack(const char *label)
261 int labelSize = strlen(label);
263 // Set Smack label for open socket file descriptors
265 std::unique_ptr<DIR, std::function<int(DIR*)>> dir(
266 opendir("/proc/self/fd"), closedir);
268 LogError("Unable to read list of open file descriptors: " <<
270 return SECURITY_MANAGER_ERROR_UNKNOWN;
275 struct dirent *dirEntry = readdir(dir.get());
276 if (dirEntry == nullptr) {
277 if (errno == 0) // NULL return value also signals end of directory
280 LogError("Unable to read list of open file descriptors: " <<
282 return SECURITY_MANAGER_ERROR_UNKNOWN;
285 // Entries with numerical names specify file descriptors, ignore the rest
286 if (!isdigit(dirEntry->d_name[0]))
290 int fd = atoi(dirEntry->d_name);
291 int ret = fstat(fd, &statBuf);
293 LogWarning("fstat failed on file descriptor " << fd << ": " <<
297 if (S_ISSOCK(statBuf.st_mode)) {
298 ret = fsetxattr(fd, XATTR_NAME_SMACKIPIN, label, labelSize, 0);
300 LogError("Setting Smack label failed on file descriptor " <<
301 fd << ": " << strerror(errno));
302 return SECURITY_MANAGER_ERROR_UNKNOWN;
305 ret = fsetxattr(fd, XATTR_NAME_SMACKIPOUT, label, labelSize, 0);
307 LogError("Setting Smack label failed on file descriptor " <<
308 fd << ": " << strerror(errno));
309 return SECURITY_MANAGER_ERROR_UNKNOWN;
314 // Set Smack label of current process
315 smack_set_label_for_self(label);
317 return SECURITY_MANAGER_SUCCESS;
321 int security_manager_set_process_label_from_appid(const char *app_id)
325 std::string appLabel;
327 LogDebug("security_manager_set_process_label_from_appid() called");
329 if (smack_smackfs_path() == NULL)
330 return SECURITY_MANAGER_SUCCESS;
332 ret = security_manager_get_app_pkgid(&pkg_id, app_id);
333 if (ret != SECURITY_MANAGER_SUCCESS) {
337 if (SecurityManager::generateAppLabel(std::string(pkg_id), appLabel)) {
338 ret = setup_smack(appLabel.c_str());
339 if (ret != SECURITY_MANAGER_SUCCESS) {
340 LogError("Failed to set smack label " << appLabel << " for current process");
344 ret = SECURITY_MANAGER_ERROR_UNKNOWN;
352 int security_manager_set_process_groups_from_appid(const char *app_id)
354 using namespace SecurityManager;
355 MessageBuffer send, recv;
358 LogDebug("security_manager_set_process_groups_from_appid() called");
360 return try_catch([&] {
361 //checking parameters
363 if (app_id == nullptr) {
364 LogError("app_id is NULL");
365 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
368 //put data into buffer
369 Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::APP_GET_GROUPS));
370 Serialization::Serialize(send, std::string(app_id));
372 //send buffer to server
373 int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
374 if (retval != SECURITY_MANAGER_API_SUCCESS) {
375 LogDebug("Error in sendToServer. Error code: " << retval);
376 return SECURITY_MANAGER_ERROR_UNKNOWN;
379 //receive response from server
380 Deserialization::Deserialize(recv, retval);
381 if (retval != SECURITY_MANAGER_API_SUCCESS)
382 return SECURITY_MANAGER_ERROR_UNKNOWN;
384 //How many new groups?
386 Deserialization::Deserialize(recv, newGroupsCnt);
388 //And how many groups do we belong to already?
390 ret = getgroups(0, nullptr);
392 LogError("Unable to get list of current supplementary groups: " <<
394 return SECURITY_MANAGER_ERROR_UNKNOWN;
398 //Allocate an array for both old and new groups gids
399 std::unique_ptr<gid_t[]> groups(new gid_t[oldGroupsCnt + newGroupsCnt]);
401 LogError("Memory allocation failed.");
402 return SECURITY_MANAGER_ERROR_MEMORY;
405 //Get the old groups from process
406 ret = getgroups(oldGroupsCnt, groups.get());
408 LogError("Unable to get list of current supplementary groups: " <<
410 return SECURITY_MANAGER_ERROR_UNKNOWN;
413 //Get the new groups from server response
414 for (int i = 0; i < newGroupsCnt; ++i) {
416 Deserialization::Deserialize(recv, gid);
417 groups.get()[oldGroupsCnt + i] = gid;
418 LogDebug("Adding process to group " << gid);
421 //Apply the modified groups list
422 ret = setgroups(oldGroupsCnt + newGroupsCnt, groups.get());
424 LogError("Unable to get list of current supplementary groups: " <<
426 return SECURITY_MANAGER_ERROR_UNKNOWN;
429 return SECURITY_MANAGER_SUCCESS;
434 int security_manager_drop_process_privileges(void)
436 LogDebug("security_manager_drop_process_privileges() called");
439 cap_t cap = cap_init();
441 LogError("Unable to allocate capability object");
442 return SECURITY_MANAGER_ERROR_MEMORY;
445 ret = cap_clear(cap);
447 LogError("Unable to initialize capability object");
449 return SECURITY_MANAGER_ERROR_UNKNOWN;
452 ret = cap_set_proc(cap);
454 LogError("Unable to drop process capabilities");
456 return SECURITY_MANAGER_ERROR_UNKNOWN;
460 return SECURITY_MANAGER_SUCCESS;
464 int security_manager_prepare_app(const char *app_id)
466 LogDebug("security_manager_prepare_app() called");
469 ret = security_manager_set_process_label_from_appid(app_id);
470 if (ret != SECURITY_MANAGER_SUCCESS)
473 ret = security_manager_set_process_groups_from_appid(app_id);
474 if (ret != SECURITY_MANAGER_SUCCESS)
477 ret = security_manager_drop_process_privileges();