• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "atm_command.h"
17 #include <getopt.h>
18 #include <string>
19 #include "accesstoken_kit.h"
20 #include "privacy_kit.h"
21 #include "singleton.h"
22 #include "status_receiver_host.h"
23 #include "to_string.h"
24 
25 using namespace OHOS::AAFwk;
26 
27 namespace OHOS {
28 namespace Security {
29 namespace AccessToken {
30 const int PERMISSION_FLAG = 2;
31 const std::string SHORT_OPTIONS_DUMP = "ht::r::i:p:";
32 const std::string TOOLS_NAME = "atm";
33 const std::string HELP_MSG = "usage: atm <command> <option>\n"
34                              "These are common atm commands list:\n"
35                              "  help    list available commands\n"
36                              "  dump    dumpsys command\n"
37                              "  perm    grant/cancel permission\n";
38 
39 const std::string HELP_MSG_DUMP =
40     "usage: atm dump <option>.\n"
41     "options list:\n"
42     "  -h, --help                                                       list available options\n"
43     "  -t, --token-info [-i <token-id>]                                 list token info in system\n"
44     "  -r, --record-info [-i <token-id>] [-p <permission-name>]         list used records in system\n";
45 
46 const std::string HELP_MSG_PERM =
47     "usage: atm perm <option>.\n"
48     "options list:\n"
49     "  -h, --help                                       list available options\n"
50     "  -g, --grant -i <token-id> -p <permission-name>   grant a permission by a specified token-id\n"
51     "  -c, --cancel -i <token-id> -p <permission-name>  cancel a permission by a specified token-id\n";
52 
53 const struct option LONG_OPTIONS_DUMP[] = {
54     {"help", no_argument, nullptr, 'h'},
55     {"token-info", no_argument, nullptr, 't'},
56     {"record-info", no_argument, nullptr, 'r'},
57     {"token-id", required_argument, nullptr, 'i'},
58     {"permission-name", required_argument, nullptr, 'p'},
59     {nullptr, 0, nullptr, 0}
60 };
61 
62 const std::string SHORT_OPTIONS_PERM = "hg::c::i:p:";
63 const struct option LONG_OPTIONS_PERM[] = {
64     {"help", no_argument, nullptr, 'h'},
65     {"grant", no_argument, nullptr, 'g'},
66     {"cancel", no_argument, nullptr, 'c'},
67     {"token-id", required_argument, nullptr, 'i'},
68     {"permission-name", required_argument, nullptr, 'p'},
69     {nullptr, 0, nullptr, 0}
70 };
71 
AtmCommand(int argc,char * argv[])72 AtmCommand::AtmCommand(int argc, char *argv[]) : ShellCommand(argc, argv, TOOLS_NAME)
73 {}
74 
CreateCommandMap()75 ErrCode AtmCommand::CreateCommandMap()
76 {
77     commandMap_ = {
78         {"help", std::bind(&AtmCommand::RunAsHelpCommand, this)},
79         {"dump", std::bind(&AtmCommand::RunAsDumpCommand, this)},
80         {"perm", std::bind(&AtmCommand::RunAsPermCommand, this)},
81     };
82 
83     return ERR_OK;
84 }
85 
CreateMessageMap()86 ErrCode AtmCommand::CreateMessageMap()
87 {
88     messageMap_ = {
89     };
90 
91     return ERR_OK;
92 }
93 
init()94 ErrCode AtmCommand::init()
95 {
96     ErrCode result = ERR_OK;
97 
98     // there is no need to get proxy currently, the function used in class AccessTokenKit is static
99 
100     return result;
101 }
102 
RunAsHelpCommand()103 ErrCode AtmCommand::RunAsHelpCommand()
104 {
105     resultReceiver_.append(HELP_MSG);
106 
107     return ERR_OK;
108 }
109 
RunAsDumpCommand()110 ErrCode AtmCommand::RunAsDumpCommand()
111 {
112     ErrCode results = ERR_OK;
113     OptType type = DEFAULT;
114     uint32_t tokenId = 0;
115     std::string permissionName = "";
116     int counter = 0;
117     while (true) {
118         counter++;
119         int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS_DUMP.c_str(), LONG_OPTIONS_DUMP, nullptr);
120         if (optind < 0 || optind > argc_) {
121             return ERR_INVALID_VALUE;
122         }
123 
124         if (option == -1) {
125             if (counter == 1) {
126                 results = RunAsCommandError();
127             }
128             break;
129         }
130 
131         if (option == '?') {
132             results = RunAsCommandMissingOptionArgument();
133             break;
134         }
135 
136         results = RunAsCommandExistentOptionArgument(option, type, tokenId, permissionName);
137     }
138 
139     if (results != ERR_OK) {
140         resultReceiver_.append(HELP_MSG_DUMP + "\n");
141     } else {
142         results = RunCommandByOperationType(type, tokenId, permissionName);
143     }
144     return results;
145 }
146 
RunAsPermCommand()147 ErrCode AtmCommand::RunAsPermCommand()
148 {
149     ErrCode result = ERR_OK;
150     OptType type = DEFAULT;
151     uint32_t tokenId = 0;
152     std::string permissionName = "";
153     int counter = 0;
154     while (true) {
155         counter++;
156         int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS_PERM.c_str(), LONG_OPTIONS_PERM, nullptr);
157         if (optind < 0 || optind > argc_) {
158             return ERR_INVALID_VALUE;
159         }
160 
161         if (option == -1) {
162             if (counter == 1) {
163                 result = RunAsCommandError();
164             }
165             break;
166         }
167 
168         if (option == '?') {
169             result = RunAsCommandMissingOptionArgument();
170             break;
171         }
172 
173         result = RunAsCommandExistentOptionArgument(option, type, tokenId, permissionName);
174     }
175 
176     if (result != ERR_OK) {
177         resultReceiver_.append(HELP_MSG_PERM + "\n");
178     } else {
179         result = RunCommandByOperationType(type, tokenId, permissionName);
180     }
181     return result;
182 }
183 
RunCommandByOperationType(const OptType & type,uint32_t & tokenId,std::string & permissionName)184 ErrCode AtmCommand::RunCommandByOperationType(const OptType& type,
185     uint32_t& tokenId, std::string& permissionName)
186 {
187     std::string dumpInfo = "";
188     ErrCode ret = ERR_OK;
189     switch (type) {
190         case DUMP_TOKEN:
191             AccessTokenKit::DumpTokenInfo(tokenId, dumpInfo);
192             break;
193         case DUMP_RECORD:
194             dumpInfo = DumpRecordInfo(tokenId, permissionName);
195             break;
196         case PERM_GRANT:
197         case PERM_REVOKE:
198             ret = ModifyPermission(type, tokenId, permissionName);
199             if (ret == ERR_OK) {
200                 dumpInfo = "Success";
201             } else {
202                 dumpInfo = "Failure";
203             }
204             break;
205         default:
206             resultReceiver_.append("error: miss option \n");
207             return ERR_INVALID_VALUE;
208     }
209     resultReceiver_.append(dumpInfo + "\n");
210     return ret;
211 }
212 
ModifyPermission(const OptType & type,uint32_t & tokenId,std::string & permissionName)213 ErrCode AtmCommand::ModifyPermission(const OptType& type, uint32_t& tokenId, std::string& permissionName)
214 {
215     if (tokenId == 0 || permissionName.empty()) {
216         return ERR_INVALID_VALUE;
217     }
218 
219     int result = 0;
220     if (type == PERM_GRANT) {
221         result = AccessTokenKit::GrantPermission(tokenId, permissionName, PERMISSION_FLAG);
222     } else if (type == PERM_REVOKE) {
223         result = AccessTokenKit::RevokePermission(tokenId, permissionName, PERMISSION_FLAG);
224     } else {
225         return ERR_INVALID_VALUE;
226     }
227     if (result != 0) {
228         return ERR_INVALID_VALUE;
229     }
230     return ERR_OK;
231 }
232 
RunAsCommandError(void)233 ErrCode AtmCommand::RunAsCommandError(void)
234 {
235     ErrCode result = ERR_OK;
236 
237     if (optind < 0 || optind >= argc_) {
238         return ERR_INVALID_VALUE;
239     }
240 
241     // When scanning the first argument
242     if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
243         // 'atm dump' with no option: atm dump
244         // 'atm dump' with a wrong argument: atm dump xxx
245 
246         resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
247         result = ERR_INVALID_VALUE;
248     }
249     return result;
250 }
251 
RunAsCommandMissingOptionArgument(void)252 ErrCode AtmCommand::RunAsCommandMissingOptionArgument(void)
253 {
254     ErrCode result = ERR_OK;
255     switch (optopt) {
256         case 'h':
257             // 'atm dump -h'
258             result = ERR_INVALID_VALUE;
259             break;
260         case 'i':
261         case 'p':
262         case 'g':
263         case 'c':
264             resultReceiver_.append("error: option ");
265             resultReceiver_.append("requires a value.\n");
266             result = ERR_INVALID_VALUE;
267             break;
268         default: {
269             std::string unknownOption = "";
270             std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
271 
272             resultReceiver_.append(unknownOptionMsg);
273             result = ERR_INVALID_VALUE;
274             break;
275         }
276     }
277     return result;
278 }
279 
RunAsCommandExistentOptionArgument(const int & option,OptType & type,uint32_t & tokenId,std::string & permissionName)280 ErrCode AtmCommand::RunAsCommandExistentOptionArgument(
281     const int& option, OptType& type, uint32_t& tokenId, std::string& permissionName)
282 {
283     ErrCode result = ERR_OK;
284     switch (option) {
285         case 'h':
286             // 'atm dump -h'
287             result = ERR_INVALID_VALUE;
288             break;
289         case 't':
290             type = DUMP_TOKEN;
291             break;
292         case 'r':
293             type = DUMP_RECORD;
294             break;
295         case 'g':
296             type = PERM_GRANT;
297             break;
298         case 'c':
299             type = PERM_REVOKE;
300             break;
301         case 'i':
302             if (optarg != nullptr) {
303                 tokenId = static_cast<uint32_t>(std::atoi(optarg));
304             }
305             break;
306         case 'p':
307             if (optarg != nullptr) {
308                 permissionName = optarg;
309             }
310             break;
311         default:
312             break;
313     }
314     return result;
315 }
316 
DumpRecordInfo(uint32_t tokenId,const std::string & permissionName)317 std::string AtmCommand::DumpRecordInfo(uint32_t tokenId, const std::string& permissionName)
318 {
319     PermissionUsedRequest request;
320     request.tokenId = tokenId;
321     request.flag = FLAG_PERMISSION_USAGE_DETAIL;
322     if (!permissionName.empty()) {
323         request.permissionList.emplace_back(permissionName);
324     }
325 
326     PermissionUsedResult result;
327     if (PrivacyKit::GetPermissionUsedRecords(request, result) != 0) {
328         return "";
329     }
330 
331     std::string dumpInfo;
332     ToString::PermissionUsedResultToString(result, dumpInfo);
333     return dumpInfo;
334 }
335 } // namespace AccessToken
336 } // namespace Security
337 } // namespace OHOS
338