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/05/16 07:27:38 UTC
directory-kerby git commit: DIRKRB-566 Implement Gss tokens defined
in RFC 1964. Contributed by Wei.
Repository: directory-kerby
Updated Branches:
refs/heads/gssapi 6e34327e2 -> aa0098253
DIRKRB-566 Implement Gss tokens defined in RFC 1964. 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/aa009825
Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/aa009825
Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/aa009825
Branch: refs/heads/gssapi
Commit: aa0098253b9ee527a077d94272b7be3ae57f780b
Parents: 6e34327
Author: plusplusjiajia <ji...@intel.com>
Authored: Mon May 16 15:32:51 2016 +0800
Committer: plusplusjiajia <ji...@intel.com>
Committed: Mon May 16 15:32:51 2016 +0800
----------------------------------------------------------------------
.../kerberos/kerb/gssapi/krb5/CredUtils.java | 8 +-
.../kerberos/kerb/gssapi/krb5/KerbyContext.java | 33 +-
.../kerb/gssapi/krb5/KerbyGssEncryptor.java | 300 +++++++++++++++--
.../kerb/gssapi/krb5/KerbyGssTokenV1.java | 319 +++++++++++++++++++
.../kerberos/kerb/gssapi/krb5/MicTokenV1.java | 92 ++++++
.../kerberos/kerb/gssapi/krb5/WrapTokenV1.java | 196 ++++++++++++
.../kerberos/kerb/gssapi/krb5/WrapTokenV2.java | 9 +-
7 files changed, 921 insertions(+), 36 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/aa009825/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
index 6d066db..f7ddc31 100644
--- 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
@@ -4,10 +4,7 @@ import org.ietf.jgss.GSSException;
import sun.security.jgss.GSSCaller;
import javax.security.auth.Subject;
-import javax.security.auth.kerberos.KerberosPrincipal;
-import javax.security.auth.kerberos.KerberosTicket;
-import javax.security.auth.kerberos.KeyTab;
-import javax.security.auth.kerberos.ServicePermission;
+import javax.security.auth.kerberos.*;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedActionException;
@@ -55,7 +52,8 @@ public class CredUtils {
public static KeyTab getKeyTabFromContext(KerberosPrincipal principal) throws GSSException {
Set<KeyTab> tabs = getContextCredentials(KeyTab.class);
for (KeyTab tab : tabs) {
- if (tab.getPrincipal().equals(principal)) {
+ KerberosKey[] keys = tab.getKeys(principal);
+ if (keys != null && keys.length > 0) {
return tab;
}
}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/aa009825/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
index 1496cac..0bdd360 100644
--- 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
@@ -469,7 +469,11 @@ public class KerbyContext implements GSSContextSpi {
public int getWrapSizeLimit(int qop, boolean confReq, int maxTokSize)
throws GSSException {
- return 65536; // TODO: to be implemented
+ 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)
@@ -490,6 +494,9 @@ public class KerbyContext implements GSSContextSpi {
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);
}
}
@@ -498,10 +505,13 @@ public class KerbyContext implements GSSContextSpi {
if (ctxState != STATE_ESTABLISHED) {
throw new GSSException(GSSException.NO_CONTEXT, -1, "Context invalid for wrap");
}
- byte[] ret = null;
+ 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;
}
@@ -515,6 +525,9 @@ public class KerbyContext implements GSSContextSpi {
if (gssEncryptor.isV2()) {
WrapTokenV2 token = new WrapTokenV2(this, msgProp, is);
token.unwrap(os);
+ } else {
+ WrapTokenV1 token = new WrapTokenV1(this, msgProp, is);
+ token.unwrap(os);
}
}
@@ -524,10 +537,13 @@ public class KerbyContext implements GSSContextSpi {
throw new GSSException(GSSException.NO_CONTEXT, -1, "Context invalid for unwrap");
}
- byte[] ret = null;
+ 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;
}
@@ -545,6 +561,9 @@ public class KerbyContext implements GSSContextSpi {
if (gssEncryptor.isV2()) {
MicTokenV2 token = new MicTokenV2(this, inMsg, 0, len, msgProp);
token.getMic(os);
+ } else {
+ MicTokenV1 token = new MicTokenV1(this, inMsg, 0, len, msgProp);
+ token.getMic(os);
}
} catch (IOException e) {
throw new GSSException(GSSException.FAILURE, -1, "Error when get user data in getMIC:" + e.getMessage());
@@ -557,10 +576,13 @@ public class KerbyContext implements GSSContextSpi {
throw new GSSException(GSSException.NO_CONTEXT, -1, "Context invalid for getMIC");
}
- byte[] ret = null;
+ byte[] ret;
if (gssEncryptor.isV2()) {
MicTokenV2 token = new MicTokenV2(this, inMsg, offset, len, msgProp);
ret = token.getMic();
+ } else {
+ MicTokenV1 token = new MicTokenV1(this, inMsg, offset, len, msgProp);
+ ret = token.getMic();
}
return ret;
}
@@ -594,6 +616,9 @@ public class KerbyContext implements GSSContextSpi {
if (gssEncryptor.isV2()) {
MicTokenV2 token = new MicTokenV2(this, msgProp, inTok, tokOffset, tokLen);
token.verify(inMsg, msgOffset, msgLen);
+ } else {
+ MicTokenV1 token = new MicTokenV1(this, msgProp, inTok, tokOffset, tokLen);
+ token.verify(inMsg, msgOffset, msgLen);
}
}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/aa009825/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyGssEncryptor.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyGssEncryptor.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyGssEncryptor.java
index d65346b..9aff63e 100644
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyGssEncryptor.java
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyGssEncryptor.java
@@ -25,29 +25,66 @@ import org.apache.kerby.kerberos.kerb.crypto.CheckSumHandler;
import org.apache.kerby.kerberos.kerb.crypto.CheckSumTypeHandler;
import org.apache.kerby.kerberos.kerb.crypto.EncTypeHandler;
import org.apache.kerby.kerberos.kerb.crypto.EncryptionHandler;
+import org.apache.kerby.kerberos.kerb.crypto.cksum.provider.Md5Provider;
+import org.apache.kerby.kerberos.kerb.crypto.enc.provider.DesProvider;
+import org.apache.kerby.kerberos.kerb.crypto.enc.provider.Rc4Provider;
import org.apache.kerby.kerberos.kerb.type.base.CheckSumType;
import org.apache.kerby.kerberos.kerb.type.base.EncryptionKey;
import org.apache.kerby.kerberos.kerb.type.base.EncryptionType;
import org.ietf.jgss.GSSException;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
/**
* This class implements encryption related function used in GSS tokens
*/
public class KerbyGssEncryptor {
- private EncryptionKey encKey;
+ private final EncryptionKey encKey;
+ private final EncryptionType encKeyType; // The following two variables used for convenience
+ private final byte[] encKeyBytes;
+
+ private CheckSumType checkSumTypeDef;
+ private int checkSumSize;
+
private boolean isV2 = false;
+ private int sgnAlg = 0xFFFF;
+ private int sealAlg = 0xFFFF;
+ private boolean isArcFourHmac = false;
+
+ private static final byte[] IV_ZEROR_8B = new byte[8];
public KerbyGssEncryptor(EncryptionKey key) throws GSSException {
encKey = key;
- EncryptionType keyType = key.getKeyType();
- // TODO: add support for other algorithms
- if (keyType == EncryptionType.AES128_CTS_HMAC_SHA1_96
- || keyType == EncryptionType.AES256_CTS_HMAC_SHA1_96) {
+ encKeyBytes = encKey.getKeyData();
+ encKeyType = key.getKeyType();
+
+ if (encKeyType == EncryptionType.AES128_CTS_HMAC_SHA1_96) {
+ checkSumSize = 12;
+ checkSumTypeDef = CheckSumType.HMAC_SHA1_96_AES128;
isV2 = true;
+ } else if (encKeyType == EncryptionType.AES256_CTS_HMAC_SHA1_96) {
+ checkSumSize = 12;
+ checkSumTypeDef = CheckSumType.HMAC_SHA1_96_AES256;
+ isV2 = true;
+ } else if (encKeyType == EncryptionType.DES_CBC_CRC || encKeyType == EncryptionType.DES_CBC_MD5) {
+ sgnAlg = KerbyGssTokenV1.SGN_ALG_DES_MAC_MD5;
+ sealAlg = KerbyGssTokenV1.SEAL_ALG_DES;
+ checkSumSize = 8;
+ } else if (encKeyType == EncryptionType.DES3_CBC_SHA1) {
+ sgnAlg = KerbyGssTokenV1.SGN_ALG_HMAC_SHA1_DES3_KD;
+ sealAlg = KerbyGssTokenV1.SEAL_ALG_DES3_KD;
+ checkSumSize = 20;
+ } else if (encKeyType == EncryptionType.ARCFOUR_HMAC) {
+ sgnAlg = KerbyGssTokenV1.SGN_ALG_RC4_HMAC;
+ sealAlg = KerbyGssTokenV1.SEAL_ALG_RC4_HMAC;
+ checkSumSize = 16;
+ isArcFourHmac = true;
} else {
throw new GSSException(GSSException.FAILURE, -1,
- "Invalid encryption type: " + key.getKeyType().getDisplayName());
+ "Invalid encryption type: " + encKeyType.getDisplayName());
}
}
@@ -59,6 +96,18 @@ public class KerbyGssEncryptor {
return isV2;
}
+ public int getSgnAlg() {
+ return sgnAlg;
+ }
+
+ public int getSealAlg() {
+ return sealAlg;
+ }
+
+ public boolean isArcFourHmac() {
+ return isArcFourHmac;
+ }
+
public byte[] encryptData(byte[] tokenHeader, byte[] data,
int offset, int len, int keyUsage) throws GSSException {
byte[] ret;
@@ -102,37 +151,238 @@ public class KerbyGssEncryptor {
}
try {
- return getCheckSumHandler().checksumWithKey(buffer, encKey.getKeyData(), keyUsage);
+ return CheckSumHandler.getCheckSumHandler(checkSumTypeDef)
+ .checksumWithKey(buffer, encKey.getKeyData(), keyUsage);
} catch (KrbException e) {
throw new GSSException(GSSException.FAILURE, -1,
- "Exception in checksum calculation:" + encKey.getKeyType().getName());
+ "Exception in checksum calculation:" + e.getMessage());
+ }
+ }
+
+ /**
+ * Get the size of the corresponding checksum algorithm
+ * @return
+ * @throws GSSException
+ */
+ public int getCheckSumSize() throws GSSException {
+ return checkSumSize;
+ }
+
+
+ private void addPadding(int paddingLen, byte[] outBuf, int offset) {
+ for (int i = 0; i < paddingLen; i++) {
+ outBuf[offset + i] = (byte) paddingLen;
+ }
+ }
+
+ private byte[] getFirstBytes(byte[] src, int len) {
+ if (len < src.length) {
+ byte[] ret = new byte[len];
+ System.arraycopy(src, 0, ret, 0, len);
+ return ret;
}
+ return src;
}
- private CheckSumTypeHandler getCheckSumHandler() throws GSSException {
- CheckSumType checkSumType;
- if (encKey.getKeyType() == EncryptionType.AES128_CTS_HMAC_SHA1_96) {
- checkSumType = CheckSumType.HMAC_SHA1_96_AES128;
- } else if (encKey.getKeyType() == EncryptionType.AES256_CTS_HMAC_SHA1_96) {
- checkSumType = CheckSumType.HMAC_SHA1_96_AES256;
+ private byte[] getKeyBytesWithLength(int len) {
+ return getFirstBytes(encKeyBytes, len);
+ }
+
+ public byte[] calculateCheckSum(byte[] confounder, byte[] header,
+ byte[] data, int offset, int len, int paddingLen, boolean isMic)
+ throws GSSException {
+ byte[] ret;
+ int keyUsage = KerbyGssTokenV1.KG_USAGE_SIGN;
+ CheckSumTypeHandler handler;
+
+ int keySize;
+ byte[] key;
+ byte[] toProc;
+ int toOffset;
+ int toLen = (confounder == null ? 0 : confounder.length)
+ + (header == null ? 0 : header.length) + len + paddingLen;
+ if (toLen == len) {
+ toProc = data;
+ toOffset = offset;
} else {
+ toOffset = 0;
+ int idx = 0;
+ toProc = new byte[toLen];
+
+ if (header != null) {
+ System.arraycopy(header, 0, toProc, idx, header.length);
+ idx += header.length;
+ }
+
+ if (confounder != null) {
+ System.arraycopy(confounder, 0, toProc, idx, confounder.length);
+ idx += confounder.length;
+ }
+
+ System.arraycopy(data, offset, toProc, idx, len);
+ addPadding(paddingLen, toProc, len + idx);
+ }
+
+ CheckSumType chksumType;
+ try {
+ switch (sgnAlg) {
+ case KerbyGssTokenV1.SGN_ALG_DES_MAC_MD5:
+ Md5Provider md5Provider = new Md5Provider();
+ md5Provider.hash(toProc);
+ toProc = md5Provider.output();
+
+ case KerbyGssTokenV1.SGN_ALG_DES_MAC:
+ DesProvider desProvider = new DesProvider();
+ return desProvider.cbcMac(encKeyBytes, IV_ZEROR_8B, toProc);
+
+ case KerbyGssTokenV1.SGN_ALG_HMAC_SHA1_DES3_KD:
+ chksumType = CheckSumType.HMAC_SHA1_DES3_KD;
+ break;
+ case KerbyGssTokenV1.SGN_ALG_RC4_HMAC:
+ chksumType = CheckSumType.MD5_HMAC_ARCFOUR;
+ if (isMic) {
+ keyUsage = KerbyGssTokenV1.KG_USAGE_MS_SIGN;
+ }
+ break;
+ case KerbyGssTokenV1.SGN_ALG_MD25:
+ throw new GSSException(GSSException.FAILURE, -1, "CheckSum not implemented for SGN_ALG_MD25");
+ default:
+ throw new GSSException(GSSException.FAILURE, -1, "CheckSum not implemented for sgnAlg=" + sgnAlg);
+ }
+ handler = CheckSumHandler.getCheckSumHandler(chksumType);
+ keySize = handler.keySize();
+ key = getKeyBytesWithLength(keySize);
+ ret = handler.checksumWithKey(toProc, toOffset, toLen, key, keyUsage);
+ } catch (KrbException e) {
throw new GSSException(GSSException.FAILURE, -1,
- "Unsupported checksum encryption type:" + encKey.getKeyType().getName());
+ "Exception in checksum calculation sgnAlg = " + sgnAlg + " : " + e.getMessage());
}
+ return ret;
+ }
+
+ public byte[] encryptSequenceNumber(byte[] seqBytes, byte[] ivSrc, boolean encrypt)
+ throws GSSException {
+ EncTypeHandler handler;
try {
- return CheckSumHandler.getCheckSumHandler(checkSumType);
+ switch (sgnAlg) {
+ case KerbyGssTokenV1.SGN_ALG_DES_MAC_MD5:
+ case KerbyGssTokenV1.SGN_ALG_DES_MAC:
+ DesProvider desProvider = new DesProvider();
+ byte[] data = seqBytes.clone();
+ if (encrypt) {
+ desProvider.encrypt(encKeyBytes, ivSrc, data);
+ } else {
+ desProvider.decrypt(encKeyBytes, ivSrc, data);
+ }
+ return data;
+ case KerbyGssTokenV1.SGN_ALG_HMAC_SHA1_DES3_KD:
+ handler = EncryptionHandler.getEncHandler(EncryptionType.DES3_CBC_SHA1_KD);
+ break;
+ case KerbyGssTokenV1.SGN_ALG_RC4_HMAC:
+ return encryptArcFourHmac(seqBytes, getKeyBytesWithLength(16), getFirstBytes(ivSrc, 8), encrypt);
+ case KerbyGssTokenV1.SGN_ALG_MD25:
+ throw new GSSException(GSSException.FAILURE, -1, "EncSeq not implemented for SGN_ALG_MD25");
+ default:
+ throw new GSSException(GSSException.FAILURE, -1, "EncSeq not implemented for sgnAlg=" + sgnAlg);
+ }
+ int keySize = handler.keySize();
+ byte[] key = getKeyBytesWithLength(keySize);
+ int ivLen = handler.encProvider().blockSize();
+ byte[] iv = getFirstBytes(ivSrc, ivLen);
+ if (encrypt) {
+ return handler.encryptRaw(seqBytes, key, iv, KerbyGssTokenV1.KG_USAGE_SEQ);
+ } else {
+ return handler.decryptRaw(seqBytes, key, iv, KerbyGssTokenV1.KG_USAGE_SEQ);
+ }
} catch (KrbException e) {
throw new GSSException(GSSException.FAILURE, -1,
- "Unsupported checksum type:" + checkSumType.getName());
+ "Exception in encrypt seq number sgnAlg = " + sgnAlg + " : " + e.getMessage());
}
}
- /**
- * Get the size of the corresponding checksum algorithm
- * @return
- * @throws GSSException
- */
- public int getCheckSumSize() throws GSSException {
- return getCheckSumHandler().cksumSize();
+ private byte[] getHmacMd5(byte[] key, byte[] salt) throws GSSException {
+ try {
+ SecretKey secretKey = new SecretKeySpec(key, "HmacMD5");
+ Mac mac = Mac.getInstance("HmacMD5");
+ mac.init(secretKey);
+ return mac.doFinal(salt);
+ } catch (Exception e) {
+ throw new GSSException(GSSException.FAILURE, -1, "Get HmacMD5 failed: " + e.getMessage());
+ }
+ }
+
+ private byte[] encryptArcFourHmac(byte[] data, byte[] key, byte[] iv, boolean encrypt)
+ throws GSSException {
+ byte[] sk1 = getHmacMd5(key, new byte[4]);
+ byte[] sk2 = getHmacMd5(sk1, iv);
+ Rc4Provider provider = new Rc4Provider();
+ try {
+ byte[] ret = data.clone();
+ if (encrypt) {
+ provider.encrypt(sk2, ret);
+ } else {
+ provider.decrypt(sk2, ret);
+ }
+ return ret;
+ } catch (KrbException e) {
+ throw new GSSException(GSSException.FAILURE, -1,
+ "En/Decrypt sequence failed for ArcFourHmac: " + e.getMessage());
+ }
+ }
+
+ private byte[] encryptDataArcFourHmac(byte[] data, byte[] key, byte[] seqNum, boolean encrypt) throws GSSException {
+ byte[] dataKey = new byte[key.length];
+ for (int i = 0; i <= 15; i++) {
+ dataKey[i] = (byte) (key[i] ^ 0xF0);
+ }
+ return encryptArcFourHmac(data, dataKey, seqNum, encrypt);
+ }
+
+ public byte[] encryptTokenV1(byte[] confounder, byte[] data, int offset, int len,
+ int paddingLen, byte[] seqNumber, boolean encrypt) throws GSSException {
+ byte[] toProc;
+ if (encrypt) {
+ int toLen = (confounder == null ? 0 : confounder.length) + len + paddingLen;
+ int index = 0;
+ toProc = new byte[toLen];
+ if (confounder != null) {
+ System.arraycopy(confounder, 0, toProc, 0, confounder.length);
+ index += confounder.length;
+ }
+ System.arraycopy(data, offset, toProc, index, len);
+ addPadding(paddingLen, toProc, index + len);
+ } else {
+ toProc = data;
+ if (data.length != len) {
+ toProc = new byte[len];
+ System.arraycopy(data, offset, toProc, 0, len);
+ }
+ }
+ EncTypeHandler handler;
+ try {
+ switch (sealAlg) {
+ case KerbyGssTokenV1.SEAL_ALG_DES:
+ handler = EncryptionHandler.getEncHandler(EncryptionType.DES_CBC_MD5);
+ break;
+ case KerbyGssTokenV1.SEAL_ALG_DES3_KD:
+ handler = EncryptionHandler.getEncHandler(EncryptionType.DES3_CBC_SHA1_KD);
+ break;
+ case KerbyGssTokenV1.SEAL_ALG_RC4_HMAC:
+ return encryptDataArcFourHmac(toProc, getKeyBytesWithLength(16), seqNumber, encrypt);
+ default:
+ throw new GSSException(GSSException.FAILURE, -1, "Unknown encryption type sealAlg = " + sealAlg);
+ }
+
+ int keySize = handler.keySize();
+ byte[] key = getKeyBytesWithLength(keySize);
+ if (encrypt) {
+ return handler.encryptRaw(toProc, key, KerbyGssTokenV1.KG_USAGE_SEAL);
+ } else {
+ return handler.decryptRaw(toProc, key, KerbyGssTokenV1.KG_USAGE_SEAL);
+ }
+ } catch (KrbException e) {
+ throw new GSSException(GSSException.FAILURE, -1,
+ "Exception in encrypt data sealAlg = " + sealAlg + " : " + e.getMessage());
+ }
}
-}
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/aa009825/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyGssTokenV1.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyGssTokenV1.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyGssTokenV1.java
new file mode 100644
index 0000000..6b1a2c7
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/KerbyGssTokenV1.java
@@ -0,0 +1,319 @@
+/**
+ * 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 org.ietf.jgss.MessageProp;
+import sun.security.jgss.GSSHeader;
+import sun.security.util.ObjectIdentifier;
+
+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 1964 and its updates
+ *
+ * The GSS Wrap token has the following format:
+ *
+ * Byte no Name Description
+ * 0..1 TOK_ID 0201
+ *
+ * 2..3 SGN_ALG Checksum algorithm indicator.
+ * 00 00 DES MAC MD5
+ * 01 00 MD2.5
+ * 02 00 DES MAC
+ * 04 00 HMAC SHA1 DES3-KD
+ * 11 00 RC4-HMAC used by Microsoft Windows, RFC 4757
+ * 4..5 SEAL_ALG ff ff none
+ * 00 00 DES
+ * 02 00 DES3-KD
+ * 10 00 RC4-HMAC
+ * 6..7 Filler FF FF
+ * 8..15 SND_SEQ Encrypted sequence number field.
+ * 16..23 SNG_CKSUM Checksum of plaintext padded data,
+ * calculated according to algorithm
+ * specified in SGN_ALG field.
+ * 24.. Data Encrypted or plaintext padded data
+ *
+ *
+ *
+ * Use of the GSS MIC token has the following format:
+
+ * Byte no Name Description
+ * 0..1 TOK_ID 0101
+ * 2..3 SGN_ALG Integrity algorithm indicator.
+ * 4..7 Filler Contains ff ff ff ff
+ * 8..15 SND_SEQ Sequence number field.
+ * 16..23 SGN_CKSUM Checksum of "to-be-signed data",
+ * calculated according to algorithm
+ * specified in SGN_ALG field.
+ *
+ */
+abstract class KerbyGssTokenV1 extends KerbyGssTokenBase {
+ // SGN ALG
+ public static final int SGN_ALG_DES_MAC_MD5 = 0;
+ public static final int SGN_ALG_MD25 = 0x0100;
+ public static final int SGN_ALG_DES_MAC = 0x0200;
+ public static final int SGN_ALG_HMAC_SHA1_DES3_KD = 0x0400;
+ public static final int SGN_ALG_RC4_HMAC = 0x1100;
+
+ // SEAL ALG
+ public static final int SEAL_ALG_NONE = 0xFFFF;
+ public static final int SEAL_ALG_DES = 0x0; // "DES/CBC/NoPadding"
+ public static final int SEAL_ALG_DES3_KD = 0x0200;
+ public static final int SEAL_ALG_RC4_HMAC = 0x1000;
+
+ public static final int KG_USAGE_SEAL = 22;
+ public static final int KG_USAGE_SIGN = 23;
+ public static final int KG_USAGE_SEQ = 24;
+ public static final int KG_USAGE_MS_SIGN = 15;
+
+ private boolean isInitiator;
+ private boolean confState;
+ private int sequenceNumber;
+
+ protected KerbyGssEncryptor encryptor;
+
+ private GSSHeader gssHeader;
+
+ public static final int TOKEN_HEADER_COMM_SIZE = 8;
+ public static final int TOKEN_HEADER_SEQ_SIZE = 8;
+
+ // Token commHeader data
+ private int tokenType;
+ private byte[] commHeader = new byte[TOKEN_HEADER_COMM_SIZE];
+ private int sgnAlg;
+ private int sealAlg;
+
+ private byte[] plainSequenceBytes;
+ private byte[] encryptedSequenceNumber = new byte[TOKEN_HEADER_SEQ_SIZE];
+ private byte[] checkSum;
+ private int checkSumSize;
+
+ protected int reconHeaderLen; // only used for certain reason
+
+ public static ObjectIdentifier objId;
+
+ static {
+ try {
+ objId = new ObjectIdentifier("1.2.840.113554.1.2.2");
+ } catch (IOException ioe) { // NOPMD
+ }
+ }
+
+ protected int getTokenHeaderSize() {
+ return TOKEN_HEADER_COMM_SIZE + TOKEN_HEADER_SEQ_SIZE + checkSumSize;
+ }
+
+ protected byte[] getPlainSequenceBytes() {
+ byte[] ret = new byte[4];
+ ret[0] = plainSequenceBytes[0];
+ ret[1] = plainSequenceBytes[1];
+ ret[2] = plainSequenceBytes[2];
+ ret[3] = plainSequenceBytes[3];
+ return ret;
+ }
+
+ // Generate a new token
+ KerbyGssTokenV1(int tokenType, KerbyContext context) throws GSSException {
+ initialize(tokenType, context, false);
+ createTokenHeader();
+ }
+
+ // Reconstruct a token
+ KerbyGssTokenV1(int tokenType, KerbyContext context, MessageProp prop,
+ byte[] token, int offset, int size) throws GSSException {
+ int proxLen = size > 64 ? 64 : size;
+ InputStream is = new ByteArrayInputStream(token, offset, proxLen);
+ reconstructInitializaion(tokenType, context, prop, is);
+ reconHeaderLen = gssHeader.getLength() + getTokenHeaderSize();
+ }
+
+ // Reconstruct a token
+ KerbyGssTokenV1(int tokenType, KerbyContext context, MessageProp prop, InputStream is) throws GSSException {
+ reconstructInitializaion(tokenType, context, prop, is);
+ }
+
+ private void reconstructInitializaion(int tokenType, KerbyContext context, MessageProp prop, InputStream is)
+ throws GSSException {
+ initialize(tokenType, context, true);
+ if (!confState) {
+ prop.setPrivacy(false);
+ }
+
+ try {
+ gssHeader = new GSSHeader(is);
+ } catch (IOException e) {
+ throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1, "Invalid token:" + e.getMessage());
+ }
+
+ if (!gssHeader.getOid().equals((Object) objId)) {
+ throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1, "Invalid token OID");
+ }
+
+ reconstructTokenHeader(is, prop);
+ }
+
+ private void initialize(int tokenType,
+ KerbyContext context,
+ boolean reconstruct) throws GSSException {
+ this.tokenType = tokenType;
+ this.isInitiator = context.isInitiator();
+ this.confState = context.getConfState();
+ this.encryptor = context.getGssEncryptor();
+ this.checkSumSize = encryptor.getCheckSumSize();
+ if (!reconstruct) {
+ this.sequenceNumber = context.incMySequenceNumber();
+ } else {
+ checkSum = new byte[checkSumSize];
+ }
+ }
+
+ protected void calcPrivacyInfo(MessageProp prop, byte[] confounder, byte[] data,
+ int dataOffset, int dataLength, int paddingLen) throws GSSException {
+ prop.setQOP(0);
+ if (!confState) {
+ prop.setPrivacy(false);
+ }
+
+ checkSum = calcCheckSum(confounder, commHeader, data, dataOffset, dataLength, paddingLen);
+ encryptSequenceNumber();
+ }
+
+ protected void verifyToken(byte[] confounder, byte[] data, int dataOffset, int dataLength, int paddingLen)
+ throws GSSException {
+ byte[] sum = calcCheckSum(confounder, commHeader, data, dataOffset, dataLength, paddingLen);
+ if (!MessageDigest.isEqual(checkSum, sum)) {
+ throw new GSSException(GSSException.BAD_MIC, -1,
+ "Corrupt token checksum for " + (tokenType == TOKEN_MIC_V1 ? "Mic" : "Wrap") + "TokenV1");
+ }
+ }
+
+ private byte[] calcCheckSum(byte[] confounder, byte[] header, byte[] data,
+ int dataOffset, int dataLength, int paddingLen) throws GSSException {
+ return encryptor.calculateCheckSum(confounder, header, data, dataOffset, dataLength, paddingLen,
+ tokenType == TOKEN_MIC_V1);
+ }
+
+ private void encryptSequenceNumber() throws GSSException {
+ plainSequenceBytes = new byte[8];
+ if (encryptor.isArcFourHmac()) {
+ writeBigEndian(plainSequenceBytes, 0, sequenceNumber);
+ } else {
+ plainSequenceBytes[0] = (byte) sequenceNumber;
+ plainSequenceBytes[1] = (byte) (sequenceNumber >>> 8);
+ plainSequenceBytes[2] = (byte) (sequenceNumber >>> 16);
+ plainSequenceBytes[3] = (byte) (sequenceNumber >>> 24);
+ }
+
+ // Hex 0 - sender is the context initiator, Hex FF - sender is the context acceptor
+ if (!isInitiator) {
+ plainSequenceBytes[4] = (byte) 0xFF;
+ plainSequenceBytes[5] = (byte) 0xFF;
+ plainSequenceBytes[6] = (byte) 0xFF;
+ plainSequenceBytes[7] = (byte) 0xFF;
+ }
+
+ encryptedSequenceNumber = encryptor.encryptSequenceNumber(plainSequenceBytes, checkSum, true);
+ }
+
+ public void encodeHeader(OutputStream os) throws GSSException, IOException {
+ // | GSSHeader | TokenHeader |
+ GSSHeader gssHeader = new GSSHeader(objId, getTokenSizeWithoutGssHeader());
+ gssHeader.encode(os);
+ os.write(commHeader);
+ os.write(encryptedSequenceNumber);
+ os.write(checkSum);
+ }
+
+ private void createTokenHeader() {
+ commHeader[0] = (byte) (tokenType >>> 8);
+ commHeader[1] = (byte) tokenType;
+
+ sgnAlg = encryptor.getSgnAlg();
+ commHeader[2] = (byte) (sgnAlg >>> 8);
+ commHeader[3] = (byte) sgnAlg;
+
+ if (tokenType == TOKEN_WRAP_V1) {
+ sealAlg = encryptor.getSealAlg();
+ commHeader[4] = (byte) (sealAlg >>> 8);
+ commHeader[5] = (byte) sealAlg;
+ } else {
+ commHeader[4] = (byte) 0xFF;
+ commHeader[5] = (byte) 0xFF;
+ }
+
+ commHeader[6] = (byte) 0xFF;
+ commHeader[7] = (byte) 0xFF;
+ }
+
+ // Re-construct token commHeader
+ private void reconstructTokenHeader(InputStream is, MessageProp prop) throws GSSException {
+ try {
+ if (is.read(commHeader) != commHeader.length
+ || is.read(encryptedSequenceNumber) != encryptedSequenceNumber.length
+ || is.read(checkSum) != checkSum.length) {
+ throw new GSSException(GSSException.FAILURE, -1,
+ "Insufficient in reconstruct token header");
+ }
+ initTokenHeader(commHeader, prop);
+
+ plainSequenceBytes = encryptor.encryptSequenceNumber(encryptedSequenceNumber, checkSum, false);
+ byte dirc = isInitiator ? (byte) 0xFF : 0;
+ // Hex 0 - sender is the context initiator, Hex FF - sender is the context acceptor
+ if (!(plainSequenceBytes[4] == dirc && plainSequenceBytes[5] == dirc
+ && plainSequenceBytes[6] == dirc && plainSequenceBytes[7] == dirc)) {
+ throw new GSSException(GSSException.BAD_MIC, -1,
+ "Corrupt token sequence for " + (tokenType == TOKEN_MIC_V1 ? "Mic" : "Wrap") + "TokenV1");
+ }
+ } catch (IOException e) {
+ throw new GSSException(GSSException.FAILURE, -1,
+ "Error in reconstruct token header:" + e.getMessage());
+ }
+ }
+
+ private void initTokenHeader(byte[] tokenBytes, MessageProp prop) throws GSSException {
+ int tokenIDRecv = (((int) tokenBytes[0]) << 8) + tokenBytes[1];
+ if (tokenType != tokenIDRecv) {
+ throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
+ "Token ID should be " + tokenType + " instead of " + tokenIDRecv);
+ }
+
+ sgnAlg = (((int) tokenBytes[2]) << 8) + tokenBytes[3];
+ sealAlg = (((int) tokenBytes[4]) << 8) + tokenBytes[5];
+
+ if (tokenBytes[6] != (byte) 0xFF || tokenBytes[7] != (byte) 0xFF) {
+ throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1, "Invalid token head filler");
+ }
+
+ prop.setQOP(0);
+ prop.setPrivacy(sealAlg != SEAL_ALG_NONE);
+ }
+
+ protected GSSHeader getGssHeader() {
+ return gssHeader;
+ }
+
+ abstract int getTokenSizeWithoutGssHeader();
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/aa009825/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/MicTokenV1.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/MicTokenV1.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/MicTokenV1.java
new file mode 100644
index 0000000..6a76e4c
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/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.gssapi.krb5;
+
+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 KerbyGssTokenV1 {
+ public MicTokenV1(KerbyContext 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(KerbyContext 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/aa009825/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/WrapTokenV1.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/WrapTokenV1.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/WrapTokenV1.java
new file mode 100644
index 0000000..8ecdae4
--- /dev/null
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/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.gssapi.krb5;
+
+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 KerbyGssTokenV1 {
+ 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(KerbyContext 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(KerbyContext 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(KerbyContext 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, KerbyGssEncryptor 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/aa009825/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/WrapTokenV2.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/WrapTokenV2.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/WrapTokenV2.java
index 3a128a9..57f9e45 100644
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/WrapTokenV2.java
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gssapi/krb5/WrapTokenV2.java
@@ -147,7 +147,12 @@ public class WrapTokenV2 extends KerbyGssTokenV2 {
}
}
- static int getSizeLimit(int qop, boolean confReq, int maxTokSize) {
- return maxTokSize; // TODO: to be implemented
+ public static int getMsgSizeLimit(int qop, boolean confReq, int maxTokSize, KerbyGssEncryptor encryptor)
+ throws GSSException {
+ if (confReq) {
+ return maxTokSize - encryptor.getCheckSumSize() - TOKEN_HEADER_SIZE * 2 - CONFOUNDER_SIZE;
+ } else {
+ return maxTokSize - encryptor.getCheckSumSize() - TOKEN_HEADER_SIZE;
+ }
}
}