1 /*
2 * Copyright (c) 2022-2024 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
18 #include <getopt.h>
19 #include <string>
20
21 #include "access_token_error.h"
22 #include "accesstoken_kit.h"
23 #include "privacy_kit.h"
24 #include "to_string.h"
25
26 namespace OHOS {
27 namespace Security {
28 namespace AccessToken {
29 namespace {
30 static constexpr int32_t MAX_COUNTER = 1000;
31 static constexpr int32_t MIN_ARGUMENT_NUMBER = 2;
32 static constexpr int32_t MAX_ARGUMENT_NUMBER = 4096;
33 static const std::string HELP_MSG_NO_OPTION = "error: you must specify an option at least.\n";
34 static const std::string SHORT_OPTIONS_DUMP = "d::h::t::r::v::i:p:b:n:";
35 static const std::string TOOLS_NAME = "atm";
36 static const std::string HELP_MSG =
37 "usage: atm <command> <option>\n"
38 "These are common atm commands list:\n"
39 " help list available commands\n"
40 #ifndef ATM_BUILD_VARIANT_USER_ENABLE
41 " perm grant/cancel permission\n"
42 " toggle set/get toggle request/record status\n"
43 #endif
44 " dump dump system command\n";
45
46 static const std::string HELP_MSG_DUMP =
47 "usage: atm dump <option>.\n"
48 "options list:\n"
49 " -h, --help list available options\n"
50 " -d, --definition [-p <permission-name>] list all permission definitions in system\n"
51 " -t, --all list all name of token info in system\n"
52 " -t, --token-info -i <token-id> list single token info by specific tokenId\n"
53 " -t, --token-info -b <bundle-name> list all token info by specific bundleName\n"
54 " -t, --token-info -n <process-name> list single token info by specific native processName\n"
55 #ifndef ATM_BUILD_VARIANT_USER_ENABLE
56 " -r, --record-info [-i <token-id>] [-p <permission-name>] list used records in system\n"
57 " -v, --visit-type [-i <token-id>] [-p <permission-name>] list all token used type in system\n";
58 #else
59 "";
60 #endif
61
62 static const std::string HELP_MSG_PERM =
63 #ifndef ATM_BUILD_VARIANT_USER_ENABLE
64 "usage: atm perm <option>.\n"
65 "options list:\n"
66 " -h, --help list available options\n"
67 " -g, --grant -i <token-id> -p <permission-name> grant a permission by a specified token-id\n"
68 " -c, --cancel -i <token-id> -p <permission-name> cancel a permission by a specified token-id\n";
69 #else
70 "";
71 #endif
72
73 static const std::string HELP_MSG_TOGGLE =
74 #ifndef ATM_BUILD_VARIANT_USER_ENABLE
75 "usage: atm toggle request <option>.\n"
76 "options list:\n"
77 " -h, --help list available options\n"
78 " -r -s, --set -i <user-id> -p <permission-name> -k <status> set request status by specified user-id and perm\n"
79 " -r -o, --get -i <user-id> -p <permission-name> get request status by specified user-id and perm\n"
80 " -u -s, --set -i <user-id> -k <status> set record status by a specified user-id\n"
81 " -u -o, --get -i <user-id> get record status by a specified user-id\n"
82 " <status> 0 is closed, 1 is open\n";
83 #else
84 "";
85 #endif
86
87 static const struct option LONG_OPTIONS_DUMP[] = {
88 {"definition", no_argument, nullptr, 'd'},
89 {"help", no_argument, nullptr, 'h'},
90 {"token-info", no_argument, nullptr, 't'},
91 {"record-info", no_argument, nullptr, 'r'},
92 {"token-id", required_argument, nullptr, 'i'},
93 {"permission-name", required_argument, nullptr, 'p'},
94 {"bundle-name", required_argument, nullptr, 'b'},
95 {"process-name", required_argument, nullptr, 'n'},
96 {nullptr, 0, nullptr, 0}
97 };
98 static const std::string SHORT_OPTIONS_PERM = "hg::c::i:p:";
99 static const struct option LONG_OPTIONS_PERM[] = {
100 {"help", no_argument, nullptr, 'h'},
101 {"grant", no_argument, nullptr, 'g'},
102 {"cancel", no_argument, nullptr, 'c'},
103 {"token-id", required_argument, nullptr, 'i'},
104 {"permission-name", required_argument, nullptr, 'p'},
105 {nullptr, 0, nullptr, 0}
106 };
107
108 // required option
109 static const std::vector<char> REQUIRED_OPTIONS_DUMP = {'b', 'i', 'n', 'p'};
110 static const std::vector<char> REQUIRED_OPTIONS_PERM = {'g', 'c', 'i', 'p'};
111 static const std::vector<char> REQUIRED_OPTIONS_TOGGLE = {'i', 'k', 'p'};
112
113 static const std::string SHORT_OPTIONS_TOGGLE = "hr::u::s::o::i:p:k:";
114 static const struct option LONG_OPTIONS_TOGGLE[] = {
115 {"help", no_argument, nullptr, 'h'},
116 {"request", no_argument, nullptr, 'r'},
117 {"record", no_argument, nullptr, 'u'},
118 {"set", no_argument, nullptr, 's'},
119 {"get", no_argument, nullptr, 'o'},
120 {"user-id", required_argument, nullptr, 'i'},
121 {"permission-name", required_argument, nullptr, 'p'},
122 {"status", required_argument, nullptr, 'k'},
123 {nullptr, 0, nullptr, 0}
124 };
125
126 std::map<char, OptType> DUMP_COMMAND_TYPE = {
127 // dump
128 {'d', DUMP_PERM},
129 {'t', DUMP_TOKEN},
130 {'r', DUMP_RECORD},
131 {'v', DUMP_TYPE},
132 };
133
134 std::map<char, ToggleModeType> TOGGLE_MODE_TYPE = {
135 {'r', TOGGLE_REQUEST},
136 {'u', TOGGLE_RECORD},
137 };
138 std::map<char, ToggleOperateType> TOGGLE_OPERATE_TYPE = {
139 {'s', TOGGLE_SET},
140 {'o', TOGGLE_GET},
141 };
142 }
143
AtmCommand(int32_t argc,char * argv[])144 AtmCommand::AtmCommand(int32_t argc, char* argv[]) : argc_(argc), argv_(argv), name_(TOOLS_NAME)
145 {
146 opterr = 0;
147
148 commandMap_ = {
149 {"help", [this](){return RunAsHelpCommand();}},
150 {"dump", [this]() {return RunAsCommonCommandForDump();}},
151 #ifndef ATM_BUILD_VARIANT_USER_ENABLE
152 {"perm", [this]() {return RunAsCommonCommandForPerm();}},
153 {"toggle", [this]() {return RunAsCommonCommandForToggle();}},
154 #endif
155 };
156
157 if ((argc < MIN_ARGUMENT_NUMBER) || (argc > MAX_ARGUMENT_NUMBER)) {
158 cmd_ = "help";
159
160 return;
161 }
162
163 cmd_ = argv[1];
164
165 for (int32_t i = 2; i < argc; i++) {
166 argList_.push_back(argv[i]);
167 }
168 }
169
GetCommandErrorMsg() const170 std::string AtmCommand::GetCommandErrorMsg() const
171 {
172 std::string commandErrorMsg =
173 name_ + ": '" + cmd_ + "' is not a valid " + name_ + " command. See '" + name_ + " help'.\n";
174
175 return commandErrorMsg;
176 }
177
ExecCommand()178 std::string AtmCommand::ExecCommand()
179 {
180 auto respond = commandMap_[cmd_];
181 if (respond == nullptr) {
182 resultReceiver_.append(GetCommandErrorMsg());
183 } else {
184 respond();
185 }
186
187 return resultReceiver_;
188 }
189
RunAsHelpCommand()190 int32_t AtmCommand::RunAsHelpCommand()
191 {
192 resultReceiver_.append(HELP_MSG);
193
194 return RET_SUCCESS;
195 }
196
RunAsCommandError(void)197 int32_t AtmCommand::RunAsCommandError(void)
198 {
199 int32_t result = RET_SUCCESS;
200
201 if ((optind < 0) || (optind >= argc_)) {
202 return ERR_INVALID_VALUE;
203 }
204
205 // When scanning the first argument
206 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
207 // 'atm dump' with no option: atm dump
208 // 'atm dump' with a wrong argument: atm dump xxx
209
210 resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
211 result = ERR_INVALID_VALUE;
212 }
213 return result;
214 }
215
GetUnknownOptionMsg() const216 std::string AtmCommand::GetUnknownOptionMsg() const
217 {
218 std::string result;
219
220 if ((optind < 0) || (optind > argc_)) {
221 return result;
222 }
223
224 result.append("error: unknown option.\n");
225
226 return result;
227 }
228
RunAsCommandMissingOptionArgument(const std::vector<char> & requiredOptions)229 int32_t AtmCommand::RunAsCommandMissingOptionArgument(const std::vector<char>& requiredOptions)
230 {
231 if (optopt == 'h') {
232 return ERR_INVALID_VALUE;
233 }
234 auto iter = std::find(requiredOptions.begin(), requiredOptions.end(), optopt);
235 if (iter == requiredOptions.end()) {
236 resultReceiver_.append(GetUnknownOptionMsg());
237 return ERR_INVALID_VALUE;
238 }
239 resultReceiver_.append("error: option requires a value.\n\n");
240 return ERR_INVALID_VALUE;
241 }
242
RunAsCommandExistentOptionForDump(const int32_t & option,AtmToolsParamInfo & info,OptType & type,std::string & permissionName)243 void AtmCommand::RunAsCommandExistentOptionForDump(
244 const int32_t& option, AtmToolsParamInfo& info, OptType& type, std::string& permissionName)
245 {
246 switch (option) {
247 case 'd':
248 case 't':
249 case 'r':
250 case 'v':
251 type = DUMP_COMMAND_TYPE[option];
252 break;
253 case 'i':
254 if (optarg != nullptr) {
255 info.tokenId = static_cast<AccessTokenID>(std::atoi(optarg));
256 }
257 break;
258 case 'p':
259 if (optarg != nullptr) {
260 permissionName = optarg;
261 }
262 break;
263 case 'b':
264 if (optarg != nullptr) {
265 info.bundleName = optarg;
266 }
267 break;
268 case 'n':
269 if (optarg != nullptr) {
270 info.processName = optarg;
271 }
272 break;
273 default:
274 break;
275 }
276 }
277
RunAsCommandExistentOptionForPerm(const int32_t & option,bool & isGranted,AccessTokenID & tokenID,std::string & permission)278 void AtmCommand::RunAsCommandExistentOptionForPerm(
279 const int32_t& option, bool& isGranted, AccessTokenID& tokenID, std::string& permission)
280 {
281 switch (option) {
282 case 'g':
283 isGranted = true;
284 break;
285 case 'c':
286 isGranted = false;
287 break;
288 case 'i':
289 tokenID = (optarg != nullptr) ? static_cast<AccessTokenID>(std::atoi(optarg)) : INVALID_TOKENID;
290 break;
291 case 'p':
292 permission = (optarg != nullptr) ? optarg : "";
293 break;
294 default:
295 break;
296 }
297 }
298
RunAsCommandExistentOptionForToggle(const int32_t & option,AtmToggleParamInfo & info)299 void AtmCommand::RunAsCommandExistentOptionForToggle(const int32_t& option, AtmToggleParamInfo& info)
300 {
301 switch (option) {
302 case 'r':
303 case 'u':
304 info.toggleMode = TOGGLE_MODE_TYPE[option];
305 break;
306 case 's':
307 case 'o':
308 info.type = TOGGLE_OPERATE_TYPE[option];
309 break;
310 case 'p':
311 info.permissionName = (optarg != nullptr) ? optarg : "";;
312 break;
313 case 'i':
314 if (optarg != nullptr) {
315 if (IsNumericString(optarg)) {
316 info.userID = static_cast<int32_t>(std::atoi(optarg));
317 } else {
318 info.userID = -1;
319 }
320 }
321 break;
322 case 'k':
323 if (optarg != nullptr && (strcmp(optarg, "0") == 0 || strcmp(optarg, "1") == 0)) {
324 info.status = static_cast<uint32_t>(std::atoi(optarg));
325 }
326 break;
327 default:
328 break;
329 }
330 }
331
IsNumericString(const char * string)332 bool AtmCommand::IsNumericString(const char* string)
333 {
334 if (string == nullptr || string[0] == '\0') {
335 return false;
336 }
337
338 for (int32_t i = 0; string[i] != '\0'; i++) {
339 if (!isdigit(string[i])) {
340 return false;
341 }
342 }
343
344 return true;
345 }
346
DumpRecordInfo(uint32_t tokenId,const std::string & permissionName)347 std::string AtmCommand::DumpRecordInfo(uint32_t tokenId, const std::string& permissionName)
348 {
349 PermissionUsedRequest request;
350 request.tokenId = tokenId;
351 request.flag = FLAG_PERMISSION_USAGE_DETAIL;
352 if (!permissionName.empty()) {
353 request.permissionList.emplace_back(permissionName);
354 }
355
356 PermissionUsedResult result;
357 if (PrivacyKit::GetPermissionUsedRecords(request, result) != 0) {
358 return "";
359 }
360
361 return ToString::PermissionUsedResultToString(result);
362 }
363
DumpUsedTypeInfo(uint32_t tokenId,const std::string & permissionName)364 std::string AtmCommand::DumpUsedTypeInfo(uint32_t tokenId, const std::string& permissionName)
365 {
366 std::vector<PermissionUsedTypeInfo> results;
367 if (PrivacyKit::GetPermissionUsedTypeInfos(tokenId, permissionName, results) != 0) {
368 return "";
369 }
370
371 return ToString::PermissionUsedTypeInfoToString(results);
372 }
373
ModifyPermission(bool isGranted,AccessTokenID tokenId,const std::string & permissionName)374 int32_t AtmCommand::ModifyPermission(bool isGranted, AccessTokenID tokenId, const std::string& permissionName)
375 {
376 int32_t result = 0;
377 if (isGranted) {
378 result = AccessTokenKit::GrantPermission(tokenId, permissionName, PERMISSION_USER_FIXED);
379 } else {
380 result = AccessTokenKit::RevokePermission(tokenId, permissionName, PERMISSION_USER_FIXED);
381 }
382 return result;
383 }
384
SetToggleStatus(int32_t userID,const std::string & permissionName,const uint32_t & status)385 int32_t AtmCommand::SetToggleStatus(int32_t userID, const std::string& permissionName, const uint32_t& status)
386 {
387 if ((userID < 0) || (permissionName.empty()) ||
388 ((status != PermissionRequestToggleStatus::OPEN) &&
389 (status != PermissionRequestToggleStatus::CLOSED))) {
390 return ERR_INVALID_VALUE;
391 }
392
393 return AccessTokenKit::SetPermissionRequestToggleStatus(permissionName, status, userID);
394 }
395
GetToggleStatus(int32_t userID,const std::string & permissionName,std::string & statusInfo)396 int32_t AtmCommand::GetToggleStatus(int32_t userID, const std::string& permissionName, std::string& statusInfo)
397 {
398 if ((userID < 0) || (permissionName.empty())) {
399 return ERR_INVALID_VALUE;
400 }
401
402 uint32_t status;
403 int32_t result = AccessTokenKit::GetPermissionRequestToggleStatus(permissionName, status, userID);
404 if (result != RET_SUCCESS) {
405 return result;
406 }
407
408 if (status == PermissionRequestToggleStatus::OPEN) {
409 statusInfo = "Toggle status is open";
410 } else {
411 statusInfo = "Toggle status is closed";
412 }
413
414 return result;
415 }
416
RunCommandByOperationType(const AtmToolsParamInfo & info,OptType type,std::string & permissionName)417 int32_t AtmCommand::RunCommandByOperationType(const AtmToolsParamInfo& info, OptType type, std::string& permissionName)
418 {
419 std::string dumpInfo;
420 int32_t ret = RET_SUCCESS;
421 switch (type) {
422 case DUMP_PERM:
423 dumpInfo = ToString::DumpPermDefinition(permissionName);
424 break;
425 case DUMP_TOKEN:
426 AccessTokenKit::DumpTokenInfo(info, dumpInfo);
427 break;
428 case DUMP_RECORD:
429 #ifndef ATM_BUILD_VARIANT_USER_ENABLE
430 dumpInfo = DumpRecordInfo(info.tokenId, permissionName);
431 break;
432 case DUMP_TYPE:
433 dumpInfo = DumpUsedTypeInfo(info.tokenId, permissionName);
434 break;
435 #endif
436 default:
437 resultReceiver_.append("error: miss option \n");
438 return ERR_INVALID_VALUE;
439 }
440 resultReceiver_.append(dumpInfo + "\n");
441 return ret;
442 }
443
SetRecordToggleStatus(int32_t userID,const uint32_t & recordStatus,std::string & statusInfo)444 int32_t AtmCommand::SetRecordToggleStatus(int32_t userID, const uint32_t& recordStatus, std::string& statusInfo)
445 {
446 if ((userID < 0)) {
447 statusInfo = "Invalid userID\n";
448 return ERR_INVALID_VALUE;
449 }
450
451 if ((recordStatus != 0) && (recordStatus != 1)) {
452 statusInfo = "Invalid status\n";
453 return ERR_INVALID_VALUE;
454 }
455
456 bool status = (recordStatus == 1);
457
458 return PrivacyKit::SetPermissionUsedRecordToggleStatus(userID, status);
459 }
460
GetRecordToggleStatus(int32_t userID,std::string & statusInfo)461 int32_t AtmCommand::GetRecordToggleStatus(int32_t userID, std::string& statusInfo)
462 {
463 if ((userID < 0)) {
464 statusInfo = "Invalid userID\n";
465 return ERR_INVALID_VALUE;
466 }
467
468 bool status = true;
469 int32_t result = PrivacyKit::GetPermissionUsedRecordToggleStatus(userID, status);
470 if (result != RET_SUCCESS) {
471 return result;
472 }
473
474 statusInfo = status ? "Record toggle status is open \n" : "Record toggle status is closed \n";
475
476 return result;
477 }
478
HandleToggleRequest(const AtmToggleParamInfo & info,std::string & dumpInfo)479 int32_t AtmCommand::HandleToggleRequest(const AtmToggleParamInfo& info, std::string& dumpInfo)
480 {
481 int32_t ret = RET_SUCCESS;
482
483 #ifndef ATM_BUILD_VARIANT_USER_ENABLE
484 switch (info.type) {
485 case TOGGLE_SET:
486 ret = SetToggleStatus(info.userID, info.permissionName, info.status);
487 dumpInfo = (ret == RET_SUCCESS) ? "Success" : "Failure";
488 break;
489 case TOGGLE_GET:
490 ret = GetToggleStatus(info.userID, info.permissionName, dumpInfo);
491 if (ret != RET_SUCCESS) {
492 dumpInfo = "Failure";
493 }
494 break;
495 default:
496 resultReceiver_.append("error: miss option \n");
497 return ERR_INVALID_VALUE;
498 }
499 #endif
500
501 return ret;
502 }
503
HandleToggleRecord(const AtmToggleParamInfo & info,std::string & dumpInfo)504 int32_t AtmCommand::HandleToggleRecord(const AtmToggleParamInfo& info, std::string& dumpInfo)
505 {
506 int32_t ret = RET_SUCCESS;
507
508 #ifndef ATM_BUILD_VARIANT_USER_ENABLE
509 switch (info.type) {
510 case TOGGLE_SET:
511 ret = SetRecordToggleStatus(info.userID, info.status, dumpInfo);
512 dumpInfo += (ret == RET_SUCCESS) ? "Success" : "Failure";
513 break;
514 case TOGGLE_GET:
515 ret = GetRecordToggleStatus(info.userID, dumpInfo);
516 dumpInfo += (ret == RET_SUCCESS) ? "Success" : "Failure";
517 break;
518 default:
519 resultReceiver_.append("error: miss option \n");
520 return ERR_INVALID_VALUE;
521 }
522 #endif
523 return ret;
524 }
525
RunToggleCommandByOperationType(const AtmToggleParamInfo & info)526 int32_t AtmCommand::RunToggleCommandByOperationType(const AtmToggleParamInfo& info)
527 {
528 std::string dumpInfo;
529 int32_t ret = RET_SUCCESS;
530
531 switch (info.toggleMode) {
532 case TOGGLE_REQUEST:
533 ret = HandleToggleRequest(info, dumpInfo);
534 break;
535 case TOGGLE_RECORD:
536 ret = HandleToggleRecord(info, dumpInfo);
537 break;
538 default:
539 resultReceiver_.append("error: unspecified toggle mode \n");
540 return ERR_INVALID_VALUE;
541 }
542
543 resultReceiver_.append(dumpInfo + "\n");
544 return ret;
545 }
546
RunAsCommonCommandForDump()547 int32_t AtmCommand::RunAsCommonCommandForDump()
548 {
549 int32_t result = RET_SUCCESS;
550 AtmToolsParamInfo info;
551 int32_t counter = 0;
552 OptType type = DEFAULT_OPER;
553 std::string permissionName;
554 while (true) {
555 ++counter;
556 int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS_DUMP.c_str(), LONG_OPTIONS_DUMP, nullptr);
557 if ((optind < 0) || (optind > argc_)) {
558 return ERR_INVALID_VALUE;
559 }
560
561 if (option == -1) {
562 if (counter == 1) {
563 result = RunAsCommandError();
564 }
565 break;
566 }
567
568 if (option == '?') {
569 result = RunAsCommandMissingOptionArgument(REQUIRED_OPTIONS_DUMP);
570 break;
571 }
572
573 if (option == 'h') {
574 // 'atm dump -h'
575 result = ERR_INVALID_VALUE;
576 continue;
577 }
578 RunAsCommandExistentOptionForDump(option, info, type, permissionName);
579 }
580
581 if (result != RET_SUCCESS) {
582 resultReceiver_.append(HELP_MSG_DUMP + "\n");
583 return result;
584 }
585 return RunCommandByOperationType(info, type, permissionName);
586 }
587
RunAsCommonCommandForPerm()588 int32_t AtmCommand::RunAsCommonCommandForPerm()
589 {
590 int32_t result = RET_SUCCESS;
591 int32_t counter = 0;
592 AccessTokenID tokenID;
593 std::string permission;
594 bool isGranted = false;
595 while (true) {
596 ++counter;
597 int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS_PERM.c_str(), LONG_OPTIONS_PERM, nullptr);
598 if ((optind < 0) || (optind > argc_)) {
599 return ERR_INVALID_VALUE;
600 }
601 if (option == -1) {
602 if (counter == 1) {
603 result = RunAsCommandError();
604 }
605 break;
606 }
607
608 if (option == '?') {
609 result = RunAsCommandMissingOptionArgument(REQUIRED_OPTIONS_PERM);
610 break;
611 }
612 if (option == 'h') {
613 result = ERR_INVALID_VALUE;
614 continue;
615 }
616 RunAsCommandExistentOptionForPerm(option, isGranted, tokenID, permission);
617 }
618 if (result != RET_SUCCESS) {
619 resultReceiver_.append(HELP_MSG_DUMP + "\n");
620 return result;
621 }
622 result = ModifyPermission(isGranted, tokenID, permission);
623 if (result == RET_SUCCESS) {
624 resultReceiver_.append("Success\n");
625 } else {
626 resultReceiver_.append("Failure\n");
627 }
628 return result;
629 }
630
RunAsCommonCommandForToggle()631 int32_t AtmCommand::RunAsCommonCommandForToggle()
632 {
633 int32_t result = RET_SUCCESS;
634 AtmToggleParamInfo info;
635 int32_t counter = 0;
636 while (counter < MAX_COUNTER) {
637 ++counter;
638 int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS_TOGGLE.c_str(), LONG_OPTIONS_TOGGLE, nullptr);
639 if ((optind < 0) || (optind > argc_)) {
640 return ERR_INVALID_VALUE;
641 }
642
643 if (option == -1) {
644 if (counter == 1) {
645 result = RunAsCommandError();
646 }
647 break;
648 }
649
650 if (option == '?') {
651 result = RunAsCommandMissingOptionArgument(REQUIRED_OPTIONS_TOGGLE);
652 break;
653 }
654
655 if (option == 'h') {
656 result = ERR_INVALID_VALUE;
657 continue;
658 }
659 RunAsCommandExistentOptionForToggle(option, info);
660 }
661
662 if (result != RET_SUCCESS) {
663 resultReceiver_.append(HELP_MSG_TOGGLE + "\n");
664 return result;
665 }
666 return RunToggleCommandByOperationType(info);
667 }
668 } // namespace AccessToken
669 } // namespace Security
670 } // namespace OHOS
671