Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ELY-85] GSSAPI+SPNEGO workaround for JDK-8194073 (native Kerberos) #1060

Merged
merged 1 commit into from
Jan 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -393,11 +393,11 @@ private Configuration createConfiguration() throws IOException {
if (IS_IBM) {
options.put("noAddress", "true");
options.put("credsType", (isServer && !obtainKerberosTicket) ? "acceptor" : "both");
options.put("useKeytab", keyTab.toURI().toURL().toString());
if (keyTab != null) options.put("useKeytab", keyTab.toURI().toURL().toString());
} else {
options.put("storeKey", "true");
options.put("useKeyTab", "true");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this still be true even if keyTab == null?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To set useKeyTab=true without setting of keytab is valid:

If keytab is not set then the module will locate the keytab from the Kerberos configuration file. If it is not specified in the Kerberos configuration file then it will look for the file {user.home}{file.separator}krb5.keytab.

https://docs.oracle.com/javase/7/docs/jre/api/security/jaas/spec/com/sun/security/auth/module/Krb5LoginModule.html

(even through we use undefined keyTab primary in combination with native kerberos, which ignores this properties at all)

options.put("keyTab", keyTab.getAbsolutePath());
if (keyTab != null) options.put("keyTab", keyTab.getAbsolutePath());
options.put("isInitiator", (isServer && !obtainKerberosTicket) ? "false" : "true");
}

Expand Down
7 changes: 7 additions & 0 deletions src/main/java/org/wildfly/security/http/HttpConstants.java
Expand Up @@ -66,6 +66,13 @@ private HttpConstants() {
*/
public static final String CONFIG_GSS_MANAGER = CONFIG_BASE + ".gss-manager";

/**
* This enables workaround for native GSS, where createName() needs to be called for correct GSSContext initialization.
* Set to "true" to call createName() as part of GSSContext initialization.
* This is workaround of JDK-8194073.
*/
public static final String CONFIG_CREATE_NAME_GSS_INIT = CONFIG_BASE + ".create-name-gss-init";

/**
* A comma separated list of scopes in preferred order the mechanism should attempt to use to persist state including the
* caching of any previously authenticated identity.
Expand Down
Expand Up @@ -20,7 +20,9 @@
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.wildfly.common.Assert.checkNotNullParam;
import static org.wildfly.security._private.ElytronMessages.httpSpnego;
import static org.wildfly.security.auth.util.GSSCredentialSecurityFactory.SPNEGO;
import static org.wildfly.security.http.HttpConstants.AUTHORIZATION;
import static org.wildfly.security.http.HttpConstants.CONFIG_CREATE_NAME_GSS_INIT;
import static org.wildfly.security.http.HttpConstants.CONFIG_GSS_MANAGER;
import static org.wildfly.security.http.HttpConstants.NEGOTIATE;
import static org.wildfly.security.http.HttpConstants.SPNEGO_NAME;
Expand Down Expand Up @@ -93,6 +95,16 @@ public final class SpnegoAuthenticationMechanism implements HttpServerAuthentica
this.callbackHandler = callbackHandler;
this.gssManager = properties.containsKey(CONFIG_GSS_MANAGER) ? (GSSManager) properties.get(CONFIG_GSS_MANAGER) : GSSManager.getInstance();

// JDK-8194073 workaround (for Oracle JDK + native Kerberos)
if (properties.containsKey(CONFIG_CREATE_NAME_GSS_INIT) && Boolean.parseBoolean((String) properties.get(CONFIG_CREATE_NAME_GSS_INIT))) {
try { // createName call ensure correct GSSManager initialization
gssManager.createName("dummy", GSSName.NT_USER_NAME, SPNEGO);
httpSpnego.trace("createName workaround for native GSS initialization applied");
} catch (GSSException e) {
httpSpnego.trace("Exception while applying createName workaround for native GSS initialization", e);
}
}

String scopesProperty = (String) properties.get(CONFIG_STATE_SCOPES);
if (scopesProperty == null) {
storageScopes = new Scope[] { Scope.SESSION, Scope.CONNECTION };
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/org/wildfly/security/sasl/WildFlySasl.java
Expand Up @@ -156,5 +156,13 @@ public final class WildFlySasl {
*/
public static final String AUTHENTICATION_TIMEOUT = "wildfly.sasl.authentication-timeout";

/**
* A property used to enable workaround for native GSS, where createName() needs to be called for correct GSSContext initialization.
* Set to "true" to call createName() as part of GSSContext initialization.
* This is workaround of JDK-8194073.
*
* Note: This is a server only property and is not used client side.
*/
public static final String GSSAPI_CREATE_NAME_GSS_INIT = "wildfly.sasl.gssapi.server.create-name-gss-init";

}
Expand Up @@ -28,7 +28,6 @@
import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.MessageProp;
import org.ietf.jgss.Oid;
import org.wildfly.common.Assert;
import org.wildfly.security.sasl.WildFlySasl;
import org.wildfly.security.sasl.util.AbstractSaslParticipant;
Expand All @@ -50,17 +49,6 @@ abstract class AbstractGssapiMechanism extends AbstractSaslParticipant {
private static final byte INTEGRITY_PROTECTION = (byte) 0x02;
private static final byte CONFIDENTIALITY_PROTECTION = (byte) 0x04;
protected static final int DEFAULT_MAX_BUFFER_SIZE = (int) 0xFFFFFF; // 3 bytes
protected static final Oid KERBEROS_V5;

// Kerberos V5 OID

static {
try {
KERBEROS_V5 = new Oid("1.2.840.113554.1.2.2");
} catch (GSSException e) {
throw saslGssapi.unableToInitialiseOid(e);
}
}

protected GSSContext gssContext;
protected final int configuredMaxReceiveBuffer;
Expand Down
Expand Up @@ -19,6 +19,8 @@
package org.wildfly.security.sasl.gssapi;

import static org.wildfly.security._private.ElytronMessages.saslGssapi;
import static org.wildfly.security.auth.util.GSSCredentialSecurityFactory.KERBEROS_V5;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/org/wildfly/security/sasl/gssapi/GssapiServer.java
Expand Up @@ -18,6 +18,8 @@

package org.wildfly.security.sasl.gssapi;

import static org.wildfly.security.auth.util.GSSCredentialSecurityFactory.KERBEROS_V5;
import static org.wildfly.security.sasl.WildFlySasl.GSSAPI_CREATE_NAME_GSS_INIT;
import static org.wildfly.security.sasl.util.SaslMechanismInformation.Names.GSSAPI;
import static org.wildfly.security._private.ElytronMessages.saslGssapi;
import java.io.IOException;
Expand Down Expand Up @@ -67,6 +69,16 @@ final class GssapiServer extends AbstractGssapiMechanism implements SaslServer {
// Initialise our GSSContext
GSSManager manager = GSSManager.getInstance();

// JDK-8194073 workaround (for Oracle JDK + native Kerberos)
if (props.containsKey(GSSAPI_CREATE_NAME_GSS_INIT) && Boolean.parseBoolean((String) props.get(GSSAPI_CREATE_NAME_GSS_INIT))) {
try { // createName call ensure correct GSSManager initialization
manager.createName("dummy", GSSName.NT_USER_NAME, KERBEROS_V5);
saslGssapi.trace("createName workaround for native GSS initialization applied");
} catch (GSSException e1) {
saslGssapi.trace("Exception while applying createName workaround for native GSS initialization", e1);
}
}

GSSContext gssContext = null;

GSSCredential ourCredential = null;
Expand Down