You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by pl...@apache.org on 2015/11/04 09:26:02 UTC

[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 <co...@apache.org>
Authored: Thu Oct 22 11:26:57 2015 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
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<String> 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;
     }
 }