You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by co...@apache.org on 2017/07/21 15:03:30 UTC
[13/18] directory-kerby git commit: Refactoring the package and
structure
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/976b16cf/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssTokenV2.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssTokenV2.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssTokenV2.java
new file mode 100644
index 0000000..5220900
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssTokenV2.java
@@ -0,0 +1,282 @@
+/**
+ * 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.gss.impl;
+
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.MessageProp;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.MessageDigest;
+
+/**
+ * This class implements the token formats defined in RFC 4121.
+ */
+abstract class GssTokenV2 extends GssTokenBase {
+ public static final int CONFOUNDER_SIZE = 16;
+ public static final int TOKEN_HEADER_SIZE = 16;
+ private static final int OFFSET_EC = 4;
+ private static final int OFFSET_RRC = 6;
+
+ // context states
+ private boolean isInitiator = true;
+ private boolean acceptorSubKey = false;
+ private boolean confState = true;
+ private int sequenceNumber;
+
+ // token data
+ protected int tokenType;
+ private byte[] header = new byte[TOKEN_HEADER_SIZE];
+ protected byte[] tokenData;
+
+ protected byte[] checkSum;
+ private int ec;
+ private int rrc;
+
+ static final int KG_USAGE_ACCEPTOR_SEAL = 22;
+ static final int KG_USAGE_ACCEPTOR_SIGN = 23;
+ static final int KG_USAGE_INITIATOR_SEAL = 24;
+ static final int KG_USAGE_INITIATOR_SIGN = 25;
+ private int keyUsage;
+
+ private static final int FLAG_SENT_BY_ACCEPTOR = 1;
+ private static final int FLAG_SEALED = 2;
+ private static final int FLAG_ACCEPTOR_SUBKEY = 4;
+
+ protected GssEncryptor encryptor;
+
+
+ // Create a new token
+ GssTokenV2(int tokenType, GssContext context) throws GSSException {
+ initialize(tokenType, context, false);
+ }
+
+ private void initialize(int tokenType, GssContext context, boolean reconstruct) throws GSSException {
+ this.tokenType = tokenType;
+ this.isInitiator = context.isInitiator();
+ this.acceptorSubKey = context.getKeyComesFrom() == GssContext.ACCEPTOR_SUBKEY;
+ this.confState = context.getConfState();
+
+ boolean usageFlag = reconstruct ? !this.isInitiator : this.isInitiator;
+ if (tokenType == TOKEN_WRAP_V2) {
+ keyUsage = usageFlag ? KG_USAGE_INITIATOR_SEAL : KG_USAGE_ACCEPTOR_SEAL;
+ } else if (tokenType == TOKEN_MIC_V2) {
+ keyUsage = usageFlag ? KG_USAGE_INITIATOR_SIGN : KG_USAGE_ACCEPTOR_SIGN;
+ }
+
+ encryptor = context.getGssEncryptor();
+
+ if (!reconstruct) {
+ this.sequenceNumber = context.incMySequenceNumber();
+ }
+ }
+
+ // Reconstruct token from bytes received
+ GssTokenV2(int tokenType, GssContext context,
+ MessageProp prop, byte[] token, int offset, int len) throws GSSException {
+ this(tokenType, context, prop, new ByteArrayInputStream(token, offset, len));
+ }
+
+ // Reconstruct token from input stream
+ GssTokenV2(int tokenType, GssContext context,
+ MessageProp prop, InputStream is) throws GSSException {
+ initialize(tokenType, context, true);
+
+ if (!confState) {
+ prop.setPrivacy(false);
+ }
+
+ reconstructTokenHeader(prop, is);
+
+ int minSize;
+ if (tokenType == TOKEN_WRAP_V2 && prop.getPrivacy()) {
+ minSize = CONFOUNDER_SIZE + TOKEN_HEADER_SIZE + encryptor.getCheckSumSize();
+ } else {
+ minSize = encryptor.getCheckSumSize();
+ }
+
+ try {
+ int tokenLen = is.available();
+
+ if (tokenType == TOKEN_MIC_V2) {
+ tokenLen = minSize;
+ tokenData = new byte[tokenLen];
+ is.read(tokenData);
+ } else {
+ if (tokenLen >= minSize) {
+ tokenData = new byte[tokenLen];
+ is.read(tokenData);
+ } else {
+ throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1, "Invalid token length");
+ }
+ }
+
+ if (tokenType == TOKEN_WRAP_V2) {
+ tokenData = rotate(tokenData);
+ }
+
+ if (tokenType == TOKEN_MIC_V2
+ || tokenType == TOKEN_WRAP_V2 && !prop.getPrivacy()) {
+ int checksumLen = encryptor.getCheckSumSize();
+
+ if (tokenType != TOKEN_MIC_V2 && checksumLen != ec) {
+ throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1, "Invalid EC");
+ }
+
+ checkSum = new byte[checksumLen];
+ System.arraycopy(tokenData, tokenLen - checksumLen, checkSum, 0, checksumLen);
+ }
+ } catch (IOException e) {
+ throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1, "Invalid token");
+ }
+ }
+
+ private byte[] rotate(byte[] data) {
+ int dataLen = data.length;
+ if (rrc % dataLen != 0) {
+ rrc = rrc % dataLen;
+ byte[] newBytes = new byte[dataLen];
+
+ System.arraycopy(data, rrc, newBytes, 0, dataLen - rrc);
+ System.arraycopy(data, 0, newBytes, dataLen - rrc, rrc);
+ data = newBytes;
+ }
+ return data;
+ }
+
+ public int getKeyUsage() {
+ return keyUsage;
+ }
+
+ public void generateCheckSum(MessageProp prop, byte[] data, int offset, int len) throws GSSException {
+ // generate token header
+ createTokenHeader(prop.getPrivacy());
+
+ if (tokenType == TOKEN_MIC_V2
+ || !prop.getPrivacy() && tokenType == TOKEN_WRAP_V2) {
+ checkSum = getCheckSum(data, offset, len);
+ }
+
+ if (!prop.getPrivacy() && tokenType == TOKEN_WRAP_V2) {
+ header[4] = (byte) (checkSum.length >>> 8);
+ header[5] = (byte) (checkSum.length & 0xFF);
+ }
+ }
+
+ public byte[] getCheckSum(byte[] data, int offset, int len) throws GSSException {
+ int confidentialFlag = header[2] & 2;
+ if (confidentialFlag == 0 && tokenType == TOKEN_WRAP_V2) {
+ header[4] = 0;
+ header[5] = 0;
+ header[6] = 0;
+ header[7] = 0;
+ }
+ return encryptor.calculateCheckSum(header, data, offset, len, keyUsage);
+ }
+
+ public boolean verifyCheckSum(byte[] data, int offset, int len) throws GSSException {
+ byte[] dataCheckSum = getCheckSum(data, offset, len);
+ return MessageDigest.isEqual(checkSum, dataCheckSum);
+ }
+
+ // Create a new header
+ private void createTokenHeader(boolean privacy) {
+ header[0] = (byte) (tokenType >>> 8);
+ header[1] = (byte) tokenType;
+
+ int flags = isInitiator ? 0 : FLAG_SENT_BY_ACCEPTOR;
+ flags |= privacy && tokenType != TOKEN_MIC_V2 ? FLAG_SEALED : 0;
+ flags |= acceptorSubKey ? FLAG_ACCEPTOR_SUBKEY : 0;
+
+ header[2] = (byte) (flags & 0xFF);
+ header[3] = (byte) 0xFF;
+
+ if (tokenType == TOKEN_WRAP_V2) {
+ header[4] = (byte) 0;
+ header[5] = (byte) 0;
+ header[6] = (byte) 0;
+ header[7] = (byte) 0;
+ } else if (tokenType == TOKEN_MIC_V2) {
+ header[4] = (byte) 0xFF;
+ header[5] = (byte) 0xFF;
+ header[6] = (byte) 0xFF;
+ header[7] = (byte) 0xFF;
+ }
+ writeBigEndian(header, 12, sequenceNumber);
+ }
+
+ // Reconstruct a token header
+ private void reconstructTokenHeader(MessageProp prop, InputStream is) throws GSSException {
+ try {
+ if (is.read(header, 0, header.length) != header.length) {
+ throw new GSSException(GSSException.FAILURE, -1, "Token header can not be read");
+ }
+ int tokenIDRecv = (((int) header[0]) << 8) + header[1];
+ if (tokenIDRecv != tokenType) {
+ throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
+ "Token ID should be " + tokenType + " instead of " + tokenIDRecv);
+ }
+
+ int senderFlag = isInitiator ? FLAG_SENT_BY_ACCEPTOR : 0;
+ int senderFlagRecv = header[2] & FLAG_SENT_BY_ACCEPTOR;
+ if (senderFlagRecv != senderFlag) {
+ throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1, "Invalid acceptor flag");
+ }
+
+ int confFlagRecv = header[2] & FLAG_SEALED;
+ if (confFlagRecv == FLAG_SEALED && tokenType == TOKEN_WRAP_V2) {
+ prop.setPrivacy(true);
+ } else {
+ prop.setPrivacy(false);
+ }
+
+ if (tokenType == TOKEN_WRAP_V2) {
+ if (header[3] != (byte) 0xFF) {
+ throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1, "Invalid token filler");
+ }
+
+ ec = readBigEndian(header, OFFSET_EC, 2);
+ rrc = readBigEndian(header, OFFSET_RRC, 2);
+ } else if (tokenType == TOKEN_MIC_V2) {
+ for (int i = 3; i < 8; i++) {
+ if ((header[i] & 0xFF) != 0xFF) {
+ throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1, "Invalid token filler");
+ }
+ }
+ }
+
+ prop.setQOP(0);
+ sequenceNumber = readBigEndian(header, 0, 8);
+ } catch (IOException e) {
+ throw new GSSException(GSSException.FAILURE, -1, "Phrase token header failed");
+ }
+ }
+
+ public int encodeHeader(byte[] buf, int offset) {
+ System.arraycopy(header, 0, buf, offset, TOKEN_HEADER_SIZE);
+ return TOKEN_HEADER_SIZE;
+ }
+
+ public void encodeHeader(OutputStream os) throws IOException {
+ os.write(header);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/976b16cf/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssUtil.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssUtil.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssUtil.java
new file mode 100644
index 0000000..372abcb
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssUtil.java
@@ -0,0 +1,386 @@
+/**
+ * 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.gss.impl;
+
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.client.KrbClientBase;
+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 sun.security.jgss.GSSCaller;
+
+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 GssUtil {
+ 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());
+ }
+ }
+
+ /**
+ * Scan current context for SgtTicket
+ * @param client
+ * @param service
+ * @return
+ */
+ public static SgtTicket getSgtCredentialFromContext(GSSCaller caller, String client, String service)
+ throws GSSException {
+ KerberosTicket ticket = CredUtils.getKerberosTicketFromContext(caller, client, service);
+ return getSgtTicketFromKerberosTicket(ticket);
+ }
+
+ /**
+ * 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 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/976b16cf/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/MicTokenV1.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/MicTokenV1.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/MicTokenV1.java
new file mode 100644
index 0000000..63baa6b
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/MicTokenV1.java
@@ -0,0 +1,92 @@
+/**
+ * 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.gss.impl;
+
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.MessageProp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class MicTokenV1 extends GssTokenV1 {
+ public MicTokenV1(GssContext context,
+ byte[] inMsg,
+ int msgOffset,
+ int msgLength,
+ MessageProp messageProp) throws GSSException {
+ super(TOKEN_MIC_V1, context);
+ calcPrivacyInfo(messageProp, null, inMsg, msgOffset, msgLength, 0);
+ }
+
+ // This is called to construct MicToken from MicToken bytes
+ MicTokenV1(GssContext context,
+ MessageProp messageProp,
+ byte[] inToken,
+ int tokenOffset,
+ int tokenLength) throws GSSException {
+ super(TOKEN_MIC_V1, context, messageProp, inToken, tokenOffset, tokenLength);
+ }
+
+ public int getMic(byte[] outToken, int offset) throws GSSException, IOException {
+ byte[] data = getMic();
+ System.arraycopy(data, 0, outToken, offset, data.length);
+ return data.length;
+ }
+
+ /**
+ * Get bytes for this Mic token
+ * @return
+ */
+ public byte[] getMic() throws GSSException {
+ ByteArrayOutputStream os = new ByteArrayOutputStream(64);
+ getMic(os);
+ return os.toByteArray();
+ }
+
+ public void getMic(OutputStream os) throws GSSException {
+ try {
+ encodeHeader(os);
+ } catch (IOException e) {
+ throw new GSSException(GSSException.FAILURE, -1, "Error in output MicTokenV1 bytes:" + e.getMessage());
+ }
+ }
+
+ public void verify(InputStream is) throws GSSException {
+ byte[] data;
+ try {
+ data = new byte[is.available()];
+ is.read(data);
+ } catch (IOException e) {
+ throw new GSSException(GSSException.FAILURE, -1,
+ "Read plain data for MicTokenV1 error:" + e.getMessage());
+ }
+ verify(data, 0, data.length);
+ }
+
+ public void verify(byte[] data, int offset, int len) throws GSSException {
+ verifyToken(null, data, offset, len, 0);
+ }
+
+ protected int getTokenSizeWithoutGssHeader() {
+ return getTokenHeaderSize();
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/976b16cf/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/MicTokenV2.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/MicTokenV2.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/MicTokenV2.java
new file mode 100644
index 0000000..2441823
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/MicTokenV2.java
@@ -0,0 +1,94 @@
+/**
+ * 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.gss.impl;
+
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.MessageProp;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class MicTokenV2 extends GssTokenV2 {
+ private MessageProp prop;
+
+ // This is called to construct MicToken from user input
+ MicTokenV2(GssContext context,
+ byte[] inMsg,
+ int msgOffset,
+ int msgLength,
+ MessageProp messageProp) throws GSSException {
+ super(TOKEN_MIC_V2, context);
+
+ prop = messageProp;
+ if (prop == null) {
+ prop = new MessageProp(0, false);
+ }
+
+ generateCheckSum(prop, inMsg, msgOffset, msgLength);
+ }
+
+ // This is called to construct MicToken from MicToken bytes
+ MicTokenV2(GssContext context,
+ MessageProp messageProp,
+ byte[] inToken,
+ int tokenOffset,
+ int tokenLength) throws GSSException {
+ super(TOKEN_MIC_V2, context, messageProp, inToken, tokenOffset, tokenLength);
+ this.prop = messageProp;
+ }
+
+ public int getMic(byte[] outToken, int offset) {
+ encodeHeader(outToken, offset);
+ System.arraycopy(checkSum, 0, outToken, TOKEN_HEADER_SIZE + offset, checkSum.length);
+ return TOKEN_HEADER_SIZE + checkSum.length;
+ }
+
+ /**
+ * Get bytes for this Mic token
+ * @return
+ */
+ public byte[] getMic() {
+ byte[] ret = new byte[TOKEN_HEADER_SIZE + checkSum.length];
+ getMic(ret, 0);
+ return ret;
+ }
+
+ public void getMic(OutputStream os) throws GSSException {
+ try {
+ encodeHeader(os);
+ os.write(checkSum);
+ } catch (IOException e) {
+ throw new GSSException(GSSException.FAILURE, -1, "Output MicTokenV2 error:" + e.getMessage());
+ }
+ }
+
+ /**
+ * Calculate the checksum for inMsg and compare with it with this token, throw GssException if not equal
+ * @param inMsg
+ * @param msgOffset
+ * @param msgLen
+ * @throws GSSException
+ */
+ public void verify(byte[] inMsg, int msgOffset, int msgLen) throws GSSException {
+ if (!verifyCheckSum(inMsg, msgOffset, msgLen)) {
+ throw new GSSException(GSSException.BAD_MIC, -1, "Corrupt MIC token");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/976b16cf/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/WrapTokenV1.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/WrapTokenV1.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/WrapTokenV1.java
new file mode 100644
index 0000000..03395bb
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/WrapTokenV1.java
@@ -0,0 +1,196 @@
+/**
+ * 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.gss.impl;
+
+import org.apache.kerby.kerberos.kerb.crypto.util.Random;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.MessageProp;
+import sun.security.jgss.GSSHeader;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class WrapTokenV1 extends GssTokenV1 {
+ public static final int CONFOUNDER_SIZE = 8;
+
+ private boolean privacy;
+
+ private byte[] inData;
+ private int inOffset;
+ private int inLen;
+
+ private int paddingLen;
+ private byte[] confounder;
+ private int tokenBodyLen;
+
+ private byte[] bodyData;
+ private int bodyOffset;
+ private int bodyLen;
+
+ // for reconstruct
+ private int rawDataLength;
+ private byte[] rawData;
+ private int rawDataOffset;
+
+
+ // Generate wrap token according user data
+ public WrapTokenV1(GssContext context,
+ byte[] inMsg,
+ int msgOffset,
+ int msgLength,
+ MessageProp prop) throws GSSException {
+ super(TOKEN_WRAP_V1, context);
+
+ paddingLen = getPaddingLength(msgLength);
+ confounder = Random.makeBytes(CONFOUNDER_SIZE);
+ tokenBodyLen = CONFOUNDER_SIZE + msgLength + paddingLen;
+
+ calcPrivacyInfo(prop, confounder, inMsg, msgOffset, msgLength, paddingLen);
+
+ if (!context.getConfState()) {
+ prop.setPrivacy(false);
+ }
+ privacy = prop.getPrivacy();
+ inData = inMsg;
+ inOffset = msgOffset;
+ inLen = msgLength;
+ }
+
+ // Reconstruct a token from token bytes
+ public WrapTokenV1(GssContext context, MessageProp prop,
+ byte[] token, int offset, int len) throws GSSException {
+ super(TOKEN_WRAP_V1, context, prop, token, offset, len);
+ // adjust the offset to the beginning of the body
+ bodyData = token;
+ bodyOffset = offset + reconHeaderLen;
+ bodyLen = len - reconHeaderLen;
+ getRawData(prop);
+ }
+
+ // Reconstruct a token from token bytes stream
+ public WrapTokenV1(GssContext context, MessageProp prop, InputStream is) throws GSSException {
+ super(TOKEN_WRAP_V1, context, prop, is);
+ byte[] token;
+ int len;
+ try {
+ len = is.available();
+ token = new byte[len];
+ is.read(token);
+ } catch (IOException e) {
+ throw new GSSException(GSSException.FAILURE, -1, "Read wrap token V1 error:" + e.getMessage());
+ }
+ bodyData = token;
+ bodyOffset = 0;
+ bodyLen = len;
+ getRawData(prop);
+ }
+
+ private void getRawData(MessageProp prop) throws GSSException {
+ privacy = prop.getPrivacy();
+ tokenBodyLen = getGssHeader().getMechTokenLength() - getTokenHeaderSize();
+
+ if (bodyLen < tokenBodyLen) {
+ throw new GSSException(GSSException.FAILURE, -1, "Insufficient data for Wrap token V1");
+ }
+
+ if (privacy) {
+ rawData = encryptor.encryptTokenV1(null, bodyData, bodyOffset, tokenBodyLen, 0,
+ encryptor.isArcFourHmac() ? getPlainSequenceBytes() : null, false);
+ paddingLen = rawData[rawData.length - 1];
+ rawDataOffset = CONFOUNDER_SIZE;
+ } else {
+ rawData = bodyData;
+ paddingLen = bodyData[bodyOffset + tokenBodyLen - 1];
+ rawDataOffset = bodyOffset + CONFOUNDER_SIZE;
+ }
+ rawDataLength = tokenBodyLen - CONFOUNDER_SIZE - paddingLen;
+
+ verifyToken(null, rawData, rawDataOffset - CONFOUNDER_SIZE, tokenBodyLen, 0);
+ }
+
+ // Get plain text data from token data bytes
+ public byte[] unwrap() throws GSSException {
+ byte[] ret = new byte[rawDataLength];
+ System.arraycopy(rawData, rawDataOffset, ret, 0, rawDataLength);
+ return ret;
+ }
+
+ public void unwrap(OutputStream os) throws GSSException {
+ try {
+ os.write(rawData, rawDataOffset, rawDataLength);
+ } catch (IOException e) {
+ throw new GSSException(GSSException.FAILURE, -1,
+ "Error in output wrap token v1 data bytes:" + e.getMessage());
+ }
+ }
+
+ public byte[] wrap() throws GSSException {
+ ByteArrayOutputStream os = new ByteArrayOutputStream(getTokenSizeWithoutGssHeader() + inLen + 64);
+ wrap(os);
+ return os.toByteArray();
+ }
+
+ public void wrap(OutputStream os) throws GSSException {
+ try {
+ encodeHeader(os);
+ if (privacy) {
+ byte[] enc = encryptor.encryptTokenV1(confounder, inData, inOffset, inLen, paddingLen,
+ encryptor.isArcFourHmac() ? getPlainSequenceBytes() : null, true);
+ os.write(enc);
+ } else {
+ os.write(confounder);
+ os.write(inData, inOffset, inLen);
+ os.write(getPaddingBytes(paddingLen));
+ }
+ } catch (IOException e) {
+ throw new GSSException(GSSException.FAILURE, -1, "Error in output wrap token v1 bytes:" + e.getMessage());
+ }
+ }
+
+ protected int getTokenSizeWithoutGssHeader() {
+ return tokenBodyLen + getTokenHeaderSize();
+ }
+
+ private int getPaddingLength(int dataLen) {
+ if (encryptor.isArcFourHmac()) {
+ return 1;
+ }
+ return 8 - (dataLen % 8);
+ }
+
+ private byte[] getPaddingBytes(int len) {
+ byte[] ret = new byte[len];
+ int i = 0;
+ while (i < len) {
+ ret[i++] = (byte) len;
+ }
+ return ret;
+ }
+
+ public static int getMsgSizeLimit(int qop, boolean confReq, int maxTokSize, GssEncryptor encryptor)
+ throws GSSException {
+ return GSSHeader.getMaxMechTokenSize(objId, maxTokSize)
+ - encryptor.getCheckSumSize()
+ - TOKEN_HEADER_COMM_SIZE - TOKEN_HEADER_SEQ_SIZE
+ - CONFOUNDER_SIZE - 8;
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/976b16cf/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/WrapTokenV2.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/WrapTokenV2.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/WrapTokenV2.java
new file mode 100644
index 0000000..8f4cae4
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/WrapTokenV2.java
@@ -0,0 +1,159 @@
+/**
+ * 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.gss.impl;
+
+import org.apache.kerby.kerberos.kerb.Message;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.MessageProp;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+
+public class WrapTokenV2 extends GssTokenV2 {
+ private MessageProp prop;
+
+ // Generate a token from user input data
+ WrapTokenV2(GssContext context,
+ byte[] data,
+ int dataOffset,
+ int dataLength,
+ MessageProp messageProp) throws GSSException {
+ super(TOKEN_WRAP_V2, context);
+
+ prop = messageProp;
+
+ if (prop.getQOP() != 0) {
+ prop.setQOP(0);
+ }
+
+ if (!context.getConfState()) {
+ prop.setPrivacy(false);
+ }
+
+ generateCheckSum(prop, data, dataOffset, dataLength);
+
+ if (prop.getPrivacy()) {
+ byte[] toProcess = new byte[dataLength + TOKEN_HEADER_SIZE];
+ System.arraycopy(data, dataOffset, toProcess, 0, dataLength);
+ encodeHeader(toProcess, dataLength);
+
+ tokenData = encryptor.encryptData(toProcess, getKeyUsage());
+ } else {
+ tokenData = data; // keep it for now
+ }
+ }
+
+ /**
+ * Get bytes of the token
+ * @return
+ */
+ public byte[] wrap() {
+ int dataSize = tokenData.length;
+ int ckSize = checkSum == null ? 0 : checkSum.length;
+ byte[] ret = new byte[TOKEN_HEADER_SIZE + dataSize + ckSize];
+ encodeHeader(ret, 0);
+ System.arraycopy(tokenData, 0, ret, TOKEN_HEADER_SIZE, dataSize);
+ if (ckSize > 0) {
+ System.arraycopy(checkSum, 0, ret, TOKEN_HEADER_SIZE + dataSize, ckSize);
+ }
+ return ret;
+ }
+
+ public void wrap(OutputStream os) throws GSSException {
+ try {
+ encodeHeader(os);
+ os.write(tokenData);
+ int ckSize = checkSum == null ? 0 : checkSum.length;
+ if (ckSize > 0) {
+ os.write(checkSum);
+ }
+ } catch (IOException e) {
+ throw new GSSException(GSSException.FAILURE, -1, "Output token error:" + e.getMessage());
+ }
+ }
+
+ // Reconstruct a token from token bytes
+ public WrapTokenV2(GssContext context, MessageProp prop, byte[] token, int offset, int len) throws GSSException {
+ super(TOKEN_WRAP_V2, context, prop, token, offset, len);
+ this.prop = prop;
+ }
+
+ // Reconstruct a token from token bytes stream
+ public WrapTokenV2(GssContext context, MessageProp prop, InputStream is) throws GSSException {
+ super(TOKEN_WRAP_V2, context, prop, is);
+ this.prop = prop;
+ }
+
+ /**
+ * Get plain text data from token bytes
+ * @param outBuffer
+ * @param offset
+ * @return plain text contained in the wrap token
+ * @throws GSSException
+ */
+ public byte[] unwrap(byte[] outBuffer, int offset) throws GSSException {
+ int lenToCopy;
+ if (prop.getPrivacy()) {
+ byte[] plainText = encryptor.decryptData(tokenData, getKeyUsage());
+ lenToCopy = plainText.length - TOKEN_HEADER_SIZE;
+ if (outBuffer == null) {
+ outBuffer = new byte[lenToCopy];
+ offset = 0;
+ }
+ System.arraycopy(plainText, 0, outBuffer, offset, lenToCopy);
+ } else {
+ lenToCopy = tokenData.length - encryptor.getCheckSumSize();
+ if (outBuffer == null) {
+ outBuffer = new byte[lenToCopy];
+ offset = 0;
+ }
+ System.arraycopy(tokenData, 0, outBuffer, offset, lenToCopy);
+
+ if (!verifyCheckSum(outBuffer, offset, lenToCopy)) {
+ throw new GSSException(GSSException.BAD_MIC, -1, "Corrupt token checksum");
+ }
+ }
+ return outBuffer;
+ }
+
+ public byte[] unwrap() throws GSSException {
+ return unwrap(null, 0);
+ }
+
+ public void unwrap(OutputStream os) throws GSSException {
+ byte[] data = unwrap();
+ try {
+ os.write(data);
+ } catch (IOException e) {
+ throw new GSSException(GSSException.FAILURE, -1, "Output token error:" + e.getMessage());
+ }
+ }
+
+ public static int getMsgSizeLimit(int qop, boolean confReq, int maxTokSize, GssEncryptor encryptor)
+ throws GSSException {
+ if (confReq) {
+ return maxTokSize - encryptor.getCheckSumSize() - TOKEN_HEADER_SIZE * 2 - CONFOUNDER_SIZE;
+ } else {
+ return maxTokSize - encryptor.getCheckSumSize() - TOKEN_HEADER_SIZE;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/976b16cf/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/KerbyMechFactory.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/KerbyMechFactory.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/KerbyMechFactory.java
deleted file mode 100644
index adacb27..0000000
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/KerbyMechFactory.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/**
- * 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;
-
-import org.apache.kerby.kerberos.kerb.gssapi.krb5.KerbyAcceptCred;
-import org.apache.kerby.kerberos.kerb.gssapi.krb5.KerbyContext;
-import org.apache.kerby.kerberos.kerb.gssapi.krb5.KerbyCredElement;
-import org.apache.kerby.kerberos.kerb.gssapi.krb5.KerbyInitCred;
-import org.apache.kerby.kerberos.kerb.gssapi.krb5.KerbyNameElement;
-import org.ietf.jgss.GSSCredential;
-import org.ietf.jgss.GSSException;
-import org.ietf.jgss.GSSName;
-import org.ietf.jgss.Oid;
-import sun.security.jgss.GSSCaller;
-import sun.security.jgss.spi.GSSContextSpi;
-import sun.security.jgss.spi.GSSCredentialSpi;
-import sun.security.jgss.spi.GSSNameSpi;
-import sun.security.jgss.spi.MechanismFactory;
-
-import java.security.Provider;
-
-/**
- * Kerby Kerberos V5 plugin for JGSS
- */
-public class KerbyMechFactory implements MechanismFactory {
- private static final Provider PROVIDER =
- new org.apache.kerby.kerberos.kerb.gssapi.Provider();
-
- private static final String KRB5_OID_STRING = "1.2.840.113554.1.2.2";
- private static final Oid KRB5_OID = createOid(KRB5_OID_STRING);
-
- private static Oid[] nameTypes =
- new Oid[] {
- GSSName.NT_USER_NAME,
- GSSName.NT_EXPORT_NAME,
- GSSName.NT_HOSTBASED_SERVICE
- };
-
- private final GSSCaller caller;
-
- public Oid getMechanismOid() {
- return KRB5_OID;
- }
-
- public Provider getProvider() {
- return PROVIDER;
- }
-
- public Oid[] getNameTypes() throws GSSException {
- return nameTypes;
- }
-
- public KerbyMechFactory(GSSCaller caller) {
- this.caller = caller;
- }
-
- public GSSNameSpi getNameElement(String nameStr, Oid nameType)
- throws GSSException {
- return KerbyNameElement.getInstance(nameStr, nameType);
- }
-
- public GSSNameSpi getNameElement(byte[] name, Oid nameType)
- throws GSSException {
- return KerbyNameElement.getInstance(name.toString(), nameType);
- }
-
- // Used by initiator
- public GSSContextSpi getMechanismContext(GSSNameSpi peer,
- GSSCredentialSpi myInitiatorCred,
- int lifetime) throws GSSException {
- if (peer != null && !(peer instanceof KerbyNameElement)) {
- peer = KerbyNameElement.getInstance(peer.toString(), peer.getStringNameType());
- }
- if (myInitiatorCred == null) {
- myInitiatorCred = getCredentialElement(null, lifetime, 0, GSSCredential.INITIATE_ONLY);
- }
- return new KerbyContext(caller, (KerbyNameElement) peer, (KerbyInitCred) myInitiatorCred, lifetime);
- }
-
- public GSSContextSpi getMechanismContext(GSSCredentialSpi myAcceptorCred)
- throws GSSException {
- if (myAcceptorCred == null) {
- myAcceptorCred = getCredentialElement(null, 0,
- GSSCredential.INDEFINITE_LIFETIME, GSSCredential.ACCEPT_ONLY);
- }
- return new KerbyContext(caller, (KerbyAcceptCred) myAcceptorCred);
- }
-
- // Reconstruct from previously exported context
- public GSSContextSpi getMechanismContext(byte[] exportedContext)
- throws GSSException {
- return new KerbyContext(caller, exportedContext);
- }
-
- public GSSCredentialSpi getCredentialElement(GSSNameSpi name,
- int initLifetime,
- int acceptLifetime,
- int usage)
- throws GSSException {
- if (name != null && !(name instanceof KerbyNameElement)) {
- name = KerbyNameElement.getInstance(name.toString(), name.getStringNameType());
- }
-
- KerbyCredElement credElement;
-
- if (usage == GSSCredential.INITIATE_ONLY) {
- credElement = KerbyInitCred.getInstance(caller, (KerbyNameElement) name, initLifetime);
- } else if (usage == GSSCredential.ACCEPT_ONLY) {
- credElement = KerbyAcceptCred.getInstance(caller, (KerbyNameElement) name, acceptLifetime);
- } else if (usage == GSSCredential.INITIATE_AND_ACCEPT) {
- throw new GSSException(GSSException.FAILURE, -1, "Unsupported usage mode: INITIATE_AND_ACCEPT");
- } else {
- throw new GSSException(GSSException.FAILURE, -1, "Unknown usage mode: " + usage);
- }
-
- return credElement;
- }
-
- private static Oid createOid(String oidStr) {
- Oid retVal;
- try {
- retVal = new Oid(oidStr);
- } catch (GSSException e) {
- retVal = null;
- }
- return retVal;
- }
-
- public static Oid getOid() {
- return KRB5_OID;
- }
-}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/976b16cf/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/Provider.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/Provider.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/Provider.java
deleted file mode 100644
index ad3a614..0000000
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/Provider.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * 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;
-
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-/**
- * Proivder is used to register the implementation of gssapi mechanism into the system
- */
-public final class Provider extends java.security.Provider {
- private static final long serialVersionUID = 3787378212107821987L;
- private static final String INFO = "Kerby GssApi Provider";
- private static final String MECHANISM_GSSAPI = "GssApiMechanism.1.2.840.113554.1.2.2";
- private static final String MECHANISM_GSSAPI_CLASS = "org.apache.kerby.kerberos.kerb.gssapi.KerbyMechFactory";
-
- public Provider() {
- super("KerbyGssApi", 0.01d, INFO);
-
- AccessController.doPrivileged(new PrivilegedAction<Void>() {
- public Void run() {
-
- put(MECHANISM_GSSAPI, MECHANISM_GSSAPI_CLASS);
-
- return null;
- }
- });
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/976b16cf/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/CredUtils.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/CredUtils.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/CredUtils.java
deleted file mode 100644
index f7ddc31..0000000
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/CredUtils.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.apache.kerby.kerberos.kerb.gssapi.krb5;
-
-import org.ietf.jgss.GSSException;
-import sun.security.jgss.GSSCaller;
-
-import javax.security.auth.Subject;
-import javax.security.auth.kerberos.*;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.Set;
-
-/**
- * Utility functions to deal with credentials in Context
- */
-public class CredUtils {
-
- public static <T> Set<T> getContextPrivateCredentials(Class<T> credentialType, AccessControlContext acc) {
- Subject subject = Subject.getSubject(acc);
- Set<T> creds = subject.getPrivateCredentials(credentialType);
- return creds;
- }
-
- public static <T> Set<T> getContextCredentials(final Class<T> credentialType) throws GSSException {
- final AccessControlContext acc = AccessController.getContext();
- try {
- return AccessController.doPrivileged(
- new PrivilegedExceptionAction<Set<T>>() {
- public Set<T> run() throws Exception {
- return CredUtils.getContextPrivateCredentials(credentialType, acc);
- }
- });
- } catch (PrivilegedActionException e) {
- throw new GSSException(GSSException.NO_CRED, -1, "Get credential from context failed");
- }
- }
-
- public static KerberosTicket getKerberosTicketFromContext(GSSCaller caller,
- final String clientName,
- final String serverName) throws GSSException {
- Set<KerberosTicket> tickets = getContextCredentials(KerberosTicket.class);
- for (KerberosTicket ticket : tickets) {
- if (ticket.isCurrent() && (serverName == null || ticket.getServer().getName().equals(serverName))
- && (clientName == null || ticket.getClient().getName().equals(clientName))) {
- return ticket;
- }
- }
- return null;
- }
-
- public static KeyTab getKeyTabFromContext(KerberosPrincipal principal) throws GSSException {
- Set<KeyTab> tabs = getContextCredentials(KeyTab.class);
- for (KeyTab tab : tabs) {
- KerberosKey[] keys = tab.getKeys(principal);
- if (keys != null && keys.length > 0) {
- return tab;
- }
- }
- return null;
- }
-
- public static void addCredentialToSubject(final KerberosTicket ticket) throws GSSException {
- final AccessControlContext acc = AccessController.getContext();
-
- final Subject subject = AccessController.doPrivileged(
- new java.security.PrivilegedAction<Subject>() {
- public Subject run() {
- return Subject.getSubject(acc);
- }
- });
-
- AccessController.doPrivileged(
- new java.security.PrivilegedAction<Void>() {
- public Void run() {
- subject.getPrivateCredentials().add(ticket);
- return null;
- }
- });
- }
-
- public static void checkPrincipalPermission(String principalName, String action) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- ServicePermission sp = new ServicePermission(principalName, action);
- sm.checkPermission(sp);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/976b16cf/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyAcceptCred.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyAcceptCred.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyAcceptCred.java
deleted file mode 100644
index a7331fa..0000000
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyAcceptCred.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * 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.ietf.jgss.GSSException;
-import sun.security.jgss.GSSCaller;
-
-import javax.security.auth.kerberos.KerberosKey;
-import javax.security.auth.kerberos.KerberosPrincipal;
-import javax.security.auth.kerberos.KeyTab;
-
-public final class KerbyAcceptCred extends KerbyCredElement {
-
- private final KeyTab keyTab;
-
- public static KerbyAcceptCred getInstance(final GSSCaller caller,
- KerbyNameElement name, int lifeTime) throws GSSException {
-
- KerberosPrincipal princ = new KerberosPrincipal(name.getPrincipalName().getName(),
- name.getPrincipalName().getNameType().getValue());
- KeyTab keyTab = CredUtils.getKeyTabFromContext(princ);
-
- if (keyTab == null) {
- throw new GSSException(GSSException.NO_CRED, -1,
- "Failed to find any Kerberos credential for " + name.getPrincipalName().getName());
- }
-
- return new KerbyAcceptCred(caller, name, keyTab, lifeTime);
- }
-
- private KerbyAcceptCred(GSSCaller caller, KerbyNameElement name, KeyTab keyTab, int lifeTime) {
- super(caller, name);
- this.keyTab = keyTab;
- this.accLifeTime = lifeTime;
- }
-
- public boolean isInitiatorCredential() throws GSSException {
- return false;
- }
-
- public boolean isAcceptorCredential() throws GSSException {
- return true;
- }
-
- public KeyTab getKeyTab() {
- return this.keyTab;
- }
-
- public KerberosKey[] getKeys() {
- KerberosPrincipal princ = new KerberosPrincipal(name.getPrincipalName().getName(),
- name.getPrincipalName().getNameType().getValue());
- return keyTab.getKeys(princ);
- }
-}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/976b16cf/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyContext.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyContext.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyContext.java
deleted file mode 100644
index 5395afd..0000000
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyContext.java
+++ /dev/null
@@ -1,673 +0,0 @@
-/**
- * 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 com.sun.security.jgss.InquireType;
-import org.apache.kerby.kerberos.kerb.KrbException;
-import org.apache.kerby.kerberos.kerb.gssapi.KerbyMechFactory;
-import org.apache.kerby.kerberos.kerb.request.ApRequest;
-import org.apache.kerby.kerberos.kerb.response.ApResponse;
-import org.apache.kerby.kerberos.kerb.type.ad.AuthorizationData;
-import org.apache.kerby.kerberos.kerb.type.ap.ApRep;
-import org.apache.kerby.kerberos.kerb.type.ap.ApReq;
-import org.apache.kerby.kerberos.kerb.type.ap.Authenticator;
-import org.apache.kerby.kerberos.kerb.type.base.EncryptionKey;
-import org.apache.kerby.kerberos.kerb.type.base.PrincipalName;
-import org.apache.kerby.kerberos.kerb.type.kdc.EncKdcRepPart;
-import org.apache.kerby.kerberos.kerb.type.ticket.EncTicketPart;
-import org.apache.kerby.kerberos.kerb.type.ticket.SgtTicket;
-import org.apache.kerby.kerberos.kerb.type.ticket.TicketFlags;
-import org.ietf.jgss.ChannelBinding;
-import org.ietf.jgss.GSSContext;
-import org.ietf.jgss.GSSException;
-import org.ietf.jgss.MessageProp;
-import org.ietf.jgss.Oid;
-import sun.security.jgss.GSSCaller;
-import sun.security.jgss.spi.GSSContextSpi;
-import sun.security.jgss.spi.GSSCredentialSpi;
-import sun.security.jgss.spi.GSSNameSpi;
-
-import javax.security.auth.kerberos.KerberosTicket;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.security.Provider;
-
-@SuppressWarnings("PMD")
-public class KerbyContext implements GSSContextSpi {
-
- private static final int STATE_NONE = 0;
- private static final int STATE_ESTABLISHING = 1;
- private static final int STATE_ESTABLISHED = 2;
- private static final int STATE_DESTROYED = 3;
-
- private static final byte[] MSG_AP_REQ = {(byte) 0x1, (byte) 0};
- private static final byte[] MSG_AP_REP = {(byte) 0x2, (byte) 0};
-
- private int ctxState = STATE_NONE;
-
- private final GSSCaller caller;
- private KerbyCredElement myCred;
- private boolean initiator;
- private KerbyNameElement myName;
- private KerbyNameElement peerName;
- private int lifeTime;
- private ChannelBinding channelBinding;
-
- private boolean mutualAuth = true;
- private boolean replayDet = true;
- private boolean sequenceDet = true;
- private boolean credDeleg = false;
- private boolean confState = true;
- private boolean integState = true;
- private boolean delegPolicy = false;
-
- public static final int INVALID_KEY = 0;
- public static final int SESSION_KEY = 1;
- public static final int INITIATOR_SUBKEY = 2;
- public static final int ACCEPTOR_SUBKEY = 4;
- private int keyComesFrom = INVALID_KEY;
-
- private EncryptionKey sessionKey; // used between client and app server
- private TicketFlags ticketFlags;
- private ApReq outApReq;
-
- private KerbyGssEncryptor gssEncryptor;
-
- // Called on initiator's side.
- public KerbyContext(GSSCaller caller, KerbyNameElement peerName, KerbyCredElement myCred,
- int lifeTime)
- throws GSSException {
- if (peerName == null) {
- throw new IllegalArgumentException("Cannot have null peer name");
- }
-
- this.caller = caller;
- this.peerName = peerName;
- this.myCred = myCred;
- this.lifeTime = lifeTime;
- this.initiator = true;
-
- mySequenceNumberLock = new Object();
- peerSequenceNumberLock = new Object();
- }
-
- public KerbyContext(GSSCaller caller, KerbyAcceptCred myCred)
- throws GSSException {
- this.caller = caller;
- this.myCred = myCred;
- this.initiator = false;
-
- mySequenceNumberLock = new Object();
- peerSequenceNumberLock = new Object();
- }
-
- public KerbyContext(GSSCaller caller, byte[] interProcessToken)
- throws GSSException {
- throw new GSSException(GSSException.UNAVAILABLE, -1, "Unsupported feature");
- }
-
- public Provider getProvider() {
- return new org.apache.kerby.kerberos.kerb.gssapi.Provider();
- }
-
- public void requestLifetime(int lifeTime) throws GSSException {
- if (ctxState == STATE_NONE && isInitiator()) {
- this.lifeTime = lifeTime;
- }
- }
-
- public void requestMutualAuth(boolean state) throws GSSException {
- if (ctxState == STATE_NONE && isInitiator()) {
- mutualAuth = state;
- }
- }
-
- public void requestReplayDet(boolean state) throws GSSException {
- if (ctxState == STATE_NONE && isInitiator()) {
- replayDet = state;
- }
- }
-
- public void requestSequenceDet(boolean state) throws GSSException {
- if (ctxState == STATE_NONE && isInitiator()) {
- replayDet = state;
- }
- }
-
- public void requestCredDeleg(boolean state) throws GSSException {
- if (ctxState == STATE_NONE && isInitiator() && myCred == null) {
- credDeleg = state;
- }
- }
-
- public void requestAnonymity(boolean state) throws GSSException {
- // anonymous context not supported
- }
-
- public void requestConf(boolean state) throws GSSException {
- if (ctxState == STATE_NONE && isInitiator()) {
- confState = state;
- }
- }
-
- public void requestInteg(boolean state) throws GSSException {
- if (ctxState == STATE_NONE && isInitiator()) {
- integState = state;
- }
- }
-
- public void requestDelegPolicy(boolean state) throws GSSException {
- if (ctxState == STATE_NONE && isInitiator()) {
- delegPolicy = state;
- }
- }
-
- public void setChannelBinding(ChannelBinding cb) throws GSSException {
- this.channelBinding = cb;
- }
-
- public boolean getCredDelegState() {
- return credDeleg;
- }
-
- public boolean getMutualAuthState() {
- return mutualAuth;
- }
-
- public boolean getReplayDetState() {
- return replayDet || sequenceDet;
- }
-
- public boolean getSequenceDetState() {
- return sequenceDet;
- }
-
- public boolean getAnonymityState() {
- return false;
- }
-
- public boolean getDelegPolicyState() {
- return delegPolicy;
- }
-
- public boolean isTransferable() throws GSSException {
- return false;
- }
-
- public boolean isProtReady() {
- return ctxState == STATE_ESTABLISHED;
- }
-
- public boolean isInitiator() {
- return initiator;
- }
-
- public boolean getConfState() {
- return confState;
- }
-
- public boolean getIntegState() {
- return integState;
- }
-
- public int getLifetime() {
- return GSSContext.INDEFINITE_LIFETIME;
- }
-
- public boolean isEstablished() {
- return ctxState == STATE_ESTABLISHED;
- }
-
- public GSSNameSpi getSrcName() throws GSSException {
- return isInitiator() ? myName : peerName;
- }
-
- public GSSNameSpi getTargName() throws GSSException {
- return !isInitiator() ? myName : peerName;
- }
-
- public Oid getMech() throws GSSException {
- return KerbyMechFactory.getOid();
- }
-
- public GSSCredentialSpi getDelegCred() throws GSSException {
- throw new GSSException(GSSException.FAILURE, -1, "API not implemented"); // TODO:
- }
-
- public byte[] initSecContext(InputStream is, int mechTokenSize)
- throws GSSException {
- if (!isInitiator()) {
- throw new GSSException(GSSException.FAILURE, -1, "initSecContext called on acceptor");
- }
-
- byte[] ret = null;
-
- if (ctxState == STATE_NONE) {
-
- if (!myCred.isInitiatorCredential()) {
- throw new GSSException(GSSException.NO_CRED, -1, "No TGT available");
- }
-
- // check if service ticket already exists
- // if not, prepare to get it through TGS_REQ
- SgtTicket sgtTicket = null;
- String serviceName = peerName.getPrincipalName().getName();
- myName = (KerbyNameElement) myCred.getName();
- PrincipalName clientPrincipal = myName.getPrincipalName();
-
- sgtTicket = KerbyUtil.getSgtCredentialFromContext(caller, clientPrincipal.getName(), serviceName);
-
- if (sgtTicket == null) {
- sgtTicket = KerbyUtil.applySgtCredential(((KerbyInitCred) myCred).ticket, serviceName);
-
- // add this service credential to context
- final KerberosTicket ticket =
- KerbyUtil.convertKrbTicketToKerberosTicket(sgtTicket, myName.getPrincipalName().getName());
- CredUtils.addCredentialToSubject(ticket);
- }
-
- ApRequest apRequest = new ApRequest(clientPrincipal, sgtTicket);
- try {
- outApReq = apRequest.getApReq();
- } catch (KrbException e) {
- throw new GSSException(GSSException.FAILURE, -1, "Generate ApReq failed: " + e.getMessage());
- }
- setupInitiatorContext(sgtTicket, apRequest);
- try {
- ByteBuffer outBuffer = ByteBuffer.allocate(outApReq.encodingLength() + 2);
- outBuffer.put(MSG_AP_REQ);
- outApReq.encode(outBuffer);
- outBuffer.flip();
- ret = outBuffer.array();
- } catch (IOException e) {
- throw new GSSException(GSSException.FAILURE, -1, "Generate ApReq bytes failed: " + e.getMessage());
- }
-
- ctxState = STATE_ESTABLISHING;
- if (!getMutualAuthState()) {
- gssEncryptor = new KerbyGssEncryptor(getSessionKey());
- ctxState = STATE_ESTABLISHED;
- }
-
- } else if (ctxState == STATE_ESTABLISHING) {
- verifyServerToken(is, mechTokenSize);
- gssEncryptor = new KerbyGssEncryptor(getSessionKey());
- outApReq = null;
- ctxState = STATE_ESTABLISHED;
- }
- return ret;
- }
-
- private void setupInitiatorContext(SgtTicket sgt, ApRequest apRequest) throws GSSException {
- EncKdcRepPart encKdcRepPart = sgt.getEncKdcRepPart();
- TicketFlags ticketFlags = encKdcRepPart.getFlags();
- setTicketFlags(ticketFlags);
-
- setAuthTime(encKdcRepPart.getAuthTime().toString());
-
- Authenticator auth;
- try {
- auth = apRequest.getApReq().getAuthenticator();
- } catch (KrbException e) {
- throw new GSSException(GSSException.FAILURE, -1, "ApReq failed in Initiator");
- }
- setMySequenceNumber(auth.getSeqNumber());
-
- EncryptionKey subKey = auth.getSubKey();
- if (subKey != null) {
- setSessionKey(subKey, KerbyContext.INITIATOR_SUBKEY);
- } else {
- setSessionKey(sgt.getSessionKey(), KerbyContext.SESSION_KEY);
- }
-
- if (!getMutualAuthState()) {
- setPeerSequenceNumber(0);
- }
- }
-
- /**
- * Verify the AP_REP from server and set context accordingly
- * @param is
- * @param mechTokenSize
- * @return
- * @throws GSSException
- * @throws IOException
- */
- private void verifyServerToken(InputStream is, int mechTokenSize)
- throws GSSException {
- byte[] token;
- ApRep apRep;
- try {
- if (!(is.read() == MSG_AP_REP[0] && is.read() == MSG_AP_REP[1])) {
- throw new GSSException(GSSException.FAILURE, -1, "Invalid ApRep message ID");
- }
- token = new byte[mechTokenSize - MSG_AP_REP.length];
- is.read(token);
- apRep = new ApRep();
- apRep.decode(token);
- } catch (IOException e) {
- throw new GSSException(GSSException.FAILURE, -1, "Invalid ApRep " + e.getMessage());
- }
-
- try {
- ApResponse.validate(getSessionKey(), apRep, outApReq);
- } catch (KrbException e) {
- throw new GSSException(GSSException.UNAUTHORIZED, -1, "ApRep verification failed");
- }
-
- EncryptionKey key = apRep.getEncRepPart().getSubkey();
- if (key != null) {
- setSessionKey(key, ACCEPTOR_SUBKEY);
- }
-
- int seqNum = apRep.getEncRepPart().getSeqNumber();
- setPeerSequenceNumber(seqNum == -1 ? 0 : seqNum);
- }
-
- public byte[] acceptSecContext(InputStream is, int mechTokenSize)
- throws GSSException {
- byte[] ret = null;
-
- if (isInitiator()) {
- throw new GSSException(GSSException.FAILURE, -1, "acceptSecContext called on initiator");
- }
-
- if (ctxState == STATE_NONE) {
- ctxState = STATE_ESTABLISHING;
- if (!myCred.isAcceptorCredential()) {
- throw new GSSException(GSSException.FAILURE, -1, "No acceptor credential available");
- }
-
- KerbyAcceptCred acceptCred = (KerbyAcceptCred) myCred;
- CredUtils.checkPrincipalPermission(
- ((KerbyNameElement) acceptCred.getName()).getPrincipalName().getName(), "accept");
-
- if (getMutualAuthState()) {
- ret = verifyClientToken(acceptCred, is, mechTokenSize);
- }
-
- gssEncryptor = new KerbyGssEncryptor(getSessionKey());
-
- myCred = null;
- ctxState = STATE_ESTABLISHED;
- }
-
- return ret;
- }
-
- private byte[] verifyClientToken(KerbyAcceptCred acceptCred, InputStream is, int mechTokenSize)
- throws GSSException {
- byte[] token;
- ApReq apReq;
- try {
- if (!(is.read() == MSG_AP_REQ[0] && is.read() == MSG_AP_REQ[1])) {
- throw new GSSException(GSSException.FAILURE, -1, "Invalid ApReq message ID");
- }
-
- token = new byte[mechTokenSize - MSG_AP_REQ.length];
- is.read(token);
- apReq = new ApReq();
- apReq.decode(token);
- } catch (IOException e) {
- throw new GSSException(GSSException.UNAUTHORIZED, -1, "ApReq invalid:" + e.getMessage());
- }
-
- int kvno = apReq.getTicket().getEncryptedEncPart().getKvno();
- int encryptType = apReq.getTicket().getEncryptedEncPart().getEType().getValue();
-
- // Get server key from credential
- EncryptionKey serverKey = KerbyUtil.getEncryptionKey(acceptCred.getKeys(), encryptType, kvno);
- if (serverKey == null) {
- throw new GSSException(GSSException.FAILURE, -1, "Server key not found");
- }
-
- try {
- ApRequest.validate(serverKey, apReq, channelBinding.getInitiatorAddress(), 5 * 60 * 1000);
- } catch (KrbException e) {
- throw new GSSException(GSSException.UNAUTHORIZED, -1, "ApReq verification failed: " + e.getMessage());
- }
-
- ApResponse apResponse = new ApResponse(apReq);
- ApRep apRep;
- try {
- apRep = apResponse.getApRep();
- } catch (KrbException e) {
- throw new GSSException(GSSException.UNAUTHORIZED, -1, "Generate ApRep failed");
- }
-
- EncTicketPart apReqTicketEncPart = apReq.getTicket().getEncPart();
-
- EncryptionKey ssKey = apReqTicketEncPart.getKey();
- Authenticator auth = apReq.getAuthenticator();
- EncryptionKey subKey = auth.getSubKey();
-
- if (subKey != null) {
- setSessionKey(subKey, INITIATOR_SUBKEY);
- } else {
- setSessionKey(ssKey, SESSION_KEY);
- }
-
- // initial seqNumber
- int seqNumber = auth.getSeqNumber();
- setMySequenceNumber(seqNumber);
- // initial authtime, tktflags, authdata,
- setAuthTime(apReqTicketEncPart.getAuthTime().toString());
- setTicketFlags(apReqTicketEncPart.getFlags());
- setAuthData(apReqTicketEncPart.getAuthorizationData());
-
- byte[] ret = null;
- try {
- ByteBuffer outBuffer = ByteBuffer.allocate(apRep.encodingLength() + 2);
- outBuffer.put(MSG_AP_REP);
- apRep.encode(outBuffer);
- outBuffer.flip();
- ret = outBuffer.array();
- } catch (IOException e) {
- throw new GSSException(GSSException.FAILURE, -1, "Generate ApRep bytes failed:" + e.getMessage());
- }
- return ret;
- }
-
- public int getWrapSizeLimit(int qop, boolean confReq, int maxTokSize)
- throws GSSException {
- if (gssEncryptor.isV2()) {
- return WrapTokenV2.getMsgSizeLimit(qop, confReq, maxTokSize, gssEncryptor);
- } else {
- return WrapTokenV1.getMsgSizeLimit(qop, confReq, maxTokSize, gssEncryptor);
- }
- }
-
- public void wrap(InputStream is, OutputStream os, MessageProp msgProp)
- throws GSSException {
- if (ctxState != STATE_ESTABLISHED) {
- throw new GSSException(GSSException.NO_CONTEXT, -1, "Context invalid for wrap");
- }
- if (gssEncryptor.isV2()) {
- WrapTokenV2 token = new WrapTokenV2(this, inBuf, 0, len, msgProp);
- token.wrap(os);
- } else {
- WrapTokenV1 token = new WrapTokenV1(this, inBuf, 0, len, msgProp);
- token.wrap(os);
- }
- }
-
- public byte[] wrap(byte[] inBuf, int offset, int len,
- MessageProp msgProp) throws GSSException {
- if (ctxState != STATE_ESTABLISHED) {
- throw new GSSException(GSSException.NO_CONTEXT, -1, "Context invalid for wrap");
- }
- byte[] ret;
- if (gssEncryptor.isV2()) {
- WrapTokenV2 token = new WrapTokenV2(this, inBuf, offset, len, msgProp);
- ret = token.wrap();
- } else {
- WrapTokenV1 token = new WrapTokenV1(this, inBuf, offset, len, msgProp);
- ret = token.wrap();
- }
- return ret;
- }
-
- public void unwrap(InputStream is, OutputStream os,
- MessageProp msgProp) throws GSSException {
- if (gssEncryptor.isV2()) {
- WrapTokenV2 token = new WrapTokenV2(this, msgProp, is);
- token.unwrap(os);
- } else {
- WrapTokenV1 token = new WrapTokenV1(this, msgProp, is);
- token.unwrap(os);
- }
- }
-
- public byte[] unwrap(byte[] inBuf, int offset, int len,
- MessageProp msgProp) throws GSSException {
- if (ctxState != STATE_ESTABLISHED) {
- throw new GSSException(GSSException.NO_CONTEXT, -1, "Context invalid for unwrap");
- }
- byte[] ret;
- if (gssEncryptor.isV2()) {
- WrapTokenV2 token = new WrapTokenV2(this, msgProp, inBuf, offset, len);
- ret = token.unwrap();
- } else {
- WrapTokenV1 token = new WrapTokenV1(this, msgProp, inBuf, offset, len);
- ret = token.unwrap();
- }
- return ret;
- }
-
- public void getMIC(InputStream is, OutputStream os,
- MessageProp msgProp)
- throws GSSException {
- }
-
- public byte[] getMIC(byte[] inMsg, int offset, int len,
- MessageProp msgProp) throws GSSException {
- return null; // TODO: to be implemented
- }
-
- public void verifyMIC(InputStream is, InputStream msgStr,
- MessageProp msgProp) throws GSSException {
- }
-
- public void verifyMIC(byte[]inTok, int tokOffset, int tokLen,
- byte[] inMsg, int msgOffset, int msgLen,
- MessageProp msgProp) throws GSSException {
- }
-
- public byte[] export() throws GSSException {
- throw new GSSException(GSSException.UNAVAILABLE, -1, "Unsupported export method");
- }
-
- public void dispose() throws GSSException {
- ctxState = STATE_DESTROYED;
- setSessionKey(null, 0);
- peerName = null;
- myCred = null;
- myName = null;
- }
-
-
- private String authTime;
- private void setAuthTime(String authTime) {
- this.authTime = authTime;
- }
-
- public Object inquireSecContext(InquireType type) throws GSSException {
- if (ctxState != STATE_ESTABLISHED) {
- throw new GSSException(GSSException.NO_CONTEXT, -1, "Invalid context");
- }
-
- switch (type) {
- case KRB5_GET_SESSION_KEY:
- return getSessionKey();
- case KRB5_GET_TKT_FLAGS:
- return KerbyUtil.ticketFlagsToBooleans(ticketFlags);
- case KRB5_GET_AUTHZ_DATA:
- if (isInitiator()) {
- throw new GSSException(GSSException.UNAVAILABLE, -1,
- "Authorization data not available for initiator");
- } else {
- return KerbyUtil.kerbyAuthorizationDataToJgssAuthorizationDataEntries(authData);
- }
- case KRB5_GET_AUTHTIME:
- return authTime;
- }
- throw new GSSException(GSSException.UNAVAILABLE, -1, "Unsupported inquire type");
- }
-
-
- // functions not belong to SPI
- private void setSessionKey(EncryptionKey encryptionKey, int keyComesFrom) {
- this.sessionKey = encryptionKey;
- this.keyComesFrom = keyComesFrom;
- }
-
- public int getKeyComesFrom() {
- return keyComesFrom;
- }
-
- private EncryptionKey getSessionKey() {
- return sessionKey;
- }
-
- private void setTicketFlags(TicketFlags ticketFlags) {
- this.ticketFlags = ticketFlags;
- }
-
- private AuthorizationData authData;
- private void setAuthData(AuthorizationData authData) {
- this.authData = authData;
- }
-
-
- private int mySequenceNumber;
- private int peerSequenceNumber;
- private Object mySequenceNumberLock;
- private Object peerSequenceNumberLock;
-
- public void setMySequenceNumber(int sequenceNumber) {
- synchronized (mySequenceNumberLock) {
- mySequenceNumber = sequenceNumber;
- }
- }
-
- public int incMySequenceNumber() {
- synchronized (mySequenceNumberLock) {
- return mySequenceNumber++;
- }
- }
-
- public void setPeerSequenceNumber(int sequenceNumber) {
- synchronized (peerSequenceNumberLock) {
- peerSequenceNumber = sequenceNumber;
- }
- }
-
- public int incPeerSequenceNumber() {
- synchronized (peerSequenceNumberLock) {
- return peerSequenceNumber++;
- }
- }
-
- public KerbyGssEncryptor getGssEncryptor() {
- return gssEncryptor;
- }
-}