You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by co...@apache.org on 2014/05/23 16:27:12 UTC

svn commit: r1597101 - in /webservices/wss4j/trunk: ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/ ws-security-common/src/main/java/org/apache/wss4j/common/spnego/ ws-security-dom/src/main/java/org/apache/wss4j/dom/message/token/ ws...

Author: coheigea
Date: Fri May 23 14:27:12 2014
New Revision: 1597101

URL: http://svn.apache.org/r1597101
Log:
[WSS-500,WSS-501] - Various Kerberos enhancements, thanks to Boris Dushanov

Added:
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosClientExceptionAction.java
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosContext.java
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosServiceContext.java
      - copied, changed from r1595226, webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoServiceAction.java
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosServiceExceptionAction.java
Modified:
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosClientAction.java
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosContextAndServiceNameCallback.java
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosServiceAction.java
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/DefaultSpnegoClientAction.java
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/DefaultSpnegoServiceAction.java
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoClientAction.java
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoServiceAction.java
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoTokenContext.java
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/token/KerberosSecurity.java
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/validate/KerberosTokenValidator.java
    webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosClientSecurityToken.java
    webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosServiceSecurityTokenImpl.java

Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosClientAction.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosClientAction.java?rev=1597101&r1=1597100&r2=1597101&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosClientAction.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosClientAction.java Fri May 23 14:27:12 2014
@@ -22,13 +22,6 @@ package org.apache.wss4j.common.kerberos
 import java.security.Principal;
 import java.security.PrivilegedAction;
 
-import org.ietf.jgss.GSSContext;
-import org.ietf.jgss.GSSCredential;
-import org.ietf.jgss.GSSException;
-import org.ietf.jgss.GSSManager;
-import org.ietf.jgss.GSSName;
-import org.ietf.jgss.Oid;
-
 /**
  * This class represents a PrivilegedAction implementation to obtain a service ticket from a Kerberos
  * Key Distribution Center.
@@ -39,35 +32,23 @@ public class KerberosClientAction implem
     
     private Principal clientPrincipal;
     private String serviceName;
+    private boolean isUsernameServiceNameForm;
     
     public KerberosClientAction(Principal clientPrincipal, String serviceName) {
+        this(clientPrincipal, serviceName, false);
+    }
+    
+    public KerberosClientAction(Principal clientPrincipal, String serviceName, boolean isUsernameServiceNameForm) {
         this.clientPrincipal = clientPrincipal;
         this.serviceName = serviceName;
+        this.isUsernameServiceNameForm = isUsernameServiceNameForm;
     }
 
     public byte[] run() {
         try {
-            GSSManager gssManager = GSSManager.getInstance();
-        
-            Oid kerberos5Oid = new Oid("1.2.840.113554.1.2.2");
-            GSSName gssClient = gssManager.createName(clientPrincipal.getName(), GSSName.NT_USER_NAME);
-            GSSCredential credentials = 
-                gssManager.createCredential(
-                    gssClient, GSSCredential.DEFAULT_LIFETIME, kerberos5Oid, GSSCredential.INITIATE_ONLY
-                );
-            
-            GSSName gssService = gssManager.createName(serviceName, GSSName.NT_HOSTBASED_SERVICE);
-            GSSContext secContext =
-                gssManager.createContext(
-                    gssService, kerberos5Oid, credentials, GSSContext.DEFAULT_LIFETIME
-                );
- 
-            secContext.requestMutualAuth(false);
-            byte[] token = new byte[0];
-            byte[] returnedToken = secContext.initSecContext(token, 0, token.length);
-            secContext.dispose();
-            return returnedToken;
-        } catch (GSSException e) {
+            KerberosContext krbCtx = (KerberosContext)new KerberosClientExceptionAction(clientPrincipal, serviceName, isUsernameServiceNameForm).run();
+            return krbCtx.getKerberosToken();
+        } catch (Exception e) {
             if (LOG.isDebugEnabled()) {
                 LOG.debug("Error in obtaining a Kerberos token", e);
             }

Added: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosClientExceptionAction.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosClientExceptionAction.java?rev=1597101&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosClientExceptionAction.java (added)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosClientExceptionAction.java Fri May 23 14:27:12 2014
@@ -0,0 +1,128 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.wss4j.common.kerberos;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.Key;
+import java.security.Principal;
+import java.security.PrivilegedExceptionAction;
+
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.ext.WSSecurityException.ErrorCode;
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSCredential;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.GSSManager;
+import org.ietf.jgss.GSSName;
+import org.ietf.jgss.Oid;
+
+/**
+ * This class represents a PrivilegedExceptionAction implementation to obtain a service ticket from a Kerberos
+ * Key Distribution Center.
+ */
+public class KerberosClientExceptionAction implements PrivilegedExceptionAction<KerberosContext> {
+    private static final String javaVersion = System.getProperty("java.version");
+    private static final boolean isJava5Or6 = javaVersion.startsWith("1.5") || javaVersion.startsWith("1.6");
+    private static final boolean isOracleJavaVendor = System.getProperty("java.vendor").startsWith("Oracle");
+    private static final boolean isIBMJavaVendor = System.getProperty("java.vendor").startsWith("IBM");
+
+    private static final String SUN_JGSS_INQUIRE_TYPE_CLASS = "com.sun.security.jgss.InquireType";
+    private static final String SUN_JGSS_EXT_GSSCTX_CLASS = "com.sun.security.jgss.ExtendedGSSContext";
+
+    private static final String IBM_JGSS_INQUIRE_TYPE_CLASS = "com.ibm.security.jgss.InquireType";
+    private static final String IBM_JGSS_EXT_GSSCTX_CLASS = "com.ibm.security.jgss.ExtendedGSSContext";
+
+    private Principal clientPrincipal;
+    private String serviceName;
+    private boolean isUsernameServiceNameForm;
+
+    public KerberosClientExceptionAction(Principal clientPrincipal, String serviceName, boolean isUsernameServiceNameForm) {
+        this.clientPrincipal = clientPrincipal;
+        this.serviceName = serviceName;
+        this.isUsernameServiceNameForm = isUsernameServiceNameForm;
+    }
+
+    public KerberosContext run() throws GSSException, WSSecurityException {
+        GSSManager gssManager = GSSManager.getInstance();
+
+        Oid kerberos5Oid = new Oid("1.2.840.113554.1.2.2");
+        GSSName gssClient = gssManager.createName(clientPrincipal.getName(), GSSName.NT_USER_NAME);
+        GSSCredential credentials = 
+            gssManager.createCredential(
+                gssClient, GSSCredential.DEFAULT_LIFETIME, kerberos5Oid, GSSCredential.INITIATE_ONLY
+            );
+
+        GSSName gssService = gssManager.createName(serviceName, isUsernameServiceNameForm ? GSSName.NT_USER_NAME : GSSName.NT_HOSTBASED_SERVICE);
+        GSSContext secContext =
+            gssManager.createContext(
+                gssService, kerberos5Oid, credentials, GSSContext.DEFAULT_LIFETIME
+            );
+
+        secContext.requestMutualAuth(false);
+
+        byte[] token = new byte[0];
+        byte[] returnedToken = secContext.initSecContext(token, 0, token.length);
+
+        KerberosContext krbCtx = new KerberosContext();
+        krbCtx.setGssContext(secContext);
+        krbCtx.setKerberosToken(returnedToken);
+
+        if (!isJava5Or6 && (isOracleJavaVendor || isIBMJavaVendor)) {
+            try {
+                @SuppressWarnings("rawtypes")
+                Class inquireType = Class.forName(isOracleJavaVendor ? SUN_JGSS_INQUIRE_TYPE_CLASS : IBM_JGSS_INQUIRE_TYPE_CLASS);
+
+                @SuppressWarnings("rawtypes")
+                Class extendedGSSContext = Class.forName(isOracleJavaVendor ? SUN_JGSS_EXT_GSSCTX_CLASS : IBM_JGSS_EXT_GSSCTX_CLASS);
+
+                @SuppressWarnings("unchecked")
+                Method inquireSecContext = extendedGSSContext.getMethod("inquireSecContext", inquireType);
+
+                @SuppressWarnings("unchecked")
+                Key key = (Key) inquireSecContext.invoke(secContext, Enum.valueOf(inquireType, "KRB5_GET_SESSION_KEY"));
+
+                krbCtx.setSecretKey(key);
+            }
+            catch (ClassNotFoundException e) {
+                throw new WSSecurityException(
+                    ErrorCode.FAILURE, "kerberosServiceTicketError", new Object[] {}, e
+                );
+            }
+            catch (NoSuchMethodException e) {
+                throw new WSSecurityException(
+                    ErrorCode.FAILURE, "kerberosServiceTicketError", new Object[] {}, e
+                );
+            }
+            catch (InvocationTargetException e) {
+                throw new WSSecurityException(
+                    ErrorCode.FAILURE, "kerberosServiceTicketError", new Object[] {}, e.getCause()
+                );
+            }
+            catch (IllegalAccessException e) {
+                throw new WSSecurityException(
+                     ErrorCode.FAILURE, "kerberosServiceTicketError", new Object[] {}, e
+                );
+            }
+        }
+
+        return krbCtx;
+    }
+}

Added: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosContext.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosContext.java?rev=1597101&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosContext.java (added)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosContext.java Fri May 23 14:27:12 2014
@@ -0,0 +1,128 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.wss4j.common.kerberos;
+
+import java.security.Key;
+
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSException;
+
+/**
+ * Encapsulates Kerberos token (service ticket) and secret key returned by
+ * {@link KerberosClientExceptionAction}.
+ * 
+ * The secret key might be null, in which case it must be obtained from the current subject's 
+ * {@link javax.security.auth.kerberos.KerberosTicket} private credential. 
+ * 
+ * @author bgde
+ */
+public class KerberosContext {
+    private static final org.slf4j.Logger LOG =
+        org.slf4j.LoggerFactory.getLogger(KerberosContext.class);
+
+    private boolean disposed;
+    private GSSContext gssContext;
+    private byte[] kerberosToken;
+    private Key secretKey;
+
+    /**
+     * @return The Kerberos service ticket bytes or null they are not available/set.
+     * @throws IllegalStateException If this context was already disposed.
+     */
+    public byte[] getKerberosToken() {
+        if (disposed) {
+            throw new IllegalStateException("Kerberos context is disposed.");
+        }
+
+        return kerberosToken;
+    }
+
+    public void setKerberosToken(byte[] kerberosToken) {
+        this.kerberosToken = kerberosToken;
+    }
+
+    /**
+     * @return The secret session key, or null if it is not available.
+     * In this case it must be obtained from the current subject's {@link javax.security.auth.kerberos.KerberosTicket KerberosTicket} private credential.
+     * 
+     * @see {@link javax.security.auth.kerberos.KerberosTicket#getSessionKey()}
+     * @throws IllegalStateException If this context was already disposed.
+     */
+    public Key getSecretKey() {
+        if (disposed) {
+            throw new IllegalStateException("Kerberos context is disposed.");
+        }
+        return secretKey; 
+    }
+
+    public void setSecretKey(Key secretKey) {
+        this.secretKey = secretKey;
+    }
+
+    /**
+     * @return The GSSContext as initialized during Kerberos service ticket retrieval.
+     * @throws IllegalStateException If this context was already disposed.
+     */
+    public GSSContext getGssContext() {
+        if (disposed) {
+            throw new IllegalStateException("Kerberos context is disposed.");
+        }
+        return this.gssContext;
+    }
+
+    public void setGssContext(GSSContext gssContext) {
+        this.gssContext = gssContext;
+    }
+
+    /**
+     * Destroys all data held in this context instance. After calling this method, 
+     * an attempt to retrieve any field of this context instance will throw an IllegalArgumentException.
+     */
+    public void dispose() {
+        if (!disposed) {
+            if (kerberosToken != null) {
+                for (int i = 0; i < kerberosToken.length; i++) {
+                    kerberosToken[i] = 0;
+                }
+            }
+
+            secretKey = null;
+
+            if (gssContext != null) {
+                try {
+                    gssContext.dispose();
+                }
+                catch (GSSException e) {
+                    LOG.error("Error disposing of the GSSContext", e);
+                }
+            }
+
+            disposed = true;
+        }
+    }
+
+    /**
+     * Checks if this context instance is already destroyed.
+     * @return
+     */
+    public boolean isDisposed() {
+        return disposed;
+    }
+}

Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosContextAndServiceNameCallback.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosContextAndServiceNameCallback.java?rev=1597101&r1=1597100&r2=1597101&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosContextAndServiceNameCallback.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosContextAndServiceNameCallback.java Fri May 23 14:27:12 2014
@@ -24,6 +24,7 @@ public class KerberosContextAndServiceNa
 
     private String contextName;
     private String serviceName;
+    private boolean isUsernameServiceNameForm;
 
     public String getContextName() {
         return contextName;
@@ -40,4 +41,13 @@ public class KerberosContextAndServiceNa
     public void setServiceName(String serviceName) {
         this.serviceName = serviceName;
     }
+    
+    public void setIsUsernameServiceNameForm(boolean isUsernameServiceNameForm){
+    	this.isUsernameServiceNameForm = isUsernameServiceNameForm;
+    }
+    
+    public boolean isUsernameServiceNameForm(){
+    	return this.isUsernameServiceNameForm;
+    }
+
 }

Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosServiceAction.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosServiceAction.java?rev=1597101&r1=1597100&r2=1597101&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosServiceAction.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosServiceAction.java Fri May 23 14:27:12 2014
@@ -22,49 +22,34 @@ package org.apache.wss4j.common.kerberos
 import java.security.Principal;
 import java.security.PrivilegedAction;
 
-import javax.security.auth.kerberos.KerberosPrincipal;
-
-import org.ietf.jgss.GSSContext;
-import org.ietf.jgss.GSSCredential;
-import org.ietf.jgss.GSSException;
-import org.ietf.jgss.GSSManager;
-import org.ietf.jgss.GSSName;
-import org.ietf.jgss.Oid;
-
 /**
  * This class represents a PrivilegedAction implementation to validate a received ticket to a KDC.
  */
 public class KerberosServiceAction implements PrivilegedAction<Principal> {
     private static final org.slf4j.Logger LOG =
-        org.slf4j.LoggerFactory.getLogger(KerberosServiceAction.class);
+            org.slf4j.LoggerFactory.getLogger(KerberosServiceAction.class);
     
     private byte[] ticket;
     private String serviceName;
+    private boolean isUsernameServiceNameForm;
     
     public KerberosServiceAction(byte[] ticket, String serviceName) {
+        this(ticket, serviceName, false);
+    }
+    
+    public KerberosServiceAction(byte[] ticket, String serviceName, boolean isUsernameServiceNameForm) {
         this.ticket = ticket;
         this.serviceName = serviceName;
+        this.isUsernameServiceNameForm = isUsernameServiceNameForm;
     }
 
     public Principal run() {
         try {
-            GSSManager gssManager = GSSManager.getInstance();
-        
-            Oid kerberos5Oid = new Oid("1.2.840.113554.1.2.2");
-            GSSName gssService = gssManager.createName(serviceName, GSSName.NT_HOSTBASED_SERVICE);
-            GSSCredential credentials = 
-                gssManager.createCredential(
-                    gssService, GSSCredential.DEFAULT_LIFETIME, kerberos5Oid, GSSCredential.ACCEPT_ONLY
-                );
-            
-            GSSContext secContext =
-                gssManager.createContext(credentials);
-            secContext.acceptSecContext(ticket, 0, ticket.length);
- 
-            GSSName clientName = secContext.getSrcName();
-            secContext.dispose();
-            return new KerberosPrincipal(clientName.toString());
-        } catch (GSSException e) {
+            KerberosServiceExceptionAction action = 
+                new KerberosServiceExceptionAction(this.ticket, this.serviceName, this.isUsernameServiceNameForm);            
+            KerberosServiceContext krbServiceCtx = action.run();            
+            return krbServiceCtx.getPrincipal();
+        } catch (Exception e) {
             if (LOG.isDebugEnabled()) {
                 LOG.debug("Error in validating a Kerberos token", e);
             }

Copied: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosServiceContext.java (from r1595226, webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoServiceAction.java)
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosServiceContext.java?p2=webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosServiceContext.java&p1=webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoServiceAction.java&r1=1595226&r2=1597101&rev=1597101&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoServiceAction.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosServiceContext.java Fri May 23 14:27:12 2014
@@ -16,37 +16,43 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.wss4j.common.kerberos;
 
-package org.apache.wss4j.common.spnego;
+import java.security.Key;
+import java.security.Principal;
 
-import java.security.PrivilegedAction;
 
-import org.ietf.jgss.GSSContext;
-
-/**
- * This interface represents a PrivilegedAction implementation to validate a received (SPNEGO) 
- * ticket to a KDC.
- */
-public interface SpnegoServiceAction extends PrivilegedAction<byte[]> {
+public class KerberosServiceContext {
+    
+    private Principal principal = null;
+    private Key sessionKey = null;
     
     /**
-     * Set the ticket to validate
+     * @return the principal
      */
-    void setTicket(byte[] ticket);
+    public Principal getPrincipal() {
+        return principal;
+    }
     
     /**
-     * The Service Name
+     * @param principal the principal to set
      */
-    void setServiceName(String serviceName);
+    public void setPrincipal(Principal principal) {
+        this.principal = principal;
+    }
     
     /**
-     * Validate a service ticket
+     * @return the sessionKey
      */
-    byte[] run();
+    public Key getSessionKey() {
+        return sessionKey;
+    }
     
     /**
-     * Get the GSSContext that was created after a service ticket was obtained
+     * @param sessionKey the sessionKey to set
      */
-    GSSContext getContext();
+    public void setSessionKey(Key sessionKey) {
+        this.sessionKey = sessionKey;
+    }
     
 }

Added: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosServiceExceptionAction.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosServiceExceptionAction.java?rev=1597101&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosServiceExceptionAction.java (added)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/kerberos/KerberosServiceExceptionAction.java Fri May 23 14:27:12 2014
@@ -0,0 +1,141 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.wss4j.common.kerberos;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.Key;
+import java.security.PrivilegedExceptionAction;
+
+import javax.security.auth.kerberos.KerberosPrincipal;
+
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.ext.WSSecurityException.ErrorCode;
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSCredential;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.GSSManager;
+import org.ietf.jgss.GSSName;
+import org.ietf.jgss.Oid;
+
+
+public class KerberosServiceExceptionAction implements PrivilegedExceptionAction<KerberosServiceContext> {
+
+    private static final String javaVersion = System.getProperty("java.version");
+    private static final boolean isJava5Or6 = javaVersion.startsWith("1.5") || javaVersion.startsWith("1.6");
+    private static final boolean isOracleJavaVendor = System.getProperty("java.vendor").startsWith("Oracle");
+    private static final boolean isIBMJavaVendor = System.getProperty("java.vendor").startsWith("IBM");
+
+    private static final String SUN_JGSS_INQUIRE_TYPE_CLASS = "com.sun.security.jgss.InquireType";
+    private static final String SUN_JGSS_EXT_GSSCTX_CLASS = "com.sun.security.jgss.ExtendedGSSContext";
+
+    private static final String IBM_JGSS_INQUIRE_TYPE_CLASS = "com.ibm.security.jgss.InquireType";
+    private static final String IBM_JGSS_EXT_GSSCTX_CLASS = "com.ibm.security.jgss.ExtendedGSSContext";
+
+    private static final String EXTENDED_JGSS_CONTEXT_INQUIRE_SEC_CONTEXT_METHOD_NAME = "inquireSecContext";
+    private static final String EXTENDED_JGSS_CONTEXT_INQUIRE_TYPE_KRB5_GET_SESSION_KEY = "KRB5_GET_SESSION_KEY";
+
+    private static final String JGSS_KERBEROS_TICKET_OID = "1.2.840.113554.1.2.2";
+
+    private static final String KERBEROS_TICKET_VALIDATION_ERROR_MSG_ID = "kerberosTicketValidationError";
+
+    private byte[] ticket;
+    private String serviceName;
+    private boolean isUsernameServiceNameForm;
+
+    public KerberosServiceExceptionAction(byte[] ticket, String serviceName, boolean isUsernameServiceNameForm) {
+        this.ticket = ticket;
+        this.serviceName = serviceName;
+        this.isUsernameServiceNameForm = isUsernameServiceNameForm;
+    }
+
+
+    /* (non-Javadoc)
+     * @see java.security.PrivilegedExceptionAction#run()
+     */
+    public KerberosServiceContext run() throws GSSException, WSSecurityException{
+
+        GSSManager gssManager = GSSManager.getInstance();
+
+        Oid kerberos5Oid = new Oid(JGSS_KERBEROS_TICKET_OID);
+        GSSName gssService = gssManager.createName(serviceName, isUsernameServiceNameForm ? GSSName.NT_USER_NAME : GSSName.NT_HOSTBASED_SERVICE);
+        GSSCredential credentials = 
+            gssManager.createCredential(
+                gssService, GSSCredential.DEFAULT_LIFETIME, kerberos5Oid, GSSCredential.ACCEPT_ONLY
+            );
+
+        KerberosServiceContext krbServiceCtx = null;
+        GSSContext secContext = null;
+
+        try{
+            secContext = gssManager.createContext(credentials);
+            secContext.acceptSecContext(ticket, 0, ticket.length);
+
+            krbServiceCtx = new KerberosServiceContext();            
+
+            GSSName clientName = secContext.getSrcName();
+            krbServiceCtx.setPrincipal(new KerberosPrincipal(clientName.toString()));
+
+            if (!isJava5Or6 && (isOracleJavaVendor || isIBMJavaVendor)) {
+                try {
+                    @SuppressWarnings("rawtypes")
+                    Class inquireType = Class.forName(isOracleJavaVendor ? SUN_JGSS_INQUIRE_TYPE_CLASS : IBM_JGSS_INQUIRE_TYPE_CLASS);
+
+                    @SuppressWarnings("rawtypes")
+                    Class extendedGSSContext = Class.forName(isOracleJavaVendor ? SUN_JGSS_EXT_GSSCTX_CLASS : IBM_JGSS_EXT_GSSCTX_CLASS);
+
+                    @SuppressWarnings("unchecked")
+                    Method inquireSecContext = extendedGSSContext.getMethod(EXTENDED_JGSS_CONTEXT_INQUIRE_SEC_CONTEXT_METHOD_NAME, inquireType);
+
+                    @SuppressWarnings("unchecked")
+                    Key key = (Key) inquireSecContext.invoke(secContext, Enum.valueOf(inquireType, EXTENDED_JGSS_CONTEXT_INQUIRE_TYPE_KRB5_GET_SESSION_KEY));
+
+                    krbServiceCtx.setSessionKey(key);
+                }
+                catch (ClassNotFoundException e) {
+                    throw new WSSecurityException(
+                        ErrorCode.FAILURE, KERBEROS_TICKET_VALIDATION_ERROR_MSG_ID, new Object[] {}, e
+                    );
+                }
+                catch (NoSuchMethodException e) {
+                    throw new WSSecurityException(
+                        ErrorCode.FAILURE, KERBEROS_TICKET_VALIDATION_ERROR_MSG_ID, new Object[] {}, e
+                    );
+                }
+                catch (InvocationTargetException e) {
+                    throw new WSSecurityException(
+                        ErrorCode.FAILURE, KERBEROS_TICKET_VALIDATION_ERROR_MSG_ID, new Object[] {}, e.getCause()
+                    );
+                }
+                catch (IllegalAccessException e) {
+                    throw new WSSecurityException(
+                        ErrorCode.FAILURE, KERBEROS_TICKET_VALIDATION_ERROR_MSG_ID, new Object[] {}, e
+                    );
+                }            
+            }            
+        } finally {
+            if (null != secContext) {
+                secContext.dispose();    
+            }  
+        }               
+
+        return krbServiceCtx;
+    }
+
+}

Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/DefaultSpnegoClientAction.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/DefaultSpnegoClientAction.java?rev=1597101&r1=1597100&r2=1597101&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/DefaultSpnegoClientAction.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/DefaultSpnegoClientAction.java Fri May 23 14:27:12 2014
@@ -36,6 +36,7 @@ public class DefaultSpnegoClientAction i
     private String serviceName;
     private GSSContext secContext;
     private boolean mutualAuth;
+    private boolean isUsernameServiceNameForm;
     
     /**
      * Whether to enable mutual authentication or not.
@@ -59,7 +60,7 @@ public class DefaultSpnegoClientAction i
             GSSManager gssManager = GSSManager.getInstance();
             Oid oid = new Oid("1.3.6.1.5.5.2");
 
-            GSSName gssService = gssManager.createName(serviceName, GSSName.NT_HOSTBASED_SERVICE);
+            GSSName gssService = gssManager.createName(serviceName, isUsernameServiceNameForm ? GSSName.NT_USER_NAME : GSSName.NT_HOSTBASED_SERVICE);
             secContext = gssManager.createContext(gssService, oid, null, GSSContext.DEFAULT_LIFETIME);
 
             secContext.requestMutualAuth(mutualAuth);
@@ -82,5 +83,10 @@ public class DefaultSpnegoClientAction i
     public GSSContext getContext() {
         return secContext;
     }
-    
+
+    @Override
+    public void setUserNameServiceForm(boolean isUsernameServiceNameForm) {
+        this.isUsernameServiceNameForm = isUsernameServiceNameForm;
+    }
+
 }

Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/DefaultSpnegoServiceAction.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/DefaultSpnegoServiceAction.java?rev=1597101&r1=1597100&r2=1597101&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/DefaultSpnegoServiceAction.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/DefaultSpnegoServiceAction.java Fri May 23 14:27:12 2014
@@ -35,6 +35,7 @@ public class DefaultSpnegoServiceAction 
     
     private byte[] ticket;
     private String serviceName;
+    private boolean isUsernameServiceNameForm;
     private GSSContext secContext;
     
     /**
@@ -59,7 +60,7 @@ public class DefaultSpnegoServiceAction 
             GSSManager gssManager = GSSManager.getInstance();
             Oid oid = new Oid("1.3.6.1.5.5.2");
 
-            GSSName gssService = gssManager.createName(serviceName, GSSName.NT_HOSTBASED_SERVICE);
+            GSSName gssService = gssManager.createName(serviceName, isUsernameServiceNameForm ? GSSName.NT_USER_NAME : GSSName.NT_HOSTBASED_SERVICE);
             secContext = gssManager.createContext(gssService, oid, null, GSSContext.DEFAULT_LIFETIME);
 
             return secContext.acceptSecContext(ticket, 0, ticket.length);
@@ -78,5 +79,10 @@ public class DefaultSpnegoServiceAction 
     public GSSContext getContext() {
         return secContext;
     }
-    
+
+    @Override
+    public void setUsernameServiceNameForm(boolean isUsernameServiceNameForm) {
+        this.isUsernameServiceNameForm = isUsernameServiceNameForm;
+    }
+
 }

Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoClientAction.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoClientAction.java?rev=1597101&r1=1597100&r2=1597101&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoClientAction.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoClientAction.java Fri May 23 14:27:12 2014
@@ -40,6 +40,14 @@ public interface SpnegoClientAction exte
     void setServiceName(String serviceName);
 
     /**
+     * If true - sets the SPN form to "username"
+     * <br/>If false<b>(default)</b> - the SPN form is "hostbased"
+     * 
+     * @param isUsernameServiceNameForm the isUsernameServiceNameForm to set
+     */
+    void setUserNameServiceForm(boolean isUsernameServiceNameForm);
+
+    /**
      * Obtain a service ticket
      */
     byte[] run();

Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoServiceAction.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoServiceAction.java?rev=1597101&r1=1597100&r2=1597101&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoServiceAction.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoServiceAction.java Fri May 23 14:27:12 2014
@@ -40,6 +40,14 @@ public interface SpnegoServiceAction ext
     void setServiceName(String serviceName);
     
     /**
+     * If true - sets the SPN form to "username"
+     * <br/>If false<b>(default)</b> - the SPN form is "hostbased"
+     * 
+     * @param isUsernameServiceNameForm the isUsernameServiceNameForm to set
+     */
+    void setUsernameServiceNameForm(boolean isUsernameServiceNameForm);
+    
+    /**
      * Validate a service ticket
      */
     byte[] run();

Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoTokenContext.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoTokenContext.java?rev=1597101&r1=1597100&r2=1597101&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoTokenContext.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/spnego/SpnegoTokenContext.java Fri May 23 14:27:12 2014
@@ -59,6 +59,26 @@ public class SpnegoTokenContext {
         CallbackHandler callbackHandler,
         String serviceName
     ) throws WSSecurityException {
+    	retrieveServiceTicket(jaasLoginModuleName, callbackHandler, serviceName, false);
+    }
+    
+    
+    /**
+     * Retrieve a service ticket from a KDC using the Kerberos JAAS module, and set it in this
+     * BinarySecurityToken.
+     * @param jaasLoginModuleName the JAAS Login Module name to use
+     * @param callbackHandler a CallbackHandler instance to retrieve a password (optional)
+     * @param serviceName the desired Kerberized service
+     * @param serviceNameForm 
+     * @throws WSSecurityException
+     */
+    public void retrieveServiceTicket(
+        String jaasLoginModuleName, 
+        CallbackHandler callbackHandler,
+        String serviceName,
+        boolean isUsernameServiceNameForm
+    ) throws WSSecurityException {
+    	
         // Get a TGT from the KDC using JAAS
         LoginContext loginContext = null;
         try {
@@ -94,6 +114,7 @@ public class SpnegoTokenContext {
         // Get the service ticket
         clientAction.setServiceName(serviceName);
         clientAction.setMutualAuth(mutualAuth);
+        clientAction.setUserNameServiceForm(isUsernameServiceNameForm);
         token = Subject.doAs(clientSubject, clientAction);
         if (token == null) {
             throw new WSSecurityException(
@@ -105,7 +126,6 @@ public class SpnegoTokenContext {
         if (LOG.isDebugEnabled()) {
             LOG.debug("Successfully retrieved a service ticket");
         }
-        
     }
     
     /**
@@ -122,6 +142,24 @@ public class SpnegoTokenContext {
         String serviceName,
         byte[] ticket
     ) throws WSSecurityException {
+    	validateServiceTicket(jaasLoginModuleName, callbackHandler, serviceName, false, ticket);
+     }
+    
+    /**
+     * Validate a service ticket.
+     * @param jaasLoginModuleName
+     * @param callbackHandler
+     * @param serviceName
+     * @param ticket
+     * @throws WSSecurityException
+     */
+    public void validateServiceTicket(
+        String jaasLoginModuleName, 
+        CallbackHandler callbackHandler,
+        String serviceName,
+        boolean isUsernameServiceNameForm,
+        byte[] ticket
+    ) throws WSSecurityException {
         // Get a TGT from the KDC using JAAS
         LoginContext loginContext = null;
         try {
@@ -162,6 +200,7 @@ public class SpnegoTokenContext {
         // Validate the ticket
         serviceAction.setTicket(ticket);
         serviceAction.setServiceName(service);
+        serviceAction.setUsernameServiceNameForm(isUsernameServiceNameForm);
         token = Subject.doAs(subject, serviceAction);
         
         secContext = serviceAction.getContext();

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/token/KerberosSecurity.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/token/KerberosSecurity.java?rev=1597101&r1=1597100&r2=1597101&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/token/KerberosSecurity.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/token/KerberosSecurity.java Fri May 23 14:27:12 2014
@@ -20,10 +20,13 @@
 package org.apache.wss4j.dom.message.token;
 
 import java.io.IOException;
+import java.security.Key;
 import java.security.Principal;
+import java.security.PrivilegedActionException;
 import java.util.Set;
 
 import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
 import javax.security.auth.Subject;
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
@@ -32,12 +35,14 @@ import javax.security.auth.kerberos.Kerb
 import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
 
-import org.apache.wss4j.common.kerberos.KerberosClientAction;
+import org.apache.wss4j.common.bsp.BSPRule;
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.ext.WSSecurityException.ErrorCode;
+import org.apache.wss4j.common.kerberos.KerberosClientExceptionAction;
+import org.apache.wss4j.common.kerberos.KerberosContext;
 import org.apache.wss4j.common.kerberos.KerberosContextAndServiceNameCallback;
 import org.apache.wss4j.dom.WSConstants;
 import org.apache.wss4j.dom.bsp.BSPEnforcer;
-import org.apache.wss4j.common.bsp.BSPRule;
-import org.apache.wss4j.common.ext.WSSecurityException;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
@@ -45,11 +50,11 @@ import org.w3c.dom.Element;
  * Kerberos Security Token.
  */
 public class KerberosSecurity extends BinarySecurity {
-    
+
     private static final org.slf4j.Logger LOG =
         org.slf4j.LoggerFactory.getLogger(KerberosSecurity.class);
     private SecretKey secretKey;
-    
+
     /**
      * This constructor creates a new Kerberos token object and initializes
      * it from the data contained in the element.
@@ -74,7 +79,7 @@ public class KerberosSecurity extends Bi
     public KerberosSecurity(Document doc) {
         super(doc);
     }
-    
+
     /**
      * Return true if this token is a Kerberos V5 AP REQ token
      */
@@ -87,7 +92,7 @@ public class KerberosSecurity extends Bi
         }
         return false;
     }
-    
+
     /**
      * Return true if this token is a Kerberos GSS V5 AP REQ token
      */
@@ -100,7 +105,7 @@ public class KerberosSecurity extends Bi
         }
         return false;
     }
-    
+
     /**
      * Retrieve a service ticket from a KDC using the Kerberos JAAS module, and set it in this
      * BinarySecurityToken.
@@ -128,7 +133,7 @@ public class KerberosSecurity extends Bi
         if (serviceName == null) {
             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "kerberosCallbackServiceNameNotSupplied");
         }
-        
+
         retrieveServiceTicket(jaasLoginModuleName, callbackHandler, serviceName);
     }
 
@@ -145,6 +150,15 @@ public class KerberosSecurity extends Bi
         CallbackHandler callbackHandler,
         String serviceName
     ) throws WSSecurityException {
+        retrieveServiceTicket(jaasLoginModuleName, callbackHandler, serviceName, false);
+    }
+
+    public void retrieveServiceTicket(
+        String jaasLoginModuleName, 
+        CallbackHandler callbackHandler,
+        String serviceName,
+        boolean isUsernameServiceNameForm
+    ) throws WSSecurityException {
         // Get a TGT from the KDC using JAAS
         LoginContext loginContext = null;
         try {
@@ -161,12 +175,13 @@ public class KerberosSecurity extends Bi
             throw new WSSecurityException(
                 WSSecurityException.ErrorCode.FAILURE,
                 "kerberosLoginError", 
-                ex, ex.getMessage());
+                ex, ex.getMessage()
+            );
         }
         if (LOG.isDebugEnabled()) {
             LOG.debug("Successfully authenticated to the TGT");
         }
-        
+
         Subject clientSubject = loginContext.getSubject();
         Set<Principal> clientPrincipals = clientSubject.getPrincipals();
         if (clientPrincipals.isEmpty()) {
@@ -177,33 +192,51 @@ public class KerberosSecurity extends Bi
         }
         // Store the TGT
         KerberosTicket tgt = getKerberosTicket(clientSubject, null);
-        
+
         // Get the service ticket
-        KerberosClientAction action =
-            new KerberosClientAction(clientPrincipals.iterator().next(), serviceName);
-        byte[] ticket = Subject.doAs(clientSubject, action);
-        if (ticket == null) {
-            throw new WSSecurityException(
-                WSSecurityException.ErrorCode.FAILURE, "kerberosServiceTicketError"
-            );
+        KerberosClientExceptionAction action = 
+            new KerberosClientExceptionAction(clientPrincipals.iterator().next(), serviceName, isUsernameServiceNameForm);
+        KerberosContext krbCtx = null;
+        try {
+            krbCtx = (KerberosContext) Subject.doAs(clientSubject, action);
+
+            // Get the secret key from KerberosContext if available, otherwise use Kerberos ticket's session key
+            Key sessionKey = krbCtx.getSecretKey();
+            if (sessionKey != null) {
+                secretKey = new SecretKeySpec(sessionKey.getEncoded(), sessionKey.getAlgorithm());
+            } else {
+                KerberosTicket serviceTicket = getKerberosTicket(clientSubject, tgt);
+                secretKey = serviceTicket.getSessionKey();
+            }
+
+            setToken(krbCtx.getKerberosToken());
+        }
+        catch (PrivilegedActionException e) {
+            Throwable cause = e.getCause();
+            if (cause instanceof WSSecurityException) {
+                throw (WSSecurityException) cause;
+            }
+            else {
+                throw new WSSecurityException(
+                     ErrorCode.FAILURE, "kerberosServiceTicketError", new Object[] {}, cause
+                );
+            }
+        } finally {
+            if (krbCtx != null) {
+                krbCtx.dispose();
+            }
         }
         if (LOG.isDebugEnabled()) {
             LOG.debug("Successfully retrieved a service ticket");
         }
-        
-        // Get the Service Ticket (private credential)
-        KerberosTicket serviceTicket = getKerberosTicket(clientSubject, tgt);
-        if (serviceTicket != null) {
-            secretKey = serviceTicket.getSessionKey();
-        }
-        
-        setToken(ticket);
-        
+
         if ("".equals(getValueType())) {
             setValueType(WSConstants.WSS_GSS_KRB_V5_AP_REQ);
         }
     }
-    
+
+
+
     /**
      * Get a KerberosTicket from the clientSubject parameter, that is not equal to the supplied KerberosTicket
      * parameter (can be null)
@@ -216,7 +249,7 @@ public class KerberosSecurity extends Bi
             }
             return null;
         }
-        
+
         for (KerberosTicket privateCredential : privateCredentials) {
             if (!privateCredential.equals(previousTicket)) {
                 return privateCredential;
@@ -224,7 +257,7 @@ public class KerberosSecurity extends Bi
         }
         return null;
     }
-    
+
     /**
      * Get the SecretKey associated with the service principal
      * @return the SecretKey associated with the service principal
@@ -232,7 +265,7 @@ public class KerberosSecurity extends Bi
     public SecretKey getSecretKey() {
         return secretKey;
     }
-    
+
     /**
      * Return true if the valueType represents a Kerberos Token
      * @param valueType the valueType of the token
@@ -249,5 +282,5 @@ public class KerberosSecurity extends Bi
         }
         return false;
     }
-    
+
 }

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/validate/KerberosTokenValidator.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/validate/KerberosTokenValidator.java?rev=1597101&r1=1597100&r2=1597101&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/validate/KerberosTokenValidator.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/validate/KerberosTokenValidator.java Fri May 23 14:27:12 2014
@@ -19,7 +19,9 @@
 
 package org.apache.wss4j.dom.validate;
 
+import java.security.Key;
 import java.security.Principal;
+import java.security.PrivilegedActionException;
 import java.util.Set;
 
 import javax.security.auth.Subject;
@@ -28,26 +30,29 @@ import javax.security.auth.login.LoginCo
 import javax.security.auth.login.LoginException;
 
 import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.ext.WSSecurityException.ErrorCode;
+import org.apache.wss4j.common.kerberos.KerberosServiceContext;
+import org.apache.wss4j.common.kerberos.KerberosServiceExceptionAction;
 import org.apache.wss4j.common.kerberos.KerberosTokenDecoder;
 import org.apache.wss4j.common.kerberos.KerberosTokenDecoderException;
 import org.apache.wss4j.common.kerberos.KerberosTokenDecoderImpl;
 import org.apache.wss4j.dom.handler.RequestData;
 import org.apache.wss4j.dom.message.token.BinarySecurity;
 import org.apache.wss4j.dom.message.token.KerberosSecurity;
-import org.apache.wss4j.common.kerberos.KerberosServiceAction;
 
 /**
  */
 public class KerberosTokenValidator implements Validator {
-    
+
     private static final org.slf4j.Logger LOG =
         org.slf4j.LoggerFactory.getLogger(KerberosTokenValidator.class);
-    
+
     private String serviceName;
     private CallbackHandler callbackHandler;
     private String contextName;
     private KerberosTokenDecoder kerberosTokenDecoder;
-    
+    private boolean isUsernameServiceNameForm;
+
     /**
      * Get the JAAS Login context name to use.
      * @return the JAAS Login context name to use
@@ -63,7 +68,7 @@ public class KerberosTokenValidator impl
     public void setContextName(String contextName) {
         this.contextName = contextName;
     }
-    
+
     /**
      * Get the CallbackHandler to use with the LoginContext
      * @return the CallbackHandler to use with the LoginContext
@@ -88,7 +93,7 @@ public class KerberosTokenValidator impl
     public void setServiceName(String serviceName) {
         this.serviceName = serviceName;
     }
-    
+
     /**
      * Get the name of the service to use when contacting the KDC. This value can be null, in which
      * case it defaults to the current principal name.
@@ -97,7 +102,7 @@ public class KerberosTokenValidator impl
     public String getServiceName() {
         return serviceName;
     }
-    
+
     /**
      * Get the KerberosTokenDecoder instance used to extract a session key from the received Kerberos
      * token.
@@ -115,7 +120,7 @@ public class KerberosTokenValidator impl
     public void setKerberosTokenDecoder(KerberosTokenDecoder kerberosTokenDecoder) {
         this.kerberosTokenDecoder = kerberosTokenDecoder;
     }
-    
+
     /**
      * Validate the credential argument. It must contain a non-null BinarySecurityToken. 
      * 
@@ -127,12 +132,12 @@ public class KerberosTokenValidator impl
         if (credential == null || credential.getBinarySecurityToken() == null) {
             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noCredential");
         }
-        
+
         BinarySecurity binarySecurity = credential.getBinarySecurityToken();
         if (!(binarySecurity instanceof KerberosSecurity)) {
             return credential;
         }
-        
+
         if (LOG.isDebugEnabled()) {
             try {
                 String jaasAuth = System.getProperty("java.security.auth.login.config");
@@ -143,7 +148,7 @@ public class KerberosTokenValidator impl
                 LOG.debug(ex.getMessage(), ex);
             }
         }
-        
+
         // Get a TGT from the KDC using JAAS
         LoginContext loginContext = null;
         try {
@@ -163,14 +168,15 @@ public class KerberosTokenValidator impl
                 WSSecurityException.ErrorCode.FAILURE,
                 "kerberosLoginError", 
                 ex,
-                ex.getMessage());
+                ex.getMessage()
+            );
         }
         if (LOG.isDebugEnabled()) {
             LOG.debug("Successfully authenticated to the TGT");
         }
-        
+
         byte[] token = binarySecurity.getToken();
-        
+
         // Get the service name to use - fall back on the principal
         Subject subject = loginContext.getSubject();
         String service = serviceName;
@@ -184,37 +190,92 @@ public class KerberosTokenValidator impl
             }
             service = principals.iterator().next().getName();
         }
-        
+
         // Validate the ticket
-        KerberosServiceAction action = new KerberosServiceAction(token, service);
-        Principal principal = Subject.doAs(subject, action);
-        if (principal == null) {
-            throw new WSSecurityException(
-                WSSecurityException.ErrorCode.FAILURE, "kerberosTicketValidationError"
-            );
-        }
-        credential.setPrincipal(principal);
-        credential.setSubject(subject);
-        
-        KerberosTokenDecoder kerberosTokenDecoder = this.kerberosTokenDecoder;
-        if (kerberosTokenDecoder == null) {
-            kerberosTokenDecoder = new KerberosTokenDecoderImpl();
+        KerberosServiceExceptionAction action = new KerberosServiceExceptionAction(token, service, isUsernameServiceNameForm());
+        KerberosServiceContext krbServiceCtx = null;
+        try {
+            krbServiceCtx = Subject.doAs(subject, action);
+        } catch (PrivilegedActionException e) {
+            Throwable cause = e.getCause();
+            if (cause instanceof WSSecurityException) {
+                throw (WSSecurityException) cause;
+            } else {
+                throw new WSSecurityException(
+                    ErrorCode.FAILURE, "kerberosTicketValidationError", new Object[] {}, cause
+                );
+            }
         }
 
-        kerberosTokenDecoder.clear();
-        kerberosTokenDecoder.setToken(token);
-        kerberosTokenDecoder.setSubject(subject);
-        try {
-            byte[] sessionKey = kerberosTokenDecoder.getSessionKey();
-            credential.setSecretKey(sessionKey);
-        } catch (KerberosTokenDecoderException e) {
-            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
+        credential.setPrincipal(krbServiceCtx.getPrincipal());
+
+        // Check to see if the session key is available in KerberosServiceContext
+        LOG.debug("Trying to obtain the Session Key from the KerberosServiceContext.");
+        Key sessionKey = krbServiceCtx.getSessionKey();
+        if (null != sessionKey) {
+            LOG.debug("Found session key in the KerberosServiceContext.");
+            credential.setSecretKey(sessionKey.getEncoded());
+        } else {
+            LOG.debug("Session key is not found in the KerberosServiceContext.");
+        }
+        
+        // Otherwise, try to extract the session key from the token if a KerberosTokenDecoder implementation is
+        // available
+        if (null == credential.getSecretKey()) {    
+            KerberosTokenDecoder kerberosTokenDecoder = this.kerberosTokenDecoder;
+            if (kerberosTokenDecoder == null) {
+                kerberosTokenDecoder = new KerberosTokenDecoderImpl();
+            }
+            
+            LOG.debug("KerberosTokenDecoder is set.Trying to obtain the session key from it.");            
+            kerberosTokenDecoder.clear();
+            kerberosTokenDecoder.setToken(token);
+            kerberosTokenDecoder.setSubject(subject);
+            try {
+                byte[] key = kerberosTokenDecoder.getSessionKey();
+                if (null != key) {
+                    LOG.debug("Session key obtained from the KerberosTokenDecoder.");
+                    credential.setSecretKey(key);
+                } else {
+                    LOG.debug("Session key could not be obtained from the KerberosTokenDecoder.");
+                }
+            } catch (KerberosTokenDecoderException e) {
+                // TODO
+                throw new WSSecurityException(ErrorCode.FAILURE, "Error retrieving session key.", e);
+            }            
+        } else {
+            LOG.debug("KerberosTokenDecoder is not set.");
         }
 
         if (LOG.isDebugEnabled()) {
             LOG.debug("Successfully validated a ticket");
         }
-        
+
         return credential;
     }
+
+    /**
+     * SPN can be configured to be in either <b>"hostbased"</b> or <b>"username"</b> form.<br/>
+     *     - <b>"hostbased"</b> - specifies that the service principal name should be interpreted as a "host-based" name as specified in GSS API Rfc, section "4.1: Host-Based Service Name Form" - The service name, as it is specified in LDAP/AD, as it is listed in the KDC.<br/>
+     *     - <b>"username"</b> - specifies that the service principal name should be interpreted as a "username" name as specified in GSS API Rfc, section "4.2: User Name Form" � This is usually the client username in LDAP/AD used for authentication to the KDC.
+     * 
+     * <br/><br/>Default is <b>"hostbased"</b>.
+     * 
+     * @return the isUsernameServiceNameForm
+     */
+    public boolean isUsernameServiceNameForm() {
+        return isUsernameServiceNameForm;
+    }
+
+    /**
+     * If true - sets the SPN form to "username"
+     * <br/>If false<b>(default)</b> - the SPN form is "hostbased"
+     * 
+     * @see KerberosSecurity#retrieveServiceTicket(String, CallbackHandler, String, boolean)
+     * 
+     * @param isUsernameServiceNameForm the isUsernameServiceNameForm to set
+     */
+    public void setUsernameServiceNameForm(boolean isUsernameServiceNameForm) {
+        this.isUsernameServiceNameForm = isUsernameServiceNameForm;
+    }
 }

Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosClientSecurityToken.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosClientSecurityToken.java?rev=1597101&r1=1597100&r2=1597101&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosClientSecurityToken.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosClientSecurityToken.java Fri May 23 14:27:12 2014
@@ -18,14 +18,13 @@
  */
 package org.apache.wss4j.stax.impl.securityToken;
 
-import org.apache.wss4j.common.ext.WSSecurityException;
-import org.apache.wss4j.common.kerberos.KerberosClientAction;
-import org.apache.wss4j.common.kerberos.KerberosContextAndServiceNameCallback;
-import org.apache.wss4j.common.util.KeyUtils;
-import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
-import org.apache.xml.security.exceptions.XMLSecurityException;
-import org.apache.xml.security.stax.impl.securityToken.GenericOutboundSecurityToken;
+import java.io.IOException;
+import java.security.Key;
+import java.security.Principal;
+import java.security.PrivilegedActionException;
+import java.util.Set;
 
+import javax.crypto.spec.SecretKeySpec;
 import javax.security.auth.Subject;
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
@@ -34,10 +33,15 @@ import javax.security.auth.kerberos.Kerb
 import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
 
-import java.io.IOException;
-import java.security.Key;
-import java.security.Principal;
-import java.util.Set;
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.ext.WSSecurityException.ErrorCode;
+import org.apache.wss4j.common.kerberos.KerberosClientExceptionAction;
+import org.apache.wss4j.common.kerberos.KerberosContext;
+import org.apache.wss4j.common.kerberos.KerberosContextAndServiceNameCallback;
+import org.apache.wss4j.common.util.KeyUtils;
+import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
+import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.stax.impl.securityToken.GenericOutboundSecurityToken;
 
 public class KerberosClientSecurityToken extends GenericOutboundSecurityToken {
 
@@ -50,7 +54,7 @@ public class KerberosClientSecurityToken
         this.ticket = ticket;
         this.secretKey = secretKey;
     }
-    
+
     public KerberosClientSecurityToken(CallbackHandler callbackHandler, String id) {
         super(id, WSSecurityTokenConstants.KerberosToken);
         this.callbackHandler = callbackHandler;
@@ -75,33 +79,43 @@ public class KerberosClientSecurityToken
             Set<Principal> clientPrincipals = clientSubject.getPrincipals();
             if (clientPrincipals.isEmpty()) {
                 throw new WSSecurityException(
-                        WSSecurityException.ErrorCode.FAILURE,
-                        "kerberosLoginError", "No Client principals found after login"
+                    WSSecurityException.ErrorCode.FAILURE,
+                    "kerberosLoginError", "No Client principals found after login"
                 );
             }
             // Store the TGT
             KerberosTicket tgt = getKerberosTicket(clientSubject, null);
 
-            // Get the service ticket
-            KerberosClientAction action =
-                    new KerberosClientAction(
-                            clientPrincipals.iterator().next(), contextAndServiceNameCallback.getServiceName()
+            // Get the service ticket           
+            KerberosClientExceptionAction action = 
+                new KerberosClientExceptionAction(clientPrincipals.iterator().next(),
+                                                  contextAndServiceNameCallback.getServiceName(),
+                                                  contextAndServiceNameCallback.isUsernameServiceNameForm());
+            KerberosContext krbCtx = null;
+            try {
+                krbCtx = (KerberosContext) Subject.doAs(clientSubject, action);
+
+                // Get the secret key from KerberosContext if available, otherwise use Kerberos ticket's session key
+                Key sessionKey = krbCtx.getSecretKey();
+                if (sessionKey != null) {
+                    secretKey = new SecretKeySpec(sessionKey.getEncoded(), sessionKey.getAlgorithm());
+                } else {
+                    KerberosTicket serviceTicket = getKerberosTicket(clientSubject, tgt);
+                    secretKey = serviceTicket.getSessionKey();
+                }
+
+                ticket = krbCtx.getKerberosToken();
+            }
+            catch (PrivilegedActionException e) {
+                Throwable cause = e.getCause();
+                if (cause instanceof WSSecurityException) {
+                    throw (WSSecurityException) cause;
+                } else {
+                    throw new WSSecurityException(
+                         ErrorCode.FAILURE, "kerberosServiceTicketError", new Object[] {}, cause
                     );
-            byte[] ticket = Subject.doAs(clientSubject, action);
-            if (ticket == null) {
-                throw new WSSecurityException(
-                        WSSecurityException.ErrorCode.FAILURE, "kerberosServiceTicketError"
-                );
-            }
-
-            // Get the Service Ticket (private credential)
-            KerberosTicket serviceTicket = getKerberosTicket(clientSubject, tgt);
-            if (serviceTicket != null) {
-                this.secretKey = serviceTicket.getSessionKey();
+                }
             }
-
-            this.ticket = ticket;
-
         } catch (LoginException e) {
             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
         } catch (UnsupportedCallbackException e) {

Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosServiceSecurityTokenImpl.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosServiceSecurityTokenImpl.java?rev=1597101&r1=1597100&r2=1597101&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosServiceSecurityTokenImpl.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosServiceSecurityTokenImpl.java Fri May 23 14:27:12 2014
@@ -19,6 +19,7 @@
 package org.apache.wss4j.stax.impl.securityToken;
 
 import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.ext.WSSecurityException.ErrorCode;
 import org.apache.wss4j.common.kerberos.*;
 import org.apache.wss4j.common.util.KeyUtils;
 import org.apache.wss4j.stax.ext.WSInboundSecurityContext;
@@ -38,6 +39,7 @@ import javax.security.auth.login.LoginEx
 import java.io.IOException;
 import java.security.Key;
 import java.security.Principal;
+import java.security.PrivilegedActionException;
 import java.util.Set;
 
 public class KerberosServiceSecurityTokenImpl extends AbstractInboundSecurityToken implements KerberosServiceSecurityToken {
@@ -92,28 +94,50 @@ public class KerberosServiceSecurityToke
                 Set<Principal> principals = subject.getPrincipals();
                 if (principals.isEmpty()) {
                     throw new WSSecurityException(
-                            WSSecurityException.ErrorCode.FAILURE,
-                            "kerberosLoginError",
-                            "No Client principals found after login"
+                        WSSecurityException.ErrorCode.FAILURE,
+                        "kerberosLoginError",
+                        "No Client principals found after login"
                     );
                 }
                 service = principals.iterator().next().getName();
             }
 
-            // Validate the ticket
-            KerberosServiceAction action = new KerberosServiceAction(binaryContent, service);
-            this.principal = Subject.doAs(subject, action);
-            if (this.principal == null) {
-                throw new WSSecurityException(
-                        WSSecurityException.ErrorCode.FAILURE, "kerberosTicketValidationError"
-                );
+            KerberosServiceExceptionAction action = new KerberosServiceExceptionAction(binaryContent,
+                                                                                       service, 
+                                                                                       contextAndServiceNameCallback.isUsernameServiceNameForm());
+            KerberosServiceContext krbServiceCtx= null;
+            try {
+                krbServiceCtx = Subject.doAs(subject, action);
+            } catch (PrivilegedActionException e) {
+                Throwable cause = e.getCause();
+                if (cause instanceof WSSecurityException) {
+                    throw (WSSecurityException) cause;
+                } else {
+                    throw new WSSecurityException(
+                        ErrorCode.FAILURE, "kerberosTicketValidationError", new Object[] {}, cause
+                    );
+                }
             }
 
-            KerberosTokenDecoder kerberosTokenDecoder = new KerberosTokenDecoderImpl();
-            kerberosTokenDecoder.setToken(binaryContent);
-            kerberosTokenDecoder.setSubject(subject);
-            return kerberosTokenDecoder;
+            this.principal = krbServiceCtx.getPrincipal();
 
+            final Key sessionKey = krbServiceCtx.getSessionKey();
+
+            if (null != sessionKey) {
+                return new KerberosTokenDecoder() {
+                    public void setToken(byte[] token) {}
+                    public void setSubject(Subject subject) {}
+                    public byte[] getSessionKey() throws KerberosTokenDecoderException {
+                        return sessionKey.getEncoded();
+                    }
+                    public void clear() {}
+                };
+            } else {
+                KerberosTokenDecoder kerberosTokenDecoder = new KerberosTokenDecoderImpl();
+                kerberosTokenDecoder.setToken(binaryContent);
+                kerberosTokenDecoder.setSubject(subject);
+                return kerberosTokenDecoder;            	
+            }
         } catch (LoginException e) {
             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
         } catch (UnsupportedCallbackException e) {