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
19 * @file service-manager-cmd.cpp
20 * @author Sebastian Grabowski (s.grabowski@samsung.com)
22 * @brief Implementation of security-manager-cmd tool for offline mode
24 /* vim: set ts=4 et sw=4 tw=78 : */
31 #include <dpl/log/log.h>
32 #include <dpl/singleton.h>
33 #include <dpl/singleton_safe_impl.h>
34 #include <protocols.h>
35 #include <security-manager.h>
37 #include <boost/program_options.hpp>
38 namespace po = boost::program_options;
40 IMPLEMENT_SAFE_SINGLETON(SecurityManager::Log::LogSystem);
42 static std::map <std::string, enum app_install_path_type> app_install_path_type_map = {
43 {"private", SECURITY_MANAGER_PATH_PRIVATE},
44 {"public", SECURITY_MANAGER_PATH_PUBLIC},
45 {"public_ro", SECURITY_MANAGER_PATH_PUBLIC_RO}
48 static std::map <std::string, enum security_manager_user_type> user_type_map = {
49 {"system", SM_USER_TYPE_SYSTEM},
50 {"admin", SM_USER_TYPE_ADMIN},
51 {"guest", SM_USER_TYPE_GUEST},
52 {"normal", SM_USER_TYPE_NORMAL}
55 static po::options_description getGenericOptions()
57 po::options_description opts("Generic options");
59 ("help,h", "produce help message")
60 ("install,i", "install an application")
61 ("manage-users,m", po::value<std::string>(), "add or remove user, parameter is 'a' or 'add' (for add) and 'r' or 'remove' (for remove)")
66 static po::options_description getInstallOptions()
68 po::options_description opts("Install options");
70 ("app,a", po::value<std::string>()->required(),
71 "application name (required)")
72 ("pkg,g", po::value<std::string>()->required(),
73 "package name for the application (required)")
75 * multitoken: Specifies that the value can span multiple tokens.
76 * So it is possible to pass values to an option like
78 * --path=/home/user dirtype
79 * --path /home/user dirtype
80 * --path="/home/user" dirtype
82 ("path,p", po::value< std::vector<std::string> >()->multitoken(),
83 "path for setting smack labels (may occur more than once).\n"
84 "Format: --path <path> <path type>\n"
85 " where <path type> is: \tprivate, public, public_ro\n"
87 " \t--path=/home/user/app private")
88 ("privilege,s", po::value< std::vector<std::string> >(),
89 "privilege for the application (may occur more than once)")
90 ("uid,u", po::value<uid_t>()->required(),
91 "user identifier number (required)")
96 static po::options_description getUserOptions()
98 po::options_description opts("User management options");
100 ("uid,u", po::value<uid_t>()->required(), "user identifier number (required)")
101 ("usertype,t", po::value<std::string>(), "user type:"
102 "one of system, admin, guest, normal. Set to 'normal' by default,"
103 "ignored on user removal")
108 static po::options_description getAllOptions()
110 po::options_description opts("Allowed options");
111 opts.add(getGenericOptions());
112 opts.add(getInstallOptions());
113 opts.add(getUserOptions());
118 static void usage(std::string name)
122 cout << endl << name << " usage:" << endl;
123 cout << endl << getAllOptions() << endl << endl;
126 void parseCommandOptions(int argc, char *argv[],
127 po::options_description opts,
128 po::variables_map &vm)
130 const po::positional_options_description p;
132 * unix_style: The more-or-less traditional unix style. It looks as
133 * follows: unix_style = (allow_short | short_allow_adjacent |
134 * short_allow_next | allow_long |
135 * long_allow_adjacent | long_allow_next |
136 * allow_sticky | allow_guessing |
137 * allow_dash_for_short)
138 * allow_long_disguise: Allow long options with single option starting
139 * character, e.g -foo=10
140 * allow_guessing: Allow abbreviated spellings for long options, if
141 * they unambiguously identify long option. No long
142 * option name should be prefix of other long option name if
143 * guessing is in effect.
144 * allow_short: Alow "-<single character" style.
145 * short_allow_adjacent: Allow option parameter in the same token for
147 * short_allow_next: Allow option parameter in the next token for
149 * allow_long: Allow "--long_name" style.
150 * long_allow_adjacent: Allow option parameter in the same token for
151 * long option, like in --foo=10
152 * long_allow_next: Allow option parameter in the next token for long
154 * allow_sticky: Allow to merge several short options together, so
155 * that "-s -k" become "-sk". All of the options but
156 * last should accept no parameter. For example, if "-s" accept a
157 * parameter, then "k" will be taken as
158 * parameter, not another short option. Dos-style short options
160 * allow_dash_for_short: Allow "-" in short options.
162 po::store(po::command_line_parser(argc, argv).
163 options(getGenericOptions().add(opts)).positional(p).
164 style((po::command_line_style::unix_style |
165 po::command_line_style::allow_long_disguise) &
166 ~po::command_line_style::allow_guessing).
172 static bool loadPaths(const std::vector<std::string> &paths,
173 struct app_inst_req &req)
175 if (paths.size() & 1) {
176 std::cout << "Wrong number of tokens was given for path option." <<
178 LogDebug("Wrong paths size: " << paths.size());
181 req.appPaths.clear();
182 for (std::vector<std::string>::size_type i = 1; i < paths.size(); i += 2) {
183 app_install_path_type pathType;
184 LogDebug("path: " << paths[i - 1]);
186 pathType = app_install_path_type_map.at(paths[i]);
187 } catch (const std::out_of_range &e) {
188 std::cout << "Invalid path type found." << std::endl;
189 LogError("Invalid path type found.");
190 req.appPaths.clear();
193 LogDebug("path type: " << pathType << " (" << paths[i] << ")");
194 req.appPaths.push_back(std::make_pair(paths[i - 1], pathType));
196 return (!req.appPaths.empty());
199 static void parseInstallOptions(int argc, char *argv[],
200 struct app_inst_req &req,
201 po::variables_map &vm)
204 parseCommandOptions(argc, argv, getInstallOptions(), vm);
207 req.appId = vm["app"].as<std::string>();
209 req.pkgId = vm["pkg"].as<std::string>();
210 if (vm.count("path")) {
211 const std::vector<std::string> paths =
212 vm["path"].as<std::vector<std::string> >();
213 if (!loadPaths(paths, req)) {
214 po::error e("Error in parsing path arguments.");
218 if (vm.count("privilege")) {
219 req.privileges = vm["privilege"].as<std::vector<std::string> >();
220 if (req.privileges.empty()) {
221 po::error e("Error in parsing privilege arguments.");
224 #ifdef BUILD_TYPE_DEBUG
225 LogDebug("Passed privileges:");
226 for (const auto &p : req.privileges) {
232 req.uid = vm["uid"].as<uid_t>();
236 static void parseUserOptions(int argc, char *argv[],
237 struct user_req &req,
238 po::variables_map &vm)
240 parseCommandOptions(argc, argv, getUserOptions(), vm);
243 req.uid = vm["uid"].as<uid_t>();
244 if (vm.count("usertype")){
245 req.utype = user_type_map.at(vm["usertype"].as<std::string>());
247 req.utype = SM_USER_TYPE_NORMAL;
248 } catch (const std::out_of_range &e) {
249 po::error er("Invalid user type found.");
254 static int installApp(const struct app_inst_req &req)
256 int ret = EXIT_FAILURE;
258 ret = security_manager_app_install(&req);
259 if (SECURITY_MANAGER_SUCCESS == ret) {
260 std::cout << "Application " << req.appId <<
261 " installed successfully." << std::endl;
262 LogDebug("Application " << req.appId <<
263 " installed successfully.");
265 std::cout << "Failed to install " << req.appId << " application: " <<
266 security_manager_strerror(static_cast<lib_retcode>(ret)) <<
267 " (" << ret << ")." << std::endl;
268 LogError("Failed to install " << req.appId << " application: " <<
269 security_manager_strerror(static_cast<lib_retcode>(ret)) <<
270 " (" << ret << ")." << std::endl);
275 static int manageUserOperation(const struct user_req &req, std::string operation)
277 int ret = EXIT_FAILURE;
278 if (operation == "a" || operation == "add") {
279 ret = security_manager_user_add(&req);
282 else if (operation == "r" || operation == "remove") {
283 ret = security_manager_user_delete(&req);
284 operation = "remove";
286 std::cout << "Manage user option requires argument:"
287 "\n\t'a' or 'add' (for adding user)"
288 "\n\t'r' or 'remove' (for removing user)" << std::endl;
289 LogError("Manage user option wrong argument");
293 if (SECURITY_MANAGER_SUCCESS == ret) {
294 std::cout << "User " << operation << " operation successfully finished (uid: "
295 << req.uid << ")" << std::endl;
296 LogDebug("User " << operation << " operation successfully finished (uid: "
299 std::cout << "Failed to "<< operation << " user of uid " << req.uid << ". " <<
300 security_manager_strerror(static_cast<lib_retcode>(ret)) <<
301 " (" << ret << ")." << std::endl;
302 LogError("Failed to "<< operation << " user of uid " << req.uid << "." <<
303 security_manager_strerror(static_cast<lib_retcode>(ret)) <<
304 " (" << ret << ").");
309 int main(int argc, char *argv[])
311 po::variables_map vm;
315 SecurityManager::Singleton<SecurityManager::Log::LogSystem>::Instance().SetTag("SECURITY_MANAGER_INSTALLER");
317 LogDebug("argc: " << argc);
318 for (int i = 0; i < argc; ++i)
319 LogDebug("argv [" << i << "]: " << argv[i]);
321 std::cout << "Missing arguments." << std::endl;
322 usage(std::string(argv[0]));
326 po::store(po::command_line_parser(argc, argv).
327 options(getGenericOptions()).allow_unregistered().run(),
329 if (vm.count("help")) {
330 usage(std::string(argv[0]));
333 LogDebug("Generic arguments has been parsed.");
335 if (vm.count("install")) {
336 struct app_inst_req *req = nullptr;
337 LogDebug("Install command.");
338 if (security_manager_app_inst_req_new(&req) != SECURITY_MANAGER_SUCCESS)
340 parseInstallOptions(argc, argv, *req, vm);
341 return installApp(*req);
342 } else if (vm.count("manage-users")) {
343 std::string operation = vm["manage-users"].as<std::string>();
344 struct user_req *req = nullptr;
345 LogDebug("Manage users command.");
346 if (security_manager_user_req_new(&req) != SECURITY_MANAGER_SUCCESS)
348 parseUserOptions(argc, argv, *req, vm);
349 return manageUserOperation(*req, operation);
351 std::cout << "No command argument was given." << std::endl;
352 usage(std::string(argv[0]));
356 catch (po::error &e) {
357 std::cout << e.what() << std::endl;
358 LogError("Program options error occured: " << e.what());
361 catch (const std::exception &e) {
362 std::cout << "Error occured: " << e.what() << std::endl;
363 LogError("Error occured: " << e.what());