static int android_unlock_primary_user(char *password) { char storage_path[MAX_PATH_LENGTH]; char private_dir_path[MAX_PATH_LENGTH]; struct crypto_header header; int ret; ret = read_crypto_header(&header, CRYPTO_HEADER_COPY); if (ret < 0) return ret; ret = check_passwd(&header, password); if (ret < 0) return ret; property_set("vold.decrypt", "trigger_reset_main"); sleep(2); umount("/data", MNT_FORCE); memset(storage_path, 0, sizeof(storage_path)); sprintf(storage_path, "%s%d", ANDROID_USER_DATA_PATH, PRIMARY_USER); ret = get_private_storage_path(private_dir_path, storage_path); if (ret < 0) { LOGE("Error getting private storage for %s", storage_path); return ret; } ret = access(private_dir_path, F_OK); if (ret < 0) { LOGE("Private storage %s does not exist", private_dir_path); return ret; } if (check_fs_mounted(private_dir_path) == 1) { LOGE("ecryptfs is already mounted on %s", storage_path); return 0; } ret = remove_dir_content(storage_path); if (ret < 0) { LOGE("Error removing data from %s directory", storage_path); return ret; } ret = EFS_unlock(storage_path, password); if (ret < 0) { LOGE("Error unlocking efs storage %s", storage_path); return ret; } memset(storage_path, 0, sizeof(storage_path)); sprintf(storage_path, "%s%d", ANDROID_VIRTUAL_SDCARD_PATH, PRIMARY_USER); if (check_fs_mounted(storage_path) == 1) { LOGE("ecryptfs is already mounted on %s", storage_path); return 0; } ret = remove_dir_content(storage_path); if (ret < 0) { LOGE("Error removing data from %s directory", storage_path); return ret; } ret = EFS_unlock(storage_path, password); if (ret < 0) { LOGE("Error unlocking efs storage %s", storage_path); return ret; } property_set("crypto.primary_user", "decrypted"); sleep(2); property_set("vold.decrypt", "trigger_restart_framework"); return 0; }
/** * Mount encrypted data for an Android user * * @param user Android user id * @param password Android user password * * @return 0 on success, negative value on error */ int android_unlock_user_data(int user, char *password) { char storage_path[MAX_PATH_LENGTH]; char private_dir_path[MAX_PATH_LENGTH]; int ret = -1; LOGI("Unlock user %d", user); if (user == PRIMARY_USER) { ret = android_unlock_primary_user(password); return ret; } memset(storage_path, 0, sizeof(storage_path)); sprintf(storage_path, "%s%d", ANDROID_USER_DATA_PATH, user); ret = get_private_storage_path(private_dir_path, storage_path); if (ret < 0) { LOGE("Error getting private storage for %s", storage_path); return ret; } ret = access(private_dir_path, F_OK); if (ret < 0) { LOGE("Private storage %s does not exist", private_dir_path); return ret; } if (check_fs_mounted(private_dir_path) == 1) { LOGE("ecryptfs is already mounted on %s", storage_path); return 0; } ret = remove_dir_content(storage_path); if (ret < 0) { LOGE("Error removing data from %s directory", storage_path); return ret; } ret = EFS_unlock(storage_path, password); if (ret < 0) { LOGE("Error unlocking efs storage %s", storage_path); return ret; } memset(storage_path, 0, sizeof(storage_path)); sprintf(storage_path, "%s%d", ANDROID_VIRTUAL_SDCARD_PATH, user); if (check_fs_mounted(storage_path) == 1) { LOGE("ecryptfs is already mounted on %s", storage_path); return 0; } ret = remove_dir_content(storage_path); if (ret < 0) { LOGE("Error removing data from %s directory", storage_path); return ret; } ret = EFS_unlock(storage_path, password); if (ret < 0) { LOGE("Error unlocking efs storage %s", storage_path); return ret; } return 0; }
int EncryptedFileStorageCmd::runCommand(SocketClient *cli, int argc, char **argv) { int rc = 0; if ((cli->getUid() != 0) && (cli->getUid() != AID_SYSTEM)) { cli->sendMsg(ResponseCode::CommandNoPermission, "No permission to run EFS commands", false); return 0; } if (argc < 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); return 0; } if (!strcmp(argv[1], "create")) { if (argc != 4) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: efs create <storage_path> <passwd>", false); return 0; } rc = EFS_create(argv[2],argv[3]); } else if (!strcmp(argv[1], "unlock")) { if (argc != 4) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: efs unlock <storage_path> <passwd>", false); return 0; } rc = EFS_unlock(argv[2], argv[3]); } else if (!strcmp(argv[1], "lock")) { if (argc != 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: efs lock <storage_path>", false); return 0; } rc = EFS_lock(argv[2]); } else if (!strcmp(argv[1], "change_passwd")) { if (argc != 5) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: efs change_passwd <storage_path> <old_passwd> <new_passwd>", false); return 0; } rc = EFS_change_password(argv[2],argv[3],argv[4]); } else if (!strcmp(argv[1], "remove")) { if (argc != 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: efs remove <storage_path>", false); return 0; } rc = EFS_remove(argv[2]); } else if (!strcmp(argv[1], "recover")) { if (argc != 4) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: efs recover <storage_path> <password>", false); return 0; } rc = EFS_recover_data_and_remove(argv[2], argv[3]); } else if (!strcmp(argv[1], "stat")) { if (argc != 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: efs stat <storage_path>", false); return 0; } rc = EFS_get_status(argv[2]); } else if (!strcmp(argv[1], "get_progress")) { if (argc != 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: efs get_progress <storage_path>", false); return 0; } rc = EFS_get_progress(argv[2]); } else if (!strcmp(argv[1], "encrypt_user_data")) { if (argc != 4) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: efs encrypt_user_data <userId> <password>", false); return 0; } rc = android_encrypt_user_data(atoi(argv[2]), argv[3]); } else if (!strcmp(argv[1], "unlock_user_data")) { if (argc != 4) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: efs unlock_user_data <userId> <password>", false); return 0; } rc = android_unlock_user_data(atoi(argv[2]), argv[3]); } else if (!strcmp(argv[1], "lock_user_data")) { if (argc != 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: efs lock_user_data <userId>", false); return 0; } rc = android_lock_user_data(atoi(argv[2])); } else if (!strcmp(argv[1], "change_user_data_passwd")) { if (argc != 5) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: efs change_user_data_passwd <userId> <old_passwd> <new_passwd>", false); return 0; } rc = android_change_user_data_password(atoi(argv[2]),argv[3],argv[4]); } else if (!strcmp(argv[1], "decrypt_user_data")) { if (argc != 4) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: efs decrypt_user_data <userId> <password>", false); return 0; } rc = android_decrypt_user_data(atoi(argv[2]), argv[3]); } else if (!strcmp(argv[1], "remove_user_encrypted_data")) { if (argc != 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: efs remove_user_encrypted_data <userId>", false); return 0; } rc = android_remove_user_encrypted_data(atoi(argv[2])); } else if (!strcmp(argv[1], "user_stat")) { if (argc != 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: efs user_stat <userId>", false); return 0; } rc = android_get_encrypted_user_status(atoi(argv[2])); } else { cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown efs-tools cmd", false); } // Always report that the command succeeded and return the error code. // The caller will check the return value to see what the error was. char msg[255]; snprintf(msg, sizeof(msg), "%d", rc); cli->sendMsg(ResponseCode::CommandOkay, msg, false); return 0; }