You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by co...@apache.org on 2017/07/05 15:27:46 UTC
[1/3] directory-kerby git commit: DIRKRB-Put claims from the JWT
access token into the authorization data of the ticket
Repository: directory-kerby
Updated Branches:
refs/heads/trunk 8b990ad26 -> 0e3234bca
DIRKRB-Put claims from the JWT access token into the authorization data of the ticket
Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/commit/44c142be
Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/44c142be
Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/44c142be
Branch: refs/heads/trunk
Commit: 44c142be568960e88241990b33cab586022658c5
Parents: 8b990ad
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Wed Jul 5 15:36:06 2017 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Wed Jul 5 15:36:06 2017 +0100
----------------------------------------------------------------------
.../kerb/type/ad/AuthorizationType.java | 73 +++++++++++---------
.../backend/AbstractIdentityBackend.java | 27 +++++++-
2 files changed, 66 insertions(+), 34 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/44c142be/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AuthorizationType.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AuthorizationType.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AuthorizationType.java
index e6c40c4..80fa207 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AuthorizationType.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AuthorizationType.java
@@ -6,16 +6,16 @@
* to you 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.
- *
+ * under the License.
+ *
*/
package org.apache.kerby.kerberos.kerb.type.ad;
@@ -23,7 +23,7 @@ import org.apache.kerby.asn1.EnumType;
/**
* The various AuthorizationType values, as defined in RFC 4120 and RFC 1510.
- *
+ *
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public enum AuthorizationType implements EnumType {
@@ -36,7 +36,7 @@ public enum AuthorizationType implements EnumType {
* Constant for the "if relevant" authorization type.
*
* RFC 4120
- *
+ *
* AD elements encapsulated within the if-relevant element are intended for
* interpretation only by application servers that understand the particular
* ad-type of the embedded element. Application servers that do not
@@ -51,16 +51,16 @@ public enum AuthorizationType implements EnumType {
* Constant for the "intended for server" authorization type.
*
* RFC 4120
- *
+ *
* AD-INTENDED-FOR-SERVER SEQUENCE { intended-server[0] SEQUENCE OF
* PrincipalName elements[1] AuthorizationData }
- *
+ *
* AD elements encapsulated within the intended-for-server element may be
* ignored if the application server is not in the list of principal names
* of intended servers. Further, a KDC issuing a ticket for an application
* server can remove this element if the application server is not in the
* list of intended servers.
- *
+ *
* Application servers should check for their principal name in the
* intended-server field of this element. If their principal name is not
* found, this element should be ignored. If found, then the encapsulated
@@ -75,16 +75,16 @@ public enum AuthorizationType implements EnumType {
* Constant for the "intended for application class" authorization type.
*
* RFC 4120
- *
+ *
* AD-INTENDED-FOR-APPLICATION-CLASS SEQUENCE {
* intended-application-class[0] SEQUENCE OF GeneralString elements[1]
* AuthorizationData } AD elements
- *
+ *
* encapsulated within the intended-for-application-class element may be
* ignored if the application server is not in one of the named classes of
* application servers. Examples of application server classes include
* "FILESYSTEM", and other kinds of servers.
- *
+ *
* This element and the elements it encapsulates may be safely ignored by
* applications, application servers, and KDCs that do not implement this
* element.
@@ -95,11 +95,11 @@ public enum AuthorizationType implements EnumType {
* Constant for the "kdc issued" authorization type.
*
* RFC 4120
- *
+ *
* AD-KDCIssued SEQUENCE { ad-checksum[0] Checksum, i-realm[1] Realm
* OPTIONAL, i-sname[2] PrincipalName OPTIONAL, elements[3]
* AuthorizationData. }
- *
+ *
* ad-checksum A checksum over the elements field using a cryptographic
* checksum method that is identical to the checksum used to protect the
* ticket itself (i.e. using the same hash function and the same encryption
@@ -110,13 +110,13 @@ public enum AuthorizationType implements EnumType {
* issuing principal and it allows this KDC to notify the application server
* of the validity of those elements. elements A sequence of authorization
* data elements issued by the KDC.
- *
+ *
* The KDC-issued ad-data field is intended to provide a means for Kerberos
* principal credentials to embed within themselves privilege attributes and
* other mechanisms for positive authorization, amplifying the privileges of
* the principal beyond what can be done using a credentials without such an
* a-data element.
- *
+ *
* This can not be provided without this element because the definition of
* the authorization-data field allows elements to be added at will by the
* bearer of a TGT at the time that they request service tickets and
@@ -129,7 +129,7 @@ public enum AuthorizationType implements EnumType {
* Constant for the "and/or" authorization type.
*
* RFC 4120
- *
+ *
* When restrictive AD elements encapsulated within the and-or element are
* encountered, only the number specified in condition-count of the
* encapsulated conditions must be met in order to satisfy this element.
@@ -145,9 +145,9 @@ public enum AuthorizationType implements EnumType {
* Constant for the "mandatory ticket extensions" authorization type.
*
* RFC 4120
- *
+ *
* AD-Mandatory-Ticket-Extensions Checksum
- *
+ *
* An authorization data element of type mandatory-ticket-extensions
* specifies a collision-proof checksum using the same hash algorithm used
* to protect the integrity of the ticket itself. This checksum will be
@@ -164,9 +164,9 @@ public enum AuthorizationType implements EnumType {
* Constant for the "in ticket extensions" authorization type.
*
* RFC 4120
- *
+ *
* AD-IN-Ticket-Extensions Checksum
- *
+ *
* An authorization data element of type in-ticket-extensions specifies a
* collision-proof checksum using the same hash algorithm used to protect
* the integrity of the ticket itself. This checksum is calculated over a
@@ -187,9 +187,9 @@ public enum AuthorizationType implements EnumType {
* Constant for the "mandatory-for-kdc" authorization type.
*
* RFC 4120
- *
+ *
* AD-MANDATORY-FOR-KDC ::= AuthorizationData
- *
+ *
* AD elements encapsulated within the mandatory-for-kdc element are to be
* interpreted by the KDC. KDCs that do not understand the type of an
* element embedded within the mandatory-for-kdc element MUST reject the
@@ -201,22 +201,22 @@ public enum AuthorizationType implements EnumType {
* Constant for the "initial-verified-cas" authorization type.
*
* RFC 4556
- *
+ *
* AD-INITIAL-VERIFIED-CAS ::= SEQUENCE OF ExternalPrincipalIdentifier --
* Identifies the certification path with which -- the client certificate
* was validated. -- Each ExternalPrincipalIdentifier identifies a CA -- or
* a CA certificate (thereby its public key).
- *
+ *
* The AD-INITIAL-VERIFIED-CAS structure identifies the certification path
* with which the client certificate was validated. Each
* ExternalPrincipalIdentifier (as defined in Section 3.2.1) in the AD-
* INITIAL-VERIFIED-CAS structure identifies a CA or a CA certificate
* (thereby its public key).
- *
+ *
* Note that the syntax for the AD-INITIAL-VERIFIED-CAS authorization data
* does permit empty SEQUENCEs to be encoded. Such empty sequences may only
* be used if the KDC itself vouches for the user's certificate.
- *
+ *
* The AS wraps any AD-INITIAL-VERIFIED-CAS data in AD-IF-RELEVANT
* containers if the list of CAs satisfies the AS' realm's local policy
* (this corresponds to the TRANSITED-POLICY-CHECKED ticket flag [RFC4120]).
@@ -225,7 +225,7 @@ public enum AuthorizationType implements EnumType {
* of CAs satisfies the local KDC's realm's policy, the TGS MAY wrap the
* data into the AD-IF-RELEVANT container; otherwise, it MAY unwrap the
* authorization data out of the AD-IF-RELEVANT container.
- *
+ *
* Application servers that understand this authorization data type SHOULD
* apply local policy to determine whether a given ticket bearing such a
* type *not* contained within an AD-IF-RELEVANT container is acceptable.
@@ -234,7 +234,7 @@ public enum AuthorizationType implements EnumType {
* data type is contained within an AD-IF- RELEVANT container, AP servers
* MAY apply local policy to determine whether the authorization data is
* acceptable.
- *
+ *
* ExternalPrincipalIdentifier ::= SEQUENCE { subjectName [0] IMPLICIT OCTET
* STRING OPTIONAL, -- Contains a PKIX type Name encoded according to --
* [RFC3280]. -- Identifies the certificate subject by the -- distinguished
@@ -287,7 +287,7 @@ public enum AuthorizationType implements EnumType {
* authorization type.
*
* RFC 4120
- *
+ *
* See: Microsoft standard documents MS-PAC and MS-KILE.
*/
AD_WIN2K_PAC(128),
@@ -300,8 +300,15 @@ public enum AuthorizationType implements EnumType {
AD_ETYPE_NEGOTIATION(129),
/**
+ * Constant for the Authorization Data Type. Note that this is not a standard Type as of yet.
+ *
+ * See the draft spec "Token Pre-Authentication for Kerberos".
+ */
+ AD_TOKEN(256),
+
+ /**
* Constant for the "Authentication-Indicator" authorization type.
- *
+ *
* RFC 6711 An IANA Registry for Level of Assurance (LoA) Profiles provides
* the syntax and semantics of LoA profiles.
*
@@ -313,7 +320,7 @@ public enum AuthorizationType implements EnumType {
private final int value;
/**
- * Create a new enum
+ * Create a new enum
*/
AuthorizationType(int value) {
this.value = value;
@@ -337,7 +344,7 @@ public enum AuthorizationType implements EnumType {
/**
* Get the AuthorizationType associated with a value.
- *
+ *
* @param value The integer value of the AuthorizationType we are looking for
* @return The associated AuthorizationType, or NULL if not found or if value is null
*/
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/44c142be/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/AbstractIdentityBackend.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/AbstractIdentityBackend.java b/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/AbstractIdentityBackend.java
index 7db2a48..d965dc3 100644
--- a/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/AbstractIdentityBackend.java
+++ b/kerby-kerb/kerb-identity/src/main/java/org/apache/kerby/kerberos/kerb/identity/backend/AbstractIdentityBackend.java
@@ -19,11 +19,19 @@
*/
package org.apache.kerby.kerberos.kerb.identity.backend;
+import java.io.IOException;
+import java.util.Collections;
+
import org.apache.kerby.config.Configured;
import org.apache.kerby.kerberos.kerb.KrbException;
import org.apache.kerby.kerberos.kerb.identity.BatchTrans;
import org.apache.kerby.kerberos.kerb.identity.KrbIdentity;
+import org.apache.kerby.kerberos.kerb.type.ad.AdToken;
import org.apache.kerby.kerberos.kerb.type.ad.AuthorizationData;
+import org.apache.kerby.kerberos.kerb.type.ad.AuthorizationDataEntry;
+import org.apache.kerby.kerberos.kerb.type.ad.AuthorizationType;
+import org.apache.kerby.kerberos.kerb.type.base.KrbToken;
+import org.apache.kerby.kerberos.kerb.type.base.TokenFormat;
import org.apache.kerby.kerberos.kerb.type.kdc.KdcClientRequest;
import org.apache.kerby.kerberos.kerb.type.ticket.EncTicketPart;
import org.slf4j.Logger;
@@ -196,7 +204,24 @@ public abstract class AbstractIdentityBackend
*/
protected AuthorizationData doGetIdentityAuthorizationData(
KdcClientRequest kdcClientRequest, EncTicketPart encTicketPart)
- throws KrbException {
+ throws KrbException {
+ if (kdcClientRequest.isToken()) {
+ KrbToken krbToken = new KrbToken(kdcClientRequest.getToken(), TokenFormat.JWT);
+ AdToken adToken = new AdToken();
+ adToken.setToken(krbToken);
+
+ AuthorizationData authzData = new AuthorizationData();
+ AuthorizationDataEntry authzDataEntry = new AuthorizationDataEntry();
+ try {
+ authzDataEntry.setAuthzData(adToken.encode());
+ } catch (IOException e) {
+ throw new KrbException("Error encoding AdToken", e);
+ }
+
+ authzDataEntry.setAuthzType(AuthorizationType.AD_TOKEN);
+ authzData.setElements(Collections.singletonList(authzDataEntry));
+ return authzData;
+ }
return null;
}
[3/3] directory-kerby git commit: Adding signature tests
Posted by co...@apache.org.
Adding signature tests
Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/commit/0e3234bc
Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/0e3234bc
Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/0e3234bc
Branch: refs/heads/trunk
Commit: 0e3234bca25e4a607dca507b9d9e0387e475794d
Parents: 7c89f0a
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Wed Jul 5 16:27:38 2017 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Wed Jul 5 16:27:38 2017 +0100
----------------------------------------------------------------------
.../kerb/integration/test/JWTTokenTest.java | 88 +++++++++++++++++---
1 file changed, 75 insertions(+), 13 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/0e3234bc/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java
index 04ba1d0..aeb0ced 100644
--- a/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java
+++ b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java
@@ -24,6 +24,8 @@ import static org.junit.Assert.*;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.interfaces.RSAPrivateKey;
import java.util.Collections;
@@ -89,7 +91,10 @@ public class JWTTokenTest extends TokenLoginTestBase {
authToken.isIdToken(false);
authToken.setAudiences(Collections.singletonList(getServerPrincipal()));
KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
- krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ InputStream is = Files.newInputStream(getSignKeyFile().toPath());
+ PrivateKey signKey = PrivateKeyReader.loadPrivateKey(is);
+ krbToken.setTokenValue(signToken(authToken, signKey));
// Now get a SGT using the JWT
SgtTicket tkt = tokenClient.requestSgt(krbToken, getServerPrincipal(), cCacheFile.getPath());
@@ -148,7 +153,10 @@ public class JWTTokenTest extends TokenLoginTestBase {
authToken.isIdToken(false);
authToken.setAudiences(Collections.singletonList(getServerPrincipal() + "_"));
KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
- krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ InputStream is = Files.newInputStream(getSignKeyFile().toPath());
+ PrivateKey signKey = PrivateKeyReader.loadPrivateKey(is);
+ krbToken.setTokenValue(signToken(authToken, signKey));
// Now get a SGT using the JWT
try {
@@ -162,7 +170,6 @@ public class JWTTokenTest extends TokenLoginTestBase {
}
@org.junit.Test
- @org.junit.Ignore
public void accessTokenInvalidSignature() throws Exception {
KrbClient client = getKrbClient();
@@ -194,8 +201,9 @@ public class JWTTokenTest extends TokenLoginTestBase {
authToken.isIdToken(false);
authToken.setAudiences(Collections.singletonList(getServerPrincipal()));
KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
- File signKeyFile = new File(this.getClass().getResource("/kdckeytest.pem").getPath());
- krbToken.setTokenValue(signToken(authToken, signKeyFile));
+
+ KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
+ krbToken.setTokenValue(signToken(authToken, keyPair.getPrivate()));
// Now get a SGT using the JWT
try {
@@ -241,7 +249,10 @@ public class JWTTokenTest extends TokenLoginTestBase {
authToken.setAudiences(Collections.singletonList(getServerPrincipal()));
authToken.setIssuer("unknown-issuer");
KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
- krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ InputStream is = Files.newInputStream(getSignKeyFile().toPath());
+ PrivateKey signKey = PrivateKeyReader.loadPrivateKey(is);
+ krbToken.setTokenValue(signToken(authToken, signKey));
// Now get a SGT using the JWT
try {
@@ -283,7 +294,10 @@ public class JWTTokenTest extends TokenLoginTestBase {
// Create a JWT token
AuthToken authToken = issueToken(getClientPrincipal());
KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
- krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ InputStream is = Files.newInputStream(getSignKeyFile().toPath());
+ PrivateKey signKey = PrivateKeyReader.loadPrivateKey(is);
+ krbToken.setTokenValue(signToken(authToken, signKey));
// Now get a TGT using the JWT token
tgt = tokenClient.requestTgt(krbToken, cCacheFile.getPath());
@@ -338,7 +352,10 @@ public class JWTTokenTest extends TokenLoginTestBase {
AuthToken authToken = issueToken(getClientPrincipal());
authToken.setAudiences(Collections.singletonList(authToken.getAudiences().get(0) + "_"));
KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
- krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ InputStream is = Files.newInputStream(getSignKeyFile().toPath());
+ PrivateKey signKey = PrivateKeyReader.loadPrivateKey(is);
+ krbToken.setTokenValue(signToken(authToken, signKey));
// Now get a TGT using the JWT token
try {
@@ -352,6 +369,51 @@ public class JWTTokenTest extends TokenLoginTestBase {
}
@org.junit.Test
+ public void identityTokenInvalidSignature() throws Exception {
+
+ KrbClient client = getKrbClient();
+
+ // Get a TGT
+ TgtTicket tgt = client.requestTgt(getClientPrincipal(), getClientPassword());
+ assertNotNull(tgt);
+
+ // Write to cache
+ Credential credential = new Credential(tgt);
+ CredentialCache cCache = new CredentialCache();
+ cCache.addCredential(credential);
+ cCache.setPrimaryPrincipal(tgt.getClientPrincipal());
+
+ File cCacheFile = File.createTempFile("krb5_" + getClientPrincipal(), "cc");
+ cCache.store(cCacheFile);
+
+ KrbTokenClient tokenClient = new KrbTokenClient(client);
+
+ tokenClient.setKdcHost(client.getSetting().getKdcHost());
+ tokenClient.setKdcTcpPort(client.getSetting().getKdcTcpPort());
+
+ tokenClient.setKdcRealm(client.getSetting().getKdcRealm());
+ tokenClient.init();
+
+ // Create a JWT token
+ AuthToken authToken = issueToken(getClientPrincipal());
+ authToken.setAudiences(Collections.singletonList(authToken.getAudiences().get(0) + "_"));
+ KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
+
+ KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
+ krbToken.setTokenValue(signToken(authToken, keyPair.getPrivate()));
+
+ // Now get a TGT using the JWT token
+ try {
+ tokenClient.requestTgt(krbToken, cCacheFile.getPath());
+ fail("Failure expected on an invalid signature");
+ } catch (KrbException ex) { //NOPMD
+ // expected
+ }
+
+ cCacheFile.delete();
+ }
+
+ @org.junit.Test
public void identityTokenUnknownIssuer() throws Exception {
KrbClient client = getKrbClient();
@@ -381,7 +443,10 @@ public class JWTTokenTest extends TokenLoginTestBase {
AuthToken authToken = issueToken(getClientPrincipal());
authToken.setIssuer("unknown-issuer");
KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
- krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ InputStream is = Files.newInputStream(getSignKeyFile().toPath());
+ PrivateKey signKey = PrivateKeyReader.loadPrivateKey(is);
+ krbToken.setTokenValue(signToken(authToken, signKey));
// Now get a TGT using the JWT token
try {
@@ -394,13 +459,10 @@ public class JWTTokenTest extends TokenLoginTestBase {
cCacheFile.delete();
}
- private byte[] signToken(AuthToken authToken, File signKeyFile) throws Exception {
+ private byte[] signToken(AuthToken authToken, PrivateKey signKey) throws Exception {
TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
assertTrue(tokenEncoder instanceof JwtTokenEncoder);
- InputStream is = Files.newInputStream(signKeyFile.toPath());
- PrivateKey signKey = PrivateKeyReader.loadPrivateKey(is);
-
((JwtTokenEncoder) tokenEncoder).setSignKey((RSAPrivateKey) signKey);
return tokenEncoder.encodeAsBytes(authToken);
}
[2/3] directory-kerby git commit: DIRKRB-632 - Adding unit tests for
identity and access tokens
Posted by co...@apache.org.
DIRKRB-632 - Adding unit tests for identity and access tokens
Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/commit/7c89f0a9
Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/7c89f0a9
Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/7c89f0a9
Branch: refs/heads/trunk
Commit: 7c89f0a9d1f9a77730e561e40925447f30498c95
Parents: 44c142b
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Wed Jul 5 16:11:50 2017 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Wed Jul 5 16:11:50 2017 +0100
----------------------------------------------------------------------
.../kerb/integration/test/JWTTokenTest.java | 407 +++++++++++++++++++
.../integration/test/TokenLoginTestBase.java | 6 +-
.../kerby/kerberos/kerb/server/KdcTestBase.java | 17 +-
3 files changed, 423 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/7c89f0a9/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java
new file mode 100644
index 0000000..04ba1d0
--- /dev/null
+++ b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java
@@ -0,0 +1,407 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.kerby.kerberos.kerb.integration.test;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.security.PrivateKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.util.Collections;
+
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.KrbRuntime;
+import org.apache.kerby.kerberos.kerb.ccache.Credential;
+import org.apache.kerby.kerberos.kerb.ccache.CredentialCache;
+import org.apache.kerby.kerberos.kerb.client.KrbClient;
+import org.apache.kerby.kerberos.kerb.client.KrbTokenClient;
+import org.apache.kerby.kerberos.kerb.common.EncryptionUtil;
+import org.apache.kerby.kerberos.kerb.common.PrivateKeyReader;
+import org.apache.kerby.kerberos.kerb.crypto.EncryptionHandler;
+import org.apache.kerby.kerberos.kerb.provider.TokenEncoder;
+import org.apache.kerby.kerberos.kerb.type.ad.AdToken;
+import org.apache.kerby.kerberos.kerb.type.ad.AuthorizationData;
+import org.apache.kerby.kerberos.kerb.type.ad.AuthorizationDataEntry;
+import org.apache.kerby.kerberos.kerb.type.base.AuthToken;
+import org.apache.kerby.kerberos.kerb.type.base.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.type.base.KeyUsage;
+import org.apache.kerby.kerberos.kerb.type.base.KrbToken;
+import org.apache.kerby.kerberos.kerb.type.base.TokenFormat;
+import org.apache.kerby.kerberos.kerb.type.ticket.EncTicketPart;
+import org.apache.kerby.kerberos.kerb.type.ticket.SgtTicket;
+import org.apache.kerby.kerberos.kerb.type.ticket.TgtTicket;
+import org.apache.kerby.kerberos.kerb.type.ticket.Ticket;
+import org.apache.kerby.kerberos.provider.token.JwtTokenEncoder;
+
+/**
+ * Some tests for JWT tokens using the Kerby client API
+ */
+public class JWTTokenTest extends TokenLoginTestBase {
+
+ @org.junit.Test
+ public void accessToken() throws Exception {
+
+ KrbClient client = getKrbClient();
+
+ // Get a TGT
+ TgtTicket tgt = client.requestTgt(getClientPrincipal(), getClientPassword());
+ assertNotNull(tgt);
+
+ // Write to cache
+ Credential credential = new Credential(tgt);
+ CredentialCache cCache = new CredentialCache();
+ cCache.addCredential(credential);
+ cCache.setPrimaryPrincipal(tgt.getClientPrincipal());
+
+ File cCacheFile = File.createTempFile("krb5_" + getClientPrincipal(), "cc");
+ cCache.store(cCacheFile);
+
+ KrbTokenClient tokenClient = new KrbTokenClient(client);
+
+ tokenClient.setKdcHost(client.getSetting().getKdcHost());
+ tokenClient.setKdcTcpPort(client.getSetting().getKdcTcpPort());
+
+ tokenClient.setKdcRealm(client.getSetting().getKdcRealm());
+ tokenClient.init();
+
+ // Create a JWT token
+ AuthToken authToken = issueToken(getClientPrincipal());
+ authToken.isAcToken(true);
+ authToken.isIdToken(false);
+ authToken.setAudiences(Collections.singletonList(getServerPrincipal()));
+ KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
+ krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ // Now get a SGT using the JWT
+ SgtTicket tkt = tokenClient.requestSgt(krbToken, getServerPrincipal(), cCacheFile.getPath());
+ assertTrue(tkt != null);
+
+ // Decrypt the ticket
+ Ticket ticket = tkt.getTicket();
+ EncryptionKey key = EncryptionHandler.string2Key(getServerPrincipal(), getServerPassword(),
+ ticket.getEncryptedEncPart().getEType());
+
+ EncTicketPart encPart =
+ EncryptionUtil.unseal(ticket.getEncryptedEncPart(),
+ key, KeyUsage.KDC_REP_TICKET, EncTicketPart.class);
+
+ // Examine the authorization data
+ AuthorizationData authzData = encPart.getAuthorizationData();
+ assertEquals(1, authzData.getElements().size());
+ AuthorizationDataEntry dataEntry = authzData.getElements().iterator().next();
+ AdToken token = dataEntry.getAuthzDataAs(AdToken.class);
+ KrbToken decodedKrbToken = token.getToken();
+ assertEquals(getClientPrincipal(), decodedKrbToken.getSubject());
+ assertEquals(getServerPrincipal(), decodedKrbToken.getAudiences().get(0));
+
+ cCacheFile.delete();
+ }
+
+ @org.junit.Test
+ public void accessTokenInvalidAudience() throws Exception {
+
+ KrbClient client = getKrbClient();
+
+ // Get a TGT
+ TgtTicket tgt = client.requestTgt(getClientPrincipal(), getClientPassword());
+ assertNotNull(tgt);
+
+ // Write to cache
+ Credential credential = new Credential(tgt);
+ CredentialCache cCache = new CredentialCache();
+ cCache.addCredential(credential);
+ cCache.setPrimaryPrincipal(tgt.getClientPrincipal());
+
+ File cCacheFile = File.createTempFile("krb5_" + getClientPrincipal(), "cc");
+ cCache.store(cCacheFile);
+
+ KrbTokenClient tokenClient = new KrbTokenClient(client);
+
+ tokenClient.setKdcHost(client.getSetting().getKdcHost());
+ tokenClient.setKdcTcpPort(client.getSetting().getKdcTcpPort());
+
+ tokenClient.setKdcRealm(client.getSetting().getKdcRealm());
+ tokenClient.init();
+
+ // Create a JWT token with an invalid audience
+ AuthToken authToken = issueToken(getClientPrincipal());
+ authToken.isAcToken(true);
+ authToken.isIdToken(false);
+ authToken.setAudiences(Collections.singletonList(getServerPrincipal() + "_"));
+ KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
+ krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ // Now get a SGT using the JWT
+ try {
+ tokenClient.requestSgt(krbToken, getServerPrincipal(), cCacheFile.getPath());
+ fail("Failure expected on an invalid audience");
+ } catch (KrbException ex) { //NOPMD
+ // expected
+ }
+
+ cCacheFile.delete();
+ }
+
+ @org.junit.Test
+ @org.junit.Ignore
+ public void accessTokenInvalidSignature() throws Exception {
+
+ KrbClient client = getKrbClient();
+
+ // Get a TGT
+ TgtTicket tgt = client.requestTgt(getClientPrincipal(), getClientPassword());
+ assertNotNull(tgt);
+
+ // Write to cache
+ Credential credential = new Credential(tgt);
+ CredentialCache cCache = new CredentialCache();
+ cCache.addCredential(credential);
+ cCache.setPrimaryPrincipal(tgt.getClientPrincipal());
+
+ File cCacheFile = File.createTempFile("krb5_" + getClientPrincipal(), "cc");
+ cCache.store(cCacheFile);
+
+ KrbTokenClient tokenClient = new KrbTokenClient(client);
+
+ tokenClient.setKdcHost(client.getSetting().getKdcHost());
+ tokenClient.setKdcTcpPort(client.getSetting().getKdcTcpPort());
+
+ tokenClient.setKdcRealm(client.getSetting().getKdcRealm());
+ tokenClient.init();
+
+ // Create a JWT token with an invalid audience
+ AuthToken authToken = issueToken(getClientPrincipal());
+ authToken.isAcToken(true);
+ authToken.isIdToken(false);
+ authToken.setAudiences(Collections.singletonList(getServerPrincipal()));
+ KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
+ File signKeyFile = new File(this.getClass().getResource("/kdckeytest.pem").getPath());
+ krbToken.setTokenValue(signToken(authToken, signKeyFile));
+
+ // Now get a SGT using the JWT
+ try {
+ tokenClient.requestSgt(krbToken, getServerPrincipal(), cCacheFile.getPath());
+ fail("Failure expected on an invalid signature");
+ } catch (KrbException ex) { //NOPMD
+ // expected
+ }
+
+ cCacheFile.delete();
+ }
+
+ @org.junit.Test
+ public void accessTokenUnknownIssuer() throws Exception {
+
+ KrbClient client = getKrbClient();
+
+ // Get a TGT
+ TgtTicket tgt = client.requestTgt(getClientPrincipal(), getClientPassword());
+ assertNotNull(tgt);
+
+ // Write to cache
+ Credential credential = new Credential(tgt);
+ CredentialCache cCache = new CredentialCache();
+ cCache.addCredential(credential);
+ cCache.setPrimaryPrincipal(tgt.getClientPrincipal());
+
+ File cCacheFile = File.createTempFile("krb5_" + getClientPrincipal(), "cc");
+ cCache.store(cCacheFile);
+
+ KrbTokenClient tokenClient = new KrbTokenClient(client);
+
+ tokenClient.setKdcHost(client.getSetting().getKdcHost());
+ tokenClient.setKdcTcpPort(client.getSetting().getKdcTcpPort());
+
+ tokenClient.setKdcRealm(client.getSetting().getKdcRealm());
+ tokenClient.init();
+
+ // Create a JWT token with an invalid audience
+ AuthToken authToken = issueToken(getClientPrincipal());
+ authToken.isAcToken(true);
+ authToken.isIdToken(false);
+ authToken.setAudiences(Collections.singletonList(getServerPrincipal()));
+ authToken.setIssuer("unknown-issuer");
+ KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
+ krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ // Now get a SGT using the JWT
+ try {
+ tokenClient.requestSgt(krbToken, getServerPrincipal(), cCacheFile.getPath());
+ fail("Failure expected on an unknown issuer");
+ } catch (KrbException ex) { //NOPMD
+ // expected
+ }
+
+ cCacheFile.delete();
+ }
+
+ @org.junit.Test
+ public void identityToken() throws Exception {
+
+ KrbClient client = getKrbClient();
+
+ // Get a TGT
+ TgtTicket tgt = client.requestTgt(getClientPrincipal(), getClientPassword());
+ assertNotNull(tgt);
+
+ // Write to cache
+ Credential credential = new Credential(tgt);
+ CredentialCache cCache = new CredentialCache();
+ cCache.addCredential(credential);
+ cCache.setPrimaryPrincipal(tgt.getClientPrincipal());
+
+ File cCacheFile = File.createTempFile("krb5_" + getClientPrincipal(), "cc");
+ cCache.store(cCacheFile);
+
+ KrbTokenClient tokenClient = new KrbTokenClient(client);
+
+ tokenClient.setKdcHost(client.getSetting().getKdcHost());
+ tokenClient.setKdcTcpPort(client.getSetting().getKdcTcpPort());
+
+ tokenClient.setKdcRealm(client.getSetting().getKdcRealm());
+ tokenClient.init();
+
+ // Create a JWT token
+ AuthToken authToken = issueToken(getClientPrincipal());
+ KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
+ krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ // Now get a TGT using the JWT token
+ tgt = tokenClient.requestTgt(krbToken, cCacheFile.getPath());
+
+ // Now get a SGT using the TGT
+ SgtTicket tkt = tokenClient.requestSgt(tgt, getServerPrincipal());
+ assertTrue(tkt != null);
+
+ // Decrypt the ticket
+ Ticket ticket = tkt.getTicket();
+ EncryptionKey key = EncryptionHandler.string2Key(getServerPrincipal(), getServerPassword(),
+ ticket.getEncryptedEncPart().getEType());
+
+ EncTicketPart encPart =
+ EncryptionUtil.unseal(ticket.getEncryptedEncPart(),
+ key, KeyUsage.KDC_REP_TICKET, EncTicketPart.class);
+
+ // Check the authorization data is not present
+ AuthorizationData authzData = encPart.getAuthorizationData();
+ assertNull(authzData);
+
+ cCacheFile.delete();
+ }
+
+ @org.junit.Test
+ public void identityTokenInvalidAudience() throws Exception {
+
+ KrbClient client = getKrbClient();
+
+ // Get a TGT
+ TgtTicket tgt = client.requestTgt(getClientPrincipal(), getClientPassword());
+ assertNotNull(tgt);
+
+ // Write to cache
+ Credential credential = new Credential(tgt);
+ CredentialCache cCache = new CredentialCache();
+ cCache.addCredential(credential);
+ cCache.setPrimaryPrincipal(tgt.getClientPrincipal());
+
+ File cCacheFile = File.createTempFile("krb5_" + getClientPrincipal(), "cc");
+ cCache.store(cCacheFile);
+
+ KrbTokenClient tokenClient = new KrbTokenClient(client);
+
+ tokenClient.setKdcHost(client.getSetting().getKdcHost());
+ tokenClient.setKdcTcpPort(client.getSetting().getKdcTcpPort());
+
+ tokenClient.setKdcRealm(client.getSetting().getKdcRealm());
+ tokenClient.init();
+
+ // Create a JWT token
+ AuthToken authToken = issueToken(getClientPrincipal());
+ authToken.setAudiences(Collections.singletonList(authToken.getAudiences().get(0) + "_"));
+ KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
+ krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ // Now get a TGT using the JWT token
+ try {
+ tokenClient.requestTgt(krbToken, cCacheFile.getPath());
+ fail("Failure expected on an invalid audience");
+ } catch (KrbException ex) { //NOPMD
+ // expected
+ }
+
+ cCacheFile.delete();
+ }
+
+ @org.junit.Test
+ public void identityTokenUnknownIssuer() throws Exception {
+
+ KrbClient client = getKrbClient();
+
+ // Get a TGT
+ TgtTicket tgt = client.requestTgt(getClientPrincipal(), getClientPassword());
+ assertNotNull(tgt);
+
+ // Write to cache
+ Credential credential = new Credential(tgt);
+ CredentialCache cCache = new CredentialCache();
+ cCache.addCredential(credential);
+ cCache.setPrimaryPrincipal(tgt.getClientPrincipal());
+
+ File cCacheFile = File.createTempFile("krb5_" + getClientPrincipal(), "cc");
+ cCache.store(cCacheFile);
+
+ KrbTokenClient tokenClient = new KrbTokenClient(client);
+
+ tokenClient.setKdcHost(client.getSetting().getKdcHost());
+ tokenClient.setKdcTcpPort(client.getSetting().getKdcTcpPort());
+
+ tokenClient.setKdcRealm(client.getSetting().getKdcRealm());
+ tokenClient.init();
+
+ // Create a JWT token
+ AuthToken authToken = issueToken(getClientPrincipal());
+ authToken.setIssuer("unknown-issuer");
+ KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
+ krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ // Now get a TGT using the JWT token
+ try {
+ tokenClient.requestTgt(krbToken, cCacheFile.getPath());
+ fail("Failure expected on an unknown issuer");
+ } catch (KrbException ex) { //NOPMD
+ // expected
+ }
+
+ cCacheFile.delete();
+ }
+
+ private byte[] signToken(AuthToken authToken, File signKeyFile) throws Exception {
+ TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
+ assertTrue(tokenEncoder instanceof JwtTokenEncoder);
+
+ InputStream is = Files.newInputStream(signKeyFile.toPath());
+ PrivateKey signKey = PrivateKeyReader.loadPrivateKey(is);
+
+ ((JwtTokenEncoder) tokenEncoder).setSignKey((RSAPrivateKey) signKey);
+ return tokenEncoder.encodeAsBytes(authToken);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/7c89f0a9/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenLoginTestBase.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenLoginTestBase.java b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenLoginTestBase.java
index 140a81d..044870b 100644
--- a/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenLoginTestBase.java
+++ b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenLoginTestBase.java
@@ -106,7 +106,7 @@ public class TokenLoginTestBase extends LoginTestBase {
return tokenStr;
}
- private AuthToken issueToken(String principal) {
+ protected AuthToken issueToken(String principal) {
AuthToken authToken = KrbRuntime.getTokenProvider().createTokenFactory().createToken();
String iss = "token-service";
@@ -174,4 +174,8 @@ public class TokenLoginTestBase extends LoginTestBase {
protected File getTGTCache() {
return tgtCache;
}
+
+ protected File getSignKeyFile() {
+ return signKeyFile;
+ }
}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/7c89f0a9/kerby-kerb/kerb-kdc-test/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTestBase.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-kdc-test/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTestBase.java b/kerby-kerb/kerb-kdc-test/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTestBase.java
index c4a87be..547db27 100644
--- a/kerby-kerb/kerb-kdc-test/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTestBase.java
+++ b/kerby-kerb/kerb-kdc-test/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTestBase.java
@@ -6,16 +6,16 @@
* to you 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.
- *
+ * under the License.
+ *
*/
package org.apache.kerby.kerberos.kerb.server;
@@ -41,6 +41,7 @@ public abstract class KdcTestBase {
private final String clientPrincipalName = "drankye";
private final String clientPrincipal =
clientPrincipalName + "@" + TestKdcServer.KDC_REALM;
+ private final String serverPassword = "654321";
private final String serverPrincipalName = "test-service";
private final String serverPrincipal;
@@ -112,6 +113,10 @@ public abstract class KdcTestBase {
return clientPassword;
}
+ protected String getServerPassword() {
+ return serverPassword;
+ }
+
protected String getServerPrincipal() {
return serverPrincipal;
}
@@ -127,7 +132,7 @@ public abstract class KdcTestBase {
protected boolean allowTcp() {
return true;
}
-
+
@Before
public void setUp() throws Exception {
setUpKdcServer();
@@ -159,7 +164,7 @@ public abstract class KdcTestBase {
}
protected void createPrincipals() throws KrbException {
- kdcServer.createPrincipals(serverPrincipal);
+ kdcServer.createPrincipal(serverPrincipal, serverPassword);
kdcServer.createPrincipal(clientPrincipal, clientPassword);
}