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 import static com.android.internal.widget.LockPatternUtils.stringToPattern; 22 23 import android.app.ActivityManager; 24 import android.content.Context; 25 import android.os.RemoteException; 26 import android.os.ShellCommand; 27 28 import com.android.internal.widget.LockPatternUtils; 29 import com.android.internal.widget.LockPatternUtils.RequestThrottledException; 30 31 class LockSettingsShellCommand extends ShellCommand { 32 33 private static final String COMMAND_SET_PATTERN = "set-pattern"; 34 private static final String COMMAND_SET_PIN = "set-pin"; 35 private static final String COMMAND_SET_PASSWORD = "set-password"; 36 private static final String COMMAND_CLEAR = "clear"; 37 private static final String COMMAND_SP = "sp"; 38 private static final String COMMAND_SET_DISABLED = "set-disabled"; 39 private static final String COMMAND_VERIFY = "verify"; 40 private static final String COMMAND_GET_DISABLED = "get-disabled"; 41 42 private int mCurrentUserId; 43 private final LockPatternUtils mLockPatternUtils; 44 private final Context mContext; 45 private String mOld = ""; 46 private String mNew = ""; 47 48 LockSettingsShellCommand(Context context, LockPatternUtils lockPatternUtils) { 49 mContext = context; 50 mLockPatternUtils = lockPatternUtils; 51 } 52 53 @Override 54 public int onCommand(String cmd) { 55 try { 56 mCurrentUserId = ActivityManager.getService().getCurrentUser().id; 57 58 parseArgs(); 59 if (!checkCredential()) { 60 return -1; 61 } 62 switch (cmd) { 63 case COMMAND_SET_PATTERN: 64 runSetPattern(); 65 break; 66 case COMMAND_SET_PASSWORD: 67 runSetPassword(); 68 break; 69 case COMMAND_SET_PIN: 70 runSetPin(); 71 break; 72 case COMMAND_CLEAR: 73 runClear(); 74 break; 75 case COMMAND_SP: 76 runChangeSp(); 77 break; 78 case COMMAND_SET_DISABLED: 79 runSetDisabled(); 80 break; 81 case COMMAND_VERIFY: 82 runVerify(); 83 break; 84 case COMMAND_GET_DISABLED: 85 runGetDisabled(); 86 break; 87 default: 88 getErrPrintWriter().println("Unknown command: " + cmd); 89 break; 90 } 91 return 0; 92 } catch (Exception e) { 93 getErrPrintWriter().println("Error while executing command: " + cmd); 94 e.printStackTrace(getErrPrintWriter()); 95 return -1; 96 } 97 } 98 99 private void runVerify() { 100 // The command is only run if the credential is correct. 101 getOutPrintWriter().println("Lock credential verified successfully"); 102 } 103 104 @Override 105 public void onHelp() { 106 } 107 108 private void parseArgs() { 109 String opt; 110 while ((opt = getNextOption()) != null) { 111 if ("--old".equals(opt)) { 112 mOld = getNextArgRequired(); 113 } else if ("--user".equals(opt)) { 114 mCurrentUserId = Integer.parseInt(getNextArgRequired()); 115 } else { 116 getErrPrintWriter().println("Unknown option: " + opt); 117 throw new IllegalArgumentException(); 118 } 119 } 120 mNew = getNextArg(); 121 } 122 123 private void runChangeSp() { 124 if (mNew != null ) { 125 if ("1".equals(mNew)) { 126 mLockPatternUtils.enableSyntheticPassword(); 127 getOutPrintWriter().println("Synthetic password enabled"); 128 } else if ("0".equals(mNew)) { 129 mLockPatternUtils.disableSyntheticPassword(); 130 getOutPrintWriter().println("Synthetic password disabled"); 131 } 132 } 133 getOutPrintWriter().println(String.format("SP Enabled = %b", 134 mLockPatternUtils.isSyntheticPasswordEnabled())); 135 } 136 137 private void runSetPattern() throws RemoteException { 138 mLockPatternUtils.saveLockPattern(stringToPattern(mNew), mOld, mCurrentUserId); 139 getOutPrintWriter().println("Pattern set to '" + mNew + "'"); 140 } 141 142 private void runSetPassword() throws RemoteException { 143 mLockPatternUtils.saveLockPassword(mNew, mOld, PASSWORD_QUALITY_ALPHABETIC, mCurrentUserId); 144 getOutPrintWriter().println("Password set to '" + mNew + "'"); 145 } 146 147 private void runSetPin() throws RemoteException { 148 mLockPatternUtils.saveLockPassword(mNew, mOld, PASSWORD_QUALITY_NUMERIC, mCurrentUserId); 149 getOutPrintWriter().println("Pin set to '" + mNew + "'"); 150 } 151 152 private void runClear() throws RemoteException { 153 mLockPatternUtils.clearLock(mOld, mCurrentUserId); 154 getOutPrintWriter().println("Lock credential cleared"); 155 } 156 157 private void runSetDisabled() throws RemoteException { 158 final boolean disabled = Boolean.parseBoolean(mNew); 159 mLockPatternUtils.setLockScreenDisabled(disabled, mCurrentUserId); 160 getOutPrintWriter().println("Lock screen disabled set to " + disabled); 161 } 162 163 private void runGetDisabled() { 164 boolean isLockScreenDisabled = mLockPatternUtils.isLockScreenDisabled(mCurrentUserId); 165 getOutPrintWriter().println(isLockScreenDisabled); 166 } 167 168 private boolean checkCredential() throws RemoteException { 169 final boolean havePassword = mLockPatternUtils.isLockPasswordEnabled(mCurrentUserId); 170 final boolean havePattern = mLockPatternUtils.isLockPatternEnabled(mCurrentUserId); 171 if (havePassword || havePattern) { 172 if (mLockPatternUtils.isManagedProfileWithUnifiedChallenge(mCurrentUserId)) { 173 getOutPrintWriter().println("Profile uses unified challenge"); 174 return false; 175 } 176 177 try { 178 final boolean result; 179 if (havePassword) { 180 result = mLockPatternUtils.checkPassword(mOld, mCurrentUserId); 181 } else { 182 result = mLockPatternUtils.checkPattern(stringToPattern(mOld), mCurrentUserId); 183 } 184 if (!result) { 185 if (!mLockPatternUtils.isManagedProfileWithUnifiedChallenge(mCurrentUserId)) { 186 mLockPatternUtils.reportFailedPasswordAttempt(mCurrentUserId); 187 } 188 getOutPrintWriter().println("Old password '" + mOld + "' didn't match"); 189 } 190 return result; 191 } catch (RequestThrottledException e) { 192 getOutPrintWriter().println("Request throttled"); 193 return false; 194 } 195 } else { 196 return true; 197 } 198 } 199 } 200