GT-2658 - more finishing touches

docs, exception handling, direct config file parsing instead of system
property.
This commit is contained in:
dev747368 2019-09-06 14:27:12 -04:00
parent 0ae460952e
commit 58f93ea0e7
11 changed files with 95 additions and 47 deletions

View file

@ -0,0 +1 @@
This directory is for additional JAVA libraries (*.jar) that you want to make available to GhidraServer.

View file

@ -0,0 +1,4 @@
This directory is for additional native system libraries that you want to make available to GhidraServer.
Place the system library in either a win64, linux64, or osx64 subdirectory, depending on the type of the
system library.

View file

@ -140,7 +140,8 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
GhidraServer(File rootDir, AuthMode authMode, String loginDomain,
boolean allowUserToSpecifyName, boolean altSSHLoginAllowed,
int defaultPasswordExpirationDays, boolean allowAnonymousAccess,
boolean autoProvisionAuthedUsers) throws IOException, CertificateException {
boolean autoProvisionAuthedUsers, File jaasConfigFile)
throws IOException, CertificateException {
super(ServerPortFactory.getRMISSLPort(), clientSocketFactory, serverSocketFactory);
@ -179,7 +180,8 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
}
break;
case JAAS_LOGIN:
authModule = new JAASAuthenticationModule("auth", allowUserToSpecifyName);
authModule =
new JAASAuthenticationModule("auth", allowUserToSpecifyName, jaasConfigFile);
break;
case KRB5_AD_LOGIN:
if (loginDomain == null || loginDomain.isBlank()) {
@ -329,9 +331,15 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
}
}
else {
throw new FailedLoginException(
RepositoryManager.log(null, null,
"User successfully authenticated, but does not exist in Ghidra user list: " +
username);
username,
null);
// Throw LoginException instead of FailedLoginException to prevent
// the user from being asked to retry the login, which might
// lead them to try older/different passwords and get their system
// account locked.
throw new LoginException("Unknown user: " + username);
}
}
RepositoryManager.log(null, null, "User '" + username + "' authenticated",
@ -341,7 +349,11 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
catch (LoginException e) {
RepositoryManager.log(null, null, "Login failed (" + e.getMessage() + ")",
username);
throw e;
// Create new exceptions so we don't leak config info to the client.
if (e instanceof FailedLoginException) {
throw new FailedLoginException("User authentication failed");
}
throw new LoginException("User login system failure");
}
if (authModule instanceof PasswordFileAuthenticationModule) {
supportPasswordChange = true;
@ -671,21 +683,19 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
serverRoot = new File(installRoot.getFile(false), rootPath);
}
File jaasConfigFile = null;
if (authMode == JAAS_LOGIN) {
if (jaasConfigFileStr == null) {
displayUsage("JAAS config file argument (-jaas <configfile>) not specified");
System.exit(-1);
}
File jaasConfigFile = getServerCfgFile(jaasConfigFileStr);
if (!jaasConfigFile.exists() || !jaasConfigFile.isFile()) {
jaasConfigFile = getServerCfgFile(jaasConfigFileStr);
if (!jaasConfigFile.isFile()) {
displayUsage(
"JAAS config file (-jaas <configfile>) does not exist or is not file: " +
jaasConfigFile.getAbsolutePath());
System.exit(-1);
}
// NOTE: there is a leading '=' char to force this path to be the one-and-only config file
System.setProperty("java.security.auth.login.config",
"=" + jaasConfigFile.getAbsolutePath());
}
try {
@ -788,7 +798,7 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
GhidraServer svr = new GhidraServer(serverRoot, authMode, loginDomain,
nameCallbackAllowed, altSSHLoginAllowed, defaultPasswordExpiration,
allowAnonymousAccess, autoProvision);
allowAnonymousAccess, autoProvision, jaasConfigFile);
log.info("Registering Ghidra Server...");

View file

@ -27,17 +27,16 @@ Command line parameters:
-jaas <config_file> : specifies the path to the JAAS config file (when using -a4), relative
to the ghidra/server directory (if not absolute).
See jaas/jaas.conf for examples and suggestions.
See jaas.conf for examples and suggestions.
It is the system administrator's responsibility to craft their own
JAAS configuration directive when using the -a4 mode.
-u : enable users to be prompted for user ID (does not apply to -a2 PKI mode)
-autoProvision : enable the auto-creation of Ghidra users when the authenticator module
(ie. OS or other authentication method specified by JAAS) authenticates
a new unknown user.
Users deleted in the OS or other source system will need to be
deleted manually from the Ghidra system.
-autoProvision : enable the auto-creation of new Ghidra Server
users when they successfully authenticate to the server (-a1 and -a4 modes only).
Users removed from the authentication provider (e.g., Active Directory) will need to be
deleted manually from the Ghidra Server using svrAdmin command.
-anonymous : enables anonymous repository access (see svrREADME.html for details)

View file

@ -15,7 +15,11 @@
*/
package ghidra.server.security;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.security.NoSuchAlgorithmException;
import java.security.URIParameter;
import java.util.concurrent.atomic.AtomicReference;
import javax.security.auth.Subject;
@ -42,6 +46,7 @@ public class JAASAuthenticationModule implements AuthenticationModule {
private boolean allowUserToSpecifyName;
private String loginContextName;
private File jaasConfigFile;
/**
* Creates a new {@link JAASAuthenticationModule} instance.
@ -50,18 +55,42 @@ public class JAASAuthenticationModule implements AuthenticationModule {
* @param allowUserToSpecifyName flag, if true will include a {@link NameCallback} in the
* {@link #getAuthenticationCallbacks()} list, which allows the user to specify a different
* name than their {@link GhidraPrincipal}.
* @throws IllegalArgumentException if the loginContextName is not present in the JAAS configuration
* @param jaasConfigFile JAAS config file
* @throws IllegalArgumentException if the loginContextName is not present in the JAAS configuration or
* if the JAAS config file does not exist
*/
public JAASAuthenticationModule(String loginContextName, boolean allowUserToSpecifyName)
throws IllegalArgumentException {
public JAASAuthenticationModule(String loginContextName, boolean allowUserToSpecifyName,
File jaasConfigFile) throws IllegalArgumentException {
this.loginContextName = loginContextName;
this.allowUserToSpecifyName = allowUserToSpecifyName;
this.jaasConfigFile = jaasConfigFile;
Configuration cfg = Configuration.getConfiguration();
if (jaasConfigFile == null) {
throw new IllegalArgumentException("JAAS config file not specified");
}
if (!jaasConfigFile.exists() || !jaasConfigFile.isFile()) {
throw new IllegalArgumentException("JAAS config file does not exist or is not file: " +
jaasConfigFile.getAbsolutePath());
}
// force early check for valid config file
getJAASConfig();
}
private Configuration getJAASConfig() {
try {
URI jaasConfigFileUri = jaasConfigFile.toURI();
Configuration cfg =
Configuration.getInstance("JavaLoginConfig", new URIParameter(jaasConfigFileUri));
AppConfigurationEntry[] authEntry = cfg.getAppConfigurationEntry(loginContextName);
if (authEntry == null) {
throw new IllegalArgumentException(
"Missing '" + loginContextName + "' entry in JAAS config file");
throw new IllegalArgumentException("Missing '" + loginContextName +
"' entry in JAAS config file: " + jaasConfigFile);
}
return cfg;
}
catch (NoSuchAlgorithmException e) {
throw new RuntimeException("JAAS config error", e);
}
}
@ -70,14 +99,20 @@ public class JAASAuthenticationModule implements AuthenticationModule {
throws LoginException {
GhidraPrincipal principal = GhidraPrincipal.getGhidraPrincipal(subject);
AtomicReference<String> loginName = new AtomicReference<>();
LoginContext loginCtx = new LoginContext(loginContextName, loginModuleCallbacks -> {
loginName.set(copyCallbackValues(callbacks, loginModuleCallbacks, principal));
});
try {
Configuration jaasCfg = getJAASConfig();
LoginContext loginCtx =
new LoginContext(loginContextName, null, loginModuleCallbacks -> {
loginName.set(copyCallbackValues(callbacks, loginModuleCallbacks, principal));
}, jaasCfg);
// this is where the callback is triggered
loginCtx.login();
}
catch (IllegalArgumentException e) {
throw new LoginException("JAAS configuration error: " + e.getMessage());
}
catch (LoginException e) {
// Convert plain LoginExceptions to FailedLoginExceptions to enable
// the client to retry the login if desired.

View file

@ -55,7 +55,7 @@ public class GhidraServerAWTTest extends AbstractGenericTest {
// directly instantiate to avoid GhidraServer.main which may
// invoke System.exit
GhidraServer server = new GhidraServer(myTmpDir, GhidraServer.AuthMode.NO_AUTH_LOGIN,
null, true, true, -1, true, false);
null, true, true, -1, true, false, null);
// exercise server elements, including a repository and buffer file
RepositoryManager mgr = (RepositoryManager) getInstanceField("mgr", server);

View file

@ -40,8 +40,8 @@ example_ad_ldap_auth {
// JPAM is not included in the Ghidra distro. See http://jpam.sourceforge.net/.
//
// Additionally:
// the libjpam.so native library needs to be copied to your <ghidra>/server/os/[linux|linux64] directory.
// the JPAM-x.y.jar java library needs to be copied to your <ghidra>/server/lib directory.
// the libjpam.so native library needs to be copied to your Ghidra/Features/GhidraServer/os/linux64 directory.
// the JPAM-x.y.jar java library needs to be copied to your Ghidra/Features/GhidraServer/lib directory.
example_jpam_auth {
net.sf.jpam.jaas.JpamLoginModule REQUIRED
@ -62,7 +62,7 @@ example_external_auth {
ghidra.server.security.loginmodule.ExternalProgramLoginModule REQUIRED
// Path to the external program. An absolute path is preferable.
PROGRAM="server/jaas/jaas_external_program.example.sh"
PROGRAM="server/jaas_external_program.example.sh"
// Time to wait for external program to finish before killing it, in milliseconds.
TIMEOUT="1000"

View file

@ -132,17 +132,16 @@ ghidra.repositories.dir=./repositories
#
# -jaas <config_file> : specifies the path to the JAAS config file (when using -a4), relative
# to the ghidra/server directory (if not absolute).
# See jaas/jaas.conf for examples and suggestions.
# See jaas.conf for examples and suggestions.
# It is the system administrator's responsibility to craft their own
# JAAS configuration directive when using the -a4 mode.
#
# -u : enable users to be prompted for user ID (does not apply to -a2 PKI mode)
#
# -autoProvision : enable the auto-creation of Ghidra users when the authenticator module
# (ie. OS or other authentication method specified by JAAS) authenticates
# a new unknown user.
# Users deleted in the OS or other source system will need to be
# deleted manually from the Ghidra system.
# -autoProvision : enable the auto-creation of new Ghidra Server
# users when they successfully authenticate to the server (-a1 and -a4 modes only).
# Users removed from the authentication provider (e.g., Active Directory) will need to be
# deleted manually from the Ghidra Server using svrAdmin command.
#
# -anonymous : enables anonymous repository access (see svrREADME.html for details)
#

View file

@ -259,7 +259,7 @@ The Ghidra Server has been designed to support many possible user authenticatio
<LI><u>JAAS - Java Authentication and Authorization Service (<typewriter>-a4</typewriter>)</u> -
user authentication is delegated to the JAAS subsystem. The -jaas &lt;config_file&gt; argument
is required to specify the JAAS config file. There is an example config file in the GhidraServer
directory called jaas/jaas.conf.
directory called jaas.conf.
<p>
JAAS is architected similar to Linux/Unix PAM, where a named authentication configuration is possibly
composed of several different modules. Ghidra's support of JAAS only handles single simple
@ -280,7 +280,7 @@ The Ghidra Server has been designed to support many possible user authenticatio
of successful authentication.
<p>
There is an example (and non-useful) implementation of an external authenticator in the GhidraServer
directory called jaas/jaas_external_program.example.sh.
directory called jaas_external_program.example.sh.
<p>
This login module strives to be compatible with Apache's mod_authnz_external API, and you should
be able to use any mod_authnz_external authenticator with Ghidra.
@ -367,17 +367,17 @@ public key files may be made without restarting the Ghidra Server.
<LI><typewriter>-jaas &lt;config_file&gt;</typewriter><br>Specifies the path to the JAAS
config file (when using -a4), relative to the ghidra/server directory (if not absolute).
<p>
See jaas/jaas.conf for examples and suggestions. It is the system administrator's
See jaas.conf for examples and suggestions. It is the system administrator's
responsibility to craft their own JAAS configuration directive when using the -a4 mode.</LI>
<br>
<LI><typewriter>-u</typewriter><br>Allows the server login user ID to be specified at time of
login for <typewriter>-a0</typewriter> authentication mode. Without this option, the users
client-side login ID will be assumed.</LI>
<br>
<LI><typewriter>-autoProvision</typewriter><br>Enable the auto-creation of Ghidra users when
the authenticator module (ie. OS or other authentication method specified by JAAS) authenticates
a new unknown user. Users deleted in the OS or other source system will need to be deleted
manually from the Ghidra system.</LI>
<LI><typewriter>-autoProvision</typewriter><br>Enable the auto-creation of new Ghidra Server
users when they successfully authenticate to the server (-a1 and -a4 modes only).
Users removed from the authentication provider (e.g., Active Directory) will need to be
deleted manually from the Ghidra Server using svrAdmin command.</LI>
<br>
<LI><typewriter>-anonymous</typewriter><br>Enable anonymous access support for Ghidra Server
and its repositories. Only those repositories which specifically enable anonymous access will be

View file

@ -1,7 +1,7 @@
##VERSION: 2.0
##MODULE IP: Copyright Distribution Permitted
Common/server/jaas/jaas.conf||GHIDRA||||END|
Common/server/jaas/jaas_external_program.example.sh||GHIDRA||||END|
Common/server/jaas.conf||GHIDRA||||END|
Common/server/jaas_external_program.example.sh||GHIDRA||||END|
Common/server/server.conf||GHIDRA||||END|
Common/server/svrREADME.html||GHIDRA||||END|
Common/support/analyzeHeadlessREADME.html||GHIDRA||||END|