Merged V4.0-BUG-FIX to HEAD

37586: ALF-14309: Cannot run project using Alfresco SDK
      - sdk-common target now depends on sdk-extras target
   37604: Merged V3.4-BUG-FIX to V4.0-BUG-FIX
      37573: Merged DEV to V3.4-BUG-FIX (with improvements)
         37547: ALF-13621: Encoding issue in passwords for webscript and webdav authentication
            Validation of BASIC username, password using following encoding in a sequence, ignoring duplicate decodings
            1. UTF-8 (skip if fails to decode) 
            2. System.getProperty("file.encoding") (platform default encoding) 
            3. ISO-8859-1
            It succeeds if one of them succeeds.
      37591: ALF-14457: Merged PATCHES/V3.4.8 to V3.4-BUG-FIX
         37288: ALF-14315: Localname is too long when upgrading from 3.1 to 3.4.8 or 3.4.9
         - Truncate migrated group names within QName.MAX_LENGTH whilst maintaining uniqueness
         37392: ALF-14315: Localname is too long when upgrading from 3.1 to 3.4.8 or 3.4.9
         - Prevent NPE when re-parenting exising users
      37593: (RECORD ONLY) Incremented version revision for 3.4.11
      37599: Make this class compile so I can import all projects into Eclipse!
      37601: ALF-14462: Stop Kerberos authentication from barfing when it comes across a NegoEx SPNEGO request from Windows 7 / 2008
         http://blogs.msdn.com/b/openspecification/archive/2011/07/01/a-quick-look-at-the-new-negotiation-mechanism-negoex-used-with-spnego-in-windows-7.aspx
      37602: ALF-10785: Locale not forwarded in webscripts when using Kerberos SSO
      - Previous solution didn't work when failover manual login form was used (as Accept-Language header wasn't always sent by all Surf machinery) and would also mean Share wasn't responsive to browser locale changes, unlike when using the /s endpoint.
      - Now we use a more foolproof solution on the /wcs endpoint
      - Session initiation (as detected by an authentication filter) sets an attribute that decides whether a session 'sticky' locale should be used for the rest of the session
      - It's set to false if a webscript is the first to access it or the session was established by a ticket. This means the Accept-Language header will drive the rest of the session.
      - This also means Explorer can still control the locale of a session initiated by it
      - Glad to see the back of this long-running bug. The good news is I now have a Kerberos EC2 image!
      37603: ALF-14462: Fixed same potential NegoEx problem in Share SSOAuthenticationFilter (although not observed)
   37605: Merged V3.4-BUG-FIX to V4.0-BUG-FIX (RECORD ONLY)
      37590: Merged V4.0-BUG-FIX to V3.4-BUG-FIX
         37586: ALF-14309: Cannot run project using Alfresco SDK


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@37606 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Dave Ward
2012-06-10 18:14:54 +00:00
parent f8de3d92e0
commit 4e954020b1
2 changed files with 96 additions and 34 deletions

View File

@@ -20,6 +20,15 @@
package org.alfresco.repo.webdav.auth;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.servlet.FilterChain;
import javax.servlet.ServletContext;
@@ -52,6 +61,31 @@ public class AuthenticationFilter extends BaseAuthenticationFilter implements De
private static final String PPT_EXTN = ".ppt";
/** The password encodings to try in priority order **/
private static final String[] ENCODINGS = new String[] {
"UTF-8",
System.getProperty("file.encoding"),
"ISO-8859-1"
};
/** Corresponding array of CharsetDecoders with CodingErrorAction.REPORT. Duplicates removed. */
private static final CharsetDecoder[] DECODERS;
static
{
Map<String, CharsetDecoder> decoders = new LinkedHashMap<String, CharsetDecoder>(ENCODINGS.length * 2);
for (String encoding : ENCODINGS)
{
if (!decoders.containsKey(encoding))
{
decoders.put(encoding, Charset.forName(encoding).newDecoder()
.onMalformedInput(CodingErrorAction.REPORT));
}
}
DECODERS = new CharsetDecoder[decoders.size()];
decoders.values().toArray(DECODERS);
}
// Various services required by NTLM authenticator
/**
@@ -84,41 +118,58 @@ public class AuthenticationFilter extends BaseAuthenticationFilter implements De
if ( authHdr != null && authHdr.length() > 5 && authHdr.substring(0,5).equalsIgnoreCase("BASIC"))
{
// Basic authentication details present
String basicAuth = new String(Base64.decodeBase64(authHdr.substring(5).getBytes()));
byte[] encodedString = Base64.decodeBase64(authHdr.substring(5).getBytes());
// Split the username and password
String username = null;
String password = null;
int pos = basicAuth.indexOf(":");
if ( pos != -1)
{
username = basicAuth.substring(0, pos);
password = basicAuth.substring(pos + 1);
}
else
{
username = basicAuth;
password = "";
}
try
{
// Authenticate the user
authenticationService.authenticate(username, password.toCharArray());
user = createUserEnvironment(httpReq.getSession(), authenticationService.getCurrentUserName(), authenticationService.getCurrentTicket(), false);
}
catch ( AuthenticationException ex)
{
// Do nothing, user object will be null
}
catch (NoSuchPersonException e)
{
// Do nothing, user object will be null
// ALF-13621: Due to browser inconsistencies we have to try a fallback path of encodings
Set<String> attemptedAuths = new HashSet<String>(DECODERS.length * 2);
for (CharsetDecoder decoder : DECODERS)
{
try
{
// Attempt to decode using this charset
String basicAuth = decoder.decode(ByteBuffer.wrap(encodedString)).toString();
// It decoded OK but we may already have tried this string.
if (!attemptedAuths.add(basicAuth))
{
// Already tried - no need to try again
continue;
}
String username;
String password;
// Split the username and password
int pos = basicAuth.indexOf(":");
if (pos != -1)
{
username = basicAuth.substring(0, pos);
password = basicAuth.substring(pos + 1);
}
else
{
username = basicAuth;
password = "";
}
// Authenticate the user
authenticationService.authenticate(username, password.toCharArray());
user = createUserEnvironment(httpReq.getSession(), authenticationService.getCurrentUserName(), authenticationService.getCurrentTicket(), false);
// Success so break out
break;
}
catch (CharacterCodingException e)
{
// Didn't decode using this charset. Try the next one or fail
}
catch (AuthenticationException ex)
{
// Do nothing, user object will be null
}
catch (NoSuchPersonException e)
{
// Do nothing, user object will be null
}
}
}
else

View File

@@ -418,6 +418,17 @@ public abstract class BaseKerberosAuthenticationFilter extends BaseSSOAuthentica
return false;
}
}
else
{
// Unsupported mechanism, e.g. NegoEx
if ( getLogger().isDebugEnabled())
getLogger().debug( "Unsupported SPNEGO mechanism " + oidStr);
// Try again!
restartLoginChallenge(context, req, resp);
}
}
catch ( IOException ex)
{