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) {