| /******************************************************************************* |
| * 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(); |
| } |
| } |
| |
| } |