mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-06-01 05:14:53 +08:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
@@ -357,10 +357,12 @@ public class Repository implements FileSystemListener, RepositoryLogger {
|
|||||||
LinkedHashMap<String, User> newUserMap = new LinkedHashMap<>();
|
LinkedHashMap<String, User> newUserMap = new LinkedHashMap<>();
|
||||||
for (User user : users) {
|
for (User user : users) {
|
||||||
String userName = user.getName();
|
String userName = user.getName();
|
||||||
if (UserManager.ANONYMOUS_USERNAME.equals(userName) ||
|
if (UserManager.ANONYMOUS_USERNAME.equals(userName)) {
|
||||||
!allUsers.contains(userName)) {
|
|
||||||
continue; // ignore
|
continue; // ignore
|
||||||
}
|
}
|
||||||
|
if (!allUsers.contains(userName)) {
|
||||||
|
throw new IOException("Unknown user specified: " + userName);
|
||||||
|
}
|
||||||
if (!user.hasWritePermission() && !user.isReadOnly() && !user.isAdmin()) {
|
if (!user.hasWritePermission() && !user.isReadOnly() && !user.isAdmin()) {
|
||||||
throw new IOException("User specified with invalid permission: " + userName);
|
throw new IOException("User specified with invalid permission: " + userName);
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-7
@@ -16,8 +16,7 @@
|
|||||||
package ghidra.server.security;
|
package ghidra.server.security;
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.Date;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
import generic.random.SecureRandomFactory;
|
import generic.random.SecureRandomFactory;
|
||||||
@@ -84,13 +83,45 @@ public class TokenGenerator {
|
|||||||
return ++offset;
|
return ++offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Token} provides a byte array token wrapper to facilitate value-based
|
||||||
|
* hashcode and equality when used as a map key.
|
||||||
|
*/
|
||||||
|
private static class Token {
|
||||||
|
private byte[] token;
|
||||||
|
|
||||||
|
Token(byte[] token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + Arrays.hashCode(token);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Token other = (Token) obj;
|
||||||
|
return Arrays.equals(token, other.token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link CachedTokenSet} tracks timed token issuance and insures that they remain
|
* {@link CachedTokenSet} tracks timed token issuance and insures that they remain
|
||||||
* valid for one-time consumption within limited life-span.
|
* valid for one-time consumption within limited life-span.
|
||||||
*/
|
*/
|
||||||
private static class CachedTokenSet {
|
private static class CachedTokenSet {
|
||||||
|
|
||||||
private final Map<byte[], Long> cache = new ConcurrentHashMap<>();
|
private final Map<Token, Long> cache = new ConcurrentHashMap<>();
|
||||||
private final ScheduledExecutorService scheduler =
|
private final ScheduledExecutorService scheduler =
|
||||||
Executors.newSingleThreadScheduledExecutor();
|
Executors.newSingleThreadScheduledExecutor();
|
||||||
|
|
||||||
@@ -100,11 +131,11 @@ public class TokenGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add(byte[] token) {
|
void add(byte[] token) {
|
||||||
cache.put(token, System.currentTimeMillis());
|
cache.put(new Token(token), System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean consume(byte[] value) {
|
boolean consume(byte[] token) {
|
||||||
Long storedAt = cache.remove(value); // remove on retrieval
|
Long storedAt = cache.remove(new Token(token)); // remove on retrieval
|
||||||
if (storedAt == null)
|
if (storedAt == null)
|
||||||
return false;
|
return false;
|
||||||
return (System.currentTimeMillis() - storedAt < MAX_TTL_MS);
|
return (System.currentTimeMillis() - storedAt < MAX_TTL_MS);
|
||||||
@@ -115,5 +146,4 @@ public class TokenGenerator {
|
|||||||
cache.entrySet().removeIf(e -> now - e.getValue() >= MAX_TTL_MS);
|
cache.entrySet().removeIf(e -> now - e.getValue() >= MAX_TTL_MS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -18,6 +18,7 @@ package ghidra.server;
|
|||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
@@ -50,7 +51,13 @@ public class RepositoryTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
serverRoot.mkdir();
|
serverRoot.mkdir();
|
||||||
|
|
||||||
mgr = new RepositoryManager(serverRoot, false, 0, false);
|
mgr = new RepositoryManager(serverRoot, false, 0, false);
|
||||||
mgr.getUserManager().addUser(userName);
|
UserManager userManager = mgr.getUserManager();
|
||||||
|
userManager.addUser(userName);
|
||||||
|
|
||||||
|
userManager.addUser("user-a");
|
||||||
|
userManager.addUser("user-b");
|
||||||
|
userManager.addUser("user-c");
|
||||||
|
userManager.addUser("user-d");
|
||||||
|
|
||||||
repository = mgr.createRepository(userName, REPOSITORY_NAME);
|
repository = mgr.createRepository(userName, REPOSITORY_NAME);
|
||||||
}
|
}
|
||||||
@@ -94,17 +101,10 @@ public class RepositoryTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
Assert.fail("Should not have been able to change current user's access!");
|
Assert.fail("Should not have been able to change current user's access!");
|
||||||
}
|
}
|
||||||
catch (UserAccessException e) {
|
catch (UserAccessException e) {
|
||||||
|
// expected
|
||||||
}
|
}
|
||||||
|
|
||||||
users[3] = new User("user-x", User.ADMIN);
|
users[4] = new User(userName, User.ADMIN); // restore current users Admin access
|
||||||
try {
|
|
||||||
repository.setUserList(userName, users, false);
|
|
||||||
Assert.fail("Should not have been able to set the user list!");
|
|
||||||
}
|
|
||||||
catch (UserAccessException e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
users[4] = new User(userName, User.ADMIN);
|
|
||||||
repository.setUserList(userName, users, false);
|
repository.setUserList(userName, users, false);
|
||||||
|
|
||||||
User[] reportedUsers = repository.getUserList(userName);
|
User[] reportedUsers = repository.getUserList(userName);
|
||||||
@@ -113,6 +113,15 @@ public class RepositoryTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
assertEquals(users[i].getName(), reportedUsers[i].getName());
|
assertEquals(users[i].getName(), reportedUsers[i].getName());
|
||||||
assertEquals(users[i].getPermissionType(), reportedUsers[i].getPermissionType());
|
assertEquals(users[i].getPermissionType(), reportedUsers[i].getPermissionType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
users[3] = new User("user-x", User.ADMIN);
|
||||||
|
try {
|
||||||
|
repository.setUserList(userName, users, false);
|
||||||
|
Assert.fail("Should not have been able to specify unknown user");
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user