blob: 6163077e1acf86d91acc751848f79e5f896796ae [file] [log] [blame]
Jorim Jaggi2fef6f72016-11-01 19:06:25 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
Andrew Scull507d11c2017-05-03 17:19:01 +010017package com.android.server.locksettings;
Jorim Jaggi2fef6f72016-11-01 19:06:25 -070018
19import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
20import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
Lenka Trochtova66c492a2018-12-06 11:29:21 +010021
Jorim Jaggi2fef6f72016-11-01 19:06:25 -070022import static com.android.internal.widget.LockPatternUtils.stringToPattern;
23
Sudheer Shankadc589ac2016-11-10 15:30:17 -080024import android.app.ActivityManager;
Jorim Jaggi2fef6f72016-11-01 19:06:25 -070025import android.os.ShellCommand;
26
Jorim Jaggi2fef6f72016-11-01 19:06:25 -070027import com.android.internal.widget.LockPatternUtils;
28import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
29
Felipe Leme1fc9c812018-07-11 10:02:23 -070030import java.io.PrintWriter;
31
Jorim Jaggi2fef6f72016-11-01 19:06:25 -070032class LockSettingsShellCommand extends ShellCommand {
33
34 private static final String COMMAND_SET_PATTERN = "set-pattern";
35 private static final String COMMAND_SET_PIN = "set-pin";
36 private static final String COMMAND_SET_PASSWORD = "set-password";
37 private static final String COMMAND_CLEAR = "clear";
Rubin Xu3bf722a2016-12-15 16:07:38 +000038 private static final String COMMAND_SP = "sp";
Jeff Sharkey65440992017-03-31 09:45:46 -060039 private static final String COMMAND_SET_DISABLED = "set-disabled";
Pavel Grafov5f679b22017-06-26 18:39:10 +010040 private static final String COMMAND_VERIFY = "verify";
chaviw5953e662017-08-21 10:46:11 -070041 private static final String COMMAND_GET_DISABLED = "get-disabled";
Felipe Leme1fc9c812018-07-11 10:02:23 -070042 private static final String COMMAND_HELP = "help";
Jorim Jaggi2fef6f72016-11-01 19:06:25 -070043
44 private int mCurrentUserId;
45 private final LockPatternUtils mLockPatternUtils;
Jorim Jaggi2fef6f72016-11-01 19:06:25 -070046 private String mOld = "";
47 private String mNew = "";
48
Felipe Leme1fc9c812018-07-11 10:02:23 -070049 LockSettingsShellCommand(LockPatternUtils lockPatternUtils) {
Jorim Jaggi2fef6f72016-11-01 19:06:25 -070050 mLockPatternUtils = lockPatternUtils;
51 }
52
53 @Override
54 public int onCommand(String cmd) {
Felipe Leme1fc9c812018-07-11 10:02:23 -070055 if (cmd == null) {
56 return handleDefaultCommands(cmd);
57 }
Jorim Jaggi2fef6f72016-11-01 19:06:25 -070058 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -080059 mCurrentUserId = ActivityManager.getService().getCurrentUser().id;
Jorim Jaggi2fef6f72016-11-01 19:06:25 -070060
61 parseArgs();
Lenka Trochtova66c492a2018-12-06 11:29:21 +010062 if (!mLockPatternUtils.hasSecureLockScreen()) {
63 switch (cmd) {
64 case COMMAND_HELP:
65 case COMMAND_GET_DISABLED:
66 case COMMAND_SET_DISABLED:
67 break;
68 default:
69 getErrPrintWriter().println(
70 "The device does not support lock screen - ignoring the command.");
71 return -1;
72 }
73 }
Jorim Jaggi2fef6f72016-11-01 19:06:25 -070074 if (!checkCredential()) {
75 return -1;
76 }
77 switch (cmd) {
78 case COMMAND_SET_PATTERN:
79 runSetPattern();
80 break;
81 case COMMAND_SET_PASSWORD:
82 runSetPassword();
83 break;
84 case COMMAND_SET_PIN:
85 runSetPin();
86 break;
87 case COMMAND_CLEAR:
88 runClear();
89 break;
Rubin Xu3bf722a2016-12-15 16:07:38 +000090 case COMMAND_SP:
Paul Crowley7a0cc0a2017-05-31 22:12:57 +000091 runChangeSp();
Rubin Xu3bf722a2016-12-15 16:07:38 +000092 break;
Jeff Sharkey65440992017-03-31 09:45:46 -060093 case COMMAND_SET_DISABLED:
94 runSetDisabled();
95 break;
Pavel Grafov5f679b22017-06-26 18:39:10 +010096 case COMMAND_VERIFY:
97 runVerify();
98 break;
chaviw5953e662017-08-21 10:46:11 -070099 case COMMAND_GET_DISABLED:
100 runGetDisabled();
101 break;
Felipe Leme1fc9c812018-07-11 10:02:23 -0700102 case COMMAND_HELP:
103 onHelp();
104 break;
Jorim Jaggi2fef6f72016-11-01 19:06:25 -0700105 default:
106 getErrPrintWriter().println("Unknown command: " + cmd);
107 break;
108 }
109 return 0;
110 } catch (Exception e) {
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000111 getErrPrintWriter().println("Error while executing command: " + cmd);
112 e.printStackTrace(getErrPrintWriter());
Jorim Jaggi2fef6f72016-11-01 19:06:25 -0700113 return -1;
114 }
115 }
116
Pavel Grafov5f679b22017-06-26 18:39:10 +0100117 private void runVerify() {
118 // The command is only run if the credential is correct.
119 getOutPrintWriter().println("Lock credential verified successfully");
120 }
121
Jorim Jaggi2fef6f72016-11-01 19:06:25 -0700122 @Override
123 public void onHelp() {
Felipe Leme1fc9c812018-07-11 10:02:23 -0700124 try (final PrintWriter pw = getOutPrintWriter();) {
125 pw.println("lockSettings service commands:");
126 pw.println("");
127 pw.println("NOTE: when lock screen is set, all commands require the --old <CREDENTIAL>"
128 + " argument.");
129 pw.println("");
130 pw.println(" help");
131 pw.println(" Prints this help text.");
132 pw.println("");
133 pw.println(" get-disabled [--old <CREDENTIAL>] [--user USER_ID]");
134 pw.println(" Checks whether lock screen is disabled.");
135 pw.println("");
136 pw.println(" set-disabled [--old <CREDENTIAL>] [--user USER_ID] <true|false>");
137 pw.println(" When true, disables lock screen.");
138 pw.println("");
139 pw.println(" set-pattern [--old <CREDENTIAL>] [--user USER_ID] <PATTERN>");
140 pw.println(" Sets the lock screen as pattern, using the given PATTERN to unlock.");
141 pw.println("");
142 pw.println(" set-pin [--old <CREDENTIAL>] [--user USER_ID] <PIN>");
143 pw.println(" Sets the lock screen as PIN, using the given PIN to unlock.");
144 pw.println("");
145 pw.println(" set-pin [--old <CREDENTIAL>] [--user USER_ID] <PASSWORD>");
146 pw.println(" Sets the lock screen as password, using the given PASSOWRD to unlock.");
147 pw.println("");
148 pw.println(" sp [--old <CREDENTIAL>] [--user USER_ID]");
149 pw.println(" Gets whether synthetic password is enabled.");
150 pw.println("");
151 pw.println(" sp [--old <CREDENTIAL>] [--user USER_ID] <1|0>");
152 pw.println(" Enables / disables synthetic password.");
153 pw.println("");
154 pw.println(" clear [--old <CREDENTIAL>] [--user USER_ID]");
155 pw.println(" Clears the lock credentials.");
156 pw.println("");
157 pw.println(" verify [--old <CREDENTIAL>] [--user USER_ID]");
158 pw.println(" Verifies the lock credentials.");
159 pw.println("");
160 }
Jorim Jaggi2fef6f72016-11-01 19:06:25 -0700161 }
162
163 private void parseArgs() {
164 String opt;
165 while ((opt = getNextOption()) != null) {
166 if ("--old".equals(opt)) {
167 mOld = getNextArgRequired();
Rubin Xu3bf722a2016-12-15 16:07:38 +0000168 } else if ("--user".equals(opt)) {
169 mCurrentUserId = Integer.parseInt(getNextArgRequired());
Jorim Jaggi2fef6f72016-11-01 19:06:25 -0700170 } else {
171 getErrPrintWriter().println("Unknown option: " + opt);
172 throw new IllegalArgumentException();
173 }
174 }
175 mNew = getNextArg();
176 }
177
Paul Crowley7a0cc0a2017-05-31 22:12:57 +0000178 private void runChangeSp() {
179 if (mNew != null ) {
180 if ("1".equals(mNew)) {
181 mLockPatternUtils.enableSyntheticPassword();
182 getOutPrintWriter().println("Synthetic password enabled");
183 } else if ("0".equals(mNew)) {
184 mLockPatternUtils.disableSyntheticPassword();
185 getOutPrintWriter().println("Synthetic password disabled");
186 }
Rubin Xu3bf722a2016-12-15 16:07:38 +0000187 }
188 getOutPrintWriter().println(String.format("SP Enabled = %b",
189 mLockPatternUtils.isSyntheticPasswordEnabled()));
190 }
191
Felipe Leme1fc9c812018-07-11 10:02:23 -0700192 private void runSetPattern() {
Jorim Jaggi2fef6f72016-11-01 19:06:25 -0700193 mLockPatternUtils.saveLockPattern(stringToPattern(mNew), mOld, mCurrentUserId);
194 getOutPrintWriter().println("Pattern set to '" + mNew + "'");
195 }
196
Felipe Leme1fc9c812018-07-11 10:02:23 -0700197 private void runSetPassword() {
Jorim Jaggi2fef6f72016-11-01 19:06:25 -0700198 mLockPatternUtils.saveLockPassword(mNew, mOld, PASSWORD_QUALITY_ALPHABETIC, mCurrentUserId);
199 getOutPrintWriter().println("Password set to '" + mNew + "'");
200 }
201
Felipe Leme1fc9c812018-07-11 10:02:23 -0700202 private void runSetPin() {
Jorim Jaggi2fef6f72016-11-01 19:06:25 -0700203 mLockPatternUtils.saveLockPassword(mNew, mOld, PASSWORD_QUALITY_NUMERIC, mCurrentUserId);
204 getOutPrintWriter().println("Pin set to '" + mNew + "'");
205 }
206
Felipe Leme1fc9c812018-07-11 10:02:23 -0700207 private void runClear() {
Rubin Xua55b1682017-01-31 10:06:56 +0000208 mLockPatternUtils.clearLock(mOld, mCurrentUserId);
Jorim Jaggi2fef6f72016-11-01 19:06:25 -0700209 getOutPrintWriter().println("Lock credential cleared");
210 }
211
Felipe Leme1fc9c812018-07-11 10:02:23 -0700212 private void runSetDisabled() {
Jeff Sharkey65440992017-03-31 09:45:46 -0600213 final boolean disabled = Boolean.parseBoolean(mNew);
214 mLockPatternUtils.setLockScreenDisabled(disabled, mCurrentUserId);
215 getOutPrintWriter().println("Lock screen disabled set to " + disabled);
216 }
217
chaviw5953e662017-08-21 10:46:11 -0700218 private void runGetDisabled() {
219 boolean isLockScreenDisabled = mLockPatternUtils.isLockScreenDisabled(mCurrentUserId);
220 getOutPrintWriter().println(isLockScreenDisabled);
221 }
222
Felipe Leme1fc9c812018-07-11 10:02:23 -0700223 private boolean checkCredential() {
Jorim Jaggi2fef6f72016-11-01 19:06:25 -0700224 final boolean havePassword = mLockPatternUtils.isLockPasswordEnabled(mCurrentUserId);
225 final boolean havePattern = mLockPatternUtils.isLockPatternEnabled(mCurrentUserId);
226 if (havePassword || havePattern) {
Pavel Grafovfc135c72017-07-25 16:38:04 +0100227 if (mLockPatternUtils.isManagedProfileWithUnifiedChallenge(mCurrentUserId)) {
228 getOutPrintWriter().println("Profile uses unified challenge");
229 return false;
230 }
231
Pavel Grafovc07067d2017-07-05 16:30:04 +0100232 try {
233 final boolean result;
234 if (havePassword) {
235 result = mLockPatternUtils.checkPassword(mOld, mCurrentUserId);
236 } else {
237 result = mLockPatternUtils.checkPattern(stringToPattern(mOld), mCurrentUserId);
238 }
239 if (!result) {
Pavel Grafovb3191252017-07-14 12:30:31 +0100240 if (!mLockPatternUtils.isManagedProfileWithUnifiedChallenge(mCurrentUserId)) {
241 mLockPatternUtils.reportFailedPasswordAttempt(mCurrentUserId);
242 }
Pavel Grafovc07067d2017-07-05 16:30:04 +0100243 getOutPrintWriter().println("Old password '" + mOld + "' didn't match");
Irina Dumitrescu472dae52018-07-19 18:07:58 +0100244 } else {
245 // Resets the counter for failed password attempts to 0.
246 mLockPatternUtils.reportSuccessfulPasswordAttempt(mCurrentUserId);
Pavel Grafovc07067d2017-07-05 16:30:04 +0100247 }
248 return result;
249 } catch (RequestThrottledException e) {
250 getOutPrintWriter().println("Request throttled");
Jorim Jaggi2fef6f72016-11-01 19:06:25 -0700251 return false;
252 }
253 } else {
254 return true;
255 }
256 }
257}