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 2017/04/19 06:37:34 UTC

directory-kerby git commit: DIRKRB-621 0x502 version keytab with multiple entries are not read properly. Contributed by Attila Sasvari.

Repository: directory-kerby
Updated Branches:
  refs/heads/trunk 38c50aa73 -> bfc00c357


DIRKRB-621 0x502 version keytab with multiple entries are not read properly. Contributed by Attila Sasvari.


Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/commit/bfc00c35
Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/bfc00c35
Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/bfc00c35

Branch: refs/heads/trunk
Commit: bfc00c357264d817cc0a97c9d685cb58a3c9b3c4
Parents: 38c50aa
Author: plusplusjiajia <ji...@intel.com>
Authored: Wed Apr 19 14:44:55 2017 +0800
Committer: plusplusjiajia <ji...@intel.com>
Committed: Wed Apr 19 14:44:55 2017 +0800

----------------------------------------------------------------------
 kerby-kerb/kerb-util/pom.xml                    |  11 +++
 .../kerby/kerberos/kerb/keytab/Keytab.java      |  22 +++---
 .../kerby/kerberos/kerb/keytab/KeytabEntry.java |  32 +++++++--
 .../kerberos/kerb/keytab/KeytabInputStream.java |   8 +--
 .../kerberos/kerb/keytab/KeytabEntryTest.java   |  67 +++++++++++++++++
 .../kerby/kerberos/kerb/util/KeytabTest.java    |  71 +++++++++++++++----
 .../resources/test_multiple_principles.keytab   | Bin 0 -> 1202 bytes
 7 files changed, 180 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/bfc00c35/kerby-kerb/kerb-util/pom.xml
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/pom.xml b/kerby-kerb/kerb-util/pom.xml
index ab64ad6..3d6fc94 100644
--- a/kerby-kerb/kerb-util/pom.xml
+++ b/kerby-kerb/kerb-util/pom.xml
@@ -42,5 +42,16 @@
       <artifactId>kerb-crypto</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <version>1.9.0</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/bfc00c35/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/Keytab.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/Keytab.java b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/Keytab.java
index e7d6251..460f1aa 100644
--- a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/Keytab.java
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/Keytab.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.keytab;
 
@@ -181,21 +181,27 @@ public final class Keytab implements KrbKeytab {
     private List<KeytabEntry> readEntries(KeytabInputStream kis) throws IOException {
         List<KeytabEntry> entries = new ArrayList<KeytabEntry>();
 
-        while (kis.available() > 0) {
+        int bytesLeft = kis.available();
+        while (bytesLeft > 0) {
             int entrySize = kis.readInt();
             if (kis.available() < entrySize) {
                 throw new IOException("Bad input stream with less data than expected: " + entrySize);
             }
-            KeytabEntry entry = readEntry(kis);
+            KeytabEntry entry = readEntry(kis, entrySize);
             entries.add(entry);
+            int bytesReadForEntry = bytesLeft - kis.available();
+            if (bytesReadForEntry != entrySize) {
+                kis.skipBytes(entrySize - bytesReadForEntry); // reposition to the next keytab entry
+            }
+            bytesLeft = kis.available();
         }
 
         return entries;
     }
 
-    private KeytabEntry readEntry(KeytabInputStream kis) throws IOException {
+    private KeytabEntry readEntry(KeytabInputStream kis, int entrySize) throws IOException {
         KeytabEntry entry = new KeytabEntry();
-        entry.load(kis, version);
+        entry.load(kis, version, entrySize);
         return entry;
     }
 

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/bfc00c35/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabEntry.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabEntry.java b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabEntry.java
index 2744aad..8f6f1bd 100644
--- a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabEntry.java
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabEntry.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.keytab;
 
@@ -44,7 +44,8 @@ public class KeytabEntry {
 
     }
 
-    public void load(KeytabInputStream kis, int version) throws IOException {
+    void load(KeytabInputStream kis, int version, int entrySize) throws IOException {
+        int bytesLeft = kis.available();
         this.principal = kis.readPrincipal(version);
 
         this.timestamp = kis.readTime();
@@ -52,9 +53,26 @@ public class KeytabEntry {
         this.kvno = kis.readByte();
 
         this.key = kis.readKey();
+
+        int entryBytesRead = bytesLeft - kis.available();
+
+        // Some implementations of Kerberos recognize a 32-bit key version at the end of an entry, if record length is
+        // at least 4 bytes longer than the entry and the value of those 32 bits is not 0. If present, this key version
+        // supersedes the 8-bit key version.
+        if (entryBytesRead + 4 <= entrySize) {
+            int tmp = kis.readInt();
+
+            if (tmp != 0) {
+                this.kvno = tmp;
+            }
+        } else if (entryBytesRead != entrySize) {
+            throw new IOException(
+                    String.format("Bad input stream with less data read [%d] than expected [%d] for keytab entry.",
+                            entryBytesRead, entrySize));
+        }
     }
 
-    public void store(KeytabOutputStream kos) throws IOException {
+    void store(KeytabOutputStream kos) throws IOException {
         byte[] body = null;
 
         // compute entry body content first so that to get and write the size
@@ -84,7 +102,7 @@ public class KeytabEntry {
         return timestamp;
     }
 
-    public void writeBody(KeytabOutputStream kos, int version) throws IOException {
+    void writeBody(KeytabOutputStream kos, int version) throws IOException {
         kos.writePrincipal(principal, version);
 
         kos.writeTime(timestamp);

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/bfc00c35/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabInputStream.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabInputStream.java b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabInputStream.java
index 111ad14..0b839c7 100644
--- a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabInputStream.java
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabInputStream.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.keytab;
 

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/bfc00c35/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/keytab/KeytabEntryTest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/keytab/KeytabEntryTest.java b/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/keytab/KeytabEntryTest.java
new file mode 100644
index 0000000..2afc33f
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/keytab/KeytabEntryTest.java
@@ -0,0 +1,67 @@
+/**
+ *  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.keytab;
+
+import org.apache.kerby.kerberos.kerb.type.KerberosTime;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.stubbing.Answer;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+@RunWith(MockitoJUnitRunner.class)
+public class KeytabEntryTest {
+    @Test(expected = IOException.class)
+    public void exceptionThrownWhenLoadingInvalidKeytabEntry() throws Exception {
+        KeytabInputStream mockKeytabInputStream = spy(
+                new KeytabInputStream(
+                        new ByteArrayInputStream(new String("randomtestarray").getBytes())));
+
+        doAnswer(new Answer<Integer>() {
+                     private boolean isFirstCall = true;
+
+                     @Override
+                     public Integer answer(InvocationOnMock invocationOnMock) throws Throwable {
+                         if (isFirstCall) {
+                             isFirstCall = false;
+                             return 200;
+                         }
+                         return 20;
+                     }
+                 }).when(mockKeytabInputStream).available();
+        doReturn(120).when(mockKeytabInputStream).readOctetsCount();
+        doReturn(new byte[]{}).when(mockKeytabInputStream).readCountedOctets();
+        doReturn(null).when(mockKeytabInputStream).readPrincipal(Matchers.any(Integer.class));
+        doReturn(new KerberosTime()).when(mockKeytabInputStream).readTime();
+
+        KeytabEntry keytabEntry = new KeytabEntry();
+        keytabEntry.load(mockKeytabInputStream, 0x502, 100);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/bfc00c35/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/KeytabTest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/KeytabTest.java b/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/KeytabTest.java
index 11d434a..c312d59 100644
--- a/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/KeytabTest.java
+++ b/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/KeytabTest.java
@@ -22,15 +22,18 @@ package org.apache.kerby.kerberos.kerb.util;
 import org.apache.kerby.kerberos.kerb.keytab.Keytab;
 import org.apache.kerby.kerberos.kerb.keytab.KeytabEntry;
 import org.apache.kerby.kerberos.kerb.type.base.PrincipalName;
-import org.junit.Before;
 import org.junit.Test;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
 
+import static junit.framework.TestCase.assertEquals;
 import static org.assertj.core.api.Assertions.assertThat;
 
+public class KeytabTest {
+    @Test
+    public void testKeytab() throws IOException  {
 /*
 The principal was created with password '123456'
 
@@ -45,18 +48,8 @@ KVNO Principal
    1 test@SH.INTEL.COM (camellia256-cts-cmac)
    1 test@SH.INTEL.COM (camellia128-cts-cmac)
  */
-public class KeytabTest {
-
-    private Keytab keytab;
-
-    @Before
-    public void setUp() throws IOException {
         InputStream kis = KeytabTest.class.getResourceAsStream("/test.keytab");
-        keytab = Keytab.loadKeytab(kis);
-    }
-
-    @Test
-    public void testKeytab() {
+        Keytab keytab = Keytab.loadKeytab(kis);
         assertThat(keytab).isNotNull();
 
         List<PrincipalName> principals = keytab.getPrincipals();
@@ -65,6 +58,60 @@ public class KeytabTest {
         for (KeytabEntry ke : entries) {
             assertThat(ke.getKvno() == 1).isTrue();
         }
+        assertEquals(8, entries.size());
+    }
+
+    @Test
+    public void testKeytabWithMultiplePrinciples() throws IOException {
+/*
+The principal was created with password 'test'
+
+Keytab name: FILE:test.keytab
+KVNO Timestamp         Principal
+---- ----------------- --------------------------------------------------------
+   3 04/11/17 14:16:34 test/examples.com@EXAMPLE.COM (aes256-cts-hmac-sha1-96)
+   3 04/11/17 14:16:34 test/examples.com@EXAMPLE.COM (aes128-cts-hmac-sha1-96)
+   3 04/11/17 14:16:34 test/examples.com@EXAMPLE.COM (des3-cbc-sha1)
+   3 04/11/17 14:16:34 test/examples.com@EXAMPLE.COM (arcfour-hmac)
+   3 04/11/17 14:16:34 test/examples.com@EXAMPLE.COM (camellia256-cts-cmac)
+   3 04/11/17 14:16:34 test/examples.com@EXAMPLE.COM (camellia128-cts-cmac)
+   3 04/11/17 14:16:34 test/examples.com@EXAMPLE.COM (des-hmac-sha1)
+   3 04/11/17 14:16:34 test/examples.com@EXAMPLE.COM (des-cbc-md5)
+   3 04/11/17 14:16:51 HTTP/examples.com@EXAMPLE.COM (aes256-cts-hmac-sha1-96)
+   3 04/11/17 14:16:52 HTTP/examples.com@EXAMPLE.COM (aes128-cts-hmac-sha1-96)
+   3 04/11/17 14:16:52 HTTP/examples.com@EXAMPLE.COM (des3-cbc-sha1)
+   3 04/11/17 14:16:52 HTTP/examples.com@EXAMPLE.COM (arcfour-hmac)
+   3 04/11/17 14:16:52 HTTP/examples.com@EXAMPLE.COM (camellia256-cts-cmac)
+   3 04/11/17 14:16:52 HTTP/examples.com@EXAMPLE.COM (camellia128-cts-cmac)
+   3 04/11/17 14:16:52 HTTP/examples.com@EXAMPLE.COM (des-hmac-sha1)
+   3 04/11/17 14:16:52 HTTP/examples.com@EXAMPLE.COM (des-cbc-md5)
+ */
+        InputStream kis = KeytabTest.class.getResourceAsStream("/test_multiple_principles.keytab");
+        Keytab keytab = Keytab.loadKeytab(kis);
+        assertThat(keytab).isNotNull();
+
+        List<PrincipalName> principals = keytab.getPrincipals();
+        assertEquals(2, keytab.getPrincipals().size());
+
+        int numEntries = keytab.getKeytabEntries(principals.get(0)).size()
+                + keytab.getKeytabEntries(principals.get(1)).size();
+        assertEquals(16, numEntries);
+    }
+
+    @Test
+    public void testSKeytab() throws IOException {
+
+        InputStream kis = KeytabTest.class.getResourceAsStream("/test_multiple_principles.keytab");
+
+        Keytab keytab = Keytab.loadKeytab(kis);
+        assertThat(keytab).isNotNull();
+
+        List<PrincipalName> principals = keytab.getPrincipals();
+        assertEquals(2, keytab.getPrincipals().size());
+
+        int numEntries = keytab.getKeytabEntries(principals.get(0)).size()
+                + keytab.getKeytabEntries(principals.get(1)).size();
+        assertEquals(16, numEntries);
     }
 
     public static void main(String[] args) throws IOException {

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/bfc00c35/kerby-kerb/kerb-util/src/test/resources/test_multiple_principles.keytab
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/test/resources/test_multiple_principles.keytab b/kerby-kerb/kerb-util/src/test/resources/test_multiple_principles.keytab
new file mode 100644
index 0000000..5e4b64b
Binary files /dev/null and b/kerby-kerb/kerb-util/src/test/resources/test_multiple_principles.keytab differ