blob: 877f7c2491abfeb2510d7b16aa77ccd73a2d0506 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 SAP AG
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Lazar Kirchev, SAP AG - initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.console.ssh;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.felix.service.command.CommandSession;
import org.apache.felix.service.command.Descriptor;
import org.eclipse.equinox.console.common.ConsoleInputScanner;
import org.eclipse.equinox.console.common.Scanner;
import org.eclipse.equinox.console.storage.DigestUtil;
import org.eclipse.equinox.console.storage.SecureUserStore;
/**
* This class provides commands for administering users: adding, removing and listing users; setting or changing password;
* resetting password; adding and removing roles
*
*
*/
public class UserAdminCommand {
private static final String INPUT_SCANNER = "INPUT_SCANNER";
private static final String SSH_INPUT_SCANNER = "SSH_INPUT_SCANNER";
private static final String DEFAULT_USER = "equinox";
private static final int MINIMAL_PASSWORD_LENGTH = 8;
private static final int PASSWORD_INPUT_TRIALS_LIMIT = 3;
/**
* Command for adding a user
*
* @param args command line arguments in the format -username <username> -password <password> -roles <comma-separated list of user roles (optional)>
* @throws Exception
*/
@Descriptor("Add user with password and roles")
public void addUser(@Descriptor("-username <username>\r\n-password <password>\r\n-roles <comma-separated list of user roles (optional)>") String[] args) throws Exception {
String username = null;
String password = null;
String roles = "";
for (int i = 0; i < args.length; i++) {
if ("-username".equals(args[i]) && i < args.length - 1) {
username = args[i + 1];
i++;
} else if ("-password".equals(args[i]) && i < args.length - 1) {
password = args[i + 1];
i++;
} else if ("-roles".equals(args[i]) && i < args.length - 1) {
roles = args[i + 1];
i++;
}
}
if (! validateUsername(username)) {
throw new Exception("Invalid username");
}
if (password == null) {
throw new Exception("Password not specified");
}
if (password.length() < MINIMAL_PASSWORD_LENGTH) {
throw new Exception("Password should be at least 8 characters");
}
SecureUserStore.putUser(username, DigestUtil.encrypt(password), roles);
if(SecureUserStore.existsUser(DEFAULT_USER)) {
SecureUserStore.deleteUser(DEFAULT_USER);
}
}
/**
* Command for setting or changing the password of a user.
*
* @param args command-line arguments in the format -username <username> -password <password>
* @throws Exception
*/
@Descriptor("Set or change password")
public void setPassword(@Descriptor("-username <username>\r\n-password <password>") String[] args) throws Exception {
String username = null;
String password = null;
for (int i = 0; i < args.length; i++) {
if ("-username".equals(args[i]) && i < args.length - 1) {
username = args[i + 1];
i++;
} else if ("-password".equals(args[i]) && i < args.length - 1) {
password = args[i + 1];
i++;
}
}
if (! validateUsername(username)) {
throw new Exception("Invalid username");
}
if (password == null) {
throw new Exception("Password not specified");
}
if (password.length() < MINIMAL_PASSWORD_LENGTH) {
throw new Exception("Password should be at least 8 characters");
}
SecureUserStore.setPassword(username, DigestUtil.encrypt(password));
}
/**
* Command for adding a user. The command interactively asks for username, password and roles; the
* input plain text password is encrypted before storing.
*
* @param session
* @return true if the user was successfully added
*
* @throws Exception
*/
@Descriptor("Add user with password and roles interactively")
public boolean addUser(final CommandSession session) throws Exception {
ConsoleInputScanner inputScanner = (ConsoleInputScanner) session.get(INPUT_SCANNER);
Scanner scanner = (Scanner) session.get(SSH_INPUT_SCANNER);
try {
// switch off the history so that username, password and roles will not be saved in console history
if (scanner != null) {
inputScanner.toggleHistoryEnabled(false);
}
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String username = readUsername(reader);
if (!validateUsername(username)) {
System.out.println("Invalid username");
return false;
}
if (SecureUserStore.existsUser(username)) {
System.out.println("Username already exists");
return false;
}
// switch off the echo so that the password will not be printed in the console
if (scanner != null) {
scanner.toggleEchoEnabled(false);
}
String password = readPassword(reader);
if (password == null){
return false;
}
if (scanner != null) {
scanner.toggleEchoEnabled(true);
}
String roles = readRoles(reader);
if (roles == null) {
return false;
}
SecureUserStore.putUser(username, DigestUtil.encrypt(password), roles);
if(SecureUserStore.existsUser(DEFAULT_USER)) {
SecureUserStore.deleteUser(DEFAULT_USER);
}
} finally {
if (scanner != null) {
inputScanner.toggleHistoryEnabled(true);
scanner.toggleEchoEnabled(true);
}
}
return true;
}
@Descriptor("Delete user")
public void deleteUser(@Descriptor("username of the user to be deleted") String username) {
if (SecureUserStore.existsUser(username)) {
SecureUserStore.deleteUser(username);
}
}
/**
* Command to remove the password for a user
*
* @param username user to remove the password for
* @throws Exception
*/
@Descriptor("Reset password")
public void resetPassword(@Descriptor("username of the user whose password will be reset") String username) throws Exception {
if (!SecureUserStore.existsUser(username)) {
throw new Exception("Such user does not exist");
}
SecureUserStore.resetPassword(username);
}
/**
* Command to set or change the password for a user; the command asks interactively for the new password; the
* input plain text password is encrypted before storing.
*
* @param session
* @param username the user whose password will be changed
* @throws Exception
*/
@Descriptor("Set or change password")
public void setPassword(final CommandSession session, @Descriptor("Username of the user whose password will be changed") String username) throws Exception {
if ("".equals(username)) {
System.out.println("Username not specified");
return;
}
if (!SecureUserStore.existsUser(username)) {
throw new Exception("Such user does not exist");
}
ConsoleInputScanner inputScanner = (ConsoleInputScanner) session.get(INPUT_SCANNER);
Scanner scanner = (Scanner) session.get(SSH_INPUT_SCANNER);
try {
// switch off echo and history so that the password is neither echoed to the console, nor saved in history
if (scanner != null) {
inputScanner.toggleHistoryEnabled(false);
scanner.toggleEchoEnabled(false);
}
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String password = readPassword(reader);
if (password == null) {
return;
}
SecureUserStore.setPassword(username, DigestUtil.encrypt(password));
} finally {
if (scanner != null) {
inputScanner.toggleHistoryEnabled(true);
scanner.toggleEchoEnabled(true);
}
}
}
/**
* Command to add roles to a user
*
* @param args command line arguments in the format -username <username>\r\n-roles <comma-separated list of roles to add>
* @throws Exception
*/
@Descriptor("Add roles to user")
public void addRoles(@Descriptor("-username <username>\r\n-roles <comma-separated list of roles to add>") String[] args) throws Exception {
String username = null;
String roles = "";
for (int i = 0; i < args.length; i++) {
if ("-username".equals(args[i]) && i < args.length - 1) {
username = args[i + 1];
i++;
} else if ("-roles".equals(args[i]) && i < args.length - 1) {
roles = args[i + 1];
i++;
}
}
if (username == null) {
throw new Exception("Username not specified");
}
if("".equals(roles)) {
return;
}
if (!SecureUserStore.existsUser(username)) {
throw new Exception("Such user does not exist");
}
SecureUserStore.addRoles(username, roles);
}
/**
* Command to remove roles for a particular user
*
* @param args command line arguments in the format -username <username>\r\n-roles <comma-separated list of roles to remove>
* @throws Exception
*/
@Descriptor("Remove user roles")
public void removeRoles(@Descriptor("-username <username>\r\n-roles <comma-separated list of roles to remove>") String[] args) throws Exception {
String username = null;
String roles = "";
for (int i = 0; i < args.length; i++) {
if ("-username".equals(args[i]) && i < args.length - 1) {
username = args[i + 1];
i++;
} else if ("-roles".equals(args[i]) && i < args.length - 1) {
roles = args[i + 1];
i++;
}
}
if (username == null) {
throw new Exception("Username not specified");
}
if("".equals(roles)) {
return;
}
if (!SecureUserStore.existsUser(username)) {
throw new Exception("Such user does not exist");
}
SecureUserStore.removeRoles(username, roles);
}
/**
* Command to list available users
*/
@Descriptor("Lists available users")
public void listUsers() {
String[] users = SecureUserStore.getUserNames();
if(users.length == 0) {
System.out.println("No users available");
return;
}
for(String user : users) {
System.out.println(user);
}
}
private String readPassword(BufferedReader reader) {
String password = null;
int count = 0;
while (password == null && count < PASSWORD_INPUT_TRIALS_LIMIT){
System.out.print("password: ");
System.out.flush();
try {
password = reader.readLine();
} catch (IOException e) {
System.out.println("Error while reading password");
return null;
}
if (password == null || "".equals(password)) {
System.out.println("Password not specified");
password = null;
} else if (password.length() < MINIMAL_PASSWORD_LENGTH) {
System.out.println("Password should be at least 8 characters");
password = null;
}
count++;
}
if (password == null) {
return null;
}
String passwordConfirmation = null;
count = 0;
while (passwordConfirmation == null && count < PASSWORD_INPUT_TRIALS_LIMIT){
System.out.print("Confirm password: ");
System.out.flush();
try {
passwordConfirmation = reader.readLine();
if (!password.equals(passwordConfirmation)) {
System.out.println("The passwords do not match!");
passwordConfirmation = null;
}
} catch (IOException e) {
System.out.println("Error while reading password");
return null;
}
count++;
}
if (passwordConfirmation == null){
return null;
}
return password;
}
private String readUsername (BufferedReader reader) {
System.out.print("username: ");
System.out.flush();
String username = null;
try {
username = reader.readLine();
} catch (IOException e) {
System.out.println("Error while reading username");
return null;
}
if (username == null || "".equals(username)) {
System.out.println("Username not specified");
return null;
}
return username;
}
private String readRoles (BufferedReader reader){
//roles input validation
System.out.print("roles: ");
System.out.flush();
String roles = null;
try {
roles = reader.readLine();
} catch (IOException e) {
System.out.println("Error while reading roles");
return null;
}
if (roles == null) {
roles = "";
}
return roles;
}
private static boolean validateUsername (String username){
if( username == null){
return false;
}else{
Pattern allowedChars = Pattern.compile("[A-Za-z0-9_.]+");
Matcher matcher = allowedChars.matcher(username);
return matcher.matches();
}
}
}