mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
GT-3042 allow back, forward slashes in user name.
This commit is contained in:
parent
019594c09f
commit
bc2c1ac828
4 changed files with 89 additions and 95 deletions
|
@ -289,16 +289,17 @@ public class ServerAdmin implements GhidraLaunchable {
|
|||
System.exit(-1);
|
||||
}
|
||||
String sid = args[i];
|
||||
if (!NamingUtilities.isValidName(sid) || sid.indexOf(' ') >= 0) {
|
||||
if (!UserManager.isValidUserName(sid)) {
|
||||
Msg.error(UserAdmin.class, "Invalid username/sid: " + sid);
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate username/sid
|
||||
* Validate repository name
|
||||
* @param args
|
||||
* @param i argument index
|
||||
* @param rootDirFile base repository directory
|
||||
*/
|
||||
private void validateRepName(String[] args, int i, File rootDirFile) {
|
||||
if (args.length < (i + 1)) {
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.apache.logging.log4j.Logger;
|
|||
|
||||
import ghidra.framework.store.local.LocalFileSystem;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import utilities.util.FileUtilities;
|
||||
|
||||
/**
|
||||
* <code>UserAdmin</code> is an Application for generating administrative
|
||||
|
@ -205,35 +206,17 @@ public class UserAdmin {
|
|||
log.info("Processing " + files.length + " queued commands");
|
||||
|
||||
for (File file : files) {
|
||||
ArrayList<String> cmdList = readCommands(file);
|
||||
Iterator<String> it = cmdList.iterator();
|
||||
while (it.hasNext()) {
|
||||
processCommand(repositoryMgr, it.next());
|
||||
List<String> cmdList = FileUtilities.getLines(file);
|
||||
for (String cmdStr : cmdList) {
|
||||
if (cmdStr.isBlank()) {
|
||||
continue;
|
||||
}
|
||||
processCommand(repositoryMgr, cmdStr.trim());
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all command strings contained within a file.
|
||||
* @param cmdFile command file
|
||||
* @return list of command strings
|
||||
* @throws IOException
|
||||
*/
|
||||
private static ArrayList<String> readCommands(File cmdFile) throws IOException {
|
||||
ArrayList<String> cmdList = new ArrayList<>();
|
||||
BufferedReader rdr = new BufferedReader(new FileReader(cmdFile));
|
||||
String cmd;
|
||||
while ((cmd = rdr.readLine()) != null) {
|
||||
if (cmd.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
cmdList.add(cmd.trim());
|
||||
}
|
||||
rdr.close();
|
||||
return cmdList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a list of command strings to a new command file.
|
||||
* @param cmdList list of command strings
|
||||
|
|
|
@ -17,6 +17,7 @@ package ghidra.server;
|
|||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.security.auth.login.FailedLoginException;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
@ -26,8 +27,7 @@ import org.apache.logging.log4j.Logger;
|
|||
|
||||
import ghidra.framework.remote.User;
|
||||
import ghidra.framework.store.local.LocalFileSystem;
|
||||
import ghidra.util.HashUtilities;
|
||||
import ghidra.util.NumericUtilities;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
|
@ -183,7 +183,7 @@ public class UserManager {
|
|||
if (x500User != null) {
|
||||
dnLookupMap.put(x500User, entry);
|
||||
}
|
||||
putUserList();
|
||||
writeUserList();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -260,7 +260,7 @@ public class UserManager {
|
|||
if (x500User != null) {
|
||||
dnLookupMap.put(x500User, entry);
|
||||
}
|
||||
putUserList();
|
||||
writeUserList();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -338,7 +338,7 @@ public class UserManager {
|
|||
if (entry.x500User != null) {
|
||||
dnLookupMap.put(entry.x500User, entry);
|
||||
}
|
||||
putUserList();
|
||||
writeUserList();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -426,7 +426,7 @@ public class UserManager {
|
|||
if (oldEntry.x500User != null) {
|
||||
dnLookupMap.remove(oldEntry.x500User);
|
||||
}
|
||||
putUserList();
|
||||
writeUserList();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -457,7 +457,7 @@ public class UserManager {
|
|||
}
|
||||
userListUpdateInProgress = true;
|
||||
try {
|
||||
getUserList();
|
||||
readUserListIfNeeded();
|
||||
clearExpiredPasswords();
|
||||
if (processCmds) {
|
||||
UserAdmin.processCommands(repositoryMgr);
|
||||
|
@ -488,21 +488,22 @@ public class UserManager {
|
|||
}
|
||||
}
|
||||
if (dataChanged) {
|
||||
putUserList();
|
||||
writeUserList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read user data from file.
|
||||
* Read user data from file if the timestamp on the file has changed.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private void getUserList() throws IOException {
|
||||
private void readUserListIfNeeded() throws IOException {
|
||||
|
||||
long lastMod = userFile.lastModified();
|
||||
if (lastUserListChange == lastMod) {
|
||||
if (lastMod == 0) {
|
||||
// Create empty file if it does not yet exist
|
||||
putUserList();
|
||||
writeUserList();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -546,58 +547,62 @@ public class UserManager {
|
|||
}
|
||||
}
|
||||
|
||||
private static void readUserList(File file, LinkedHashMap<String, UserEntry> list,
|
||||
HashMap<X500Principal, UserEntry> x500LookupMap) throws IOException {
|
||||
private static void readUserList(File file, Map<String, UserEntry> usersIndexByName,
|
||||
Map<X500Principal, UserEntry> x500LookupMap) throws IOException {
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
|
||||
String line = br.readLine();
|
||||
while (line != null) {
|
||||
if (!line.startsWith("#")) {
|
||||
try {
|
||||
StringTokenizer st = new StringTokenizer(line, ":");
|
||||
UserEntry entry = new UserEntry();
|
||||
entry.username = st.nextToken();
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
if (line.startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
StringTokenizer st = new StringTokenizer(line, ":");
|
||||
UserEntry entry = new UserEntry();
|
||||
entry.username = st.nextToken();
|
||||
if (!isValidUserName(entry.username)) {
|
||||
log.error("Invalid user name, skipping: " + entry.username);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Password Hash
|
||||
// Password Hash
|
||||
if (st.hasMoreTokens()) {
|
||||
entry.passwordHash = st.nextToken().toCharArray();
|
||||
|
||||
// Password Time
|
||||
if (st.hasMoreTokens()) {
|
||||
entry.passwordHash = st.nextToken().toCharArray();
|
||||
|
||||
// Password Time
|
||||
if (st.hasMoreTokens()) {
|
||||
try {
|
||||
String timeStr = st.nextToken();
|
||||
if ("*".equals(timeStr)) {
|
||||
entry.passwordTime = NO_EXPIRATION;
|
||||
}
|
||||
else {
|
||||
entry.passwordTime = NumericUtilities.parseHexLong(timeStr);
|
||||
}
|
||||
try {
|
||||
String timeStr = st.nextToken();
|
||||
if ("*".equals(timeStr)) {
|
||||
entry.passwordTime = NO_EXPIRATION;
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
log.error("Invalid password time - forced expiration: " +
|
||||
entry.username);
|
||||
entry.passwordTime = 0;
|
||||
}
|
||||
|
||||
// Distinguished Name
|
||||
if (st.hasMoreTokens()) {
|
||||
String dn = st.nextToken();
|
||||
if (dn.length() > 0) {
|
||||
entry.x500User = new X500Principal(dn);
|
||||
}
|
||||
|
||||
else {
|
||||
entry.passwordTime = NumericUtilities.parseHexLong(timeStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
list.put(entry.username, entry);
|
||||
if (entry.x500User != null) {
|
||||
x500LookupMap.put(entry.x500User, entry);
|
||||
catch (NumberFormatException e) {
|
||||
log.error(
|
||||
"Invalid password time - forced expiration: " + entry.username);
|
||||
entry.passwordTime = 0;
|
||||
}
|
||||
|
||||
// Distinguished Name
|
||||
if (st.hasMoreTokens()) {
|
||||
String dn = st.nextToken();
|
||||
if (dn.length() > 0) {
|
||||
entry.x500User = new X500Principal(dn);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NoSuchElementException e) {
|
||||
// skip entry
|
||||
usersIndexByName.put(entry.username, entry);
|
||||
if (entry.x500User != null) {
|
||||
x500LookupMap.put(entry.x500User, entry);
|
||||
}
|
||||
}
|
||||
line = br.readLine();
|
||||
catch (NoSuchElementException e) {
|
||||
// skip entry
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -606,12 +611,9 @@ public class UserManager {
|
|||
* Write user data to file.
|
||||
* @throws IOException
|
||||
*/
|
||||
private void putUserList() throws IOException {
|
||||
BufferedWriter bw = new BufferedWriter(new FileWriter(userFile));
|
||||
try {
|
||||
Iterator<UserEntry> iter = userList.values().iterator();
|
||||
while (iter.hasNext()) {
|
||||
UserEntry entry = iter.next();
|
||||
private void writeUserList() throws IOException {
|
||||
try (BufferedWriter bw = new BufferedWriter(new FileWriter(userFile))) {
|
||||
for (UserEntry entry : userList.values()) {
|
||||
bw.write(entry.username);
|
||||
bw.write(":");
|
||||
if (entry.passwordHash != null) {
|
||||
|
@ -634,13 +636,6 @@ public class UserManager {
|
|||
bw.newLine();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
bw.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
}
|
||||
}
|
||||
lastUserListChange = userFile.lastModified();
|
||||
}
|
||||
|
||||
|
@ -743,4 +738,20 @@ public class UserManager {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Regex: matches if the entire string is alpha, digit, ".", "-", "_", fwd or back slash.
|
||||
*/
|
||||
private static final Pattern VALID_USERNAME_REGEX = Pattern.compile("[a-zA-Z0-9.-_/\\\\]+");
|
||||
|
||||
/**
|
||||
* Ensures a name only contains valid characters and meets length limitations.
|
||||
*
|
||||
* @param s name string
|
||||
* @return boolean true if valid name, false if not valid
|
||||
*/
|
||||
public static boolean isValidUserName(String s) {
|
||||
return VALID_USERNAME_REGEX.matcher(s).matches() &&
|
||||
s.length() <= NamingUtilities.MAX_NAME_LENGTH;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -785,13 +785,13 @@ public final class FileUtilities {
|
|||
* @throws IOException if there are any issues reading the file
|
||||
*/
|
||||
public static List<String> getLines(BufferedReader in) throws IOException {
|
||||
List<String> fileLines = new ArrayList<>();
|
||||
try {
|
||||
List<String> fileLines = new ArrayList<>();
|
||||
String line;
|
||||
while ((line = in.readLine()) != null) {
|
||||
fileLines.add(line);
|
||||
}
|
||||
in.close();
|
||||
return fileLines;
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
|
@ -801,7 +801,6 @@ public final class FileUtilities {
|
|||
// don't care; we tried
|
||||
}
|
||||
}
|
||||
return fileLines;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue