GT-2658 JAAS tweaks, javadoc, docs.

This commit is contained in:
dev747368 2019-09-05 12:59:49 -04:00
parent 220c3ff8d2
commit eff84e30d6
20 changed files with 412 additions and 305 deletions

View file

@ -25,6 +25,7 @@ import ghidra.framework.Application;
import ghidra.framework.Platform; import ghidra.framework.Platform;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
import ghidra.util.timer.Watchdog;
import utilities.util.FileUtilities; import utilities.util.FileUtilities;
/** /**
@ -296,7 +297,7 @@ class DmgServerProcessManager implements Closeable {
String pathValue = getLibraryPathVariable("PATH", ""); String pathValue = getLibraryPathVariable("PATH", "");
String ldLibraryPathValue = getLibraryPathVariable("LD_LIBRARY_PATH", ""); String ldLibraryPathValue = getLibraryPathVariable("LD_LIBRARY_PATH", "");
List<String> argList = new ArrayList<String>(); List<String> argList = new ArrayList<>();
Map<String, String> env = System.getenv(); Map<String, String> env = System.getenv();
Set<Entry<String, String>> entrySet = env.entrySet(); Set<Entry<String, String>> entrySet = env.entrySet();
for (Entry<String, String> entry : entrySet) { for (Entry<String, String> entry : entrySet) {
@ -321,7 +322,7 @@ class DmgServerProcessManager implements Closeable {
} }
private String getLibraryPathVariable(String pathKey, String pathValue) { private String getLibraryPathVariable(String pathKey, String pathValue) {
Set<String> libraryPaths = new HashSet<String>(); Set<String> libraryPaths = new HashSet<>();
addOSPaths(libraryPaths); addOSPaths(libraryPaths);
StringBuffer buffy = new StringBuffer(); StringBuffer buffy = new StringBuffer();

View file

@ -1,107 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.file.formats.ios.dmg;
import ghidra.util.Msg;
import ghidra.util.timer.GTimer;
import ghidra.util.timer.GTimerMonitor;
import java.io.Closeable;
import java.util.concurrent.atomic.AtomicLong;
/**
* A reusable watchdog that will execute a callback if the watchdog is not disarmed before
* it expires.
*
*/
public class Watchdog implements Closeable {
private long defaultWatchdogTimeoutMS;
private AtomicLong watchdogExpiresAt = new AtomicLong();
private Runnable timeoutMethod;
private GTimerMonitor watchdogTimer;
/**
* Creates a watchdog (initially disarmed) that will poll for expiration every
* defaultTimeoutMS milliseconds, calling {@code timeoutMethod} when triggered.
* <p>
* @param defaultTimeoutMS number of milliseconds that the watchdog will wait after
* being armed before calling the timeout method.
* @param timeoutMethod {@link Runnable} functional callback.
*/
public Watchdog(long defaultTimeoutMS, Runnable timeoutMethod) {
this.defaultWatchdogTimeoutMS = defaultTimeoutMS;
this.timeoutMethod = timeoutMethod;
this.watchdogTimer = GTimer.scheduleRepeatingRunnable(defaultTimeoutMS, defaultTimeoutMS,
this::watchdogWorker);
}
@Override
public void finalize() {
if (watchdogTimer != null) {
close();
Msg.warn(this, "Unclosed Watchdog");
}
}
/**
* Releases the background timer that this watchdog uses.
*/
@Override
public void close() {
if (watchdogTimer != null) {
watchdogTimer.cancel();
}
watchdogTimer = null;
timeoutMethod = null;
}
/**
* Called from a timer, checks to see if the watchdog is armed, and if it has expired.
* <p>
* Disarms itself before calling the timeoutMethod if the timeout period expired.
*/
private void watchdogWorker() {
long expiresAt = watchdogExpiresAt.get();
if (expiresAt > 0) {
long now = System.currentTimeMillis();
if (now > expiresAt) {
setEnabled(false);
timeoutMethod.run();
}
}
}
private void setEnabled(boolean b) {
watchdogExpiresAt.set(b ? System.currentTimeMillis() + defaultWatchdogTimeoutMS : -1);
}
/**
* Enables this watchdog so that at {@link #defaultWatchdogTimeoutMS} milliseconds in the
* future the {@link #timeoutMethod} will be called.
*/
public void arm() {
setEnabled(true);
}
/**
* Disables this watchdog.
*/
public void disarm() {
setEnabled(false);
}
}

View file

@ -5,4 +5,6 @@
Module.manifest||GHIDRA||||END| Module.manifest||GHIDRA||||END|
build.gradle||GHIDRA||||END| build.gradle||GHIDRA||||END|
data/jaas-modules-src-1.0.3.zip||LGPL 2.1|||File corresponds to original distribution with all binary product files removed.|END| data/jaas-modules-src-1.0.3.zip||LGPL 2.1|||File corresponds to original distribution with all binary product files removed.|END|
data/lib/readme.txt||GHIDRA||||END|
data/os/readme.txt||GHIDRA||||END|
src/main/java/ghidra/server/remote/ServerHelp.txt||GHIDRA||||END| src/main/java/ghidra/server/remote/ServerHelp.txt||GHIDRA||||END|

View file

@ -15,7 +15,7 @@
*/ */
package ghidra.server.remote; package ghidra.server.remote;
import static ghidra.server.remote.GhidraServer.AUTH_MODE.*; import static ghidra.server.remote.GhidraServer.AuthMode.*;
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
@ -75,23 +75,21 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
private static String HELP_FILE = "/ghidra/server/remote/ServerHelp.txt"; private static String HELP_FILE = "/ghidra/server/remote/ServerHelp.txt";
private static String USAGE_ARGS = private static String USAGE_ARGS =
" [-p<port>] [-a<authMode>] [-d<domain>] [-u] [-anonymous] [-ssh] [-ip <hostname>] [-i <ipAddress>] [-e<expireDays>] [-jaas <path>] [-autoProvision] [-n] <serverPath>"; "[-ip <hostname>] [-i #.#.#.#] [-p#] [-n] [-a#] [-d<ad_domain>] [-e<days>] [-jaas <config_file>] [-u] [-autoProvision] [-anonymous] [-ssh] <repository_path>";
private static final String RMI_SERVER_PROPERTY = "java.rmi.server.hostname"; private static final String RMI_SERVER_PROPERTY = "java.rmi.server.hostname";
public enum AUTH_MODE { enum AuthMode {
NO_AUTH_LOGIN("None"), NO_AUTH_LOGIN("None"),
PASSWORD_FILE_LOGIN("Password File"), PASSWORD_FILE_LOGIN("Password File"),
OS_PASSWORD_LOGIN("OS Password"), KRB5_AD_LOGIN("Active Directory via Kerberos"),
PKI_LOGIN("PKI"), PKI_LOGIN("PKI"),
ALT_OS_PASSWORD_LOGIN("OS Password & Password File"), JAAS_LOGIN("JAAS");
JAAS_LOGIN("JAAS"),
KRB5_AD_LOGIN("Active Directory via Kerberos");
private String description; private String description;
AUTH_MODE(String description) { AuthMode(String description) {
this.description = description; this.description = description;
} }
@ -99,15 +97,13 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
return description; return description;
} }
public static AUTH_MODE fromIndex(int index) { public static AuthMode fromIndex(int index) {
//@formatter:off //@formatter:off
switch ( index) { switch ( index) {
case 0: return PASSWORD_FILE_LOGIN; case 0: return PASSWORD_FILE_LOGIN;
case 1: return OS_PASSWORD_LOGIN; case 1: return KRB5_AD_LOGIN;
case 2: return PKI_LOGIN; case 2: return PKI_LOGIN;
case 3: return ALT_OS_PASSWORD_LOGIN;
case 4: return JAAS_LOGIN; case 4: return JAAS_LOGIN;
case 5: return KRB5_AD_LOGIN;
default: return null; default: return null;
} }
//@formatter:on //@formatter:on
@ -141,7 +137,7 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
* authenticated users to the user manager if they don't already exist * authenticated users to the user manager if they don't already exist
* @throws IOException * @throws IOException
*/ */
GhidraServer(File rootDir, AUTH_MODE authMode, String loginDomain, GhidraServer(File rootDir, AuthMode authMode, String loginDomain,
boolean allowUserToSpecifyName, boolean altSSHLoginAllowed, boolean allowUserToSpecifyName, boolean altSSHLoginAllowed,
int defaultPasswordExpirationDays, boolean allowAnonymousAccess, int defaultPasswordExpirationDays, boolean allowAnonymousAccess,
boolean autoProvisionAuthedUsers) throws IOException, CertificateException { boolean autoProvisionAuthedUsers) throws IOException, CertificateException {
@ -187,7 +183,7 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
break; break;
case KRB5_AD_LOGIN: case KRB5_AD_LOGIN:
if (loginDomain == null || loginDomain.isBlank()) { if (loginDomain == null || loginDomain.isBlank()) {
throw new IllegalArgumentException("Missing login domain value -d<domainname>"); throw new IllegalArgumentException("Missing login domain value -d<ad_domain>");
} }
authModule = new Krb5ActiveDirectoryAuthenticationModule(loginDomain, authModule = new Krb5ActiveDirectoryAuthenticationModule(loginDomain,
allowUserToSpecifyName); allowUserToSpecifyName);
@ -196,11 +192,6 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
throw new IllegalArgumentException("Unsupported Authentication mode: " + authMode); throw new IllegalArgumentException("Unsupported Authentication mode: " + authMode);
} }
if (authModule != null) {
// allow the auth modules to verify their configuration state before continuing
authModule.ensureConfig();
}
if (altSSHLoginAllowed) { if (altSSHLoginAllowed) {
SecureRandomFactory.getSecureRandom(); // incur initialization delay up-front SecureRandomFactory.getSecureRandom(); // incur initialization delay up-front
sshAuthModule = new SSHAuthenticationModule(allowUserToSpecifyName); sshAuthModule = new SSHAuthenticationModule(allowUserToSpecifyName);
@ -338,7 +329,7 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
} }
} }
else { else {
throw new LoginException( throw new FailedLoginException(
"User successfully authenticated, but does not exist in Ghidra user list: " + "User successfully authenticated, but does not exist in Ghidra user list: " +
username); username);
} }
@ -480,6 +471,23 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
return hostname; return hostname;
} }
private static File getServerCfgFile(String cfgFileName) {
File tmp = new File(cfgFileName);
if (tmp.isAbsolute()) {
return tmp;
}
ResourceFile serverRoot = new ResourceFile(Application.getInstallationDirectory(),
SystemUtilities.isInDevelopmentMode() ? "ghidra/Ghidra/RuntimeScripts/Common/server"
: "ghidra/server");
if (serverRoot == null || serverRoot.getFile(false) == null) {
System.err.println(
"Failed to resolve installation root directory!: " + serverRoot.getAbsolutePath());
System.exit(-1);
}
return new File(serverRoot.getFile(false), cfgFileName);
}
/** /**
* Main method for starting the Ghidra server. * Main method for starting the Ghidra server.
* *
@ -501,7 +509,7 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
} }
int basePort = DEFAULT_PORT; int basePort = DEFAULT_PORT;
AUTH_MODE authMode = NO_AUTH_LOGIN; AuthMode authMode = NO_AUTH_LOGIN;
boolean nameCallbackAllowed = false; boolean nameCallbackAllowed = false;
boolean altSSHLoginAllowed = false; boolean altSSHLoginAllowed = false;
boolean allowAnonymousAccess = false; boolean allowAnonymousAccess = false;
@ -509,6 +517,7 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
String rootPath = null; String rootPath = null;
int defaultPasswordExpiration = -1; int defaultPasswordExpiration = -1;
boolean autoProvision = false; boolean autoProvision = false;
String jaasConfigFileStr = null;
// Network name resolution disabled by default // Network name resolution disabled by default
InetNameLookup.setLookupEnabled(false); InetNameLookup.setLookupEnabled(false);
@ -538,7 +547,7 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
System.exit(-1); System.exit(-1);
} }
authMode = AUTH_MODE.fromIndex(authModeNum); authMode = AuthMode.fromIndex(authModeNum);
if (authMode == null) { if (authMode == null) {
displayUsage("Invalid authentication mode: " + s); displayUsage("Invalid authentication mode: " + s);
@ -620,16 +629,8 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
displayUsage("Missing -jaas config file path argument"); displayUsage("Missing -jaas config file path argument");
System.exit(-1); System.exit(-1);
} }
String jaasConfigFileStr = args[nextArgIndex]; jaasConfigFileStr = args[nextArgIndex];
i++; i++;
File jaasConfigFile = new File(jaasConfigFileStr);
if (!jaasConfigFile.exists() || !jaasConfigFile.isFile()) {
displayUsage("JAAS config file does not exist or is not file: " +
(new File("./").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", "=" + jaasConfigFileStr);
} }
else if (s.equals("-autoProvision")) { else if (s.equals("-autoProvision")) {
autoProvision = true; autoProvision = true;
@ -670,6 +671,23 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
serverRoot = new File(installRoot.getFile(false), rootPath); serverRoot = new File(installRoot.getFile(false), rootPath);
} }
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()) {
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 { try {
serverRoot = serverRoot.getCanonicalFile(); serverRoot = serverRoot.getCanonicalFile();
} }

View file

@ -1,9 +1,10 @@
Ghidra server startup parameters. Ghidra server startup parameters.
Command line parameters: Command line parameters:
[-ip <hostname>] [-i #.#.#.#] [-p#] [-n] [-ip <hostname>] [-i #.#.#.#] [-p#] [-n]
[-a#] [-d<ntDomain>] [-e<days>] [-u] [-jaas <path_to_jaas_config_file>] [-autoProvision] [-a#] [-d<ad_domain>] [-e<days>] [-jaas <config_file>] [-u] [-autoProvision] [-anonymous] [-ssh]
<repository_path> <repository_path>
-ip <hostname> : identifies the remote access IPv4 address or hostname (FQDN) which should be -ip <hostname> : identifies the remote access IPv4 address or hostname (FQDN) which should be
used by remote clients to access the server. used by remote clients to access the server.
@ -11,30 +12,38 @@ Command line parameters:
-p# : base TCP port to be used (default: 13100) [see Note 1] -p# : base TCP port to be used (default: 13100) [see Note 1]
-a# : an optional authentication mode where # is a value of 0, 2, 4, or 5 -n : enable reverse name lookup for IP addresses when logging (requires proper configuration
of reverse lookup by your DNS server)
-a# : an optional authentication mode where # is a value of 0, 1, 2, or 4
0 - Private user password 0 - Private user password
1 - Active Directory via Kerberos. Requires -d<your.ad_domainname.tld>
2 - PKI Authentication 2 - PKI Authentication
4 - JAAS Authentication controlled by config file pointed to by -jaas 4 - JAAS Authentication. See also -jaas <config_file>
5 - Active Directory via Kerberos. Requires -d<active_directory_domainname.tld>
-d<ad_domain> : the Active Directory domain name. Example: "-dmydomain.com"
-e<days> : specifies default password expiration time in days (-a0 mode only, default is 1-day)
-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.
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.
-anonymous : enables anonymous repository access (see svrREADME.html for details) -anonymous : enables anonymous repository access (see svrREADME.html for details)
-ssh : enables SSH authentication for headless clients -ssh : enables SSH authentication for headless clients
-e<days> : specifies default password expiration time in days (-a0 mode only, default is 1-day) <repository_path> : Required. Directory used to store repositories. This directory must be dedicated to this
-u : enable users to be prompted for user ID (does not apply to -a2 PKI mode)
-jaas /path/to/jaas_config_file : specifies config file to use for JAAS (enabled by -a4)
-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.
-n : enable reverse name lookup for IP addresses when logging (requires proper configuration
of reverse lookup by your DNS server)
<repository_path> : directory used to store repositories. This directory must be dedicated to this
Ghidra Server instance and may not contain files or folders not produced Ghidra Server instance and may not contain files or folders not produced
by the Ghidra Server or its administrative scripts. by the Ghidra Server or its administrative scripts.
Relative paths originate from the installation directory Relative paths originate from the installation directory
@ -48,10 +57,4 @@ NOTES:
base port (default: 13100). The wrapper.log can be examined for server base port (default: 13100). The wrapper.log can be examined for server
console output which will indicate the startup port assignments. console output which will indicate the startup port assignments.
2. Ghidra's JAAS authentication mode uses the "auth" section of the JAAS file pointed to by the -jaas
argument.
3. Example JAAS config files are included in the /server/jaas directory of the Ghidra distro. It is the
system administrator's responsibility to create the necessary JAAS config for their system.

View file

@ -17,6 +17,7 @@ package ghidra.server.security;
import javax.security.auth.Subject; import javax.security.auth.Subject;
import javax.security.auth.callback.*; import javax.security.auth.callback.*;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginException; import javax.security.auth.login.LoginException;
import ghidra.server.UserManager; import ghidra.server.UserManager;
@ -26,10 +27,6 @@ public interface AuthenticationModule {
public static final String USERNAME_CALLBACK_PROMPT = "User ID"; public static final String USERNAME_CALLBACK_PROMPT = "User ID";
public static final String PASSWORD_CALLBACK_PROMPT = "Password"; public static final String PASSWORD_CALLBACK_PROMPT = "Password";
default void ensureConfig() {
// default nothing
}
/** /**
* Complete the authentication process. * Complete the authentication process.
* <p> * <p>
@ -42,13 +39,13 @@ public interface AuthenticationModule {
* the ones your module specified in its {@link #getAuthenticationCallbacks()}</li> * the ones your module specified in its {@link #getAuthenticationCallbacks()}</li>
* </ul> * </ul>
* <p> * <p>
*
* <p>
* @param userMgr Ghidra server user manager * @param userMgr Ghidra server user manager
* @param subject unauthenticated user ID (must be used if name callback not provided/allowed) * @param subject unauthenticated user ID (must be used if name callback not provided/allowed)
* @param callbacks authentication callbacks * @param callbacks authentication callbacks
* @return authenticated user ID (may come from callbacks) * @return authenticated user ID (may come from callbacks)
* @throws LoginException * @throws LoginException if error during login. Client should not retry authentication
* @throws FailedLoginException if authentication was unsuccessful. Client may
* retry authentication
*/ */
String authenticate(UserManager userMgr, Subject subject, Callback[] callbacks) String authenticate(UserManager userMgr, Subject subject, Callback[] callbacks)
throws LoginException; throws LoginException;
@ -59,7 +56,7 @@ public interface AuthenticationModule {
Callback[] getAuthenticationCallbacks(); Callback[] getAuthenticationCallbacks();
/** /**
* Allows an AuthenticationModule to deny default anonymous login steps. * Allows this AuthenticationModule to deny default anonymous login steps.
* <p> * <p>
* @return true if a separate AnonymousCallback is allowed and may be * @return true if a separate AnonymousCallback is allowed and may be
* added to the array returned by getAuthenticationCallbacks. * added to the array returned by getAuthenticationCallbacks.
@ -72,6 +69,12 @@ public interface AuthenticationModule {
*/ */
boolean isNameCallbackAllowed(); boolean isNameCallbackAllowed();
/**
* Creates a standard pair of name and password callback instances.
*
* @param allowUserToSpecifyName boolean flag, if false, a name callback is not added to the results
* @return an array of callbacks
*/
static Callback[] createSimpleNamePasswordCallbacks(boolean allowUserToSpecifyName) { static Callback[] createSimpleNamePasswordCallbacks(boolean allowUserToSpecifyName) {
PasswordCallback passCb = new PasswordCallback(PASSWORD_CALLBACK_PROMPT + ":", false); PasswordCallback passCb = new PasswordCallback(PASSWORD_CALLBACK_PROMPT + ":", false);
if (allowUserToSpecifyName) { if (allowUserToSpecifyName) {
@ -81,23 +84,25 @@ public interface AuthenticationModule {
return new Callback[] { passCb }; return new Callback[] { passCb };
} }
/**
* Find the first callback of a specific type in the list and returns it.
*
* @param <T> the type of callback
* @param callbackClass the callback class (ie. Namecallback.class)
* @param callbackArray array of callbacks to search
* @return callback instance that is of type T, or null if not found
*/
static <T extends Callback> T getFirstCallbackOfType(Class<T> callbackClass, static <T extends Callback> T getFirstCallbackOfType(Class<T> callbackClass,
Callback[] callbackArray) { Callback[] callbackArray) {
if (callbackArray == null) { if (callbackArray == null) {
return null; return null;
} }
// dunno if this approach is warranted. the second loop with its isInstance() may be fine.
for (Callback cb : callbackArray) { for (Callback cb : callbackArray) {
if (callbackClass == cb.getClass()) { if (callbackClass == cb.getClass()) {
return callbackClass.cast(cb); return callbackClass.cast(cb);
} }
} }
for (Callback cb : callbackArray) {
if (callbackClass.isInstance(cb.getClass())) {
return callbackClass.cast(cb);
}
}
return null; return null;
} }
} }

View file

@ -20,8 +20,7 @@ import java.util.concurrent.atomic.AtomicReference;
import javax.security.auth.Subject; import javax.security.auth.Subject;
import javax.security.auth.callback.*; import javax.security.auth.callback.*;
import javax.security.auth.login.LoginContext; import javax.security.auth.login.*;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule; import javax.security.auth.spi.LoginModule;
import ghidra.framework.remote.GhidraPrincipal; import ghidra.framework.remote.GhidraPrincipal;
@ -44,9 +43,26 @@ public class JAASAuthenticationModule implements AuthenticationModule {
private boolean allowUserToSpecifyName; private boolean allowUserToSpecifyName;
private String loginContextName; private String loginContextName;
public JAASAuthenticationModule(String loginContextName, boolean allowUserToSpecifyName) { /**
* Creates a new {@link JAASAuthenticationModule} instance.
*
* @param loginContextName the name of the configuration entry from the JAAS config to use
* @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
*/
public JAASAuthenticationModule(String loginContextName, boolean allowUserToSpecifyName)
throws IllegalArgumentException {
this.loginContextName = loginContextName; this.loginContextName = loginContextName;
this.allowUserToSpecifyName = allowUserToSpecifyName; this.allowUserToSpecifyName = allowUserToSpecifyName;
Configuration cfg = Configuration.getConfiguration();
AppConfigurationEntry[] authEntry = cfg.getAppConfigurationEntry(loginContextName);
if (authEntry == null) {
throw new IllegalArgumentException(
"Missing '" + loginContextName + "' entry in JAAS config file");
}
} }
@Override @Override
@ -58,8 +74,18 @@ public class JAASAuthenticationModule implements AuthenticationModule {
loginName.set(copyCallbackValues(callbacks, loginModuleCallbacks, principal)); loginName.set(copyCallbackValues(callbacks, loginModuleCallbacks, principal));
}); });
try {
// this is where the callback is triggered // this is where the callback is triggered
loginCtx.login(); loginCtx.login();
}
catch (LoginException e) {
// Convert plain LoginExceptions to FailedLoginExceptions to enable
// the client to retry the login if desired.
if (e instanceof FailedLoginException) {
throw e;
}
throw new FailedLoginException(e.getMessage());
}
String loginNameResult = loginName.get(); String loginNameResult = loginName.get();
return (loginNameResult != null) ? loginNameResult : principal.getName(); return (loginNameResult != null) ? loginNameResult : principal.getName();

View file

@ -40,6 +40,9 @@ import ghidra.server.UserManager;
* This auth module needs to know the Active Directory domain name, and then from there it can bootstrap * This auth module needs to know the Active Directory domain name, and then from there it can bootstrap
* itself using DNS lookups to find the Kerberos server. * itself using DNS lookups to find the Kerberos server.
* <p> * <p>
* As this class sets some global Kerberos system properties, only one copy of this class should
* be active in a JVM at a time.
*
*/ */
public class Krb5ActiveDirectoryAuthenticationModule implements AuthenticationModule { public class Krb5ActiveDirectoryAuthenticationModule implements AuthenticationModule {
@ -47,14 +50,22 @@ public class Krb5ActiveDirectoryAuthenticationModule implements AuthenticationMo
private String domainName; private String domainName;
private boolean stripDomainFromUsername = true; private boolean stripDomainFromUsername = true;
/**
* Creates a new {@link Krb5ActiveDirectoryAuthenticationModule} instance.
* <p>
*
* @param domainName the Active Directory domain name (ie. "yourdomain.tld")
* @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 domainName is null or blank, or if the Microsoft
* Active Directory domain controller can not be looked-up in DNS.
*/
public Krb5ActiveDirectoryAuthenticationModule(String domainName, public Krb5ActiveDirectoryAuthenticationModule(String domainName,
boolean allowUserToSpecifyName) { boolean allowUserToSpecifyName) throws IllegalArgumentException {
this.domainName = domainName; this.domainName = domainName;
this.allowUserToSpecifyName = allowUserToSpecifyName; this.allowUserToSpecifyName = allowUserToSpecifyName;
}
@Override
public void ensureConfig() {
if (domainName == null || domainName.isBlank()) { if (domainName == null || domainName.isBlank()) {
throw new IllegalArgumentException("Missing domain name"); throw new IllegalArgumentException("Missing domain name");
} }
@ -115,7 +126,18 @@ public class Krb5ActiveDirectoryAuthenticationModule implements AuthenticationMo
userName.set(tmpName); userName.set(tmpName);
}, new JAASConfiguration("com.sun.security.auth.module.Krb5LoginModule")); }, new JAASConfiguration("com.sun.security.auth.module.Krb5LoginModule"));
try {
lc.login(); lc.login();
}
catch (LoginException e) {
// Convert plain LoginExceptions to FailedLoginExceptions to enable
// the client to retry the login if desired.
if (e instanceof FailedLoginException) {
throw e;
}
throw new FailedLoginException(e.getMessage());
}
return userName.get(); return userName.get();
} }

View file

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

View file

@ -87,6 +87,11 @@ public class Watchdog implements Closeable {
watchdogExpiresAt.set(b ? System.currentTimeMillis() + defaultWatchdogTimeoutMS : -1); watchdogExpiresAt.set(b ? System.currentTimeMillis() + defaultWatchdogTimeoutMS : -1);
} }
/**
* Returns the status of the watchdog.
*
* @return true if the watchdog is armed, false if the watchdog is disarmed
*/
public boolean isEnabled() { public boolean isEnabled() {
return watchdogExpiresAt.get() > 0; return watchdogExpiresAt.get() > 0;
} }

View file

@ -1216,10 +1216,26 @@ public final class FileUtilities {
Desktop.getDesktop().open(file); Desktop.getDesktop().open(file);
} }
/**
* Processes each text line in a text file, in a separate thread.
* <p>
* Thread exits when EOF is reached.
*
* @param is {@link InputStream} to read
* @param consumer code that will process each text of the text file.
*/
public static void asyncForEachLine(InputStream is, Consumer<String> consumer) { public static void asyncForEachLine(InputStream is, Consumer<String> consumer) {
asyncForEachLine(new BufferedReader(new InputStreamReader(is)), consumer); asyncForEachLine(new BufferedReader(new InputStreamReader(is)), consumer);
} }
/**
* Processes each text line in a text file, in a separate thread.
* <p>
* Thread exits when EOF is reached.
*
* @param reader {@link BufferedReader} to read
* @param consumer code that will process each text of the text file.
*/
public static void asyncForEachLine(BufferedReader reader, Consumer<String> consumer) { public static void asyncForEachLine(BufferedReader reader, Consumer<String> consumer) {
new Thread(() -> { new Thread(() -> {
try { try {

View file

@ -0,0 +1,76 @@
//
// JAAS config file for GhidraServer when operating in -a4 mode.
// Only the one section that you wish to enable should be called "auth".
// All other sections will be ignored.
//**********************************************************************************
// Active Directory via LDAP
//**********************************************************************************
// The special string "{USERNAME}" in the authIdentity and userFilter parameters is replaced with the Ghidra user's name
// at runtime by the LdapLoginModule, and should not be modified.
//
// The ldap DNS hostname for your Active Directory server needs to be fixed-up in the userProvider parameter,
// and the domain name portion of your user's identity (ie. user@domain.tld) needs to be fixed up in the
// authIdentity parameter, possibly the port number also (3269).
//
// In this mode, GhidraServer will bind to the LDAP server using the Ghidra user's name and password. It will
// then query for that same user (sAMAccountName={USERNAME}) to confirm that user's DN.
//
// See https://docs.oracle.com/javase/8/docs/jre/api/security/jaas/spec/com/sun/security/auth/module/LdapLoginModule.html
// for more information about the LdapLoginModule and its configuration.
//
// Do not use a plain "ldap" URI to connect to your LDAP server unless you want your user's
// credentials to be visible as plaintext network traffic.
//
example_ad_ldap_auth {
com.sun.security.auth.module.LdapLoginModule REQUIRED
userProvider="ldaps://<your_active_directory_ldap_server_hostname>:3269"
authIdentity="{USERNAME}@<your_active_directory_domain_name.tld>"
userFilter="(sAMAccountName={USERNAME})"
debug=true;
};
//**********************************************************************************
// JPAM
//**********************************************************************************
// 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.
example_jpam_auth {
net.sf.jpam.jaas.JpamLoginModule REQUIRED
// The serviceName parameter controls which PAM service Ghidra will try to authenticate against.
// This typically corresponds to a file called /etc/pam.d/<serviceName>
serviceName="system-auth"
;
};
//**********************************************************************************
// External program (ie. mod_authnz_external)
//**********************************************************************************
// Launches an external program to perform authentication.
//
// You may need to adjust the PROGRAM="" to include the full path to the example script
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"
// Time to wait for external program to finish before killing it, in milliseconds.
TIMEOUT="1000"
// Any arguments that the external program needs. Do not include sensitive values as an
// argument because they can be seen by other users on the system.
ARG_00="arg1" ARG_01="test arg2"
;
};

View file

@ -1,19 +0,0 @@
// Example JAAS config file for Ghidra server when operating in -a4 authmode.
// Ghidra only uses the "auth" section from the JAAS configuration.
// You may need to adjust the PROGRAM="" to include the full path to the example script
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"
// Time to wait for external program to finish before killing it, in milliseconds.
TIMEOUT="1000"
// any arguments that the external program needs. Do not include sensitive values as an
// argument as they can be seen by other users on the system.
ARG_00="arg1" ARG_01="test arg2"
;
};

View file

@ -1,14 +0,0 @@
// Example JAAS config file to use the local Linux PAM system when operating in -a4 authmode.
// JPAM is not included in the Ghidra distro.
// Additionally:
// the libjpam.so native library needs to be copied to your ${JAVA_HOME}/lib directory.
// the JPAM-x.y.jar java library needs to be inserted into the GhidraServer's classpath.
auth {
net.sf.jpam.jaas.JpamLoginModule required
// The serviceName parameter controls which PAM service Ghidra will try to authenticate against.
// This corresponds to a file called /etc/pam.d/<serviceName>
serviceName="system-auth"
;
};

View file

@ -1,22 +0,0 @@
// Example JAAS config file to use an Active Directory LDAP server to authenticate users when operating in -a4 authmode.
//
// The special string "{USERNAME}" in the authIdentity and userFilter parameters is replaced with the Ghidra user's name
// at runtime by the LdapLoginModule, and should not be modified.
//
// The ldap DNS hostname for your Active Directory server needs to be fixed-up in the userProvider parameter,
// and the domain name portion of your user's identity (ie. user@domain.tld) needs to be fixed up in the
// authIdentity parameter.
//
// In this mode, the Ghidra Server will bind to the LDAP server using the Ghidra user's name and password. It will
// then query for that same user (sAMAccountName={USERNAME}) to confirm that user's DN.
//
// See https://docs.oracle.com/javase/8/docs/jre/api/security/jaas/spec/com/sun/security/auth/module/LdapLoginModule.html
// for more information about the LdapLoginModule and its configuration.
//
auth {
com.sun.security.auth.module.LdapLoginModule REQUIRED
userProvider="ldaps://<your_active_directory_ldap_server_hostname>:3269"
authIdentity="{USERNAME}@<your_active_directory_domain_name.tld>"
userFilter="(sAMAccountName={USERNAME})"
debug=true;
};

View file

@ -106,26 +106,52 @@ ghidra.repositories.dir=./repositories
# Ghidra server startup parameters. # Ghidra server startup parameters.
# #
# Command line parameters: (Add command line parameters as needed and renumber each starting from .1) # Command line parameters: (Add command line parameters as needed and renumber each starting from .1)
# [-ip <hostname>] [-i ###.###.###.###] [-p#] [-a#] [-anonymous] [-ssh] [-d<ntDomain>] [-e<days>] [-u] [-jaas <config_file>] [-autoProvision] [-n] <repositories_path> # [-ip <hostname>] [-i #.#.#.#] [-p#] [-n]
# [-a#] [-d<ad_domain>] [-e<days>] [-jaas <config_file>] [-u] [-autoProvision] [-anonymous] [-ssh]
# <repository_path>
# #
# -ip <hostname> : remote access hostname or IPv4 address to be used by clients # -ip <hostname> : identifies the remote access IPv4 address or hostname (FQDN) which should be
# -i #.#.#.# : interface IPv4 address to accept connections on (default all interfaces) # used by remote clients to access the server.
# -p# : base TCP port to be used (default: 13100) #
# -a# : an optional authentication mode where # is a value of 0, 2, 4 or 5 # -i #.#.#.# : server interface IPv4 address to listen on (default will listen on all interfaces).
#
# -p# : base TCP port to be used (default: 13100) [see Note 1]
#
# -n : enable reverse name lookup for IP addresses when logging (requires proper configuration
# of reverse lookup by your DNS server)
#
# -a# : an optional authentication mode where # is a value of 0, 1, 2, or 4
# 0 - Private user password # 0 - Private user password
# 1 - Active Directory via Kerberos. Requires -d<your.ad_domainname.tld>
# 2 - PKI Authentication # 2 - PKI Authentication
# 4 - JAAS Authentication # 4 - JAAS Authentication. See also -jaas <config_file>
# 5 - Active Directory via Kerberos. Requires -d<active_directory_domainname.tld> #
# -anonymous : enables anonymous repository access (see svrREADME.html for details) # -d<ad_domain> : the Active Directory domain name. Example: "-dmydomain.com"
# -ssh : enables SSH authentication for headless clients #
# -e<days> : specifies default password expiration time in days (-a0 mode only, default is 1-day) # -e<days> : specifies default password expiration time in days (-a0 mode only, default is 1-day)
#
# -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.
# 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) # -u : enable users to be prompted for user ID (does not apply to -a2 PKI mode)
# -jaas <path_to_config_file> : specifies JAAS config file. #
# -autoProvision : enable the auto-creation of Ghidra users when the authenticator module # -autoProvision : enable the auto-creation of Ghidra users when the authenticator module
# (ie. OS or other authentication method specified by JAAS) authenticates # (ie. OS or other authentication method specified by JAAS) authenticates
# a new unknown user. # a new unknown user.
# -n : enable reverse name lookup for IP addresses when logging (requires proper configuration # Users deleted in the OS or other source system will need to be
# of reverse lookup by your DNS server) # deleted manually from the Ghidra system.
#
# -anonymous : enables anonymous repository access (see svrREADME.html for details)
#
# -ssh : enables SSH authentication for headless clients
#
# <repository_path> : Required. Directory used to store repositories. This directory must be dedicated to this
# Ghidra Server instance and may not contain files or folders not produced
# by the Ghidra Server or its administrative scripts.
# Relative paths originate from the installation directory
# ${ghidra.repositories.dir} : config variable (defined above) which identifies the directory # ${ghidra.repositories.dir} : config variable (defined above) which identifies the directory
# used to store repositories. Use of this variable to define the # used to store repositories. Use of this variable to define the
# repositories directory must be retained. # repositories directory must be retained.

View file

@ -219,7 +219,7 @@ the <a href="#serverOptions">Server Options</a> section for more details.
<P> <P>
The Ghidra Server has been designed to support many possible user authentication modes: The Ghidra Server has been designed to support many possible user authentication modes:
<OL> <UL>
<LI><u>No authentication</u> - any user which has been added to the server may connect without <LI><u>No authentication</u> - any user which has been added to the server may connect without
password or credentials.</LI> password or credentials.</LI>
<br> <br>
@ -230,29 +230,77 @@ The Ghidra Server has been designed to support many possible user authenticatio
first added or when the user is reset (see <a href="#serverAdministration">Server first added or when the user is reset (see <a href="#serverAdministration">Server
Administration</a>). This default password must be changed by the user to avoid its expiration.</LI> Administration</a>). This default password must be changed by the user to avoid its expiration.</LI>
<br> <br>
<LI><u>Active Directory via Kerberos (<typewriter>-a1</typewriter>)</u> - user authentication is
performed against your local Active Directory system using Kerberos to do so. The -d&lt;ad_domain&gt;
argument is required to specify the domain name of your Active Directory system.
<p>
It is also possible to authenticate against your Active Directory system using LDAP. See the
LDAP example when using JAAS -a4 mode.
</LI>
<br>
<LI><u>PKI authentication (<typewriter>-a2</typewriter>)</u> - user authentication is performed <LI><u>PKI authentication (<typewriter>-a2</typewriter>)</u> - user authentication is performed
using PKI user certificates. When using this mode, the distinguished name (DN) for each user using PKI user certificates. When using this mode, the distinguished name (DN) for each user
must be associated with each server User ID (see <a href="#serverAdministration">Server must be associated with each server User ID (see <a href="#serverAdministration">Server
Administration</a>). In addition, each user must configure Ghidra with the location of their Administration</a>). In addition, each user must configure Ghidra with the location of their
signing key/certificate keystore file (see <a href="#pkiCertificates">PKI Certificates</a> signing key/certificate keystore file (see <a href="#pkiCertificates">PKI Certificates</a>
for more information). for more information).
</LI> <p>
<br>
Please note that each user&apos;s certificate must be issued by a trusted certificate authority Please note that each user&apos;s certificate must be issued by a trusted certificate authority
which has been properly added to the Ghidra Server&apos;s <typewriter>cacerts</typewriter> file. See which has been properly added to the Ghidra Server&apos;s <typewriter>cacerts</typewriter> file. See
<a href="#pkiCertificateAuthorities">Managing PKI Certificate Authorities</a> for more information. <a href="#pkiCertificateAuthorities">Managing PKI Certificate Authorities</a> for more information.
<br><br> <p>
In an attempt to simplify the determination of user DN&apos;s, a log file In an attempt to simplify the determination of user DN&apos;s, a log file
(<typewriter>UnknownDN.log</typewriter>) records user DNs which are unknown. After adding a (<typewriter>UnknownDN.log</typewriter>) records user DNs which are unknown. After adding a
user to the server, ask the user to attempt a login using their PKCS certificate. This should user to the server, ask the user to attempt a login using their PKCS certificate. This should
result in their DN being recorded to this log file. The server administrator may now copy the result in their DN being recorded to this log file. The server administrator may now copy the
appropriate DN from this log file when assigning the DN for a user. appropriate DN from this log file when assigning the DN for a user.
</LI>
<br>
<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.
<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
JAAS modules that requests the name and password from the user.
<p>
Some known JAAS login modules:
<ul>
<li><u>com.sun.security.auth.module.LdapLoginModule</u> - allows authentication to an LDAP server. There
is an example of using this module to authenticate against an Active Directory system in the
jaas.conf file.
</li>
<li><u>net.sf.jpam.jaas.JpamLoginModule</u> - (Linux/Unix server only) allows authentication against
the local PAM configuration. You will need to download JPAM from SourceForce and install the
libraries in the necessary locations. See the example in the jaas.conf file.
</li>
<li><u>ghidra.server.security.loginmodule.ExternalProgramLoginModule</u> - spawns an external
program for each authentication request, and uses the external program's exit code as the indicator
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.
<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.
<p>
The external program is fed the username\n and password\n on its STDIN (ie. two text lines).
The external authenticator needs to exit with 0 (zero) error level
if the authentication was successful, or a non-zero error level if not successful.
</li>
<li><u>com.sun.security.auth.module.Krb5LoginModule</u> - not recommended - this login module
is used in the -a1 Active Directory via Kerberos authentication mode, and as such you should use it that way.
</li>
</ul>
</LI>
<br> <br>
<LI><u>Use of an SSH pre-shared key (<typewriter>-ssh</typewriter>)</u> is supported as an <LI><u>Use of an SSH pre-shared key (<typewriter>-ssh</typewriter>)</u> is supported as an
alternate form of authentication when using Local Ghidra password (<typewriter>-a0</typewriter>). alternate form of authentication when using Local Ghidra password (<typewriter>-a0</typewriter>).
This SSH authentication is currently supported by the Headless Analyzer only. See This SSH authentication is currently supported by the Headless Analyzer only. See
<a href="#sshAuthentication">SSH User Authentication</a> for configuration details.</LI> <a href="#sshAuthentication">SSH User Authentication</a> for configuration details.</LI>
</OL> </UL>
</P> </P>
(<a href="#top">Back to Top</a>) (<a href="#top">Back to Top</a>)
@ -277,20 +325,8 @@ public key files may be made without restarting the Ghidra Server.
<h2><a name="serverOptions">Server Options</a></h2> <h2><a name="serverOptions">Server Options</a></h2>
<UL> <UL>
<LI><typewriter>-a#</typewriter><br>Allows a user authentication mode to be specified (see <LI>Networking options
<a href=#userAuthentication>User Authentication</a>)</LI> <UL>
<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
accessible as read-only to an anonymous user.</LI>
<br>
<LI><typewriter>-ssh</typewriter><br>Enable SSH as an alternate form of authentication when
using <typewriter>-a0</typewriter> authentication 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>-ip &lt;hostname&gt;</typewriter><br>Identifies the remote access hostname (FQDN) <LI><typewriter>-ip &lt;hostname&gt;</typewriter><br>Identifies the remote access hostname (FQDN)
or IPv4 address which should be used by remote clients to access the server. By default the or IPv4 address which should be used by remote clients to access the server. By default the
host name reported by the operating system is resolved to an IPv4 address, if this fails the host name reported by the operating system is resolved to an IPv4 address, if this fails the
@ -310,13 +346,48 @@ public key files may be made without restarting the Ghidra Server.
server utilizes three (3) TCP ports starting with the specified base port (e.g., 13100,13101 and 13102). server utilizes three (3) TCP ports starting with the specified base port (e.g., 13100,13101 and 13102).
The ports utilized are logged by the server during startup.</LI> The ports utilized are logged by the server during startup.</LI>
<br> <br>
<LI><typewriter>-e#</typewriter><br>Allows the reset password expiration to be set to a
specified number of days (default is 1-day).</LI>
<br>
<LI><typewriter>-n</typewriter><br>Enables reverse name lookup for IP addresses when logging <LI><typewriter>-n</typewriter><br>Enables reverse name lookup for IP addresses when logging
(requires proper configuration of reverse lookup by your DNS server). Please note that logging (requires proper configuration of reverse lookup by your DNS server). Please note that logging
of host names is now disabled by default due to the slow-down which occurs when reverse DNS is of host names is now disabled by default due to the slow-down which occurs when reverse DNS is
not properly configured on the network.</LI> not properly configured on the network.</LI>
</UL>
</LI>
<br>
<LI>Authentication options
<UL>
<LI><typewriter>-a#</typewriter><br>Allows a user authentication mode to be specified (see
<a href=#userAuthentication>User Authentication</a>)</LI>
<br>
<LI><typewriter>-d&lt;ad_domain&gt;</typewriter><br>Sets the Active Directory domain name.
Example: "-dmydomain.com"</LI>
<br>
<LI><typewriter>-e#</typewriter><br>Allows the reset password expiration to be set to a
specified number of days (default is 1-day).</LI>
<br>
<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
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>
<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
accessible as read-only to an anonymous user.</LI>
<br>
<LI><typewriter>-ssh</typewriter><br>Enable SSH as an alternate form of authentication when
using <typewriter>-a0</typewriter> authentication mode.</LI>
<br>
</UL>
</LI>
</UL> </UL>
(<a href="#top">Back to Top</a>) (<a href="#top">Back to Top</a>)

View file

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