From commits-return-43711-apmail-directory-commits-archive=directory.apache.org@directory.apache.org Wed Nov 4 08:25:37 2015 Return-Path: X-Original-To: apmail-directory-commits-archive@www.apache.org Delivered-To: apmail-directory-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 1F04418C41 for ; Wed, 4 Nov 2015 08:25:30 +0000 (UTC) Received: (qmail 34305 invoked by uid 500); 4 Nov 2015 08:25:28 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 33695 invoked by uid 500); 4 Nov 2015 08:25:28 -0000 Mailing-List: contact commits-help@directory.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@directory.apache.org Delivered-To: mailing list commits@directory.apache.org Received: (qmail 32501 invoked by uid 99); 4 Nov 2015 08:25:28 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 04 Nov 2015 08:25:28 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id E3171E03C8; Wed, 4 Nov 2015 08:25:27 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: plusplusjiajia@apache.org To: commits@directory.apache.org Date: Wed, 04 Nov 2015 08:26:02 -0000 Message-Id: <9a7da34ac63f49698681edfada50515b@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [36/48] directory-kerby git commit: Add support for decrypting JWT tokens in the KDC Add support for decrypting JWT tokens in the KDC Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/commit/b58fb7f6 Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/b58fb7f6 Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/b58fb7f6 Branch: refs/heads/pkinit-support Commit: b58fb7f69935f404e78f195892a193c8e89760e3 Parents: c3ada0c Author: Colm O hEigeartaigh Authored: Thu Oct 22 11:26:57 2015 +0100 Committer: Colm O hEigeartaigh Committed: Thu Oct 22 11:26:57 2015 +0100 ---------------------------------------------------------------------- .../kerberos/kdc/WithAccessTokenKdcTest.java | 23 +++++- .../kerberos/kdc/WithIdentityTokenKdcTest.java | 23 +++++- .../kerberos/kdc/WithTokenKdcTestBase.java | 12 ++- .../kerby/kerberos/kerb/server/KdcConfig.java | 4 + .../kerberos/kerb/server/KdcConfigKey.java | 1 + .../kerb/server/preauth/token/TokenPreauth.java | 87 +++++++++++++------- 6 files changed, 112 insertions(+), 38 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/b58fb7f6/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithAccessTokenKdcTest.java ---------------------------------------------------------------------- diff --git a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithAccessTokenKdcTest.java b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithAccessTokenKdcTest.java index 544923d..0664529 100644 --- a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithAccessTokenKdcTest.java +++ b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithAccessTokenKdcTest.java @@ -23,9 +23,11 @@ import java.io.InputStream; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; +import java.security.PublicKey; import org.apache.kerby.kerberos.kerb.KrbException; import org.apache.kerby.kerberos.kerb.common.PrivateKeyReader; +import org.apache.kerby.kerberos.kerb.common.PublicKeyReader; import org.apache.kerby.kerberos.kerb.server.TestKdcServer; import org.apache.kerby.kerberos.kerb.spec.ticket.ServiceTicket; import org.junit.Assert; @@ -43,7 +45,7 @@ public class WithAccessTokenKdcTest extends WithTokenKdcTestBase { public void testBadIssuer() throws Exception { InputStream is = WithTokenKdcTestBase.class.getResourceAsStream("/private_key.pem"); PrivateKey privateKey = PrivateKeyReader.loadPrivateKey(is); - prepareToken(getServerPrincipal(), "oauth1.com", AUDIENCE, privateKey); + prepareToken(getServerPrincipal(), "oauth1.com", AUDIENCE, privateKey, null); try { performTest(); @@ -59,7 +61,7 @@ public class WithAccessTokenKdcTest extends WithTokenKdcTestBase { InputStream is = WithTokenKdcTestBase.class.getResourceAsStream("/private_key.pem"); PrivateKey privateKey = PrivateKeyReader.loadPrivateKey(is); prepareToken("bad-service" + "/" + getHostname() + "@" + TestKdcServer.KDC_REALM, - ISSUER, AUDIENCE, privateKey); + ISSUER, AUDIENCE, privateKey, null); try { performTest(); @@ -74,7 +76,7 @@ public class WithAccessTokenKdcTest extends WithTokenKdcTestBase { @Test @org.junit.Ignore public void testUnsignedToken() throws Exception { - prepareToken(getServerPrincipal(), ISSUER, AUDIENCE, null); + prepareToken(getServerPrincipal(), ISSUER, AUDIENCE, null, null); try { performTest(); @@ -89,7 +91,7 @@ public class WithAccessTokenKdcTest extends WithTokenKdcTestBase { public void testSignedTokenWithABadKey() throws Exception { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); KeyPair keyPair = keyGen.generateKeyPair(); - prepareToken(getServerPrincipal(), ISSUER, AUDIENCE, keyPair.getPrivate()); + prepareToken(getServerPrincipal(), ISSUER, AUDIENCE, keyPair.getPrivate(), null); try { performTest(); @@ -100,6 +102,19 @@ public class WithAccessTokenKdcTest extends WithTokenKdcTestBase { } } + @Test + public void testSignedEncryptedToken() throws Exception { + InputStream is = WithTokenKdcTestBase.class.getResourceAsStream("/private_key.pem"); + PrivateKey privateKey = PrivateKeyReader.loadPrivateKey(is); + + is = WithTokenKdcTestBase.class.getResourceAsStream("/oauth2.com_public_key.pem"); + PublicKey publicKey = PublicKeyReader.loadPublicKey(is); + + prepareToken(getServerPrincipal(), ISSUER, AUDIENCE, privateKey, publicKey); + + performTest(); + } + private void performTest() throws Exception { createCredentialCache(getClientPrincipal(), getClientPassword()); http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/b58fb7f6/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithIdentityTokenKdcTest.java ---------------------------------------------------------------------- diff --git a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithIdentityTokenKdcTest.java b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithIdentityTokenKdcTest.java index 71f9da7..eb89df6 100644 --- a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithIdentityTokenKdcTest.java +++ b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithIdentityTokenKdcTest.java @@ -21,6 +21,7 @@ package org.apache.kerby.kerberos.kdc; import org.apache.kerby.kerberos.kerb.KrbException; import org.apache.kerby.kerberos.kerb.common.PrivateKeyReader; +import org.apache.kerby.kerberos.kerb.common.PublicKeyReader; import org.apache.kerby.kerberos.kerb.spec.ticket.ServiceTicket; import org.apache.kerby.kerberos.kerb.spec.ticket.TgtTicket; import org.junit.Assert; @@ -30,6 +31,7 @@ import java.io.InputStream; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; +import java.security.PublicKey; public class WithIdentityTokenKdcTest extends WithTokenKdcTestBase { @@ -44,7 +46,7 @@ public class WithIdentityTokenKdcTest extends WithTokenKdcTestBase { public void testBadIssuer() throws Exception { InputStream is = WithTokenKdcTestBase.class.getResourceAsStream("/private_key.pem"); PrivateKey privateKey = PrivateKeyReader.loadPrivateKey(is); - prepareToken(null, "oauth1.com", AUDIENCE, privateKey); + prepareToken(null, "oauth1.com", AUDIENCE, privateKey, null); try { performTest(); @@ -61,7 +63,7 @@ public class WithIdentityTokenKdcTest extends WithTokenKdcTestBase { public void testBadAudienceRestriction() throws Exception { InputStream is = WithTokenKdcTestBase.class.getResourceAsStream("/private_key.pem"); PrivateKey privateKey = PrivateKeyReader.loadPrivateKey(is); - prepareToken(null, ISSUER, "krbtgt2@EXAMPLE.COM", privateKey); + prepareToken(null, ISSUER, "krbtgt2@EXAMPLE.COM", privateKey, null); try { performTest(); @@ -76,7 +78,7 @@ public class WithIdentityTokenKdcTest extends WithTokenKdcTestBase { @Test @org.junit.Ignore public void testUnsignedToken() throws Exception { - prepareToken(null, ISSUER, "krbtgt2@EXAMPLE.COM", null); + prepareToken(null, ISSUER, "krbtgt2@EXAMPLE.COM", null, null); try { performTest(); @@ -91,7 +93,7 @@ public class WithIdentityTokenKdcTest extends WithTokenKdcTestBase { public void testSignedTokenWithABadKey() throws Exception { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); KeyPair keyPair = keyGen.generateKeyPair(); - prepareToken(null, ISSUER, AUDIENCE, keyPair.getPrivate()); + prepareToken(null, ISSUER, AUDIENCE, keyPair.getPrivate(), null); try { performTest(); @@ -102,6 +104,19 @@ public class WithIdentityTokenKdcTest extends WithTokenKdcTestBase { } } + @Test + public void testSignedEncryptedToken() throws Exception { + InputStream is = WithTokenKdcTestBase.class.getResourceAsStream("/private_key.pem"); + PrivateKey privateKey = PrivateKeyReader.loadPrivateKey(is); + + is = WithTokenKdcTestBase.class.getResourceAsStream("/oauth2.com_public_key.pem"); + PublicKey publicKey = PublicKeyReader.loadPublicKey(is); + + prepareToken(null, ISSUER, AUDIENCE, privateKey, publicKey); + + performTest(); + } + private void performTest() throws Exception { createCredentialCache(getClientPrincipal(), getClientPassword()); http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/b58fb7f6/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithTokenKdcTestBase.java ---------------------------------------------------------------------- diff --git a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithTokenKdcTestBase.java b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithTokenKdcTestBase.java index 8db50f9..0b94be5 100644 --- a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithTokenKdcTestBase.java +++ b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithTokenKdcTestBase.java @@ -39,7 +39,9 @@ import org.junit.Before; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.net.URL; import java.security.PrivateKey; +import java.security.PublicKey; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -66,6 +68,9 @@ public class WithTokenKdcTestBase extends KdcTestBase { super.configKdcSeverAndClient(); String verifyKeyPath = this.getClass().getResource("/").getPath(); getKdcServer().getKdcConfig().setString(KdcConfigKey.VERIFY_KEY, verifyKeyPath); + + URL privateKeyPath = WithTokenKdcTestBase.class.getResource("/private_key.pem"); + getKdcServer().getKdcConfig().setString(KdcConfigKey.DECRYPTION_KEY, privateKeyPath.getPath()); getKdcServer().getKdcConfig().setString(KdcConfigKey.ISSUERS, ISSUER); } @@ -86,11 +91,11 @@ public class WithTokenKdcTestBase extends KdcTestBase { e.printStackTrace(); } - return prepareToken(servicePrincipal, ISSUER, AUDIENCE, privateKey); + return prepareToken(servicePrincipal, ISSUER, AUDIENCE, privateKey, null); } protected AuthToken prepareToken(String servicePrincipal, String issuer, String audience, - PrivateKey signingKey) { + PrivateKey signingKey, PublicKey encryptionKey) { AuthToken authToken = KrbRuntime.getTokenProvider().createTokenFactory().createToken(); authToken.setIssuer(issuer); authToken.setSubject(SUBJECT); @@ -121,6 +126,9 @@ public class WithTokenKdcTestBase extends KdcTestBase { if (tokenEncoder instanceof JwtTokenEncoder && signingKey != null) { ((JwtTokenEncoder) tokenEncoder).setSignKey(signingKey); } + if (tokenEncoder instanceof JwtTokenEncoder && encryptionKey != null) { + ((JwtTokenEncoder) tokenEncoder).setEncryptionKey(encryptionKey); + } krbToken = new KrbToken(); krbToken.setInnerToken(authToken); http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/b58fb7f6/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfig.java ---------------------------------------------------------------------- diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfig.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfig.java index dc2fc78..82b8dfd 100644 --- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfig.java +++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfig.java @@ -167,6 +167,10 @@ public class KdcConfig extends Conf { return KrbConfHelper.getStringUnderSection(this, KdcConfigKey.VERIFY_KEY); } + public String getDecryptionKeyConfig() { + return KrbConfHelper.getStringUnderSection(this, KdcConfigKey.DECRYPTION_KEY); + } + public List getIssuers() { return Arrays.asList(KrbConfHelper.getStringArrayUnderSection(this, KdcConfigKey.ISSUERS)); } http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/b58fb7f6/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfigKey.java ---------------------------------------------------------------------- diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfigKey.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfigKey.java index 771c781..178d19d 100644 --- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfigKey.java +++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfigKey.java @@ -50,6 +50,7 @@ public enum KdcConfigKey implements SectionConfigKey { RESTRICT_ANONYMOUS_TO_TGT(false, "kdcdefaults"), KDC_MAX_DGRAM_REPLY_SIZE(4096, "kdcdefaults"), VERIFY_KEY(null, "kdcdefaults"), + DECRYPTION_KEY(null, "kdcdefaults"), ISSUERS(null, "kdcdefaults"); private Object defaultValue; http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/b58fb7f6/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/token/TokenPreauth.java ---------------------------------------------------------------------- diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/token/TokenPreauth.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/token/TokenPreauth.java index 2de66b5..f3c8741 100644 --- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/token/TokenPreauth.java +++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/token/TokenPreauth.java @@ -23,6 +23,7 @@ import org.apache.kerby.kerberos.kerb.KrbCodec; import org.apache.kerby.kerberos.kerb.KrbException; import org.apache.kerby.kerberos.kerb.KrbRuntime; import org.apache.kerby.kerberos.kerb.common.EncryptionUtil; +import org.apache.kerby.kerberos.kerb.common.PrivateKeyReader; import org.apache.kerby.kerberos.kerb.common.PublicKeyReader; import org.apache.kerby.kerberos.kerb.preauth.PluginRequestContext; import org.apache.kerby.kerberos.kerb.preauth.token.TokenPreauthMeta; @@ -47,6 +48,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.security.PrivateKey; import java.security.PublicKey; import java.util.List; @@ -78,25 +80,11 @@ public class TokenPreauth extends AbstractPreauthPlugin { if (!(issuers.contains(issuer))) { throw new KrbException("Unconfigured issuer: " + issuer); } + + // Configure keys TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider().createTokenDecoder(); - if (tokenDecoder instanceof JwtTokenDecoder) { - String verifyKeyPath = kdcRequest.getKdcContext().getConfig().getVerifyKeyConfig(); - if (verifyKeyPath != null) { - File verifyKeyFile = getVerifyKeyFile(verifyKeyPath, issuer); - if (verifyKeyFile != null) { - PublicKey verifyKey = null; - try { - FileInputStream fis = new FileInputStream(verifyKeyFile); - verifyKey = PublicKeyReader.loadPublicKey(fis); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } - ((JwtTokenDecoder) tokenDecoder).setVerifyKey(verifyKey); - } - } - } + configureKeys(tokenDecoder, kdcRequest, issuer); + AuthToken authToken = null; try { authToken = tokenDecoder.decodeFromBytes(token.getTokenValue()); @@ -127,18 +115,61 @@ public class TokenPreauth extends AbstractPreauthPlugin { return false; } } + + private void configureKeys(TokenDecoder tokenDecoder, KdcRequest kdcRequest, String issuer) { + if (tokenDecoder instanceof JwtTokenDecoder) { + String verifyKeyPath = kdcRequest.getKdcContext().getConfig().getVerifyKeyConfig(); + if (verifyKeyPath != null) { + File verifyKeyFile = getKeyFile(verifyKeyPath, issuer); + if (verifyKeyFile != null) { + PublicKey verifyKey = null; + try { + FileInputStream fis = new FileInputStream(verifyKeyFile); + verifyKey = PublicKeyReader.loadPublicKey(fis); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + ((JwtTokenDecoder) tokenDecoder).setVerifyKey(verifyKey); + } + } + String decryptionKeyPath = kdcRequest.getKdcContext().getConfig().getDecryptionKeyConfig(); + if (decryptionKeyPath != null) { + File decryptionKeyFile = getKeyFile(decryptionKeyPath, issuer); + if (decryptionKeyFile != null) { + PrivateKey decryptionKey = null; + try { + FileInputStream fis = new FileInputStream(decryptionKeyFile); + decryptionKey = PrivateKeyReader.loadPrivateKey(fis); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + ((JwtTokenDecoder) tokenDecoder).setDecryptionKey(decryptionKey); + } + } + } + } - private File getVerifyKeyFile(String path, String issuer) { - File folder = new File(path); - File[] listOfFiles = folder.listFiles(); - File verifyKeyFile = null; - - for (int i = 0; i < listOfFiles.length; i++) { - if (listOfFiles[i].isFile() && listOfFiles[i].getName().contains(issuer)) { - verifyKeyFile = listOfFiles[i]; - break; + private File getKeyFile(String path, String issuer) { + File file = new File(path); + if (file.isDirectory()) { + File[] listOfFiles = file.listFiles(); + File verifyKeyFile = null; + + for (int i = 0; i < listOfFiles.length; i++) { + if (listOfFiles[i].isFile() && listOfFiles[i].getName().contains(issuer)) { + verifyKeyFile = listOfFiles[i]; + break; + } } + return verifyKeyFile; + } else if (file.isFile()) { + return file; } - return verifyKeyFile; + + return null; } }