diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/kerberos/KerberosTicketValidator.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/kerberos/KerberosTicketValidator.java index 12a1a3a8f24..9f2a1828398 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/kerberos/KerberosTicketValidator.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/kerberos/KerberosTicketValidator.java @@ -41,12 +41,14 @@ import javax.security.auth.login.LoginException; * It may respond with token which needs to be communicated with the peer. */ public class KerberosTicketValidator { - static final Oid SPNEGO_OID = getSpnegoOid(); + static final Oid SPNEGO_OID = getOid("1.3.6.1.5.5.2"); + static final Oid KERBEROS_V5_OID = getOid("1.2.840.113554.1.2.2"); + static final Oid[] SUPPORTED_OIDS = new Oid[] { SPNEGO_OID, KERBEROS_V5_OID }; - private static Oid getSpnegoOid() { + private static Oid getOid(final String id) { Oid oid = null; try { - oid = new Oid("1.3.6.1.5.5.2"); + oid = new Oid(id); } catch (GSSException gsse) { throw ExceptionsHelper.convertToRuntime(gsse); } @@ -152,7 +154,7 @@ public class KerberosTicketValidator { */ private static GSSCredential createCredentials(final GSSManager gssManager, final Subject subject) throws PrivilegedActionException { return doAsWrapper(subject, (PrivilegedExceptionAction) () -> gssManager.createCredential(null, - GSSCredential.DEFAULT_LIFETIME, SPNEGO_OID, GSSCredential.ACCEPT_ONLY)); + GSSCredential.DEFAULT_LIFETIME, SUPPORTED_OIDS, GSSCredential.ACCEPT_ONLY)); } /** diff --git a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/KerberosTicketValidatorTests.java b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/KerberosTicketValidatorTests.java index 53d7b38a339..c0886f953fe 100644 --- a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/KerberosTicketValidatorTests.java +++ b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/KerberosTicketValidatorTests.java @@ -37,8 +37,8 @@ public class KerberosTicketValidatorTests extends KerberosTestCase { // Client login and init token preparation final String clientUserName = randomFrom(clientUserNames); - try (SpnegoClient spnegoClient = - new SpnegoClient(principalName(clientUserName), new SecureString("pwd".toCharArray()), principalName("differentServer"))) { + try (SpnegoClient spnegoClient = new SpnegoClient(principalName(clientUserName), new SecureString("pwd".toCharArray()), + principalName("differentServer"), randomFrom(KerberosTicketValidator.SUPPORTED_OIDS))) { final String base64KerbToken = spnegoClient.getBase64EncodedTokenForSpnegoHeader(); assertThat(base64KerbToken, is(notNullValue())); @@ -80,7 +80,7 @@ public class KerberosTicketValidatorTests extends KerberosTestCase { // Client login and init token preparation final String clientUserName = randomFrom(clientUserNames); try (SpnegoClient spnegoClient = new SpnegoClient(principalName(clientUserName), new SecureString("pwd".toCharArray()), - principalName(randomFrom(serviceUserNames)));) { + principalName(randomFrom(serviceUserNames)), randomFrom(KerberosTicketValidator.SUPPORTED_OIDS));) { final String base64KerbToken = spnegoClient.getBase64EncodedTokenForSpnegoHeader(); assertThat(base64KerbToken, is(notNullValue())); @@ -100,7 +100,8 @@ public class KerberosTicketValidatorTests extends KerberosTestCase { final String clientUserName = randomFrom(clientUserNames); final SecureString password = new SecureString("pwd".toCharArray()); final String servicePrincipalName = principalName(randomFrom(serviceUserNames)); - try (SpnegoClient spnegoClient = new SpnegoClient(principalName(clientUserName), password, servicePrincipalName)) { + try (SpnegoClient spnegoClient = new SpnegoClient(principalName(clientUserName), password, servicePrincipalName, + randomFrom(KerberosTicketValidator.SUPPORTED_OIDS))) { final String base64KerbToken = spnegoClient.getBase64EncodedTokenForSpnegoHeader(); assertThat(base64KerbToken, is(notNullValue())); diff --git a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServerTests.java b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServerTests.java index 6d9aae49a48..c1b2ff6808d 100644 --- a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServerTests.java +++ b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServerTests.java @@ -50,8 +50,8 @@ public class SimpleKdcLdapServerTests extends KerberosTestCase { final String serviceUserName = randomFrom(serviceUserNames); // Client login and init token preparation final String clientUserName = randomFrom(clientUserNames); - try (SpnegoClient spnegoClient = - new SpnegoClient(principalName(clientUserName), new SecureString("pwd".toCharArray()), principalName(serviceUserName));) { + try (SpnegoClient spnegoClient = new SpnegoClient(principalName(clientUserName), new SecureString("pwd".toCharArray()), + principalName(serviceUserName), randomFrom(KerberosTicketValidator.SUPPORTED_OIDS));) { final String base64KerbToken = spnegoClient.getBase64EncodedTokenForSpnegoHeader(); assertThat(base64KerbToken, is(notNullValue())); final KerberosAuthenticationToken kerbAuthnToken = new KerberosAuthenticationToken(Base64.getDecoder().decode(base64KerbToken)); diff --git a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SpnegoClient.java b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SpnegoClient.java index 57182f534c2..839b25c7836 100644 --- a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SpnegoClient.java +++ b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SpnegoClient.java @@ -6,17 +6,17 @@ package org.elasticsearch.xpack.security.authc.kerberos; -import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.common.SuppressForbidden; import org.elasticsearch.common.settings.SecureString; -import org.elasticsearch.xpack.security.authc.kerberos.KerberosTicketValidator; import org.ietf.jgss.GSSContext; import org.ietf.jgss.GSSCredential; import org.ietf.jgss.GSSException; import org.ietf.jgss.GSSManager; import org.ietf.jgss.GSSName; +import org.ietf.jgss.Oid; import java.io.IOException; import java.security.AccessController; @@ -43,6 +43,7 @@ import javax.security.auth.login.LoginException; /** * This class is used as a Spnego client during testing and handles SPNEGO * interactions using GSS context negotiation.
+ * It supports Kerberos V5 and Spnego mechanism.
* It is not advisable to share a SpnegoClient between threads as there is no * synchronization in place, internally this depends on {@link GSSContext} for * context negotiation which maintains sequencing for replay detections.
@@ -62,14 +63,17 @@ class SpnegoClient implements AutoCloseable { * Creates SpengoClient to interact with given service principal
* Use {@link #close()} to logout {@link LoginContext} and dispose * {@link GSSContext} after usage. + * * @param userPrincipalName User principal name for login as client * @param password password for client * @param servicePrincipalName Service principal name with whom this client - * interacts with. + * interacts with. + * @param mechanism the Oid of the desired mechanism. Use (Oid) null to request + * the default mechanism. * @throws PrivilegedActionException when privileged action threw exception * @throws GSSException thrown when GSS API error occurs */ - SpnegoClient(final String userPrincipalName, final SecureString password, final String servicePrincipalName) + SpnegoClient(final String userPrincipalName, final SecureString password, final String servicePrincipalName, final Oid mechanism) throws PrivilegedActionException, GSSException { String oldUseSubjectCredsOnlyFlag = null; try { @@ -81,9 +85,9 @@ class SpnegoClient implements AutoCloseable { .doPrivileged((PrivilegedExceptionAction) () -> loginUsingPassword(userPrincipalName, password)); final GSSCredential userCreds = KerberosTestCase.doAsWrapper(loginContext.getSubject(), (PrivilegedExceptionAction) () -> gssManager.createCredential(gssUserPrincipalName, - GSSCredential.DEFAULT_LIFETIME, KerberosTicketValidator.SPNEGO_OID, GSSCredential.INITIATE_ONLY)); - gssContext = gssManager.createContext(gssServicePrincipalName.canonicalize(KerberosTicketValidator.SPNEGO_OID), - KerberosTicketValidator.SPNEGO_OID, userCreds, GSSCredential.DEFAULT_LIFETIME); + GSSCredential.DEFAULT_LIFETIME, mechanism, GSSCredential.INITIATE_ONLY)); + gssContext = gssManager.createContext(gssServicePrincipalName.canonicalize(mechanism), + mechanism, userCreds, GSSCredential.DEFAULT_LIFETIME); gssContext.requestMutualAuth(true); } catch (PrivilegedActionException pve) { LOGGER.error("privileged action exception, with root cause", pve.getException());