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>