[jboss-cvs] JBossAS SVN: r109354 - in projects/security/security-negotiation/trunk: jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher and 5 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Wed Nov 17 11:58:58 EST 2010
Author: mmoyses
Date: 2010-11-17 11:58:57 -0500 (Wed, 17 Nov 2010)
New Revision: 109354
Added:
projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/
projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/Aes128CtsHmacSha1Decoder.java
projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/Aes256CtsHmacSha1Decoder.java
projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/AesCtsHmacSha1Decoder.java
projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/ArcFourHmacDecoder.java
projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/Decoder.java
projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/Des3CbcHmacSha1KdDecoder.java
projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/DesCbcCrcDecoder.java
projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/DesCbcDecoder.java
projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/DesCbcMd5Decoder.java
projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/encoding/TokenParser.java
projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/
projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/InitSPNEGOContextAction.java
projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SPNEGOServerSocket.java
projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SPNEGOServerSocketFactory.java
projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SPNEGOSocket.java
projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SPNEGOSocketFactory.java
projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SecurityActions.java
Modified:
projects/security/security-negotiation/trunk/jboss-negotiation-spnego/pom.xml
projects/security/security-negotiation/trunk/parent/pom.xml
Log:
SECURITY-541: allowing SSO with EJB3s
Added: projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/Aes128CtsHmacSha1Decoder.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/Aes128CtsHmacSha1Decoder.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/Aes128CtsHmacSha1Decoder.java 2010-11-17 16:58:57 UTC (rev 109354)
@@ -0,0 +1,52 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.negotiation.cipher;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * A {@link Decoder} for Aes128CtsHmacSha1.
+ *
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+public class Aes128CtsHmacSha1Decoder extends AesCtsHmacSha1Decoder
+{
+
+ public int keySize()
+ {
+ return 16;
+ }
+
+ protected int getKeySeedLength()
+ {
+ return 128;
+ }
+
+ protected byte[] decrypt(byte[] baseKey, int usage, byte[] ivec, byte[] cipherText, int start, int length)
+ throws GeneralSecurityException
+ {
+ //TODO
+ return null;
+ }
+
+}
Added: projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/Aes256CtsHmacSha1Decoder.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/Aes256CtsHmacSha1Decoder.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/Aes256CtsHmacSha1Decoder.java 2010-11-17 16:58:57 UTC (rev 109354)
@@ -0,0 +1,43 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.negotiation.cipher;
+
+/**
+ * A {@link Decoder} for Aes256CtsHmacSha1.
+ *
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+public class Aes256CtsHmacSha1Decoder extends AesCtsHmacSha1Decoder
+{
+
+ public int keySize()
+ {
+ return 32;
+ }
+
+ protected int getKeySeedLength()
+ {
+ return 256;
+ }
+
+}
Added: projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/AesCtsHmacSha1Decoder.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/AesCtsHmacSha1Decoder.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/AesCtsHmacSha1Decoder.java 2010-11-17 16:58:57 UTC (rev 109354)
@@ -0,0 +1,318 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.negotiation.cipher;
+
+import java.security.GeneralSecurityException;
+import java.util.Arrays;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.jboss.logging.Logger;
+import org.jboss.security.negotiation.NegotiationException;
+
+/**
+ * Common methods for the Aes*CtsHmacSha1 types.
+ *
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AesCtsHmacSha1Decoder extends Decoder
+{
+
+ private static Logger log = Logger.getLogger(AesCtsHmacSha1Decoder.class);
+
+ private static final int BLOCK_SIZE = 16;
+
+ private static final byte[] ZERO_IV = new byte[] {0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+
+ private static final int hashSize = 96 / 8;
+
+ public int blockSize()
+ {
+ return 16;
+ }
+
+ public int checksumSize()
+ {
+ return hashSize;
+ }
+
+ public int confounderSize()
+ {
+ return blockSize();
+ }
+
+ public byte[] decrypt(byte[] cipher, byte[] key, int usage) throws NegotiationException
+ {
+ byte[] ivec = new byte[blockSize()];
+ return decrypt(cipher, key, ivec, usage);
+ }
+
+ public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage) throws NegotiationException
+ {
+ try
+ {
+ return decrypt(key, usage, ivec, cipher, 0, cipher.length);
+ }
+ catch (GeneralSecurityException e)
+ {
+ NegotiationException ne = new NegotiationException(e.getMessage());
+ ne.initCause(e);
+ throw ne;
+ }
+ }
+
+ protected byte[] decrypt(byte[] baseKey, int usage, byte[] ivec, byte[] cipherText, int start, int length)
+ throws GeneralSecurityException
+ {
+ byte[] output = decryptCTS(baseKey, usage, ivec, cipherText, start, length, true);
+ return output;
+ }
+
+ protected byte[] decryptCTS(byte[] baseKey, int usage, byte[] ivec, byte[] ciphertext, int start, int len,
+ boolean confounder_exists) throws GeneralSecurityException
+ {
+ byte[] Ke = null;
+ byte[] Ki = null;
+
+ try
+ {
+ // Derive encryption key
+ byte[] constant = new byte[5];
+ constant[0] = (byte) ((usage >> 24) & 0xff);
+ constant[1] = (byte) ((usage >> 16) & 0xff);
+ constant[2] = (byte) ((usage >> 8) & 0xff);
+ constant[3] = (byte) (usage & 0xff);
+
+ constant[4] = (byte) 0xaa;
+ Ke = dk(baseKey, constant); // Encryption key
+
+ // Decrypt [confounder | plaintext ] (without checksum)
+
+ // AES in JCE
+ Cipher cipher = Cipher.getInstance("AES/CTS/NoPadding");
+ SecretKeySpec secretKey = new SecretKeySpec(Ke, "AES");
+ IvParameterSpec encIv = new IvParameterSpec(ivec, 0, ivec.length);
+ cipher.init(Cipher.DECRYPT_MODE, secretKey, encIv);
+ byte[] plaintext = cipher.doFinal(ciphertext, start, len - hashSize);
+
+ // Derive integrity key
+ constant[4] = (byte) 0x55;
+ Ki = dk(baseKey, constant); // Integrity key
+
+ // Verify checksum
+ // H1 = HMAC(Ki, conf | plaintext | pad)
+ byte[] calculatedHmac = getHmac(Ki, plaintext);
+ int hmacOffset = start + len - hashSize;
+ boolean cksumFailed = false;
+ if (calculatedHmac.length >= hashSize)
+ {
+ for (int i = 0; i < hashSize; i++)
+ {
+ if (calculatedHmac[i] != ciphertext[hmacOffset + i])
+ {
+ cksumFailed = true;
+ log.error("Checksum failed !");
+ break;
+ }
+ }
+ }
+ if (cksumFailed)
+ {
+ throw new GeneralSecurityException("Checksum failed");
+ }
+
+ if (confounder_exists)
+ {
+ // Get rid of confounder
+ // [ confounder | plaintext ]
+ byte[] output = new byte[plaintext.length - BLOCK_SIZE];
+ System.arraycopy(plaintext, BLOCK_SIZE, output, 0, output.length);
+ return output;
+ }
+ else
+ {
+ return plaintext;
+ }
+ }
+ finally
+ {
+ if (Ke != null)
+ {
+ Arrays.fill(Ke, 0, Ke.length, (byte) 0);
+ }
+ if (Ki != null)
+ {
+ Arrays.fill(Ki, 0, Ki.length, (byte) 0);
+ }
+ }
+ }
+
+ protected byte[] getHmac(byte[] key, byte[] msg) throws GeneralSecurityException
+ {
+ SecretKey keyKi = new SecretKeySpec(key, "HMAC");
+ Mac m = Mac.getInstance("HmacSHA1");
+ m.init(keyKi);
+
+ // generate hash
+ byte[] hash = m.doFinal(msg);
+
+ // truncate hash
+ byte[] output = new byte[hashSize];
+ System.arraycopy(hash, 0, output, 0, hashSize);
+ return output;
+ }
+
+ protected byte[] dk(byte[] key, byte[] constant) throws GeneralSecurityException
+ {
+ return randomToKey(dr(key, constant));
+ }
+
+ protected byte[] randomToKey(byte[] in)
+ {
+ // simple identity operation
+ return in;
+ }
+
+ private byte[] dr(byte[] key, byte[] constant) throws GeneralSecurityException
+ {
+ Cipher encCipher = getCipher(key, null, Cipher.ENCRYPT_MODE);
+ int blocksize = encCipher.getBlockSize();
+
+ if (constant.length != blocksize)
+ {
+ constant = nfold(constant, blocksize * 8);
+ }
+ byte[] toBeEncrypted = constant;
+
+ int keybytes = (getKeySeedLength() >> 3); // from bits to bytes
+ byte[] rawkey = new byte[keybytes];
+
+ /* loop encrypting the blocks until enough key bytes are generated */
+ int n = 0, len;
+ while (n < keybytes)
+ {
+ byte[] cipherBlock = encCipher.doFinal(toBeEncrypted);
+ len = (keybytes - n <= cipherBlock.length ? (keybytes - n) : cipherBlock.length);
+ System.arraycopy(cipherBlock, 0, rawkey, n, len);
+ n += len;
+ toBeEncrypted = cipherBlock;
+ }
+ return rawkey;
+ }
+
+ protected Cipher getCipher(byte[] key, byte[] ivec, int mode) throws GeneralSecurityException
+ {
+ // IV
+ if (ivec == null)
+ {
+ ivec = ZERO_IV;
+ }
+ SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
+ Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+ IvParameterSpec encIv = new IvParameterSpec(ivec, 0, ivec.length);
+ cipher.init(mode, secretKey, encIv);
+ return cipher;
+ }
+
+ public byte[] decryptedData(byte[] data)
+ {
+ return data;
+ }
+
+ static byte[] nfold(byte[] in, int outbits)
+ {
+ int inbits = in.length;
+ outbits >>= 3; // count in bytes
+
+ /* first compute lcm(n,k) */
+ int a, b, c, lcm;
+ a = outbits; // n
+ b = inbits; // k
+
+ while (b != 0)
+ {
+ c = b;
+ b = a % b;
+ a = c;
+ }
+ lcm = outbits * inbits / a;
+
+ /* now do the real work */
+ byte[] out = new byte[outbits];
+ Arrays.fill(out, (byte) 0);
+
+ int thisbyte = 0;
+ int msbit, i, bval, oval;
+
+ // this will end up cycling through k lcm(k,n)/k times, which
+ // is correct
+ for (i = lcm - 1; i >= 0; i--)
+ {
+ /* compute the msbit in k which gets added into this byte */
+ msbit = (/* first, start with msbit in the first, unrotated byte */
+ ((inbits << 3) - 1)
+ /* then, for each byte, shift to right for each repetition */
+ + (((inbits << 3) + 13) * (i / inbits))
+ /* last, pick out correct byte within that shifted repetition */
+ + ((inbits - (i % inbits)) << 3)) % (inbits << 3);
+
+ /* pull out the byte value itself */
+ // Mask off values using &0xff to get only the lower byte
+ // Use >>> to avoid sign extension
+ bval = ((((in[((inbits - 1) - (msbit >>> 3)) % inbits] & 0xff) << 8) | (in[((inbits) - (msbit >>> 3)) % inbits] & 0xff)) >>> ((msbit & 7) + 1)) & 0xff;
+ thisbyte += bval;
+
+ /* do the addition */
+ // Mask off values using &0xff to get only the lower byte
+ oval = (out[i % outbits] & 0xff);
+ thisbyte += oval;
+ out[i % outbits] = (byte) (thisbyte & 0xff);
+
+ /* keep around the carry bit, if any */
+ thisbyte >>>= 8;
+ }
+
+ /* if there's a carry bit left over, add it back in */
+ if (thisbyte != 0)
+ {
+ for (i = outbits - 1; i >= 0; i--)
+ {
+ /* do the addition */
+ thisbyte += (out[i] & 0xff);
+ out[i] = (byte) (thisbyte & 0xff);
+
+ /* keep around the carry bit, if any */
+ thisbyte >>>= 8;
+ }
+ }
+
+ return out;
+ }
+
+ protected abstract int getKeySeedLength();
+}
Added: projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/ArcFourHmacDecoder.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/ArcFourHmacDecoder.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/ArcFourHmacDecoder.java 2010-11-17 16:58:57 UTC (rev 109354)
@@ -0,0 +1,177 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.negotiation.cipher;
+
+import java.security.GeneralSecurityException;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.jboss.security.negotiation.NegotiationException;
+
+/**
+ * A {@link Decoder} for ArcFourHmac.
+ *
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+public class ArcFourHmacDecoder extends Decoder
+{
+
+ private static final int hashSize = 16;
+
+ public int blockSize()
+ {
+ return 1;
+ }
+
+ public int checksumSize()
+ {
+ return 16;
+ }
+
+ public int confounderSize()
+ {
+ return 8;
+ }
+
+ public int keySize()
+ {
+ return 16;
+ }
+
+ public byte[] decrypt(byte[] cipher, byte[] key, int usage) throws NegotiationException
+ {
+ byte[] ivec = new byte[blockSize()];
+ return decrypt(cipher, key, ivec, usage);
+ }
+
+ public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage) throws NegotiationException
+ {
+ try
+ {
+ return decrypt(key, usage, ivec, cipher, 0, cipher.length);
+ }
+ catch (GeneralSecurityException e)
+ {
+ NegotiationException ne = new NegotiationException(e.getMessage());
+ ne.initCause(e);
+ throw ne;
+ }
+ }
+
+ private byte[] decrypt(byte[] baseKey, int usage, byte[] ivec, byte[] ciphertext, int start, int len)
+ throws GeneralSecurityException
+ {
+ // compute K1
+ byte[] k1 = new byte[baseKey.length];
+ System.arraycopy(baseKey, 0, k1, 0, baseKey.length);
+
+ // get the salt using key usage
+ byte[] salt = getSalt(usage);
+
+ // compute K2 using K1
+ byte[] k2 = getHmac(k1, salt);
+
+ // compute K3 using K2 and checksum
+ byte[] checksum = new byte[hashSize];
+ System.arraycopy(ciphertext, start, checksum, 0, hashSize);
+ byte[] k3 = getHmac(k2, checksum);
+
+ // Decrypt [confounder | plaintext ] (without checksum)
+ Cipher cipher = Cipher.getInstance("ARCFOUR");
+ SecretKeySpec secretKey = new SecretKeySpec(k3, "ARCFOUR");
+ cipher.init(Cipher.DECRYPT_MODE, secretKey);
+ byte[] plaintext = cipher.doFinal(ciphertext, start + hashSize, len - hashSize);
+
+ // Verify checksum
+ byte[] calculatedHmac = getHmac(k2, plaintext);
+ boolean cksumFailed = false;
+ if (calculatedHmac.length >= hashSize)
+ {
+ for (int i = 0; i < hashSize; i++)
+ {
+ if (calculatedHmac[i] != ciphertext[i])
+ {
+ cksumFailed = true;
+ System.err.println("Checksum failed !");
+ break;
+ }
+ }
+ }
+ if (cksumFailed)
+ {
+ throw new GeneralSecurityException("Checksum failed");
+ }
+
+ // Get rid of confounder
+ // [ confounder | plaintext ]
+ byte[] output = new byte[plaintext.length - confounderSize()];
+ System.arraycopy(plaintext, confounderSize(), output, 0, output.length);
+
+ return output;
+ }
+
+ protected byte[] getHmac(byte[] key, byte[] msg) throws GeneralSecurityException
+ {
+ SecretKey keyKi = new SecretKeySpec(key, "HmacMD5");
+ Mac m = Mac.getInstance("HmacMD5");
+ m.init(keyKi);
+
+ // generate hash
+ byte[] hash = m.doFinal(msg);
+ return hash;
+ }
+
+ private byte[] getSalt(int usage)
+ {
+ int ms_usage = arcfour_translate_usage(usage);
+ byte[] salt = new byte[4];
+ salt[0] = (byte) (ms_usage & 0xff);
+ salt[1] = (byte) ((ms_usage >> 8) & 0xff);
+ salt[2] = (byte) ((ms_usage >> 16) & 0xff);
+ salt[3] = (byte) ((ms_usage >> 24) & 0xff);
+ return salt;
+ }
+
+ private int arcfour_translate_usage(int usage)
+ {
+ switch (usage)
+ {
+ case 3 :
+ return 8;
+ case 9 :
+ return 8;
+ case 23 :
+ return 13;
+ default :
+ return usage;
+ }
+ }
+
+ public byte[] decryptedData(byte[] data)
+ {
+ return data;
+ }
+}
Added: projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/Decoder.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/Decoder.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/Decoder.java 2010-11-17 16:58:57 UTC (rev 109354)
@@ -0,0 +1,104 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.negotiation.cipher;
+
+import org.jboss.security.negotiation.NegotiationException;
+
+/**
+ * A decoder for the encrypted part of the Kerberos ticket.
+ * We need to decode the ticket to retrieve the client principal.
+ *
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+public abstract class Decoder
+{
+
+ /**
+ * Factory method to create the correct implementation.
+ *
+ * @param type Encryption type
+ * @return concrete implementation
+ * @throws NegotiationException
+ */
+ public static Decoder getInstace(int type) throws NegotiationException
+ {
+ Decoder decoder = null;
+ switch (type)
+ {
+ case 1:
+ decoder = new DesCbcCrcDecoder();
+ break;
+ case 3:
+ decoder = new DesCbcMd5Decoder();
+ break;
+ case 16:
+ decoder = new Des3CbcHmacSha1KdDecoder();
+ break;
+ case 17:
+ decoder = new Aes128CtsHmacSha1Decoder();
+ break;
+ case 18:
+ decoder = new Aes256CtsHmacSha1Decoder();
+ break;
+ case 23:
+ decoder = new ArcFourHmacDecoder();
+ break;
+ default:
+ throw new NegotiationException("Type not supported: " + type);
+ }
+ return decoder;
+ }
+
+ public abstract int keySize();
+
+ public abstract int checksumSize();
+
+ public abstract int confounderSize();
+
+ public abstract int blockSize();
+
+ public abstract byte[] decrypt(byte[] cipher, byte[] key, int usage) throws NegotiationException;
+
+ public int startOfChecksum()
+ {
+ return confounderSize();
+ }
+
+ public int dataSize(byte[] data)
+ {
+ return data.length - startOfData();
+ }
+
+ public int startOfData()
+ {
+ return confounderSize() + checksumSize();
+ }
+
+ public byte[] decryptedData(byte[] data)
+ {
+ int tempSize = dataSize(data);
+ byte[] result = new byte[tempSize];
+ System.arraycopy(data, startOfData(), result, 0, tempSize);
+ return result;
+ }
+}
Added: projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/Des3CbcHmacSha1KdDecoder.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/Des3CbcHmacSha1KdDecoder.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/Des3CbcHmacSha1KdDecoder.java 2010-11-17 16:58:57 UTC (rev 109354)
@@ -0,0 +1,411 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.negotiation.cipher;
+
+import java.security.GeneralSecurityException;
+import java.security.InvalidKeyException;
+import java.security.spec.KeySpec;
+import java.util.Arrays;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.DESKeySpec;
+import javax.crypto.spec.DESedeKeySpec;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.jboss.security.negotiation.NegotiationException;
+
+/**
+ * A {@link Decoder} for Des3CbcHmacSha1Kd.
+ *
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+public class Des3CbcHmacSha1KdDecoder extends Decoder
+{
+
+ private static final byte[] ZERO_IV = new byte[] {0, 0, 0, 0, 0, 0, 0, 0};
+
+ private static final byte[] PARITY_BIT_MASK = {(byte)0x80, (byte)0x40, (byte)0x20, (byte)0x10,
+ (byte)0x08, (byte)0x04, (byte)0x02};
+
+ public int blockSize()
+ {
+ return 8;
+ }
+
+ public int checksumSize()
+ {
+ return 20;
+ }
+
+ public int confounderSize()
+ {
+ return blockSize();
+ }
+
+ public int keySize()
+ {
+ return 24;
+ }
+
+ public byte[] decrypt(byte[] cipher, byte[] key, int usage) throws NegotiationException
+ {
+ byte[] ivec = new byte[blockSize()];
+ return decrypt(cipher, key, ivec, usage);
+ }
+
+ public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage) throws NegotiationException
+ {
+ try
+ {
+ return decrypt(key, usage, ivec, cipher, 0, cipher.length);
+ }
+ catch (GeneralSecurityException e)
+ {
+ NegotiationException ne = new NegotiationException(e.getMessage());
+ ne.initCause(e);
+ throw ne;
+ }
+ }
+
+ private byte[] decrypt(byte[] baseKey, int usage, byte[] ivec, byte[] ciphertext, int start, int len)
+ throws GeneralSecurityException
+ {
+ byte[] Ke = null;
+ byte[] Ki = null;
+
+ try
+ {
+ // Derive encryption key
+ byte[] constant = new byte[5];
+ constant[0] = (byte) ((usage >> 24) & 0xff);
+ constant[1] = (byte) ((usage >> 16) & 0xff);
+ constant[2] = (byte) ((usage >> 8) & 0xff);
+ constant[3] = (byte) (usage & 0xff);
+
+ constant[4] = (byte) 0xaa;
+
+ Ke = dk(baseKey, constant); // Encryption key
+
+ Cipher decCipher = getCipher(Ke, ivec, Cipher.DECRYPT_MODE);
+ int blockSize = decCipher.getBlockSize();
+
+ // Decrypt [confounder | plaintext | padding] (without checksum)
+ int cksumSize = checksumSize();
+ int cipherSize = len - cksumSize;
+ byte[] decrypted = decCipher.doFinal(ciphertext, start, cipherSize);
+
+ // decrypted = [confounder | plaintext | padding]
+
+ // Derive integrity key
+ constant[4] = (byte) 0x55;
+ Ki = dk(baseKey, constant); // Integrity key
+
+ // Verify checksum
+ // H1 = HMAC(Ki, conf | plaintext | pad)
+ byte[] calculatedHmac = getHmac(Ki, decrypted);
+
+ boolean cksumFailed = false;
+ if (calculatedHmac.length >= cksumSize)
+ {
+ for (int i = 0; i < cksumSize; i++)
+ {
+ if (calculatedHmac[i] != ciphertext[cipherSize + i])
+ {
+ cksumFailed = true;
+ break;
+ }
+ }
+ }
+
+ if (cksumFailed)
+ {
+ throw new GeneralSecurityException("Checksum failed");
+ }
+
+ // Prepare decrypted msg and ivec to be returned
+ // Last blockSize bytes of ciphertext without checksum
+ if (ivec != null && ivec.length == blockSize)
+ {
+ System.arraycopy(ciphertext, start + cipherSize - blockSize, ivec, 0, blockSize);
+ }
+
+ // Get rid of confounder
+ // [plaintext | padding]
+ byte[] plaintext = new byte[decrypted.length - blockSize];
+ System.arraycopy(decrypted, blockSize, plaintext, 0, plaintext.length);
+ return plaintext; // padding still there
+ }
+ finally
+ {
+ if (Ke != null)
+ {
+ Arrays.fill(Ke, 0, Ke.length, (byte) 0);
+ }
+ if (Ki != null)
+ {
+ Arrays.fill(Ki, 0, Ki.length, (byte) 0);
+ }
+ }
+ }
+
+ protected Cipher getCipher(byte[] key, byte[] ivec, int mode) throws GeneralSecurityException
+ {
+ // NoSuchAlgorithException
+ SecretKeyFactory factory = SecretKeyFactory.getInstance("desede");
+
+ // InvalidKeyException
+ KeySpec spec = new DESedeKeySpec(key, 0);
+
+ // InvalidKeySpecException
+ SecretKey secretKey = factory.generateSecret(spec);
+
+ // IV
+ if (ivec == null)
+ {
+ ivec = ZERO_IV;
+ }
+
+ // NoSuchAlgorithmException, NoSuchPaddingException
+ // NoSuchProviderException
+ Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");
+ IvParameterSpec encIv = new IvParameterSpec(ivec, 0, ivec.length);
+
+ // InvalidKeyException, InvalidAlgorithParameterException
+ cipher.init(mode, secretKey, encIv);
+
+ return cipher;
+ }
+
+ protected byte[] getHmac(byte[] key, byte[] msg) throws GeneralSecurityException
+ {
+ SecretKey keyKi = new SecretKeySpec(key, "HmacSHA1");
+ Mac m = Mac.getInstance("HmacSHA1");
+ m.init(keyKi);
+ return m.doFinal(msg);
+ }
+
+ protected byte[] randomToKey(byte[] in)
+ {
+ if (in.length != 21)
+ {
+ throw new IllegalArgumentException("input must be 168 bits");
+ }
+
+ byte[] one = keyCorrection(des3Expand(in, 0, 7));
+ byte[] two = keyCorrection(des3Expand(in, 7, 14));
+ byte[] three = keyCorrection(des3Expand(in, 14, 21));
+
+ byte[] key = new byte[24];
+ System.arraycopy(one, 0, key, 0, 8);
+ System.arraycopy(two, 0, key, 8, 8);
+ System.arraycopy(three, 0, key, 16, 8);
+
+ return key;
+ }
+
+ byte[] dk(byte[] key, byte[] constant) throws GeneralSecurityException
+ {
+ return randomToKey(dr(key, constant));
+ }
+
+ private byte[] dr(byte[] key, byte[] constant) throws GeneralSecurityException
+ {
+
+ Cipher encCipher = getCipher(key, null, Cipher.ENCRYPT_MODE);
+ int blocksize = encCipher.getBlockSize();
+
+ if (constant.length != blocksize)
+ {
+ constant = nfold(constant, blocksize * 8);
+ }
+ byte[] toBeEncrypted = constant;
+
+ int keybytes = (getKeySeedLength() >> 3); // from bits to bytes
+ byte[] rawkey = new byte[keybytes];
+
+ /* loop encrypting the blocks until enough key bytes are generated */
+ int n = 0, len;
+ while (n < keybytes)
+ {
+ byte[] cipherBlock = encCipher.doFinal(toBeEncrypted);
+ len = (keybytes - n <= cipherBlock.length ? (keybytes - n) : cipherBlock.length);
+ System.arraycopy(cipherBlock, 0, rawkey, n, len);
+ n += len;
+ toBeEncrypted = cipherBlock;
+ }
+ return rawkey;
+ }
+
+ protected int getKeySeedLength()
+ {
+ return 168; // bits; 3DES key material has 21 bytes
+ }
+
+ static byte[] nfold(byte[] in, int outbits)
+ {
+
+ int inbits = in.length;
+ outbits >>= 3; // count in bytes
+
+ /* first compute lcm(n,k) */
+ int a, b, c, lcm;
+ a = outbits; // n
+ b = inbits; // k
+
+ while (b != 0)
+ {
+ c = b;
+ b = a % b;
+ a = c;
+ }
+ lcm = outbits * inbits / a;
+
+ /* now do the real work */
+ byte[] out = new byte[outbits];
+ Arrays.fill(out, (byte) 0);
+
+ int thisbyte = 0;
+ int msbit, i, bval, oval;
+
+ // this will end up cycling through k lcm(k,n)/k times, which
+ // is correct
+ for (i = lcm - 1; i >= 0; i--)
+ {
+ /* compute the msbit in k which gets added into this byte */
+ msbit = (/* first, start with msbit in the first, unrotated byte */
+ ((inbits << 3) - 1)
+ /* then, for each byte, shift to right for each repetition */
+ + (((inbits << 3) + 13) * (i / inbits))
+ /* last, pick out correct byte within that shifted repetition */
+ + ((inbits - (i % inbits)) << 3)) % (inbits << 3);
+
+ /* pull out the byte value itself */
+ // Mask off values using &0xff to get only the lower byte
+ // Use >>> to avoid sign extension
+ bval = ((((in[((inbits - 1) - (msbit >>> 3)) % inbits] & 0xff) << 8) | (in[((inbits) - (msbit >>> 3)) % inbits] & 0xff)) >>> ((msbit & 7) + 1)) & 0xff;
+ thisbyte += bval;
+
+ /* do the addition */
+ // Mask off values using &0xff to get only the lower byte
+ oval = (out[i % outbits] & 0xff);
+ thisbyte += oval;
+ out[i % outbits] = (byte) (thisbyte & 0xff);
+
+ /* keep around the carry bit, if any */
+ thisbyte >>>= 8;
+ }
+
+ /* if there's a carry bit left over, add it back in */
+ if (thisbyte != 0)
+ {
+ for (i = outbits - 1; i >= 0; i--)
+ {
+ /* do the addition */
+ thisbyte += (out[i] & 0xff);
+ out[i] = (byte) (thisbyte & 0xff);
+
+ /* keep around the carry bit, if any */
+ thisbyte >>>= 8;
+ }
+ }
+
+ return out;
+ }
+
+ private static byte[] des3Expand(byte[] input, int start, int end)
+ {
+ if ((end - start) != 7)
+ throw new IllegalArgumentException("Invalid length of DES Key Value:" + start + "," + end);
+
+ byte[] result = new byte[8];
+ byte last = 0;
+ System.arraycopy(input, start, result, 0, 7);
+ byte posn = 0;
+
+ // Fill in last row
+ for (int i = start; i < end; i++)
+ {
+ byte bit = (byte) (input[i] & 0x01);
+ ++posn;
+ if (bit != 0)
+ {
+ last |= (bit << posn);
+ }
+ }
+
+ result[7] = last;
+ setParityBit(result);
+ return result;
+ }
+
+ private static void setParityBit(byte[] key)
+ {
+ for (int i = 0; i < key.length; i++)
+ {
+ int bitCount = 0;
+ for (int maskIndex = 0; maskIndex < PARITY_BIT_MASK.length; maskIndex++)
+ {
+ if ((key[i] & PARITY_BIT_MASK[maskIndex]) == PARITY_BIT_MASK[maskIndex])
+ {
+ bitCount++;
+ }
+ }
+ if ((bitCount & 0x01) == 1)
+ {
+ // Odd number of 1 bits in the top 7 bits. Set parity bit to 0
+ key[i] = (byte) (key[i] & (byte) 0xfe);
+ }
+ else
+ {
+ // Even number of 1 bits in the top 7 bits. Set parity bit to 1
+ key[i] = (byte) (key[i] | 1);
+ }
+ }
+ }
+
+ private static byte[] keyCorrection(byte[] key)
+ {
+ // check for weak key
+ try
+ {
+ if (DESKeySpec.isWeak(key, 0))
+ {
+ key[7] = (byte)(key[7] ^ 0xF0);
+ }
+ }
+ catch (InvalidKeyException ex)
+ {
+ // swallow, since it should never happen
+ }
+ return key;
+ }
+
+ public byte[] decryptedData(byte[] data)
+ {
+ return data;
+ }
+}
Added: projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/DesCbcCrcDecoder.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/DesCbcCrcDecoder.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/DesCbcCrcDecoder.java 2010-11-17 16:58:57 UTC (rev 109354)
@@ -0,0 +1,142 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.negotiation.cipher;
+
+import org.jboss.security.negotiation.NegotiationException;
+
+/**
+ * A {@link Decoder} for DesCbcCrc.
+ *
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+public class DesCbcCrcDecoder extends DesCbcDecoder
+{
+
+ private static int[] crc32Table = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+ };
+
+ public int checksumSize()
+ {
+ return 4;
+ }
+
+ public byte[] decrypt(byte[] cipher, byte[] key, int usage) throws NegotiationException
+ {
+ return decrypt(cipher, key, key, usage);
+ }
+
+ protected byte[] calculateChecksum(byte[] data, int size) throws NegotiationException
+ {
+ return byte2crc32sum_bytes(data, size);
+ }
+
+ private byte[] byte2crc32sum_bytes(byte[] data, int size)
+ {
+ int temp = byte2crc32sum(0, data, size);
+ return int2quad(temp);
+ }
+
+ private int byte2crc32sum(int seed, byte[] data, int size)
+ {
+ int crc = seed;
+ for (int i = 0; i < size; i++)
+ {
+ crc = (crc >>> 8) ^ crc32Table[(crc ^ data[i]) & 0xff];
+ }
+ return crc;
+ }
+
+ private byte[] int2quad(long input)
+ {
+ byte[] output = new byte[4];
+ for (int i = 0; i < 4; i++)
+ {
+ output[i] = (byte)((input >>> (i * 8)) & 0xff);
+ }
+ return output;
+ }
+}
Added: projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/DesCbcDecoder.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/DesCbcDecoder.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/DesCbcDecoder.java 2010-11-17 16:58:57 UTC (rev 109354)
@@ -0,0 +1,170 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.negotiation.cipher;
+
+import java.security.GeneralSecurityException;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.jboss.security.negotiation.NegotiationException;
+
+/**
+ * Common methods for the DesCbc types.
+ *
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+public abstract class DesCbcDecoder extends Decoder
+{
+
+ protected abstract byte[] calculateChecksum(byte[] data, int size) throws NegotiationException;
+
+ public int blockSize()
+ {
+ return 8;
+ }
+
+ public int keySize()
+ {
+ return 8;
+ }
+
+ public int confounderSize()
+ {
+ return 8;
+ }
+
+ public byte[] decrypt(byte[] cipher, byte[] key, int usage) throws NegotiationException
+ {
+ byte[] ivec = new byte[keySize()];
+ return decrypt(cipher, key, ivec, usage);
+ }
+
+ public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage) throws NegotiationException
+ {
+ if (key.length > 8)
+ throw new NegotiationException("Invalid DES Key!");
+
+ byte[] data = new byte[cipher.length];
+ cbc_encrypt(cipher, data, key, ivec, false);
+ if (!isChecksumValid(data))
+ throw new NegotiationException("Bad integrity check on AP_REQ");
+ return data;
+ }
+
+ protected boolean isChecksumValid(byte[] data) throws NegotiationException
+ {
+ byte[] cksum1 = checksumField(data);
+ byte[] cksum2 = generateChecksum(data);
+ return isChecksumEqual(cksum1, cksum2);
+ }
+
+ private boolean isChecksumEqual(byte[] cksum1, byte[] cksum2)
+ {
+ if (cksum1 == cksum2)
+ return true;
+ if ((cksum1 == null && cksum2 != null) || (cksum1 != null && cksum2 == null))
+ return false;
+ if (cksum1.length != cksum2.length)
+ return false;
+ for (int i = 0; i < cksum1.length; i++)
+ {
+ if (cksum1[i] != cksum2[i])
+ return false;
+ }
+ return true;
+ }
+
+ private byte[] checksumField(byte[] data)
+ {
+ byte[] result = new byte[checksumSize()];
+ for (int i = 0; i < checksumSize(); i++)
+ {
+ result[i] = data[startOfChecksum() + i];
+ }
+ return result;
+ }
+
+ private byte[] generateChecksum(byte[] data) throws NegotiationException
+ {
+ byte[] cksum1 = checksumField(data);
+ resetChecksumField(data);
+ byte[] cksum2 = calculateChecksum(data, data.length);
+ copyChecksumField(data, cksum1);
+ return cksum2;
+ }
+
+ private void resetChecksumField(byte[] data)
+ {
+ for (int i = startOfChecksum(); i < startOfChecksum() + checksumSize(); i++)
+ {
+ data[i] = 0;
+ }
+ }
+
+ private void copyChecksumField(byte[] data, byte[] cksum)
+ {
+ for (int i = 0; i < checksumSize(); i++)
+ {
+ data[startOfChecksum() + i] = cksum[i];
+ }
+ }
+
+ public static void cbc_encrypt(byte[] input, byte[] output, byte[] key, byte[] ivec, boolean encrypt)
+ throws NegotiationException
+ {
+
+ Cipher cipher = null;
+ try
+ {
+ cipher = Cipher.getInstance("DES/CBC/NoPadding");
+ }
+ catch (GeneralSecurityException e)
+ {
+ NegotiationException ne = new NegotiationException("JCE provider may not be installed. " + e.getMessage());
+ ne.initCause(e);
+ throw ne;
+ }
+ IvParameterSpec params = new IvParameterSpec(ivec);
+ SecretKeySpec skSpec = new SecretKeySpec(key, "DES");
+ try
+ {
+ SecretKey sk = (SecretKey) skSpec;
+ if (encrypt)
+ cipher.init(Cipher.ENCRYPT_MODE, sk, params);
+ else
+ cipher.init(Cipher.DECRYPT_MODE, sk, params);
+ byte[] result;
+ result = cipher.doFinal(input);
+ System.arraycopy(result, 0, output, 0, result.length);
+ }
+ catch (GeneralSecurityException e)
+ {
+ NegotiationException ne = new NegotiationException(e.getMessage());
+ ne.initCause(e);
+ throw ne;
+ }
+ }
+}
Added: projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/DesCbcMd5Decoder.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/DesCbcMd5Decoder.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-common/src/main/java/org/jboss/security/negotiation/cipher/DesCbcMd5Decoder.java 2010-11-17 16:58:57 UTC (rev 109354)
@@ -0,0 +1,63 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.negotiation.cipher;
+
+import java.security.MessageDigest;
+
+import org.jboss.security.negotiation.NegotiationException;
+
+/**
+ * A {@link Decoder} for DesCbcMd5.
+ *
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+public class DesCbcMd5Decoder extends DesCbcDecoder
+{
+
+ public int checksumSize()
+ {
+ return 16;
+ }
+
+ protected byte[] calculateChecksum(byte[] data, int size) throws NegotiationException
+ {
+ MessageDigest md5 = null;
+ try
+ {
+ md5 = MessageDigest.getInstance("MD5");
+ }
+ catch (Exception e)
+ {
+ throw new NegotiationException("JCE provider may not be installed. " + e.getMessage());
+ }
+ try
+ {
+ md5.update(data);
+ return (md5.digest());
+ }
+ catch (Exception e)
+ {
+ throw new NegotiationException(e.getMessage());
+ }
+ }
+}
Modified: projects/security/security-negotiation/trunk/jboss-negotiation-spnego/pom.xml
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-spnego/pom.xml 2010-11-17 16:41:36 UTC (rev 109353)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-spnego/pom.xml 2010-11-17 16:58:57 UTC (rev 109354)
@@ -38,13 +38,18 @@
<!-- Global dependencies -->
<dependency>
- <groupId>jboss</groupId>
- <artifactId>jbosssx</artifactId>
+ <groupId>org.jboss.jbossas</groupId>
+ <artifactId>jboss-as-security</artifactId>
+ <version>5.1.0.GA</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.picketbox</groupId>
+ <artifactId>jboss-security-spi</artifactId>
+ </dependency>
</dependencies>
</project>
Added: projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/encoding/TokenParser.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/encoding/TokenParser.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/encoding/TokenParser.java 2010-11-17 16:58:57 UTC (rev 109354)
@@ -0,0 +1,335 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.negotiation.spnego.encoding;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.security.auth.kerberos.KerberosKey;
+
+import org.jboss.security.negotiation.NegotiationException;
+import org.jboss.security.negotiation.cipher.Decoder;
+
+/**
+ * Parses a token to retrieve specific parts required.
+ *
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+public class TokenParser
+{
+
+ private String crealm;
+
+ private String cname;
+
+ /**
+ * Method to be invoked to parse and decode the token.
+ *
+ * @param data byte array containing the token
+ * @param subject {@link Subject} containing the private key
+ * @throws Exception
+ */
+ public void parseToken(byte[] data, Subject subject) throws Exception
+ {
+ ByteArrayInputStream bais = new ByteArrayInputStream(data);
+ // get the AP_REQ part
+ byte[] b = getAP_REQ(bais);
+ bais.close();
+
+ bais = new ByteArrayInputStream(b);
+ // get the Ticket part
+ b = getTicket(bais);
+ bais.close();
+
+ bais = new ByteArrayInputStream(b);
+ // get the EncryptedData part
+ b = getEncryptedData(bais);
+ bais.close();
+
+ bais = new ByteArrayInputStream(b);
+ // decode the EncryptedData
+ handleEncryptedData(bais, b.length, subject);
+ bais.close();
+ }
+
+ /**
+ * Parses the {@link InputStream} until it finds the sequence at position indicated by the byte.
+ *
+ * @param is {@link InputStream} to read
+ * @param type position in the sequence
+ * @return data found
+ * @throws Exception
+ */
+ public byte[] getValueAt(InputStream is, byte type) throws Exception
+ {
+ byte[] bytes = null;
+ byte tag;
+ do
+ {
+ tag = (byte) is.read();
+ int sequenceLength = NegTokenDecoder.readLength(is);
+ bytes = new byte[sequenceLength];
+ is.read(bytes);
+ if (is.available() == 0)
+ {
+ is = new ByteArrayInputStream(bytes);
+ }
+ }
+ while (!isContextSpecific(tag, type));
+ return bytes;
+ }
+
+ /**
+ * Verify that the tag is the correct one.
+ *
+ * @param tag byte to verify
+ * @param cntxtTag byte to match
+ * @return true if match
+ */
+ public boolean isContextSpecific(byte tag, byte cntxtTag)
+ {
+ return ((tag & 0x01f) == cntxtTag);
+ }
+
+ /**
+ * Parses the {@link InputStream} until the AP_REQ is found.
+ *
+ * @param is {@link InputStream} to read
+ * @return the AP_REQ data
+ * @throws Exception
+ */
+ public byte[] getAP_REQ(InputStream is) throws Exception
+ {
+ is.read();
+ NegTokenDecoder.readLength(is);
+ byte[] bytes = getValueAt(is, (byte) 14);
+
+ return bytes;
+ }
+
+ /**
+ * Parses the {@link InputStream} until the Ticket is found.
+ *
+ * @param is {@link InputStream} to read
+ * @return the Ticket data
+ * @throws Exception
+ */
+ public byte[] getTicket(InputStream is) throws Exception
+ {
+ byte[] bytes = getValueAt(is, (byte) 3);
+
+ return bytes;
+ }
+
+ /**
+ * Parses the {@link InputStream} until the EncryptedData is found.
+ *
+ * @param is {@link InputStream} to read
+ * @return the EncryptedData data
+ * @throws Exception
+ */
+ public byte[] getEncryptedData(InputStream is) throws Exception
+ {
+ byte[] bytes = getValueAt(is, (byte) 3);
+
+ return bytes;
+ }
+
+ /**
+ * Decodes the encrypted data and parses the encrypted part to retrieve the client
+ * realm and principal.
+ *
+ * @param is {@link InputStream} to read
+ * @param size encrypted data size
+ * @param subject {@link} Subject containing the private key
+ * @throws Exception
+ */
+ public void handleEncryptedData(InputStream is, int size, Subject subject) throws Exception
+ {
+ is.mark(size);
+ byte[] bytes = getValueAt(is, (byte) 0);
+ bytes = Arrays.copyOfRange(bytes, 2, 3);
+ BigInteger bi = new BigInteger(bytes);
+ int eType = bi.intValue();
+
+ KerberosKey key = getKrbKey(subject, eType);
+
+ is.reset();
+ bytes = getValueAt(is, (byte) 2);
+ byte[] cipher = Arrays.copyOfRange(bytes, 3, bytes.length);
+
+ byte[] ticketBytes = decrypt(key, cipher);
+ byte[] temp = reset(ticketBytes);
+
+ // at this point we have the decrypted ticket
+ ByteArrayInputStream bais = new ByteArrayInputStream(temp);
+ bais.read();
+ int length = NegTokenDecoder.readLength(bais);
+ temp = new byte[length];
+ bais.read(temp);
+ bais.close();
+ bais = new ByteArrayInputStream(temp);
+
+ byte[] realm = getValueAt(bais, (byte) 2);
+ bais.close();
+
+ // at this point we have a Realm in the byte[]
+ realm = Arrays.copyOfRange(realm, 2, realm.length);
+ crealm = new String(realm);
+ bais = new ByteArrayInputStream(temp);
+ byte[] principalName = getValueAt(bais, (byte) 3);
+ bais.close();
+
+ // at this point we have a PrincipalName in the byte[]
+ bais = new ByteArrayInputStream(principalName);
+ byte[] names = getValueAt(bais, (byte) 1);
+ bais.close();
+ names = Arrays.copyOfRange(names, 2, names.length);
+
+ // at this point we have the sequence of names in the byte[]
+ bais = new ByteArrayInputStream(names);
+ String[] cnames = getNames(bais);
+ bais.close();
+ StringBuffer buffer = new StringBuffer(cnames[0]);
+ for (int i = 1; i < cnames.length; i++)
+ {
+ buffer.append("/");
+ buffer.append(cnames[i]);
+ }
+ cname = buffer.toString();
+ }
+
+ /**
+ * Parses the data to find all the principal names.
+ *
+ * @param is {@link InputStream} to read
+ * @return array of names
+ * @throws Exception
+ */
+ public String[] getNames(InputStream is) throws Exception
+ {
+ List<String> principals = new ArrayList<String>();
+ do
+ {
+ is.read();
+ int length = NegTokenDecoder.readLength(is);
+ byte[] name = new byte[length];
+ is.read(name);
+ principals.add(new String(name));
+ }
+ while (is.available() > 0);
+
+ String[] names = new String[principals.size()];
+ names = principals.toArray(names);
+
+ return names;
+ }
+
+ /**
+ * Retrieves the private key from the {@link Subject}.
+ *
+ * @param sub {@link SUbject} containing the private key
+ * @param keyType type of the key
+ * @return the private key
+ */
+ public KerberosKey getKrbKey(Subject sub, int keyType)
+ {
+ Set<Object> creds = sub.getPrivateCredentials(Object.class);
+ for (Iterator<Object> i = creds.iterator(); i.hasNext();)
+ {
+ Object cred = i.next();
+ if (cred instanceof KerberosKey)
+ {
+ KerberosKey key = (KerberosKey) cred;
+ if (key.getKeyType() == keyType)
+ {
+ return (KerberosKey) cred;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Decodes the data.
+ *
+ * @param key private key
+ * @param cipher
+ * @return decoded data
+ * @throws NegotiationException
+ */
+ public byte[] decrypt(KerberosKey key, byte[] cipher) throws NegotiationException
+ {
+ Decoder decoder = Decoder.getInstace(key.getKeyType());
+ byte[] plain = decoder.decrypt(cipher, key.getEncoded(), 2);
+ return decoder.decryptedData(plain);
+ }
+
+ /**
+ * Resets the size.
+ *
+ * @param data
+ * @return
+ */
+ public byte[] reset(byte[] data)
+ {
+ byte[] bytes = null;
+ if ((data[1] & 0xFF) < 128)
+ {
+ bytes = new byte[data[1] + 2];
+ System.arraycopy(data, 0, bytes, 0, data[1] + 2);
+ }
+ else
+ {
+ if ((data[1] & 0xFF) > 128)
+ {
+ int len = (int)(data[1] & (byte) 0x7F);
+ int result = 0;
+ for (int i = 0; i < len; i++)
+ {
+ result |= (data[i + 2] & 0xFF) << (8 * (len - i - 1));
+ }
+ bytes = new byte[result + len + 2];
+ System.arraycopy(data, 0, bytes, 0, result + len + 2);
+ }
+ }
+ return bytes;
+ }
+
+ /**
+ * Returns the principal name of the client.
+ *
+ * @return principal name
+ */
+ public String getPrincipalName()
+ {
+ return cname + "@" + crealm;
+ }
+}
Added: projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/InitSPNEGOContextAction.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/InitSPNEGOContextAction.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/InitSPNEGOContextAction.java 2010-11-17 16:58:57 UTC (rev 109354)
@@ -0,0 +1,158 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.negotiation.spnego.net;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.net.Socket;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.GSSManager;
+import org.ietf.jgss.GSSName;
+import org.ietf.jgss.Oid;
+import org.jboss.logging.Logger;
+import org.jboss.security.SecurityContext;
+
+/**
+ * A {@link PrivilegedAction} that establishes the {@link GSSContext} according to GSS API.
+ *
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+public class InitSPNEGOContextAction implements PrivilegedAction<Object>
+{
+
+ protected static Logger log = Logger.getLogger(InitSPNEGOContextAction.class);
+
+ private Socket socket;
+
+ private LoginContext lc;
+
+ /**
+ * Default constructor
+ *
+ * @param socket {@link Socket} used to exchange the tokens.
+ * @param lc {@link LoginContext} with the authenticated Subject who will execute the action
+ */
+ InitSPNEGOContextAction(Socket socket, LoginContext lc)
+ {
+ this.socket = socket;
+ this.lc = lc;
+ }
+
+ /**
+ * @see PrivilegedAction#run()
+ */
+ public Object run()
+ {
+ boolean DEBUG = log.isDebugEnabled();
+ byte[] token = new byte[0];
+ GSSManager manager = GSSManager.getInstance();
+ GSSContext context = null;
+ try
+ {
+ DataInputStream inStream = new DataInputStream(socket.getInputStream());
+ DataOutputStream outStream = new DataOutputStream(socket.getOutputStream());
+
+ Oid oid = new Oid("1.3.6.1.5.5.2");
+ GSSName serverName = manager.createName("jboss/mmoyses", null);
+ context = manager.createContext(serverName, oid, null, GSSContext.DEFAULT_LIFETIME);
+ while (!context.isEstablished())
+ {
+ token = context.initSecContext(token, 0, token.length);
+ if (token != null)
+ {
+ if (DEBUG)
+ log.debug("Sending token of length " + token.length);
+ outStream.writeInt(token.length);
+ outStream.write(token);
+ outStream.flush();
+ }
+
+ if (!context.isEstablished())
+ {
+ token = new byte[inStream.readInt()];
+ if (DEBUG)
+ log.debug("Receiving token of length " + token.length);
+ inStream.readFully(token);
+ }
+ }
+ if (DEBUG)
+ log.trace("GSSContext established");
+ Subject subject = lc.getSubject();
+ Principal principal = subject.getPrincipals().iterator().next();
+ try
+ {
+ setSecurityContext(principal, null, subject, "CLIENT");
+ }
+ catch (Exception e)
+ {
+ log.error("Error setting the SecurityContext: " + e.getMessage(), e);
+ }
+ }
+ catch (GSSException gsse)
+ {
+ log.error("Error establishing GSSContext: " + gsse.getMessage(), gsse);
+ }
+ catch (IOException ioe)
+ {
+ log.error("Error reading/writing token: " + ioe.getMessage(), ioe);
+ }
+ finally
+ {
+ if (context != null)
+ {
+ try
+ {
+ context.dispose();
+ }
+ catch (GSSException gsse)
+ {
+ log.error("Error dispoing GSSContext: " + gsse.getMessage(), gsse);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Performs JBoss specific security context association.
+ *
+ * @param principal {@link Principal} of the user
+ * @param credential Credentials of the user
+ * @param subject {@link Subject} of the user
+ * @param securityDomain Security domain of the context
+ * @throws Exception if an error occurs while setting the security context
+ */
+ protected void setSecurityContext(Principal principal, Object credential, Subject subject, String securityDomain) throws Exception
+ {
+ SecurityContext sc = SecurityActions.createSecurityContext(principal, null, subject, securityDomain);
+ SecurityActions.setSecurityContext(sc);
+ }
+}
Added: projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SPNEGOServerSocket.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SPNEGOServerSocket.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SPNEGOServerSocket.java 2010-11-17 16:58:57 UTC (rev 109354)
@@ -0,0 +1,355 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.negotiation.spnego.net;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.security.Principal;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.security.auth.Subject;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.ietf.jgss.GSSContext;
+import org.jboss.logging.Logger;
+import org.jboss.mx.util.MBeanServerLocator;
+import org.jboss.security.SecurityConstants;
+import org.jboss.security.auth.callback.SecurityAssociationHandler;
+import org.jboss.security.negotiation.MessageFactory;
+import org.jboss.security.negotiation.NegotiationException;
+import org.jboss.security.negotiation.NegotiationMessage;
+import org.jboss.security.negotiation.common.MessageTrace;
+import org.jboss.security.negotiation.common.NegotiationContext;
+import org.jboss.security.negotiation.spnego.encoding.NegTokenInit;
+import org.jboss.security.negotiation.spnego.encoding.NegTokenTarg;
+import org.jboss.security.negotiation.spnego.encoding.TokenParser;
+import org.jboss.security.plugins.JaasSecurityManager;
+
+/**
+ * An implementation of {@link ServerSocket} that tries to establish a {@link GSSContext}
+ * when a {@link Socket} connects to it.
+ *
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+public class SPNEGOServerSocket extends ServerSocket
+{
+
+ private static Logger log = Logger.getLogger(SPNEGOServerSocket.class);
+
+ private Principal principal;
+
+ private String securityDomain;
+
+ private String hostSecurityDomain;
+
+ private LoginContext lc;
+
+ private Subject subject;
+
+ /**
+ * @see ServerSocket#ServerSocket()
+ */
+ public SPNEGOServerSocket() throws IOException
+ {
+ super();
+ if (log.isTraceEnabled())
+ log.trace("Creating " + this.getClass().getName());
+ }
+
+ /**
+ * @see ServerSocket#ServerSocket(int)
+ */
+ public SPNEGOServerSocket(int port) throws IOException
+ {
+ super(port);
+ }
+
+ /**
+ * @see ServerSocket#ServerSocket(int, int)
+ */
+ public SPNEGOServerSocket(int port, int backlog) throws IOException
+ {
+ super(port, backlog);
+ }
+
+ /**
+ * @see ServerSocket#ServerSocket(int, int, InetAddress)
+ */
+ public SPNEGOServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException
+ {
+ super(port, backlog, bindAddr);
+ }
+
+ /**
+ * Tries to establish a {@link GSSContext} with the client using the tokens
+ * provided.
+ *
+ * @see ServerSocket#accept()
+ */
+ public Socket accept() throws IOException
+ {
+ boolean TRACE = log.isTraceEnabled();
+ if (TRACE)
+ log.trace(this.getClass().getName() + ".accept()");
+ Socket socket = super.accept();
+
+ if (TRACE)
+ log.trace("Creating new NegotiationContext");
+ NegotiationContext negotiationContext = new NegotiationContext();
+ try
+ {
+ negotiationContext.associate();
+ acceptSocket(socket, negotiationContext);
+ }
+ catch (Exception e)
+ {
+ // re-throw the Exception as a IOException
+ throw new IOException(e);
+ }
+ finally
+ {
+ negotiationContext.clear();
+ }
+
+ return socket;
+ }
+
+ /**
+ * @see ServerSocket#close()
+ */
+ public void close() throws IOException
+ {
+ try
+ {
+ logout();
+ }
+ catch (LoginException le)
+ {
+ // just logs error
+ log.error("Error during logout: " + le.getMessage(), le);
+ }
+ super.close();
+ }
+
+ /**
+ * Accepts a {@link Socket} connection by trying to do a JAAS Kerberos login using the tokens exchanged
+ * with the client.
+ *
+ * @param socket Client {@link Socket}
+ * @param negotiationContext {@link NegotiationContext} to be used for the JAAS login
+ * @throws IOException
+ * @throws NegotiationException
+ * @throws NamingException
+ */
+ protected void acceptSocket(Socket socket, NegotiationContext negotiationContext) throws Exception
+ {
+ boolean TRACE = log.isTraceEnabled();
+
+ byte[] token = new byte[0];
+ DataInputStream inStream = new DataInputStream(socket.getInputStream());
+ // first reads the size of the client's token
+ token = new byte[inStream.readInt()];
+ if (TRACE)
+ log.debug("Receiving token of length " + token.length);
+ // then reads the client's token
+ inStream.readFully(token);
+ MessageTrace.logRequestHex(token);
+
+ ByteArrayInputStream authTokenIS = new ByteArrayInputStream(token);
+ MessageFactory mf = MessageFactory.newInstance();
+ if (mf.accepts(authTokenIS) == false)
+ {
+ throw new IOException("Unsupported negotiation mechanism.");
+ }
+ NegotiationMessage requestMessage = mf.createMessage(authTokenIS);
+ authTokenIS.close();
+ // AP_REQ token
+ byte[] kerberosToken = ((NegTokenInit) requestMessage).getMechToken();
+ // need to pass the full token and let JDK classes parse it
+ ((NegTokenInit) requestMessage).setMechToken(token);
+ negotiationContext.setRequestMessage(requestMessage);
+
+ // retrieve client principal from the kerberos token
+ if (subject == null)
+ {
+ if (TRACE)
+ log.trace("Starting host login");
+ subject = login();
+ if (TRACE)
+ log.trace("Host login successful");
+ }
+ principal = getClientPrincipal(kerberosToken, subject);
+ // need to flush the cache first and let the tokens be validated every time
+ if (TRACE)
+ log.trace("Flushing cache");
+ flushPrincipalFromCache(principal, securityDomain);
+
+ // authenticates using the token
+ isValid(principal, null, securityDomain);
+
+ NegotiationMessage responseMessage = negotiationContext.getResponseMessage();
+ DataOutputStream outStream = new DataOutputStream(socket.getOutputStream());
+ // need to pass the full token and let JDK classes parse it
+ token = ((NegTokenTarg) responseMessage).getResponseToken();
+ if (TRACE)
+ log.debug("Sending token of length " + token.length);
+ MessageTrace.logResponseHex(token);
+ // first writes the size of the token
+ outStream.writeInt(token.length);
+ // then writes the token
+ outStream.write(token);
+ outStream.flush();
+ }
+
+ /**
+ * Performs a JAAS login.
+ *
+ * @param principal User {@link Principal} to login
+ * @param credential Credentials of the user
+ * @param securityDomain Name of the JAAS security domain
+ * @return true if authentication succeeds, false otherwise
+ * @throws Exception if an error occurs
+ */
+ protected boolean isValid(Principal principal, Object credential, String securityDomain) throws Exception
+ {
+ InitialContext ctx = new InitialContext();
+ JaasSecurityManager jsm = (JaasSecurityManager) ctx.lookup(SecurityConstants.JAAS_CONTEXT_ROOT + "/" + securityDomain);
+ return jsm.isValid(principal, credential);
+ }
+
+ /**
+ * Removes the user entry from the authentication cache.
+ *
+ * @param principal User {@link Principal} to remove from cache
+ * @param securityDomain Name of the JAAS security domain
+ * @throws Exception if an error occurs
+ */
+ protected void flushPrincipalFromCache(Principal principal, String securityDomain) throws Exception
+ {
+ MBeanServer server = MBeanServerLocator.locateJBoss();
+ ObjectName jaasMgr = new ObjectName("jboss.security:service=JaasSecurityManager");
+ Object[] params = {securityDomain, principal};
+ String[] signature = {String.class.getName(), Principal.class.getName()};
+ server.invoke(jaasMgr, "flushAuthenticationCache", params, signature);
+ }
+
+ /**
+ * Returns the security domain securing the EJBs.
+ *
+ * @return name of the security domain
+ */
+ public String getSecurityDomain()
+ {
+ return securityDomain;
+ }
+
+ /**
+ * Sets the security domain securing the EJBs.
+ *
+ * @param securityDomain name of the security domain
+ */
+ public void setSecurityDomain(String securityDomain)
+ {
+ this.securityDomain = securityDomain;
+ }
+
+ /**
+ * Returns the Kerberos security domain.
+ *
+ * @return name of the security domain
+ */
+ public String getHostSecurityDomain()
+ {
+ return hostSecurityDomain;
+ }
+
+ /**
+ * Sets the Kerberos security domain.
+ *
+ * @param hostSecurityDomain name of the security domain
+ */
+ public void setHostSecurityDomain(String hostSecurityDomain)
+ {
+ this.hostSecurityDomain = hostSecurityDomain;
+ }
+
+ /**
+ * Performs a JAAS login on the client side.
+ *
+ * @return a {@link Subject}
+ * @throws LoginException if the login fails
+ */
+ protected Subject login() throws LoginException
+ {
+ if (lc == null)
+ lc = new LoginContext(hostSecurityDomain, new SecurityAssociationHandler());
+ lc.login();
+ return lc.getSubject();
+ }
+
+ /**
+ * Performs a JAAS logout on the client side.
+ *
+ * @throws LoginException if the logout fails
+ */
+ protected void logout() throws LoginException
+ {
+ if (lc != null)
+ lc.logout();
+ subject = null;
+ }
+
+ /**
+ * Decodes and parses the ticket to retrieve the client {@link Principal}.
+ *
+ * @param ticket Kerberos ticket
+ * @param subject Subject containing the server private key
+ * @return client {@link Principal}
+ */
+ protected Principal getClientPrincipal(byte[] ticket, Subject subject)
+ {
+ TokenParser tp = new TokenParser();
+ try
+ {
+ tp.parseToken(ticket, subject);
+ }
+ catch (Exception e)
+ {
+ log.error("Error parsing/decoding ticket: " + e.getMessage(), e);
+ return null;
+ }
+ String principalName = tp.getPrincipalName();
+
+ return new KerberosPrincipal(principalName);
+ }
+}
Added: projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SPNEGOServerSocketFactory.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SPNEGOServerSocketFactory.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SPNEGOServerSocketFactory.java 2010-11-17 16:58:57 UTC (rev 109354)
@@ -0,0 +1,126 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.negotiation.spnego.net;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+
+import javax.net.ServerSocketFactory;
+
+import org.jboss.logging.Logger;
+
+/**
+ * An implementation of {@link ServerSocketFactory} that uses {@link SPNEGOServerSocket} as
+ * the sockets.
+ *
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+public class SPNEGOServerSocketFactory extends ServerSocketFactory
+{
+
+ private String securityDomain = "other";
+
+ private String hostSecurityDomain = "host";
+
+ private static Logger log = Logger.getLogger(SPNEGOServerSocketFactory.class);
+
+ /**
+ * Default constructor.
+ */
+ public SPNEGOServerSocketFactory()
+ {
+ super();
+ if (log.isTraceEnabled())
+ log.trace("Creating " + this.getClass().getName());
+ }
+
+ /**
+ * Constructor that sets the security domain
+ *
+ * @param securityDomain
+ */
+ public SPNEGOServerSocketFactory(String securityDomain, String hostSecurityDomain)
+ {
+ this();
+ if (log.isTraceEnabled())
+ log.trace("Setting security domain: " + securityDomain + ". Setting host security domain: " + hostSecurityDomain);
+ this.securityDomain = securityDomain;
+ this.hostSecurityDomain = hostSecurityDomain;
+ }
+
+ /**
+ * Some resources require this static getDefault method
+ *
+ * @return an instance of {@link SPNEGOServerSocketFactory}
+ */
+ public static ServerSocketFactory getDefault()
+ {
+ return new SPNEGOServerSocketFactory();
+ }
+
+ /**
+ * @see ServerSocketFactory#createServerSocket()
+ */
+ public ServerSocket createServerSocket() throws IOException
+ {
+ SPNEGOServerSocket socket = new SPNEGOServerSocket();
+ socket.setSecurityDomain(securityDomain);
+ socket.setHostSecurityDomain(hostSecurityDomain);
+ return socket;
+ }
+
+ /**
+ * @see ServerSocketFactory#createServerSocket(int)
+ */
+ public ServerSocket createServerSocket(int port) throws IOException
+ {
+ SPNEGOServerSocket socket = new SPNEGOServerSocket(port);
+ socket.setSecurityDomain(securityDomain);
+ socket.setHostSecurityDomain(hostSecurityDomain);
+ return socket;
+ }
+
+ /**
+ * @see ServerSocketFactory#createServerSocket(int, int))
+ */
+ public ServerSocket createServerSocket(int port, int backlog) throws IOException
+ {
+ SPNEGOServerSocket socket = new SPNEGOServerSocket(port, backlog);
+ socket.setSecurityDomain(securityDomain);
+ socket.setHostSecurityDomain(hostSecurityDomain);
+ return socket;
+ }
+
+ /**
+ * @see ServerSocketFactory#createServerSocket(int, int, InetAddress))
+ */
+ public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) throws IOException
+ {
+ SPNEGOServerSocket socket = new SPNEGOServerSocket(port, backlog, ifAddress);
+ socket.setSecurityDomain(securityDomain);
+ socket.setHostSecurityDomain(hostSecurityDomain);
+ return socket;
+ }
+
+}
Added: projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SPNEGOSocket.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SPNEGOSocket.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SPNEGOSocket.java 2010-11-17 16:58:57 UTC (rev 109354)
@@ -0,0 +1,184 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.negotiation.spnego.net;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.UnknownHostException;
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.ietf.jgss.GSSContext;
+import org.jboss.logging.Logger;
+import org.jboss.security.auth.callback.SecurityAssociationHandler;
+
+/**
+ * An implementation of {@link Socket} that tries to establish a {@link GSSContext}
+ * when connecting to a {@link ServerSocket}
+ *
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+public class SPNEGOSocket extends Socket
+{
+
+ protected static Logger log = Logger.getLogger(SPNEGOSocket.class);
+
+ private LoginContext lc;
+
+ /**
+ * @see Socket#Socket()
+ */
+ public SPNEGOSocket()
+ {
+ super();
+ if (log.isTraceEnabled())
+ log.trace("Creating " + this.getClass().getName());
+ }
+
+ /**
+ * @see Socket#Socket(InetAddress, int, InetAddress, int)
+ */
+ public SPNEGOSocket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException
+ {
+ super(address, port, localAddr, localPort);
+ }
+
+ /**
+ * @see Socket#Socket(InetAddress, int)
+ */
+ public SPNEGOSocket(InetAddress address, int port) throws IOException
+ {
+ super(address, port);
+ }
+
+ /**
+ * @see Socket#Socket(String, int, InetAddress, int)
+ */
+ public SPNEGOSocket(String host, int port, InetAddress localAddr, int localPort) throws IOException
+ {
+ super(host, port, localAddr, localPort);
+ }
+
+ /**
+ * @see Socket#Socket(String, int)
+ */
+ public SPNEGOSocket(String host, int port) throws UnknownHostException, IOException
+ {
+ super(host, port);
+ }
+
+ /**
+ * @see Socket#connect(SocketAddress)
+ */
+ public void connect(SocketAddress endpoint) throws IOException
+ {
+ super.connect(endpoint);
+ }
+
+ /**
+ * Tries to establish a {@link GSSContext} with the server using the tokens.
+ *
+ * @see Socket#connect(SocketAddress, int)
+ */
+ public void connect(SocketAddress endpoint, int timeout) throws IOException
+ {
+ boolean TRACE = log.isTraceEnabled();
+ if (TRACE)
+ log.trace(this.getClass().getName() + ".connect()");
+ super.connect(endpoint, timeout);
+
+ Subject subject = null;
+ try
+ {
+ if (TRACE)
+ log.trace("Invoking login");
+ subject = login();
+ if (TRACE)
+ log.trace("Login was successful");
+ }
+ catch (LoginException le)
+ {
+ log.error("Failed to login: " + le.getMessage(), le);
+ }
+ if (subject != null)
+ {
+ if (TRACE)
+ log.trace("Running PrivilegedAction");
+ PrivilegedAction<Object> action = getPrivilegedAction();
+ Subject.doAs(subject, action);
+ }
+ try
+ {
+ if (TRACE)
+ log.trace("Invoking logout");
+ logout();
+ if (TRACE)
+ log.trace("Logout was successful");
+ }
+ catch (LoginException le)
+ {
+ log.error("Failed to logout: " + le.getMessage(), le);
+ }
+ }
+
+ /**
+ * Performs a JAAS login on the client side.
+ *
+ * @return a {@link Subject}
+ * @throws LoginException if the login fails
+ */
+ protected Subject login() throws LoginException
+ {
+ lc = new LoginContext("com.sun.security.jgss.krb5.initiate", new SecurityAssociationHandler());
+ lc.login();
+ return lc.getSubject();
+ }
+
+ /**
+ * Performs a JAAS logout on the client side.
+ *
+ * @throws LoginException if the logout fails
+ */
+ protected void logout() throws LoginException
+ {
+ if (lc != null)
+ lc.logout();
+ }
+
+ /**
+ * Instantiates a {@link PrivilegedAction}.
+ *
+ * @return {@link PrivilegedAction} implementation that will establish the {@link GSSContext}
+ */
+ protected PrivilegedAction<Object> getPrivilegedAction()
+ {
+ return new InitSPNEGOContextAction(this, lc);
+ }
+
+}
Added: projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SPNEGOSocketFactory.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SPNEGOSocketFactory.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SPNEGOSocketFactory.java 2010-11-17 16:58:57 UTC (rev 109354)
@@ -0,0 +1,107 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.negotiation.spnego.net;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import javax.net.SocketFactory;
+
+import org.jboss.logging.Logger;
+
+/**
+ * An implementation of {@link SocketFactory} that uses {@link SPNEGOSocket} as
+ * the sockets.
+ *
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+public class SPNEGOSocketFactory extends SocketFactory
+{
+
+ private static Logger log = Logger.getLogger(SPNEGOSocketFactory.class);
+
+ /**
+ * Default constructor
+ */
+ public SPNEGOSocketFactory()
+ {
+ super();
+ if (log.isTraceEnabled())
+ log.trace("Creating " + this.getClass().getName());
+ }
+
+ /**
+ * Some resources require this static getDefault method
+ *
+ * @return an instance of {@link SPNEGOSocketFactory}
+ */
+ public static SocketFactory getDefault()
+ {
+ return new SPNEGOSocketFactory();
+ }
+
+ /**
+ * @see SocketFactory#createSocket()
+ */
+ public Socket createSocket() throws IOException
+ {
+ return new SPNEGOSocket();
+ }
+
+ /**
+ * @see SocketFactory#createSocket(String, int))
+ */
+ public Socket createSocket(String host, int port) throws IOException, UnknownHostException
+ {
+ return new SPNEGOSocket(host, port);
+ }
+
+ /**
+ * @see SocketFactory#createSocket(InetAddress, int))
+ */
+ public Socket createSocket(InetAddress host, int port) throws IOException
+ {
+ return new SPNEGOSocket(host, port);
+ }
+
+ /**
+ * @see SocketFactory#createSocket(String, int, InetAddress, int))
+ */
+ public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException,
+ UnknownHostException
+ {
+ return new SPNEGOSocket(host, port, localHost, localPort);
+ }
+
+ /**
+ * @see SocketFactory#createSocket(InetAddress, int, InetAddress, int))
+ */
+ public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
+ throws IOException
+ {
+ return new SPNEGOSocket(address, port, localAddress, localPort);
+ }
+
+}
Added: projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SecurityActions.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SecurityActions.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-spnego/src/main/java/org/jboss/security/negotiation/spnego/net/SecurityActions.java 2010-11-17 16:58:57 UTC (rev 109354)
@@ -0,0 +1,80 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.negotiation.spnego.net;
+
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import javax.security.auth.Subject;
+
+import org.jboss.security.SecurityContext;
+import org.jboss.security.SecurityContextAssociation;
+import org.jboss.security.SecurityContextFactory;
+
+/**
+ * PrivilegedActions for this package.
+ *
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+class SecurityActions
+{
+
+ static SecurityContext createSecurityContext(final Principal p, final Object cred, final Subject s,
+ final String domainName) throws PrivilegedActionException
+ {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<SecurityContext>()
+ {
+ public SecurityContext run() throws Exception
+ {
+ return SecurityContextFactory.createSecurityContext(p, cred, s, domainName);
+ }
+ });
+ }
+
+ static void setSecurityContext(final SecurityContext sc)
+ {
+ AccessController.doPrivileged(new PrivilegedAction<Object>()
+ {
+ public Object run()
+ {
+ SecurityContextAssociation.setSecurityContext(sc);
+ return null;
+ }
+ });
+ }
+
+ static SecurityContext getSecurityContext()
+ {
+ return AccessController.doPrivileged(new PrivilegedAction<SecurityContext>()
+ {
+ public SecurityContext run()
+ {
+ return SecurityContextAssociation.getSecurityContext();
+ }
+ });
+ }
+
+}
Modified: projects/security/security-negotiation/trunk/parent/pom.xml
===================================================================
--- projects/security/security-negotiation/trunk/parent/pom.xml 2010-11-17 16:41:36 UTC (rev 109353)
+++ projects/security/security-negotiation/trunk/parent/pom.xml 2010-11-17 16:58:57 UTC (rev 109354)
@@ -27,6 +27,7 @@
<version.jboss-web>2.1.0.GA</version.jboss-web>
<version.junit>3.8.1</version.junit>
<version.picketbox-commons>1.0.0.CR1</version.picketbox-commons>
+ <version.picketbox>3.0.0.CR2</version.picketbox>
</properties>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
@@ -154,6 +155,11 @@
<version>${version.jboss.jbosssx}</version>
</dependency>
<dependency>
+ <groupId>org.picketbox</groupId>
+ <artifactId>jboss-security-spi</artifactId>
+ <version>${version.picketbox}</version>
+ </dependency>
+ <dependency>
<groupId>jboss</groupId>
<artifactId>jboss-system</artifactId>
<version>${version.jboss.system}</version>
More information about the jboss-cvs-commits
mailing list