Skip to content

Commit bc177e2

Browse files
bizybotYogesh Gaikwad
authored and
Yogesh Gaikwad
committed
[Kerberos] Add support for Kerberos V5 Oid (#35764)
Clients can use the Kerberos V5 security mechanism and when it used this to establish security context it failed to do so as Elasticsearch server only accepted Spengo mechanism. This commit adds support to accept Kerberos V5 credentials over spnego. Closes #34763
1 parent d6e933d commit bc177e2

File tree

4 files changed

+26
-18
lines changed

4 files changed

+26
-18
lines changed

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/kerberos/KerberosTicketValidator.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@
4141
* It may respond with token which needs to be communicated with the peer.
4242
*/
4343
public class KerberosTicketValidator {
44-
static final Oid SPNEGO_OID = getSpnegoOid();
44+
static final Oid SPNEGO_OID = getOid("1.3.6.1.5.5.2");
45+
static final Oid KERBEROS_V5_OID = getOid("1.2.840.113554.1.2.2");
46+
static final Oid[] SUPPORTED_OIDS = new Oid[] { SPNEGO_OID, KERBEROS_V5_OID };
4547

46-
private static Oid getSpnegoOid() {
48+
private static Oid getOid(final String id) {
4749
Oid oid = null;
4850
try {
49-
oid = new Oid("1.3.6.1.5.5.2");
51+
oid = new Oid(id);
5052
} catch (GSSException gsse) {
5153
throw ExceptionsHelper.convertToRuntime(gsse);
5254
}
@@ -152,7 +154,7 @@ private static byte[] acceptSecContext(final byte[] base64decodedTicket, final G
152154
*/
153155
private static GSSCredential createCredentials(final GSSManager gssManager, final Subject subject) throws PrivilegedActionException {
154156
return doAsWrapper(subject, (PrivilegedExceptionAction<GSSCredential>) () -> gssManager.createCredential(null,
155-
GSSCredential.DEFAULT_LIFETIME, SPNEGO_OID, GSSCredential.ACCEPT_ONLY));
157+
GSSCredential.DEFAULT_LIFETIME, SUPPORTED_OIDS, GSSCredential.ACCEPT_ONLY));
156158
}
157159

158160
/**

x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/KerberosTicketValidatorTests.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ public void testKerbTicketGeneratedForDifferentServerFailsValidation() throws Ex
3939

4040
// Client login and init token preparation
4141
final String clientUserName = randomFrom(clientUserNames);
42-
try (SpnegoClient spnegoClient =
43-
new SpnegoClient(principalName(clientUserName), new SecureString("pwd".toCharArray()), principalName("differentServer"));) {
42+
try (SpnegoClient spnegoClient = new SpnegoClient(principalName(clientUserName), new SecureString("pwd".toCharArray()),
43+
principalName("differentServer"), randomFrom(KerberosTicketValidator.SUPPORTED_OIDS))) {
4444
final String base64KerbToken = spnegoClient.getBase64EncodedTokenForSpnegoHeader();
4545
assertThat(base64KerbToken, is(notNullValue()));
4646

@@ -82,7 +82,7 @@ public void testWhenKeyTabWithInvalidContentFailsValidation()
8282
// Client login and init token preparation
8383
final String clientUserName = randomFrom(clientUserNames);
8484
try (SpnegoClient spnegoClient = new SpnegoClient(principalName(clientUserName), new SecureString("pwd".toCharArray()),
85-
principalName(randomFrom(serviceUserNames)));) {
85+
principalName(randomFrom(serviceUserNames)), randomFrom(KerberosTicketValidator.SUPPORTED_OIDS));) {
8686
final String base64KerbToken = spnegoClient.getBase64EncodedTokenForSpnegoHeader();
8787
assertThat(base64KerbToken, is(notNullValue()));
8888

@@ -100,8 +100,10 @@ public void testWhenKeyTabWithInvalidContentFailsValidation()
100100
public void testValidKebrerosTicket() throws PrivilegedActionException, GSSException, LoginException {
101101
// Client login and init token preparation
102102
final String clientUserName = randomFrom(clientUserNames);
103-
try (SpnegoClient spnegoClient = new SpnegoClient(principalName(clientUserName), new SecureString("pwd".toCharArray()),
104-
principalName(randomFrom(serviceUserNames)));) {
103+
final SecureString password = new SecureString("pwd".toCharArray());
104+
final String servicePrincipalName = principalName(randomFrom(serviceUserNames));
105+
try (SpnegoClient spnegoClient = new SpnegoClient(principalName(clientUserName), password, servicePrincipalName,
106+
randomFrom(KerberosTicketValidator.SUPPORTED_OIDS))) {
105107
final String base64KerbToken = spnegoClient.getBase64EncodedTokenForSpnegoHeader();
106108
assertThat(base64KerbToken, is(notNullValue()));
107109

x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServerTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ public void testClientServiceMutualAuthentication() throws PrivilegedActionExcep
5353
final String serviceUserName = randomFrom(serviceUserNames);
5454
// Client login and init token preparation
5555
final String clientUserName = randomFrom(clientUserNames);
56-
try (SpnegoClient spnegoClient =
57-
new SpnegoClient(principalName(clientUserName), new SecureString("pwd".toCharArray()), principalName(serviceUserName));) {
56+
try (SpnegoClient spnegoClient = new SpnegoClient(principalName(clientUserName), new SecureString("pwd".toCharArray()),
57+
principalName(serviceUserName), randomFrom(KerberosTicketValidator.SUPPORTED_OIDS));) {
5858
final String base64KerbToken = spnegoClient.getBase64EncodedTokenForSpnegoHeader();
5959
assertThat(base64KerbToken, is(notNullValue()));
6060
final KerberosAuthenticationToken kerbAuthnToken = new KerberosAuthenticationToken(Base64.getDecoder().decode(base64KerbToken));

x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SpnegoClient.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@
66

77
package org.elasticsearch.xpack.security.authc.kerberos;
88

9-
import org.apache.logging.log4j.Logger;
109
import org.apache.logging.log4j.LogManager;
10+
import org.apache.logging.log4j.Logger;
1111
import org.elasticsearch.ExceptionsHelper;
1212
import org.elasticsearch.common.SuppressForbidden;
1313
import org.elasticsearch.common.settings.SecureString;
14-
import org.elasticsearch.xpack.security.authc.kerberos.KerberosTicketValidator;
1514
import org.ietf.jgss.GSSContext;
1615
import org.ietf.jgss.GSSCredential;
1716
import org.ietf.jgss.GSSException;
1817
import org.ietf.jgss.GSSManager;
1918
import org.ietf.jgss.GSSName;
19+
import org.ietf.jgss.Oid;
2020

2121
import java.io.IOException;
2222
import java.security.AccessController;
@@ -43,6 +43,7 @@
4343
/**
4444
* This class is used as a Spnego client during testing and handles SPNEGO
4545
* interactions using GSS context negotiation.<br>
46+
* It supports Kerberos V5 and Spnego mechanism.<br>
4647
* It is not advisable to share a SpnegoClient between threads as there is no
4748
* synchronization in place, internally this depends on {@link GSSContext} for
4849
* context negotiation which maintains sequencing for replay detections.<br>
@@ -62,14 +63,17 @@ class SpnegoClient implements AutoCloseable {
6263
* Creates SpengoClient to interact with given service principal<br>
6364
* Use {@link #close()} to logout {@link LoginContext} and dispose
6465
* {@link GSSContext} after usage.
66+
*
6567
* @param userPrincipalName User principal name for login as client
6668
* @param password password for client
6769
* @param servicePrincipalName Service principal name with whom this client
68-
* interacts with.
70+
* interacts with.
71+
* @param mechanism the Oid of the desired mechanism. Use (Oid) null to request
72+
* the default mechanism.
6973
* @throws PrivilegedActionException when privileged action threw exception
7074
* @throws GSSException thrown when GSS API error occurs
7175
*/
72-
SpnegoClient(final String userPrincipalName, final SecureString password, final String servicePrincipalName)
76+
SpnegoClient(final String userPrincipalName, final SecureString password, final String servicePrincipalName, final Oid mechanism)
7377
throws PrivilegedActionException, GSSException {
7478
String oldUseSubjectCredsOnlyFlag = null;
7579
try {
@@ -81,9 +85,9 @@ class SpnegoClient implements AutoCloseable {
8185
.doPrivileged((PrivilegedExceptionAction<LoginContext>) () -> loginUsingPassword(userPrincipalName, password));
8286
final GSSCredential userCreds = KerberosTestCase.doAsWrapper(loginContext.getSubject(),
8387
(PrivilegedExceptionAction<GSSCredential>) () -> gssManager.createCredential(gssUserPrincipalName,
84-
GSSCredential.DEFAULT_LIFETIME, KerberosTicketValidator.SPNEGO_OID, GSSCredential.INITIATE_ONLY));
85-
gssContext = gssManager.createContext(gssServicePrincipalName.canonicalize(KerberosTicketValidator.SPNEGO_OID),
86-
KerberosTicketValidator.SPNEGO_OID, userCreds, GSSCredential.DEFAULT_LIFETIME);
88+
GSSCredential.DEFAULT_LIFETIME, mechanism, GSSCredential.INITIATE_ONLY));
89+
gssContext = gssManager.createContext(gssServicePrincipalName.canonicalize(mechanism),
90+
mechanism, userCreds, GSSCredential.DEFAULT_LIFETIME);
8791
gssContext.requestMutualAuth(true);
8892
} catch (PrivilegedActionException pve) {
8993
LOGGER.error("privileged action exception, with root cause", pve.getException());

0 commit comments

Comments
 (0)