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_app_id(app_inst_req *p_req, const char *app_id)
77 if (!p_req || !app_id)
78 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
80 p_req->appId = app_id;
82 return SECURITY_MANAGER_SUCCESS;
86 int security_manager_app_inst_req_set_pkg_id(app_inst_req *p_req, const char *pkg_id)
88 if (!p_req || !pkg_id)
89 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
91 p_req->pkgId = pkg_id;
93 return SECURITY_MANAGER_SUCCESS;
97 int security_manager_app_inst_req_add_privilege(app_inst_req *p_req, const char *privilege)
99 if (!p_req || !privilege)
100 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
102 p_req->privileges.push_back(privilege);
104 return SECURITY_MANAGER_SUCCESS;
108 int security_manager_app_inst_req_add_path(app_inst_req *p_req, const char *path, const int path_type)
110 if (!p_req || !path || (path_type < 0) || (path_type >= SECURITY_MANAGER_ENUM_END))
111 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
113 p_req->appPaths.push_back(std::make_pair(path, path_type));
115 return SECURITY_MANAGER_SUCCESS;
119 int security_manager_app_install(const app_inst_req *p_req)
121 using namespace SecurityManager;
122 MessageBuffer send, recv;
124 return try_catch([&] {
125 //checking parameters
127 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
128 if (p_req->appId.empty() || p_req->pkgId.empty())
129 return SECURITY_MANAGER_ERROR_REQ_NOT_COMPLETE;
131 //put data into buffer
132 Serialization::Serialize(send, (int)SecurityModuleCall::APP_INSTALL);
133 Serialization::Serialize(send, p_req->appId);
134 Serialization::Serialize(send, p_req->pkgId);
135 Serialization::Serialize(send, p_req->privileges);
136 Serialization::Serialize(send, p_req->appPaths);
138 //send buffer to server
139 int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
140 if (retval != SECURITY_MANAGER_API_SUCCESS) {
141 LogError("Error in sendToServer. Error code: " << retval);
142 return SECURITY_MANAGER_ERROR_UNKNOWN;
145 //receive response from server
146 Deserialization::Deserialize(recv, retval);
148 case SECURITY_MANAGER_API_SUCCESS:
149 return SECURITY_MANAGER_SUCCESS;
150 case SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED:
151 return SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED;
153 return SECURITY_MANAGER_ERROR_UNKNOWN;
160 int security_manager_app_uninstall(const app_inst_req *p_req)
162 using namespace SecurityManager;
163 MessageBuffer send, recv;
165 return try_catch([&] {
166 //checking parameters
168 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
169 if (p_req->appId.empty())
170 return SECURITY_MANAGER_ERROR_REQ_NOT_COMPLETE;
172 //put data into buffer
173 Serialization::Serialize(send, (int)SecurityModuleCall::APP_UNINSTALL);
174 Serialization::Serialize(send, p_req->appId);
176 //send buffer to server
177 int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
178 if (retval != SECURITY_MANAGER_API_SUCCESS) {
179 LogError("Error in sendToServer. Error code: " << retval);
180 return SECURITY_MANAGER_ERROR_UNKNOWN;
183 //receive response from server
184 Deserialization::Deserialize(recv, retval);
185 if (retval != SECURITY_MANAGER_API_SUCCESS)
186 return SECURITY_MANAGER_ERROR_UNKNOWN;
188 return SECURITY_MANAGER_SUCCESS;;
193 int security_manager_get_app_pkgid(char **pkg_id, const char *app_id)
195 using namespace SecurityManager;
196 MessageBuffer send, recv;
198 LogDebug("security_manager_get_app_pkgid() called");
200 return try_catch([&] {
201 //checking parameters
203 if (app_id == NULL) {
204 LogError("security_manager_app_get_pkgid: app_id is NULL");
205 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
208 if (pkg_id == NULL) {
209 LogError("security_manager_app_get_pkgid: pkg_id is NULL");
210 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
213 //put data into buffer
214 Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::APP_GET_PKGID));
215 Serialization::Serialize(send, std::string(app_id));
217 //send buffer to server
218 int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
219 if (retval != SECURITY_MANAGER_API_SUCCESS) {
220 LogDebug("Error in sendToServer. Error code: " << retval);
221 return SECURITY_MANAGER_ERROR_UNKNOWN;
224 //receive response from server
225 Deserialization::Deserialize(recv, retval);
226 if (retval != SECURITY_MANAGER_API_SUCCESS)
227 return SECURITY_MANAGER_ERROR_UNKNOWN;
229 std::string pkgIdString;
230 Deserialization::Deserialize(recv, pkgIdString);
231 if (pkgIdString.empty()) {
232 LogError("Unexpected empty pkgId");
233 return SECURITY_MANAGER_ERROR_UNKNOWN;
236 *pkg_id = strdup(pkgIdString.c_str());
237 if (*pkg_id == NULL) {
238 LogError("Failed to allocate memory for pkgId");
239 return SECURITY_MANAGER_ERROR_MEMORY;
242 return SECURITY_MANAGER_SUCCESS;
246 static bool setup_smack(const char *label)
248 int labelSize = strlen(label);
250 // Set Smack label for open socket file descriptors
252 std::unique_ptr<DIR, std::function<int(DIR*)>> dir(
253 opendir("/proc/self/fd"), closedir);
255 LogError("Unable to read list of open file descriptors: " <<
257 return SECURITY_MANAGER_ERROR_UNKNOWN;
262 struct dirent *dirEntry = readdir(dir.get());
263 if (dirEntry == nullptr) {
264 if (errno == 0) // NULL return value also signals end of directory
267 LogError("Unable to read list of open file descriptors: " <<
269 return SECURITY_MANAGER_ERROR_UNKNOWN;
272 // Entries with numerical names specify file descriptors, ignore the rest
273 if (!isdigit(dirEntry->d_name[0]))
277 int fd = atoi(dirEntry->d_name);
278 int ret = fstat(fd, &statBuf);
280 LogWarning("fstat failed on file descriptor " << fd << ": " <<
284 if (S_ISSOCK(statBuf.st_mode)) {
285 ret = fsetxattr(fd, XATTR_NAME_SMACKIPIN, label, labelSize, 0);
287 LogError("Setting Smack label failed on file descriptor " <<
288 fd << ": " << strerror(errno));
289 return SECURITY_MANAGER_ERROR_UNKNOWN;
292 ret = fsetxattr(fd, XATTR_NAME_SMACKIPOUT, label, labelSize, 0);
294 LogError("Setting Smack label failed on file descriptor " <<
295 fd << ": " << strerror(errno));
296 return SECURITY_MANAGER_ERROR_UNKNOWN;
301 // Set Smack label of current process
302 smack_set_label_for_self(label);
304 return SECURITY_MANAGER_SUCCESS;
308 int security_manager_set_process_label_from_binary(const char *path)
313 LogDebug("security_manager_set_process_label_from_binary() called");
315 if (smack_smackfs_path() == NULL)
316 return SECURITY_MANAGER_SUCCESS;
319 LogError("security_manager_set_process_label_from_binary: path is NULL");
320 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
323 ret = SecurityManager::getSmackLabelFromBinary(&smack_label, path);
324 if (ret == SECURITY_MANAGER_SUCCESS && smack_label != NULL) {
325 ret = setup_smack(smack_label);
326 if (ret != SECURITY_MANAGER_SUCCESS) {
327 LogError("Failed to set smack label " << smack_label << " for current process");
336 int security_manager_set_process_label_from_appid(const char *app_id)
340 std::string appLabel;
342 LogDebug("security_manager_set_process_label_from_appid() called");
344 if (smack_smackfs_path() == NULL)
345 return SECURITY_MANAGER_SUCCESS;
347 ret = security_manager_get_app_pkgid(&pkg_id, app_id);
348 if (ret != SECURITY_MANAGER_SUCCESS) {
352 if (SecurityManager::generateAppLabel(std::string(pkg_id), appLabel)) {
353 ret = setup_smack(appLabel.c_str());
354 if (ret != SECURITY_MANAGER_SUCCESS) {
355 LogError("Failed to set smack label " << appLabel << " for current process");
359 ret = SECURITY_MANAGER_ERROR_UNKNOWN;
367 int security_manager_set_process_groups_from_appid(const char *app_id)
369 using namespace SecurityManager;
370 MessageBuffer send, recv;
373 LogDebug("security_manager_set_process_groups_from_appid() called");
375 return try_catch([&] {
376 //checking parameters
378 if (app_id == nullptr) {
379 LogError("app_id is NULL");
380 return SECURITY_MANAGER_ERROR_INPUT_PARAM;
383 //put data into buffer
384 Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::APP_GET_GROUPS));
385 Serialization::Serialize(send, std::string(app_id));
387 //send buffer to server
388 int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
389 if (retval != SECURITY_MANAGER_API_SUCCESS) {
390 LogDebug("Error in sendToServer. Error code: " << retval);
391 return SECURITY_MANAGER_ERROR_UNKNOWN;
394 //receive response from server
395 Deserialization::Deserialize(recv, retval);
396 if (retval != SECURITY_MANAGER_API_SUCCESS)
397 return SECURITY_MANAGER_ERROR_UNKNOWN;
399 //How many new groups?
401 Deserialization::Deserialize(recv, newGroupsCnt);
403 //And how many groups do we belong to already?
405 ret = getgroups(0, nullptr);
407 LogError("Unable to get list of current supplementary groups: " <<
409 return SECURITY_MANAGER_ERROR_UNKNOWN;
413 //Allocate an array for both old and new groups gids
414 std::unique_ptr<gid_t[]> groups(new gid_t[oldGroupsCnt + newGroupsCnt]);
416 LogError("Memory allocation failed.");
417 return SECURITY_MANAGER_ERROR_MEMORY;
420 //Get the old groups from process
421 ret = getgroups(oldGroupsCnt, groups.get());
423 LogError("Unable to get list of current supplementary groups: " <<
425 return SECURITY_MANAGER_ERROR_UNKNOWN;
428 //Get the new groups from server response
429 for (int i = 0; i < newGroupsCnt; ++i) {
431 Deserialization::Deserialize(recv, gid);
432 groups.get()[oldGroupsCnt + i] = gid;
433 LogDebug("Adding process to group " << gid);
436 //Apply the modified groups list
437 ret = setgroups(oldGroupsCnt + newGroupsCnt, groups.get());
439 LogError("Unable to get list of current supplementary groups: " <<
441 return SECURITY_MANAGER_ERROR_UNKNOWN;
444 return SECURITY_MANAGER_SUCCESS;
449 int security_manager_drop_process_privileges(void)
451 LogDebug("security_manager_drop_process_privileges() called");
454 cap_t cap = cap_init();
456 LogError("Unable to allocate capability object");
457 return SECURITY_MANAGER_ERROR_MEMORY;
460 ret = cap_clear(cap);
462 LogError("Unable to initialize capability object");
464 return SECURITY_MANAGER_ERROR_UNKNOWN;
467 ret = cap_set_proc(cap);
469 LogError("Unable to drop process capabilities");
471 return SECURITY_MANAGER_ERROR_UNKNOWN;
475 return SECURITY_MANAGER_SUCCESS;
479 int security_manager_prepare_app(const char *app_id)
481 LogDebug("security_manager_prepare_app() called");
484 ret = security_manager_set_process_label_from_appid(app_id);
485 if (ret != SECURITY_MANAGER_SUCCESS)
488 ret = security_manager_set_process_groups_from_appid(app_id);
489 if (ret != SECURITY_MANAGER_SUCCESS)
492 ret = security_manager_drop_process_privileges();