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 2016/04/15 07:48:08 UTC

directory-kerby git commit: DIRKRB-551 Data type conversion between GSSAPI interface and Kerby. Contributed by Wei.

Repository: directory-kerby
Updated Branches:
  refs/heads/gssapi 752799ec9 -> 94d2612a3


DIRKRB-551 Data type conversion between GSSAPI interface and Kerby. Contributed by Wei.


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

Branch: refs/heads/gssapi
Commit: 94d2612a32e1e128a7ad57594cb5955452f12884
Parents: 752799e
Author: plusplusjiajia <ji...@intel.com>
Authored: Fri Apr 15 13:52:47 2016 +0800
Committer: plusplusjiajia <ji...@intel.com>
Committed: Fri Apr 15 13:52:47 2016 +0800

----------------------------------------------------------------------
 .../kerby/kerberos/kerb/client/ClientUtil.java  |   9 +-
 kerby-kerb/kerb-gssapi/pom.xml                  |  41 ++
 .../kerberos/kerb/gssapi/krb5/KerbyUtil.java    | 383 +++++++++++++++++++
 kerby-kerb/pom.xml                              |   1 +
 4 files changed, 431 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/94d2612a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/ClientUtil.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/ClientUtil.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/ClientUtil.java
index 49b7666..7591af5 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/ClientUtil.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/ClientUtil.java
@@ -35,12 +35,15 @@ public final class ClientUtil {
 
     /**
      * Load krb5.conf from specified conf dir.
-     * @param confDir The conf dir
+     * @param conf The conf file or dir, default file name 'krb5.conf' is used if dir
      * @return KrbConfig
      * @throws KrbException e
      */
-    public static KrbConfig getConfig(File confDir) throws KrbException {
-        File confFile = new File(confDir, KRB5_FILE_NAME);
+    public static KrbConfig getConfig(File conf) throws KrbException {
+        if (!conf.exists()) {
+            throw new KrbException(conf + " not found");
+        }
+        File confFile = conf.isDirectory() ? new File(conf, KRB5_FILE_NAME) : conf;
         if (!confFile.exists()) {
             throw new KrbException(KRB5_FILE_NAME + " not found");
         }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/94d2612a/kerby-kerb/kerb-gssapi/pom.xml
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/pom.xml b/kerby-kerb/kerb-gssapi/pom.xml
new file mode 100644
index 0000000..fd69078
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed 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. See accompanying LICENSE file.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.kerby</groupId>
+    <artifactId>kerby-kerb</artifactId>
+    <version>1.0.0-RC3-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>kerb-gssapi</artifactId>
+
+  <name>Kerby-kerb GssAPI</name>
+  <description>Kerby-kerb GSSAPI Implementation</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerb-crypto</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerb-client</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/94d2612a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyUtil.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyUtil.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyUtil.java
new file mode 100644
index 0000000..61eeb8d
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyUtil.java
@@ -0,0 +1,383 @@
+/**
+ *  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.gssapi.krb5;
+
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.client.KrbClientBase;
+import org.apache.kerby.kerberos.kerb.request.ApRequest;
+import org.apache.kerby.kerberos.kerb.type.KerberosTime;
+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.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.type.base.HostAddress;
+import org.apache.kerby.kerberos.kerb.type.base.HostAddresses;
+import org.apache.kerby.kerberos.kerb.type.base.PrincipalName;
+import org.apache.kerby.kerberos.kerb.type.kdc.EncAsRepPart;
+import org.apache.kerby.kerberos.kerb.type.kdc.EncKdcRepPart;
+import org.apache.kerby.kerberos.kerb.type.kdc.EncTgsRepPart;
+import org.apache.kerby.kerberos.kerb.type.ticket.KrbTicket;
+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.kerb.type.ticket.TicketFlags;
+import org.ietf.jgss.GSSException;
+
+import javax.crypto.SecretKey;
+import javax.security.auth.kerberos.KerberosKey;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.kerberos.KerberosTicket;
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Some utility functions to translate types between GSS and Kerby
+ */
+public class KerbyUtil {
+    private static final int KERBEROS_TICKET_NUM_FLAGS = 32;  // KerberosTicket.NUM_LENGTH
+
+    /**
+     * Construct TgtTicket from info contained in KerberosTicket
+     * @param kerberosTicket
+     * @return
+     * @throws GSSException
+     */
+    public static TgtTicket getTgtTicketFromKerberosTicket(KerberosTicket kerberosTicket) throws GSSException {
+        String clientName = kerberosTicket.getClient().getName();
+        PrincipalName clientPrincipal = new PrincipalName(clientName);
+
+        byte[] asn1Encoded = kerberosTicket.getEncoded();
+        Ticket ticket = getTicketFromAsn1Encoded(asn1Encoded);
+
+        EncAsRepPart encAsRepPart = new EncAsRepPart();
+        fillEncKdcRepPart(encAsRepPart, kerberosTicket);
+
+        TgtTicket tgt = new TgtTicket(ticket, encAsRepPart, clientPrincipal);
+        return tgt;
+    }
+
+    /**
+     *  Init encKdcRepPart members with info from kerberosTicket
+     * @param encKdcRepPart
+     * @param kerberosTicket
+     */
+    public static void fillEncKdcRepPart(EncKdcRepPart encKdcRepPart, KerberosTicket kerberosTicket) {
+        String clientName = kerberosTicket.getClient().getName();
+        PrincipalName clientPrincipal = new PrincipalName(clientName);
+
+        SecretKey secretKey = kerberosTicket.getSessionKey();
+        int keyType = kerberosTicket.getSessionKeyType();
+        EncryptionKey key = new EncryptionKey(keyType, secretKey.getEncoded());
+        encKdcRepPart.setKey(key);
+
+        encKdcRepPart.setSname(clientPrincipal);
+        Date authTimeDate = kerberosTicket.getAuthTime();
+        if (authTimeDate != null) {
+            encKdcRepPart.setAuthTime(new KerberosTime(authTimeDate.getTime()));
+        }
+        Date startTimeDate = kerberosTicket.getStartTime();
+        if (startTimeDate != null) {
+            encKdcRepPart.setStartTime(new KerberosTime(startTimeDate.getTime()));
+        }
+        KerberosTime endTime = new KerberosTime(kerberosTicket.getEndTime().getTime());
+        encKdcRepPart.setEndTime(endTime);
+
+
+        InetAddress[] clientAddresses = kerberosTicket.getClientAddresses();
+        HostAddresses hostAddresses = null;
+        if (clientAddresses != null) {
+            hostAddresses = new HostAddresses();
+            for (InetAddress iAddr : clientAddresses) {
+                hostAddresses.add(new HostAddress(iAddr));
+            }
+        }
+        encKdcRepPart.setCaddr(hostAddresses);
+
+        boolean[] tf = kerberosTicket.getFlags();
+        TicketFlags ticketFlags = getTicketFlags(tf);
+        encKdcRepPart.setFlags(ticketFlags);
+
+
+        /* encKdcRepPart.setKeyExpiration();
+        encKdcRepPart.setLastReq();
+        encKdcRepPart.setNonce(); */
+
+        Date renewTillDate = kerberosTicket.getRenewTill();
+        KerberosTime renewTill = renewTillDate == null ? null : new KerberosTime(renewTillDate.getTime());
+        encKdcRepPart.setRenewTill(renewTill);
+
+        String serverRealm = kerberosTicket.getServer().getRealm();
+        encKdcRepPart.setSrealm(serverRealm);
+    }
+
+    /**
+     * Generate TicketFlags instance from flags
+     * @param flags each item in flags identifies an bit setted or not
+     * @return
+     */
+    public static TicketFlags getTicketFlags(boolean[] flags) {
+        if (flags == null || flags.length != KERBEROS_TICKET_NUM_FLAGS) {
+            return null;
+        }
+        int value = 0;
+        for (boolean flag : flags) {
+            value = (value << 1) + (flag ? 1 : 0);
+        }
+        return new TicketFlags(value);
+    }
+
+    /**
+     * Decode each flag in ticketFlags into an boolean array
+     * @param ticketFlags
+     * @return
+     */
+    public static boolean[] ticketFlagsToBooleans(TicketFlags ticketFlags) {
+        boolean[] ret = new boolean[KERBEROS_TICKET_NUM_FLAGS];
+        int value = ticketFlags.getFlags();
+        for (int i = 0; i < KERBEROS_TICKET_NUM_FLAGS; i++) {
+            ret[KERBEROS_TICKET_NUM_FLAGS - i - 1] = (value & 0x1) != 0;
+            value = value >> 1;
+        }
+        return ret;
+    }
+
+    /**
+     * Construct a Ticket from bytes encoded by Asn1
+     * @param encoded
+     * @return
+     * @throws GSSException
+     */
+    public static Ticket getTicketFromAsn1Encoded(byte[] encoded) throws GSSException {
+        Ticket ticket = new Ticket();
+        ByteBuffer byteBuffer = ByteBuffer.wrap(encoded);
+        try {
+            ticket.decode(byteBuffer);
+            return ticket;
+        } catch (IOException e) {
+            throw new GSSException(GSSException.FAILURE, -1, e.getMessage());
+        }
+    }
+
+    /**
+     * Construct a SgtTicket from KerberosTicket
+     * @param kerberosTicket
+     * @return
+     * @throws GSSException
+     */
+    public static SgtTicket getSgtTicketFromKerberosTicket(KerberosTicket kerberosTicket) throws GSSException {
+        if (kerberosTicket == null) {
+            return null;
+        }
+
+        Ticket ticket = getTicketFromAsn1Encoded(kerberosTicket.getEncoded());
+
+        EncTgsRepPart encTgsRepPart = new EncTgsRepPart();
+        fillEncKdcRepPart(encTgsRepPart, kerberosTicket);
+
+        SgtTicket sgt = new SgtTicket(ticket, encTgsRepPart);
+        return sgt;
+    }
+
+    /**
+     *  Apply SgtTicket by sending TGS_REQ to KDC
+     * @param ticket
+     * @param service
+     * @return
+     */
+    public static SgtTicket applySgtCredential(KerberosTicket ticket, String service) throws GSSException {
+        TgtTicket tgt = getTgtTicketFromKerberosTicket(ticket);
+        return applySgtCredential(tgt, service);
+    }
+
+    public static SgtTicket applySgtCredential(TgtTicket tgt, String server) throws GSSException {
+        KrbClientBase client = getKrbClient();
+
+        SgtTicket sgt = null;
+        try {
+            client.init();
+            sgt = client.requestSgt(tgt, server);
+            return sgt;
+        } catch (KrbException e) {
+            throw new GSSException(GSSException.FAILURE, -1, e.getMessage());
+        }
+    }
+
+    public static KerberosTicket convertKrbTicketToKerberosTicket(KrbTicket krbTicket, String clientName)
+            throws GSSException {
+        byte[] asn1Encoding;
+        try {
+            asn1Encoding = krbTicket.getTicket().encode();
+        } catch (IOException e) {
+            throw new GSSException(GSSException.FAILURE, -1, e.getMessage());
+        }
+
+        byte[] sessionKey = krbTicket.getSessionKey().getKeyData();
+        int keyType = krbTicket.getSessionKey().getKeyType().getValue();
+
+        EncKdcRepPart encKdcRepPart = krbTicket.getEncKdcRepPart();
+        KerberosPrincipal client = new KerberosPrincipal(clientName);
+
+        PrincipalName serverPrinc = krbTicket.getTicket().getSname();
+        String serverName = serverPrinc.getName() + "@" + krbTicket.getTicket().getRealm();
+        KerberosPrincipal server = new KerberosPrincipal(serverName, serverPrinc.getNameType().getValue());
+
+        TicketFlags ticketFlags = encKdcRepPart.getFlags();
+        boolean[] flags = ticketFlagsToBooleans(ticketFlags);
+
+        Date authTime = new Date(encKdcRepPart.getAuthTime().getTime());
+        Date startTime = new Date(encKdcRepPart.getStartTime().getTime());
+        Date endTime = new Date(encKdcRepPart.getEndTime().getTime());
+        Date renewTill = new Date(encKdcRepPart.getRenewTill().getTime());
+
+        InetAddress[] clientAddresses = null;
+        List<HostAddress> hostAddresses = encKdcRepPart.getCaddr().getElements();
+        if (hostAddresses != null) {
+            int i = 0;
+            clientAddresses = new InetAddress[hostAddresses.size()];
+            for (HostAddress hostAddr : hostAddresses) {
+                try {
+                    InetAddress iAddr = InetAddress.getByAddress(hostAddr.getAddress());
+                    clientAddresses[i++] = iAddr;
+                } catch (UnknownHostException e) {
+                    throw new GSSException(GSSException.FAILURE, -1, "Bad client address");
+                }
+            }
+        }
+
+        KerberosTicket ticket = new KerberosTicket(
+                asn1Encoding,
+                client,
+                server,
+                sessionKey,
+                keyType,
+                flags,
+                authTime,
+                startTime,
+                endTime,
+                renewTill,
+                clientAddresses
+        );
+        return ticket;
+    }
+
+    public static byte[] getAPRequest(PrincipalName clientPricipal, SgtTicket sgt) throws GSSException {
+        ApRequest apRequest = new ApRequest(clientPricipal, sgt);
+        try {
+            return apRequest.getApReq().encode();
+        } catch (Exception e) {  // IOExcetpion, KrbException
+            throw new GSSException(GSSException.FAILURE, -1, "Generate ApReq failed: " + e.getMessage());
+        }
+    }
+
+    public static KrbClientBase getKrbClient() {
+        KrbClientBase client;
+        try {
+            File confSpecified = new File(getSystemProperty("java.security.krb5.conf"));
+            if (confSpecified != null) {
+                client = new KrbClientBase(confSpecified);
+            } else {
+                client = new KrbClientBase();   // get configure file from environment variable or default path
+            }
+
+            return client;
+        } catch (KrbException e) {
+            return null;
+        }
+    }
+
+    public static EncryptionKey[] convertKerberosKeyToEncryptionKey(KerberosKey[] krbKeys) {
+        if (krbKeys == null) {
+            return null;
+        }
+        EncryptionKey[] keys = new EncryptionKey[krbKeys.length];
+        int i = 0;
+        for (KerberosKey krbKey : krbKeys) {
+            keys[i++] = new EncryptionKey(krbKey.getKeyType(), krbKey.getEncoded());
+        }
+        return keys;
+    }
+
+    /**
+     * Filter out an appropriate KerberosKey from krbKeys and generate a
+     * EncryptionKey accordingly
+     *
+     * @param krbKeys
+     * @param encType
+     * @param kvno
+     * @return
+     */
+    public static EncryptionKey getEncryptionKey(KerberosKey[] krbKeys, int encType, int kvno) {
+        if (krbKeys == null) {
+            return null;
+        }
+        for (KerberosKey krbKey : krbKeys) {
+            if (krbKey.getKeyType() == encType && krbKey.getVersionNumber() == kvno && !krbKey.isDestroyed()) {
+                return new EncryptionKey(krbKey.getKeyType(), krbKey.getEncoded());
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Get value of predefined system property
+     * @param name
+     * @return
+     */
+    private static String getSystemProperty(String name) {
+        if (name == null) {
+            return null;
+        }
+
+        final String propertyName = name;
+        try {
+            return AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<String>() {
+                        public String run() {
+                            return System.getProperty(propertyName);
+                        }
+                    });
+        } catch (PrivilegedActionException e) {
+            return null;    // ignored
+        }
+    }
+
+    public static com.sun.security.jgss.AuthorizationDataEntry[]
+    kerbyAuthorizationDataToJgssAuthorizationDataEntries(AuthorizationData authData) {
+        if (authData == null) {
+            return null;
+        }
+        List<AuthorizationDataEntry> kerbyEntries = authData.getElements();
+        com.sun.security.jgss.AuthorizationDataEntry[] entries =
+                new com.sun.security.jgss.AuthorizationDataEntry[kerbyEntries.size()];
+        for (int i = 0; i < kerbyEntries.size(); i++) {
+            entries[i] = new com.sun.security.jgss.AuthorizationDataEntry(
+                    kerbyEntries.get(i).getAuthzType().getValue(),
+                    kerbyEntries.get(i).getAuthzData());
+        }
+        return entries;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/94d2612a/kerby-kerb/pom.xml
----------------------------------------------------------------------
diff --git a/kerby-kerb/pom.xml b/kerby-kerb/pom.xml
index 4b2537b..b4bd52f 100644
--- a/kerby-kerb/pom.xml
+++ b/kerby-kerb/pom.xml
@@ -40,5 +40,6 @@
     <module>kerb-simplekdc</module>
     <module>kerb-client-api-all</module>
     <module>kerb-server-api-all</module>
+    <module>kerb-gssapi</module>
   </modules>
 </project>