• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.server.locksettings;
18 
19 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
20 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
21 
22 import static com.android.internal.widget.LockPatternUtils.stringToPattern;
23 
24 import android.app.ActivityManager;
25 import android.os.ShellCommand;
26 
27 import com.android.internal.widget.LockPatternUtils;
28 import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
29 
30 import java.io.PrintWriter;
31 
32 class 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";
38     private static final String COMMAND_SP = "sp";
39     private static final String COMMAND_SET_DISABLED = "set-disabled";
40     private static final String COMMAND_VERIFY = "verify";
41     private static final String COMMAND_GET_DISABLED = "get-disabled";
42     private static final String COMMAND_HELP = "help";
43 
44     private int mCurrentUserId;
45     private final LockPatternUtils mLockPatternUtils;
46     private String mOld = "";
47     private String mNew = "";
48 
LockSettingsShellCommand(LockPatternUtils lockPatternUtils)49     LockSettingsShellCommand(LockPatternUtils lockPatternUtils) {
50         mLockPatternUtils = lockPatternUtils;
51     }
52 
53     @Override
onCommand(String cmd)54     public int onCommand(String cmd) {
55         if (cmd == null) {
56             return handleDefaultCommands(cmd);
57         }
58         try {
59             mCurrentUserId = ActivityManager.getService().getCurrentUser().id;
60 
61             parseArgs();
62             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             }
74             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;
90                 case COMMAND_SP:
91                     runChangeSp();
92                     break;
93                 case COMMAND_SET_DISABLED:
94                     runSetDisabled();
95                     break;
96                 case COMMAND_VERIFY:
97                     runVerify();
98                     break;
99                 case COMMAND_GET_DISABLED:
100                     runGetDisabled();
101                     break;
102                 case COMMAND_HELP:
103                     onHelp();
104                     break;
105                 default:
106                     getErrPrintWriter().println("Unknown command: " + cmd);
107                     break;
108             }
109             return 0;
110         } catch (Exception e) {
111             getErrPrintWriter().println("Error while executing command: " + cmd);
112             e.printStackTrace(getErrPrintWriter());
113             return -1;
114         }
115     }
116 
runVerify()117     private void runVerify() {
118         // The command is only run if the credential is correct.
119         getOutPrintWriter().println("Lock credential verified successfully");
120     }
121 
122     @Override
onHelp()123     public void onHelp() {
124         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         }
161     }
162 
parseArgs()163     private void parseArgs() {
164         String opt;
165         while ((opt = getNextOption()) != null) {
166             if ("--old".equals(opt)) {
167                 mOld = getNextArgRequired();
168             } else if ("--user".equals(opt)) {
169                 mCurrentUserId = Integer.parseInt(getNextArgRequired());
170             } else {
171                 getErrPrintWriter().println("Unknown option: " + opt);
172                 throw new IllegalArgumentException();
173             }
174         }
175         mNew = getNextArg();
176     }
177 
runChangeSp()178     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             }
187         }
188         getOutPrintWriter().println(String.format("SP Enabled = %b",
189                 mLockPatternUtils.isSyntheticPasswordEnabled()));
190     }
191 
runSetPattern()192     private void runSetPattern() {
193         byte[] oldBytes = mOld != null ? mOld.getBytes() : null;
194         mLockPatternUtils.saveLockPattern(stringToPattern(mNew), oldBytes, mCurrentUserId);
195         getOutPrintWriter().println("Pattern set to '" + mNew + "'");
196     }
197 
runSetPassword()198     private void runSetPassword() {
199         byte[] newBytes = mNew != null ? mNew.getBytes() : null;
200         byte[] oldBytes = mOld != null ? mOld.getBytes() : null;
201         mLockPatternUtils.saveLockPassword(newBytes, oldBytes, PASSWORD_QUALITY_ALPHABETIC,
202                 mCurrentUserId);
203         getOutPrintWriter().println("Password set to '" + mNew + "'");
204     }
205 
runSetPin()206     private void runSetPin() {
207         byte[] newBytes = mNew != null ? mNew.getBytes() : null;
208         byte[] oldBytes = mOld != null ? mOld.getBytes() : null;
209         mLockPatternUtils.saveLockPassword(newBytes, oldBytes, PASSWORD_QUALITY_NUMERIC,
210                 mCurrentUserId);
211         getOutPrintWriter().println("Pin set to '" + mNew + "'");
212     }
213 
runClear()214     private void runClear() {
215         byte[] oldBytes = mOld != null ? mOld.getBytes() : null;
216         mLockPatternUtils.clearLock(oldBytes, mCurrentUserId);
217         getOutPrintWriter().println("Lock credential cleared");
218     }
219 
runSetDisabled()220     private void runSetDisabled() {
221         final boolean disabled = Boolean.parseBoolean(mNew);
222         mLockPatternUtils.setLockScreenDisabled(disabled, mCurrentUserId);
223         getOutPrintWriter().println("Lock screen disabled set to " + disabled);
224     }
225 
runGetDisabled()226     private void runGetDisabled() {
227         boolean isLockScreenDisabled = mLockPatternUtils.isLockScreenDisabled(mCurrentUserId);
228         getOutPrintWriter().println(isLockScreenDisabled);
229     }
230 
checkCredential()231     private boolean checkCredential() {
232         final boolean havePassword = mLockPatternUtils.isLockPasswordEnabled(mCurrentUserId);
233         final boolean havePattern = mLockPatternUtils.isLockPatternEnabled(mCurrentUserId);
234         if (havePassword || havePattern) {
235             if (mLockPatternUtils.isManagedProfileWithUnifiedChallenge(mCurrentUserId)) {
236                 getOutPrintWriter().println("Profile uses unified challenge");
237                 return false;
238             }
239 
240             try {
241                 final boolean result;
242                 if (havePassword) {
243                     byte[] passwordBytes = mOld != null ? mOld.getBytes() : null;
244                     result = mLockPatternUtils.checkPassword(passwordBytes, mCurrentUserId);
245                 } else {
246                     result = mLockPatternUtils.checkPattern(stringToPattern(mOld), mCurrentUserId);
247                 }
248                 if (!result) {
249                     if (!mLockPatternUtils.isManagedProfileWithUnifiedChallenge(mCurrentUserId)) {
250                         mLockPatternUtils.reportFailedPasswordAttempt(mCurrentUserId);
251                     }
252                     getOutPrintWriter().println("Old password '" + mOld + "' didn't match");
253                 } else {
254                     // Resets the counter for failed password attempts to 0.
255                     mLockPatternUtils.reportSuccessfulPasswordAttempt(mCurrentUserId);
256                 }
257                 return result;
258             } catch (RequestThrottledException e) {
259                 getOutPrintWriter().println("Request throttled");
260                 return false;
261             }
262         } else {
263             if (!mOld.isEmpty()) {
264                 getOutPrintWriter().println("Old password provided but user has no password");
265                 return false;
266             }
267             return true;
268         }
269     }
270 }
271