Skip to content

Commit

Permalink
Reuse GSSAPI JAAS config files when appropriate
Browse files Browse the repository at this point in the history
Added the ability to reuse automatically generated JAAS
configuration files if possible when attempting a SASL GSSAPI bind.
Previously, if the caller didn't explicitly provide a JAAS config
file, the LDAP SDK would generate one based on the provided bind
request properties.  It would do this for every GSSAPI bind attempt,
even if they all used the same properties, which means that it could
generate many copies of the same JAAS config file, which could
unnecessarily waste disk space and memory.  It will now detect when
a bind request would use a JAAS configuration that matches one that
has already been generated, and will reuse the previously generated
file rather than creating a new one.
  • Loading branch information
dirmgr committed Jan 6, 2024
1 parent 5c30c87 commit 5d55d24
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 2 deletions.
13 changes: 13 additions & 0 deletions docs/release-notes.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ <h3>Version 7.0.0</h3>
<br><br>
</li>

<li>
Added the ability to reuse automatically generated JAAS configuration files if
possible when attempting a SASL GSSAPI bind. Previously, if the caller didn't
explicitly provide a JAAS config file, the LDAP SDK would generate one based on
the provided bind request properties. It would do this for every GSSAPI bind
attempt, even if they all used the same properties, which means that it could
generate many copies of the same JAAS config file, which could unnecessarily
waste disk space and memory. It will now detect when a bind request would use a
JAAS configuration that matches one that has already been generated, and will
reuse the previously generated file rather than creating a new one.
<br><br>
</li>

<li>
Added client-side support for the LDAP relax rules request control as defined in
draft-zeilenga-ldap-relax-03. Note that this support is currently classified as
Expand Down
3 changes: 3 additions & 0 deletions messages/unboundid-ldapsdk-ldap.properties
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,9 @@ ERR_GSSAPI_REALM_REQUIRED_BUT_NONE_PROVIDED=The GSSAPI bind processing \
made available to the bind request.
ERR_GSSAPI_UNEXPECTED_CALLBACK=The GSSAPI bind request received an unexpected \
and unsupported callback type of {0}.
ERR_GSSAPI_PROPERTIES_CANNOT_COMPUTE_DIGEST=An error occurred while \
attempting to compute a SHA-256 digest of the GSSAPI bind request \
properties used to generate the JAAS configuration file: {0}
ERR_SASL_CANNOT_CREATE_INITIAL_REQUEST=Unable to create the initial {0} SASL \
request: {1}.
ERR_SASL_CANNOT_CREATE_INITIAL_REQUEST_UNHANDLED_CALLBACKS=Unable to create \
Expand Down
53 changes: 51 additions & 2 deletions src/com/unboundid/ldap/sdk/GSSAPIBindRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import javax.net.ssl.SSLSession;
Expand Down Expand Up @@ -229,6 +231,16 @@ public final class GSSAPIBindRequest



/**
* A map of generated JAAS configuration files, each of which is indexed by a
* digest of the relevant {@link GSSAPIBindRequestProperties} object used to
* generate the file.
*/
@NotNull private static final Map<ASN1OctetString,String>
JAAS_CONFIG_FILE_PATHS_BY_PROPERTIES_DIGEST = new ConcurrentHashMap<>();



/**
* The serial version UID for this serializable class.
*/
Expand Down Expand Up @@ -1027,6 +1039,27 @@ private static String getConfigFilePath(
@NotNull final GSSAPIBindRequestProperties properties)
throws LDAPException
{
// If we already have an appropriate configuration file for the given
// properties, then reuse that file.
ASN1OctetString propertiesConfigDigest = null;
try
{
final byte[] digestBytes = properties.getConfigFileDigest();
propertiesConfigDigest = new ASN1OctetString(digestBytes);

final String path = JAAS_CONFIG_FILE_PATHS_BY_PROPERTIES_DIGEST.get(
propertiesConfigDigest);
if (path != null)
{
return path;
}
}
catch (final Exception e)
{
Debug.debugException(e);
}


try
{
final File f =
Expand All @@ -1046,7 +1079,15 @@ private static String getConfigFilePath(
if (sunModuleClass != null)
{
writeSunJAASConfig(w, properties);
return f.getAbsolutePath();

final String path = f.getAbsolutePath();
if (propertiesConfigDigest != null)
{
JAAS_CONFIG_FILE_PATHS_BY_PROPERTIES_DIGEST.put(
propertiesConfigDigest, path);
}

return path;
}
}
catch (final ClassNotFoundException cnfe)
Expand All @@ -1065,7 +1106,15 @@ private static String getConfigFilePath(
if (ibmModuleClass != null)
{
writeIBMJAASConfig(w, properties);
return f.getAbsolutePath();

final String path = f.getAbsolutePath();
if (propertiesConfigDigest != null)
{
JAAS_CONFIG_FILE_PATHS_BY_PROPERTIES_DIGEST.put(
propertiesConfigDigest, path);
}

return path;
}
}
catch (final ClassNotFoundException cnfe)
Expand Down
92 changes: 92 additions & 0 deletions src/com/unboundid/ldap/sdk/GSSAPIBindRequestProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,18 @@
import java.util.Set;

import com.unboundid.asn1.ASN1OctetString;
import com.unboundid.util.CryptoHelper;
import com.unboundid.util.Debug;
import com.unboundid.util.Mutable;
import com.unboundid.util.NotNull;
import com.unboundid.util.Nullable;
import com.unboundid.util.StaticUtils;
import com.unboundid.util.ThreadSafety;
import com.unboundid.util.ThreadSafetyLevel;
import com.unboundid.util.Validator;
import com.unboundid.util.json.JSONBuffer;

import static com.unboundid.ldap.sdk.LDAPMessages.*;



Expand Down Expand Up @@ -108,6 +113,9 @@ public final class GSSAPIBindRequestProperties
// Indicates whether to enable the use of a ticket cache.
private boolean useTicketCache;

// A digest of the settings that are relevant to a JAAS configuration file.
@Nullable private byte[] configFileDigest;

// The type of channel binding to use for the bind request.
@NotNull private GSSAPIChannelBindingType channelBindingType;

Expand Down Expand Up @@ -537,6 +545,7 @@ public void setJAASClientName(@NotNull final String jaasClientName)
Validator.ensureNotNull(jaasClientName);

this.jaasClientName = jaasClientName;
configFileDigest = null;
}


Expand Down Expand Up @@ -674,6 +683,7 @@ public boolean refreshKrb5Config()
public void setRefreshKrb5Config(final boolean refreshKrb5Config)
{
this.refreshKrb5Config = refreshKrb5Config;
configFileDigest = null;
}


Expand Down Expand Up @@ -734,6 +744,7 @@ public boolean useKeyTab()
public void setUseKeyTab(final boolean useKeyTab)
{
this.useKeyTab = useKeyTab;
configFileDigest = null;
}


Expand Down Expand Up @@ -766,6 +777,7 @@ public String getKeyTabPath()
public void setKeyTabPath(@Nullable final String keyTabPath)
{
this.keyTabPath = keyTabPath;
configFileDigest = null;
}


Expand Down Expand Up @@ -799,6 +811,7 @@ public boolean useTicketCache()
public void setUseTicketCache(final boolean useTicketCache)
{
this.useTicketCache = useTicketCache;
configFileDigest = null;
}


Expand Down Expand Up @@ -835,6 +848,7 @@ public void setRequireCachedCredentials(
final boolean requireCachedCredentials)
{
this.requireCachedCredentials = requireCachedCredentials;
configFileDigest = null;
}


Expand Down Expand Up @@ -867,6 +881,7 @@ public String getTicketCachePath()
public void setTicketCachePath(@Nullable final String ticketCachePath)
{
this.ticketCachePath = ticketCachePath;
configFileDigest = null;
}


Expand Down Expand Up @@ -897,6 +912,7 @@ public boolean renewTGT()
public void setRenewTGT(final boolean renewTGT)
{
this.renewTGT = renewTGT;
configFileDigest = null;
}


Expand Down Expand Up @@ -940,6 +956,7 @@ public Boolean getIsInitiator()
public void setIsInitiator(@Nullable final Boolean isInitiator)
{
this.isInitiator = isInitiator;
configFileDigest = null;
}


Expand Down Expand Up @@ -1055,6 +1072,80 @@ public boolean enableGSSAPIDebugging()
public void setEnableGSSAPIDebugging(final boolean enableGSSAPIDebugging)
{
this.enableGSSAPIDebugging = enableGSSAPIDebugging;
configFileDigest = null;
}



/**
* Retrieves a digest of the settings that are relevant to a JAAS
* configuration file generated from these properties.
*
* @return A digest of the settings that are relevant to a JAAS configuration
* file generated from these properties.
*
* @throws LDAPException If a problem occurs while attempting to generate
* the digest.
*/
@NotNull()
byte[] getConfigFileDigest()
throws LDAPException
{
// If we have previously generated a digest from the current settings, then
// just return that.
if (configFileDigest != null)
{
return configFileDigest;
}


// Generate a JSON object from the relevant settings.
final JSONBuffer buffer = new JSONBuffer();
buffer.beginObject();
buffer.appendString("jaasClientName", jaasClientName);

if (isInitiator != null)
{
buffer.appendBoolean("isInitiator", isInitiator);
}

buffer.appendBoolean("refreshKrb5Config", refreshKrb5Config);
buffer.appendBoolean("useKeyTab", useKeyTab);

if (keyTabPath != null)
{
buffer.appendString("keyTabPath", keyTabPath);
}

buffer.appendBoolean("(useTicketCache", useTicketCache);
buffer.appendBoolean("renewTGT", renewTGT);
buffer.appendBoolean("requireCachedCredentials", requireCachedCredentials);

if (ticketCachePath != null)
{
buffer.appendString("ticketCachePath", ticketCachePath);
}

buffer.appendBoolean("enableGSSAPIDebugging", enableGSSAPIDebugging);
buffer.endObject();


// Generate, cache, and return a 256-bit SHA digest of the JSON object.
try
{
final byte[] bufferBytes = buffer.getBuffer().toByteArray();
configFileDigest = CryptoHelper.sha256(bufferBytes);
return configFileDigest;
}
catch (final Exception e)
{
Debug.debugException(e);
throw new LDAPException(ResultCode.LOCAL_ERROR,
ERR_GSSAPI_PROPERTIES_CANNOT_COMPUTE_DIGEST.get(
StaticUtils.getExceptionMessage(e)),
e);

}
}


Expand Down Expand Up @@ -1200,3 +1291,4 @@ public void toString(@NotNull final StringBuilder buffer)
buffer.append(')');
}
}

0 comments on commit 5d55d24

Please sign in to comment.