[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