Author: markt Date: Tue Mar 29 19:08:43 2011 New Revision: 1086683 URL: http://svn.apache.org/viewvc?rev=1086683&view=rev Log: Part 1 of SPNEGO/Windows authentication support. This adds authentication support but not authorisation. Some Realm refactoring is required to get authorisation working. SPNEGO is tricky to configure correctly. Some things I know will break it, some I suspect might. There is a long list of questions in the Javadoc that need to be tested. This authenticator started off as a patch by Michael Osipov.
Added: tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java (with props) Modified: tomcat/trunk/java/org/apache/catalina/authenticator/Constants.java tomcat/trunk/java/org/apache/catalina/startup/Authenticators.properties tomcat/trunk/java/org/apache/catalina/util/Base64.java tomcat/trunk/webapps/docs/config/valve.xml tomcat/trunk/webapps/docs/windows-auth-howto.xml Modified: tomcat/trunk/java/org/apache/catalina/authenticator/Constants.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/Constants.java?rev=1086683&r1=1086682&r2=1086683&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/Constants.java (original) +++ tomcat/trunk/java/org/apache/catalina/authenticator/Constants.java Tue Mar 29 19:08:43 2011 @@ -24,16 +24,23 @@ public class Constants { public static final String Package = "org.apache.catalina.authenticator"; // Authentication methods for login configuration + // Servlet spec schemes public static final String BASIC_METHOD = "BASIC"; public static final String CERT_METHOD = "CLIENT_CERT"; public static final String DIGEST_METHOD = "DIGEST"; public static final String FORM_METHOD = "FORM"; + // Vendor specific schemes + public static final String SPNEGO_METHOD = "SPNEGO"; // Form based authentication constants public static final String FORM_ACTION = "/j_security_check"; public static final String FORM_PASSWORD = "j_password"; public static final String FORM_USERNAME = "j_username"; + // SPNEGO authentication constants + public static final String DEFAULT_KEYTAB = "conf/tomcat.keytab"; + public static final String DEFAULT_SPN_CLASS = "HTTP"; + // Cookie name for single sign on support public static final String SINGLE_SIGN_ON_COOKIE = System.getProperty( Added: tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java?rev=1086683&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java (added) +++ tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java Tue Mar 29 19:08:43 2011 @@ -0,0 +1,317 @@ +/* + * 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.catalina.authenticator; + +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.security.Principal; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.HashMap; +import java.util.Map; + +import javax.security.auth.Subject; +import javax.security.auth.login.AppConfigurationEntry; +import javax.security.auth.login.Configuration; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; +import javax.servlet.http.HttpServletResponse; + +import org.apache.catalina.LifecycleException; +import org.apache.catalina.connector.Request; +import org.apache.catalina.deploy.LoginConfig; +import org.apache.catalina.realm.GenericPrincipal; +import org.apache.catalina.startup.Bootstrap; +import org.apache.catalina.util.Base64; +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.buf.ByteChunk; +import org.apache.tomcat.util.buf.MessageBytes; +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; + +/** + * A SPNEGO authenticator that uses the SPENGO/Kerberos support built in to Java + * 6. Successful Kerberos authentication depends on the correct configuration of + * multiple components. If the configuration is invalid, the error messages are + * often cryptic although a Google search will usually point you in the right + * direction. + * <p> + * TODO: + * <ul> + * <li>Add support for delegating credentials? Need this if we want to + * authenticate to a realm as the user. This is likely to result in a fair + * amount of internal refactoring.</li> + * </ul> + * <p> + * TBDs: + * <ul> + * <li>Does the domain name have to be in upper case?</li> + * <li>Does the SPN have to start with HTTP/...?</li> + * <li>Can a port number be appended to the end of the host in the SPN?</li> + * <li>Can the domain be left off the user in the ktpass command?</li> + * <li>Can -Djava.security.krb5.conf be used to change the location of krb5.ini? + * </li> + * <li>What are the limitations on the account that Tomcat can run as? SPN + * associated account works, domain admin works, local admin doesn't + * work</li> + * </ul> + */ +public class SpnegoAuthenticator extends AuthenticatorBase { + + private static final Log log = LogFactory.getLog(SpnegoAuthenticator.class); + + protected String serviceKeyTab = Constants.DEFAULT_KEYTAB; + protected String spn = null; + + protected Subject serviceSubject = null; + + + @Override + protected String getAuthMethod() { + return Constants.SPNEGO_METHOD; + } + + + @Override + public String getInfo() { + return "org.apache.catalina.authenticator.SpnegoAuthenticator/1.0"; + } + + + public String getServiceKeyTab() { + return serviceKeyTab; + } + + + public void setServiceKeyTab(String serviceKeyTab) { + this.serviceKeyTab = serviceKeyTab; + } + + + public String getSpn() { + return spn; + } + + + public void setSpn(String spn) { + this.spn = spn; + } + + + @Override + protected void initInternal() throws LifecycleException { + super.initInternal(); + + // Service keytab needs to be an absolute file name + File serviceKeyTabFile = new File(serviceKeyTab); + if (!serviceKeyTabFile.isAbsolute()) { + serviceKeyTabFile = + new File(Bootstrap.getCatalinaBase(), serviceKeyTab); + } + + // SPN is HTTP/hostname + String serviceProvideName; + if (spn == null || spn.length() == 0) { + // Construct default + StringBuilder name = new StringBuilder(Constants.DEFAULT_SPN_CLASS); + name.append('/'); + try { + name.append(InetAddress.getLocalHost().getCanonicalHostName()); + } catch (UnknownHostException e) { + // TODO add a message + throw new LifecycleException(e); + } + serviceProvideName = name.toString(); + } else { + serviceProvideName = spn; + } + + LoginContext lc; + try { + lc = new LoginContext("", null, null, + new JaasConfig(serviceKeyTabFile.getAbsolutePath(), + serviceProvideName, log.isDebugEnabled())); + lc.login(); + serviceSubject = lc.getSubject(); + } catch (LoginException e) { + // TODO add a message + throw new LifecycleException(e); + } + } + + + @Override + public boolean authenticate(Request request, HttpServletResponse response, + LoginConfig config) throws IOException { + + // Have we already authenticated someone? + Principal principal = request.getUserPrincipal(); + String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE); + if (principal != null) { + if (log.isDebugEnabled()) + log.debug("Already authenticated '" + principal.getName() + "'"); + // Associate the session with any existing SSO session + if (ssoId != null) + associate(ssoId, request.getSessionInternal(true)); + return true; + } + + // Is there an SSO session against which we can try to reauthenticate? + if (ssoId != null) { + if (log.isDebugEnabled()) + log.debug("SSO Id " + ssoId + " set; attempting " + + "reauthentication"); + /* Try to reauthenticate using data cached by SSO. If this fails, + either the original SSO logon was of DIGEST or SSL (which + we can't reauthenticate ourselves because there is no + cached username and password), or the realm denied + the user's reauthentication for some reason. + In either case we have to prompt the user for a logon */ + if (reauthenticateFromSSO(ssoId, request)) + return true; + } + + MessageBytes authorization = + request.getCoyoteRequest().getMimeHeaders() + .getValue("authorization"); + + if (authorization != null) { + authorization.toBytes(); + ByteChunk authorizationBC = authorization.getByteChunk(); + if (authorizationBC.startsWithIgnoreCase("negotiate ", 0)) { + authorizationBC.setOffset(authorizationBC.getOffset() + 10); + // FIXME: Add trimming + // authorizationBC.trim(); + + ByteChunk decoded = new ByteChunk(); + Base64.decode(authorizationBC, decoded); + + try { + principal = Subject.doAs(serviceSubject, + new KerberosAuthAction(decoded.getBytes(), response)); + } catch (PrivilegedActionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + if (principal != null) { + register(request, response, principal, Constants.SPNEGO_METHOD, + principal.getName(), null); + return true; + } + } else { + response.setHeader("WWW-Authenticate", "Negotiate"); + } + } else { + response.setHeader("WWW-Authenticate", "Negotiate"); + } + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return false; + } + + + private static class KerberosAuthAction + implements PrivilegedExceptionAction<Principal> { + + private byte[] inToken; + private HttpServletResponse resp; + + public KerberosAuthAction(byte[] inToken, HttpServletResponse resp) { + this.inToken = inToken; + this.resp = resp; + } + + @Override + public Principal run() throws Exception { + + // Assume the GSSContext is stateless + // TODO: Confirm this assumption + GSSContext context = + GSSManager.getInstance().createContext((GSSCredential) null); + + Principal principal = null; + + if (inToken == null) { + throw new IllegalArgumentException("inToken cannot be null"); + } + + byte[] outToken = + context.acceptSecContext(inToken, 0, inToken.length); + + if (outToken == null) { + throw new GSSException(GSSException.DEFECTIVE_TOKEN); + } + + GSSName initiatorName = context.getSrcName(); + + if (context.isEstablished()) { + // TODO This (and a lot of the surrounding code) needs to move + // to RealmBase so authorisation will work. This is just a quick + // hack to get authentication working. + principal = new GenericPrincipal(initiatorName.toString(), null); + } + + // Send response token on success and failure + resp.setHeader("WWW-Authenticate", "Negotiate " + + Base64.encode(outToken)); + + context.dispose(); + return principal; + } + } + + + /** + * Provides the JAAS login configuration required to create + */ + private static class JaasConfig extends Configuration { + + private String keytab; + private String spn; + private boolean debug; + + public JaasConfig(String keytab, String spn, boolean debug) { + this.keytab = keytab; + this.spn = spn; + this.debug = debug; + } + + @Override + public AppConfigurationEntry[] getAppConfigurationEntry(String name) { + Map<String, String> options = new HashMap<String, String>(); + options.put("useKeyTab", "true"); + options.put("keyTab", keytab); + options.put("principal", spn); + options.put("storeKey", "true"); + options.put("doNotPrompt", "true"); + options.put("isInitiator", "false"); + options.put("debug", Boolean.toString(debug)); + + return new AppConfigurationEntry[] { + new AppConfigurationEntry( + "com.sun.security.auth.module.Krb5LoginModule", + AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, + options) }; + } + } +} Propchange: tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/trunk/java/org/apache/catalina/startup/Authenticators.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/Authenticators.properties?rev=1086683&r1=1086682&r2=1086683&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/Authenticators.properties (original) +++ tomcat/trunk/java/org/apache/catalina/startup/Authenticators.properties Tue Mar 29 19:08:43 2011 @@ -18,3 +18,4 @@ CLIENT-CERT=org.apache.catalina.authenti DIGEST=org.apache.catalina.authenticator.DigestAuthenticator FORM=org.apache.catalina.authenticator.FormAuthenticator NONE=org.apache.catalina.authenticator.NonLoginAuthenticator +SPNEGO=org.apache.catalina.authenticator.SpnegoAuthenticator \ No newline at end of file Modified: tomcat/trunk/java/org/apache/catalina/util/Base64.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/util/Base64.java?rev=1086683&r1=1086682&r2=1086683&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/util/Base64.java (original) +++ tomcat/trunk/java/org/apache/catalina/util/Base64.java Tue Mar 29 19:08:43 2011 @@ -290,4 +290,85 @@ public final class Base64 } + /** + * Decodes Base64 data into octets + * + * @param base64DataBC Byte array containing Base64 data + * @param decodedDataBC The decoded data bytes + */ + public static void decode( ByteChunk base64DataBC, ByteChunk decodedDataBC) + { + int start = base64DataBC.getStart(); + int end = base64DataBC.getEnd(); + byte[] base64Data = base64DataBC.getBuffer(); + + decodedDataBC.recycle(); + + // handle the edge case, so we don't have to worry about it later + if(end - start == 0) { return; } + + int numberQuadruple = (end - start)/FOURBYTE; + byte b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0; + + // Throw away anything not in base64Data + + int encodedIndex = 0; + int dataIndex = start; + byte[] decodedData = null; + + { + // this sizes the output array properly - rlw + int lastData = end - start; + // ignore the '=' padding + while (base64Data[start+lastData-1] == PAD) + { + if (--lastData == 0) + { + return; + } + } + decodedDataBC.allocate(lastData - numberQuadruple, -1); + decodedDataBC.setEnd(lastData - numberQuadruple); + decodedData = decodedDataBC.getBuffer(); + } + + for (int i = 0; i < numberQuadruple; i++) + { + dataIndex = start + i * 4; + marker0 = base64Data[dataIndex + 2]; + marker1 = base64Data[dataIndex + 3]; + + b1 = base64Alphabet[base64Data[dataIndex]]; + b2 = base64Alphabet[base64Data[dataIndex +1]]; + + if (marker0 != PAD && marker1 != PAD) + { + //No PAD e.g 3cQl + b3 = base64Alphabet[ marker0 ]; + b4 = base64Alphabet[ marker1 ]; + + decodedData[encodedIndex] = (byte) (( b1 <<2 | b2>>4 ) & 0xff); + decodedData[encodedIndex + 1] = + (byte) ((((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ) & 0xff); + decodedData[encodedIndex + 2] = (byte) (( b3<<6 | b4 ) & 0xff); + } + else if (marker0 == PAD) + { + //Two PAD e.g. 3c[Pad][Pad] + decodedData[encodedIndex] = (byte) (( b1 <<2 | b2>>4 ) & 0xff); + } + else if (marker1 == PAD) + { + //One PAD e.g. 3cQ[Pad] + b3 = base64Alphabet[ marker0 ]; + + decodedData[encodedIndex] = (byte) (( b1 <<2 | b2>>4 ) & 0xff); + decodedData[encodedIndex + 1] = + (byte) ((((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ) & 0xff); + } + encodedIndex += 3; + } + } + + } Modified: tomcat/trunk/webapps/docs/config/valve.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/valve.xml?rev=1086683&r1=1086682&r2=1086683&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/config/valve.xml (original) +++ tomcat/trunk/webapps/docs/config/valve.xml Tue Mar 29 19:08:43 2011 @@ -799,6 +799,115 @@ </section> +<section name="SPNEGO Valve"> + + <subsection name="Introduction"> + + <p>The <strong>SPNEGO Authenticator Valve</strong> is automatically added to + any <a href="context.html">Context</a> that is configured to use SPNEGO + authentication.</p> + + <p>If any non-default settings are required, the valve may be configured + within <a href="context.html">Context</a> element with the required + values.</p> + + </subsection> + + <subsection name="Attributes"> + + <p>The <strong>SPNEGO Authenticator Valve</strong> supports the following + configuration attributes:</p> + + <attributes> + + <attribute name="cache" required="false"> + <p>Should we cache authenticated Principals if the request is part of an + HTTP session? If not specified, the default value of <code>true</code> + will be used.</p> + </attribute> + + <attribute name="className" required="true"> + <p>Java class name of the implementation to use. This MUST be set to + <strong>org.apache.catalina.authenticator.SpnegoAuthenticator</strong>. + </p> + </attribute> + + <attribute name="changeSessionIdOnAuthentication" required="false"> + <p>Controls if the session ID is changed if a session exists at the + point where users are authenticated. This is to prevent session fixation + attacks. If not set, the default value of <code>true</code> will be + used.</p> + </attribute> + + <attribute name="disableProxyCaching" required="false"> + <p>Controls the caching of pages that are protected by security + constraints. Setting this to <code>false</code> may help work around + caching issues in some browsers but will also cause secured pages to be + cached by proxies which will almost certainly be a security issue. + <code>securePagesWithPragma</code> offers an alternative, secure, + workaround for browser caching issues. If not set, the default value of + <code>true</code> will be used.</p> + </attribute> + + <attribute name="securePagesWithPragma" required="false"> + <p>Controls the caching of pages that are protected by security + constraints. Setting this to <code>false</code> may help work around + caching issues in some browsers by using + <code>Cache-Control: private</code> rather than the default of + <code>Pragma: No-cache</code> and <code>Cache-control: No-cache</code>. + If not set, the default value of <code>true</code> will be used.</p> + </attribute> + + <attribute name="secureRandomAlgorithm" required="false"> + <p>Name of the algorithm to use to create the + <code>java.security.SecureRandom</code> instances that generate session + IDs. If an invalid algorithm and/or provider is specified, the platform + default provider and the default algorithm will be used. If not + specified, the default algorithm of SHA1PRNG will be used. If the + default algorithm is not supported, the platform default will be used. + To specify that the platform default should be used, do not set the + secureRandomProvider attribute and set this attribute to the empty + string.</p> + </attribute> + + <attribute name="secureRandomClass" required="false"> + <p>Name of the Java class that extends + <code>java.security.SecureRandom</code> to use to generate SSO session + IDs. If not specified, the default value is + <code>java.security.SecureRandom</code>.</p> + </attribute> + + <attribute name="secureRandomProvider" required="false"> + <p>Name of the provider to use to create the + <code>java.security.SecureRandom</code> instances that generate SSO + session IDs. If an invalid algorithm and/or provider is specified, the + platform default provider and the default algorithm will be used. If not + specified, the platform default provider will be used.</p> + </attribute> + + <attribute name="serviceKeyTab" required="false"> + <p>Name of the Kerberos keytab file that contains the private key for + the service principal. The name of the service principal must match the + spn attribute. Relative file names are relative to + <code>$CATALINA_BASE</code>. If not specified, the default value of + <code>conf/tomcat.keytab</code> is used.</p> + </attribute> + + <attribute name="spn" required="false"> + <p>Service Principal Name (SPN) for this server. It must match the SPN + associated with the key in the serviceKetTab file. If not specified, the + default value of <code>HTTP/<hostname></code> where + <code><hostname></code> is obtained using + <code>InetAddress.getLocalHost().getCanonicalHostName()</code>.</p> + </attribute> + + </attributes> + + </subsection> + +</section> + + <section name="Remote IP Valve"> <subsection name="Introduction"> Modified: tomcat/trunk/webapps/docs/windows-auth-howto.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/windows-auth-howto.xml?rev=1086683&r1=1086682&r2=1086683&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/windows-auth-howto.xml (original) +++ tomcat/trunk/webapps/docs/windows-auth-howto.xml Tue Mar 29 19:08:43 2011 @@ -52,7 +52,8 @@ sections.</p> <section name="Built-in Tomcat support"> <p><strong>This is a work in progress. This warning should be removed once the -end-to-end testing is complete</strong></p> +various questions and TODOs (see the Javadoc and implementation class) have been +resolved.</strong></p> <p>There are four components to the configuration of the built-in Tomcat support for Windows authentication. The domain controller, the server hosting Tomcat, the web application wishing to use Windows authentication and the client @@ -60,8 +61,8 @@ machine. The following sections describe component.</p> <p>The names of the three machines used in the configuration examples below are win-dc01.dev.local (the domain controller), win-tc01.dev.local (the Tomcat -instance) and win-pc01.dev.local (client). The Tomcat server and the client are -both members of the domain.</p> +instance) and win-pc01.dev.local (client). All are members of the DEV.LOCAL +domain.</p> <p>Note: In order to use the passwords in the steps below, the domain password policy had to be relaxed. This is not recommended for production environments. </p> @@ -86,9 +87,9 @@ policy had to be relaxed. This is not re itself to the domain controller. This file contains the Tomcat private key for the service provider account and should be protected accordingly. To generate the file, run the following command (all on a single line): - <source>ktpass /out c:\tc01.keytab /mapuser tc01@DEV.LOCAL + <source>ktpass /out c:\tomcat.keytab /mapuser tc01@DEV.LOCAL /princ HTTP/win-tc01.dev.local@DEV.LOCAL - +andPass /kvno 0</source></li> + /pass tc01pass /kvno 0</source></li> <li>Create a domain user to be used on the client. In this how-to the domain user is <code>test</code> with a password of <code>testpass</code>.</li> </ul> @@ -100,15 +101,69 @@ policy had to be relaxed. This is not re </subsection> <subsection name="Tomcat instance"> - <p>TBD</p> + <p>These steps assume that Tomcat and a Java 6 JDK/JRE have already been + installed and configured and that Tomcat is running as the tc01@DEV.LOCAL + user. The steps to configure the Tomcat instance for Windows authentication + are as follows: + <li>Copy the <code>tomcat.keytab</code> file created on the domain controller + to <code>$CATALINA_BASE/conf</code>.</li> + <li>Create the kerberos configuration file + <code>C:\Windows\krb5.ini</code>. The file used in this how-to + contained:<source>[libdefaults] +default_realm = DEV.LOCAL +default_keytab_name = FILE:c:\apache-tomcat-7.0.x\conf\tomcat.keytab +default_tkt_enctypes = rc4-hmac,aes256-cts-hmac-sha1-96,aes128-cts-hmac-sha1-96 +default_tgs_enctypes = rc4-hmac,aes256-cts-hmac-sha1-96,aes128-cts-hmac-sha1-96 +forwardable=true + +[realms] +DEV.LOCAL = { + kdc = win-dc01.dev.local:88 +} + +[domain_realm] +dev.local= DEV.LOCAL +.dev.local= DEV.LOCAL</source></li> + </p> + <p>The above steps have been tested on a Tomcat server running Windows Server + 2008 R2 64-bit Standard with an Oracle 1.6.0_24 64-bit JDK.</p> + </subsection> + + <subsection name="Web application"> + <p>The web application needs to be configured to the use Tomcat specific + authentication method of <code>SPNEGO</code> (rather than BASIC etc.) in + web.xml. As with the other authenticators, behaviour can be customised by + explicitly configuring the <a href="config/valve.html#SPNEGO_Valve"> + authentication valve</a> and setting attributes on the Valve.</p> </subsection> - <subsection name="Wep application"> - <p>TBD</p> + <subsection name="Client"> + <p>The client must be configured to use Kerberos authentication. For Internet + Explorer this means making sure that the Tomcat instance is in the "Local + intranet" security domain and that it is configured (Tools > Internet + Options > Advanced) with integrated Windows authentication enabled. Note that + this <strong>will not</strong> work if you use the same machine for the client + and the Tomcat instance as Internet Explorer will use the unsupported NTLM + protocol.</p> </subsection> - <subsection name="Client"> - <p>TBD</p> + <subsection name="References"> + <p>Correctly configuring Kerberos authentication can be tricky. The following + references may prove helpful. Advice is also always available from the + <a href="http://tomcat.apache.org/lists.html#tomcat-users">Tomcat users + mailing list</a>. + <ol> + <li><a href="http://www.adopenstatic.com/cs/blogs/ken/archive/2006/10/19/512.aspx"> + IIS and Kerberos</a></li> + <li><a href="http://blog.springsource.com/2009/09/28/spring-security-kerberos/"> + Spring Security Kerberos extension</a></li> + <li><a href="https://cwiki.apache.org/GMOxDOC21/using-spengo-in-geronimo.html#UsingSpengoingeronimo-SettinguptheActiveDirectoryDomainController"> + Geronimo configuration for Windows authentication</a></li> + <li><a href="http://blogs.msdn.com/b/openspecification/archive/2010/11/17/encryption-type-selection-in-kerberos-exchanges.aspx"> + Encryption Selection in Kerberos Exchanges</a></li> + <li><a href="http://support.microsoft.com/kb/977321">Supported Kerberos Cipher + Suites</a></li> + </ol></p> </subsection> </section> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org