use of org.alfresco.repo.security.authentication.ntlm.NTLMPassthruToken in project alfresco-remote-api by Alfresco.
the class BaseNTLMAuthenticationFilter method processType1.
/**
* Process a type 1 NTLM message
*
* @param type1Msg Type1NTLMMessage
* @param req HttpServletRequest
* @param res HttpServletResponse
* @exception IOException
*/
protected void processType1(Type1NTLMMessage type1Msg, HttpServletRequest req, HttpServletResponse res) throws IOException {
if (getLogger().isDebugEnabled())
getLogger().debug("Received type1 " + type1Msg);
// Get the existing NTLM details
NTLMLogonDetails ntlmDetails = null;
HttpSession session = req.getSession();
ntlmDetails = (NTLMLogonDetails) session.getAttribute(NTLM_AUTH_DETAILS);
// Check if cached logon details are available
if (ntlmDetails != null && ntlmDetails.hasType2Message() && ((nltmAuthenticator.getNTLMMode() == NTLMMode.PASS_THROUGH && ntlmDetails.hasAuthenticationToken()) || !ntlmDetails.hasAuthenticationToken())) {
// Get the authentication server type2 response
Type2NTLMMessage cachedType2 = ntlmDetails.getType2Message();
byte[] type2Bytes = cachedType2.getBytes();
String ntlmBlob = "NTLM " + new String(Base64.encodeBase64(type2Bytes));
if (getLogger().isDebugEnabled())
getLogger().debug("Sending cached NTLM type2 to client - " + cachedType2);
// Send back a request for NTLM authentication
res.setHeader(WWW_AUTHENTICATE, ntlmBlob);
res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
res.flushBuffer();
} else {
// Clear any cached logon details
session.removeAttribute(NTLM_AUTH_DETAILS);
// Set the 8 byte challenge for the new logon request
byte[] challenge = null;
NTLMPassthruToken authToken = null;
if (nltmAuthenticator.getNTLMMode() == NTLMMode.MD4_PROVIDER) {
// Generate a random 8 byte challenge
challenge = new byte[8];
DataPacker.putIntelLong(m_random.nextLong(), challenge, 0);
} else {
// Get the client domain
String domain = type1Msg.getDomain();
if (domain == null || domain.length() == 0) {
domain = mapClientAddressToDomain(req.getRemoteAddr());
}
if (getLogger().isDebugEnabled())
getLogger().debug("Client domain " + domain);
// Create an authentication token for the new logon
authToken = new NTLMPassthruToken(domain);
// Run the first stage of the passthru authentication to get the challenge
nltmAuthenticator.authenticate(authToken);
// Get the challenge from the token
if (authToken.getChallenge() != null) {
challenge = authToken.getChallenge().getBytes();
}
}
// Get the flags from the client request and mask out unsupported features
int ntlmFlags = type1Msg.getFlags() & m_ntlmFlags;
// Build a type2 message to send back to the client, containing the challenge
List<TargetInfo> tList = new ArrayList<TargetInfo>();
String srvName = getServerName();
tList.add(new TargetInfo(NTLM.TargetServer, srvName));
Type2NTLMMessage type2Msg = new Type2NTLMMessage();
type2Msg.buildType2(ntlmFlags, srvName, challenge, null, tList);
// Store the NTLM logon details, cache the type2 message, and token if using passthru
ntlmDetails = new NTLMLogonDetails();
ntlmDetails.setType2Message(type2Msg);
ntlmDetails.setAuthenticationToken(authToken);
session.setAttribute(NTLM_AUTH_DETAILS, ntlmDetails);
if (getLogger().isDebugEnabled())
getLogger().debug("Sending NTLM type2 to client - " + type2Msg);
// Send back a request for NTLM authentication
byte[] type2Bytes = type2Msg.getBytes();
String ntlmBlob = "NTLM " + new String(Base64.encodeBase64(type2Bytes));
res.setHeader(WWW_AUTHENTICATE, ntlmBlob);
res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
res.flushBuffer();
}
}
use of org.alfresco.repo.security.authentication.ntlm.NTLMPassthruToken in project alfresco-remote-api by Alfresco.
the class BaseNTLMAuthenticationFilter method processType3.
/**
* Process a type 3 NTLM message
*
* @param type3Msg Type3NTLMMessage
* @param req HttpServletRequest
* @param res HttpServletResponse
*
* @exception IOException
* @exception ServletException
*/
protected boolean processType3(Type3NTLMMessage type3Msg, ServletContext context, HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
Log logger = getLogger();
if (logger.isDebugEnabled())
logger.debug("Received type3 " + type3Msg);
// Get the existing NTLM details
NTLMLogonDetails ntlmDetails = null;
SessionUser user = null;
user = getSessionUser(context, req, res, true);
HttpSession session = req.getSession();
ntlmDetails = (NTLMLogonDetails) session.getAttribute(NTLM_AUTH_DETAILS);
// Get the NTLM logon details
String userName = type3Msg.getUserName();
String workstation = type3Msg.getWorkstation();
String domain = type3Msg.getDomain();
// ALF-10997 fix, normalize the userName
// the system runAs is acceptable because we are resolving a username i.e. it's a system-wide operation that does not need permission checks
final String userName_f = userName;
String normalized = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<String>() {
public String execute() throws Throwable {
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<String>() {
public String doWork() throws Exception {
String normalized = personService.getUserIdentifier(userName_f);
return normalized;
}
}, AuthenticationUtil.SYSTEM_USER_NAME);
}
}, true);
if (normalized != null) {
userName = normalized;
}
boolean authenticated = false;
// Check if we are using cached details for the authentication
if (user != null && ntlmDetails != null && ntlmDetails.hasNTLMHashedPassword()) {
// Check if the received NTLM hashed password matches the cached password
byte[] ntlmPwd = type3Msg.getNTLMHash();
byte[] cachedPwd = ntlmDetails.getNTLMHashedPassword();
if (ntlmPwd != null) {
authenticated = Arrays.equals(cachedPwd, ntlmPwd);
}
if (logger.isDebugEnabled())
logger.debug("Using cached NTLM hash, authenticated = " + authenticated);
onValidate(context, req, res, new NTLMCredentials(userName, ntlmPwd));
// Allow the user to access the requested page
return true;
} else {
WebCredentials credentials;
// Check if we are using local MD4 password hashes or passthru authentication
if (nltmAuthenticator.getNTLMMode() == NTLMMode.MD4_PROVIDER) {
// Check if guest logons are allowed and this is a guest logon
if (m_allowGuest && userName.equalsIgnoreCase(authenticationComponent.getGuestUserName())) {
credentials = new GuestCredentials();
// Indicate that the user has been authenticated
authenticated = true;
if (getLogger().isDebugEnabled())
getLogger().debug("Guest logon");
} else {
// Get the stored MD4 hashed password for the user, or null if the user does not exist
String md4hash = getMD4Hash(userName);
if (md4hash != null) {
authenticated = validateLocalHashedPassword(type3Msg, ntlmDetails, authenticated, md4hash);
credentials = new NTLMCredentials(ntlmDetails.getUserName(), ntlmDetails.getNTLMHashedPassword());
} else {
// Check if unknown users should be logged on as guest
if (m_mapUnknownUserToGuest) {
// Reset the user name to be the guest user
userName = authenticationComponent.getGuestUserName();
authenticated = true;
credentials = new GuestCredentials();
if (logger.isDebugEnabled())
logger.debug("User " + userName + " logged on as guest, no Alfresco account");
} else {
if (logger.isDebugEnabled())
logger.debug("User " + userName + " does not have Alfresco account");
// Bypass NTLM authentication and display the logon screen,
// as user account does not exist in Alfresco
credentials = new UnknownCredentials();
authenticated = false;
}
}
}
} else {
credentials = new NTLMCredentials(type3Msg.getUserName(), type3Msg.getNTLMHash());
// Determine if the client sent us NTLMv1 or NTLMv2
if (type3Msg.hasFlag(NTLM.Flag128Bit) && type3Msg.hasFlag(NTLM.FlagNTLM2Key) || (type3Msg.getNTLMHash() != null && type3Msg.getNTLMHash().length > 24)) {
// Cannot accept NTLMv2 if we are using passthru auth
if (logger.isErrorEnabled())
logger.error("Client " + workstation + " using NTLMv2 logon, not valid with passthru authentication");
} else {
if (ntlmDetails == null) {
if (logger.isWarnEnabled())
logger.warn("Authentication failed: NTLM details can not be retrieved from session. Client must support cookies.");
restartLoginChallenge(context, req, res);
return false;
}
// Passthru mode, send the hashed password details to the passthru authentication server
NTLMPassthruToken authToken = (NTLMPassthruToken) ntlmDetails.getAuthenticationToken();
authToken.setUserAndPassword(type3Msg.getUserName(), type3Msg.getNTLMHash(), PasswordEncryptor.NTLM1);
try {
// Run the second stage of the passthru authentication
nltmAuthenticator.authenticate(authToken);
authenticated = true;
// Check if the user has been logged on as guest
if (authToken.isGuestLogon()) {
userName = authenticationComponent.getGuestUserName();
}
// Set the authentication context
authenticationComponent.setCurrentUser(userName);
} catch (BadCredentialsException ex) {
if (logger.isDebugEnabled())
logger.debug("Authentication failed, " + ex.getMessage());
} catch (AuthenticationException ex) {
if (logger.isDebugEnabled())
logger.debug("Authentication failed, " + ex.getMessage());
} finally {
// Clear the authentication token from the NTLM details
ntlmDetails.setAuthenticationToken(null);
}
}
}
// Check if the user has been authenticated, if so then setup the user environment
if (authenticated == true) {
boolean userInit = false;
if (user == null) {
try {
user = createUserEnvironment(session, userName);
userInit = true;
} catch (AuthenticationException ex) {
if (logger.isDebugEnabled())
logger.debug("Failed to validate user " + userName, ex);
onValidateFailed(context, req, res, session, credentials);
return false;
}
}
onValidate(context, req, res, credentials);
// Update the NTLM logon details in the session
String srvName = getServerName();
if (ntlmDetails == null) {
// No cached NTLM details
ntlmDetails = new NTLMLogonDetails(userName, workstation, domain, false, srvName);
ntlmDetails.setNTLMHashedPassword(type3Msg.getNTLMHash());
session.setAttribute(NTLM_AUTH_DETAILS, ntlmDetails);
if (logger.isDebugEnabled())
logger.debug("No cached NTLM details, created");
} else {
// Update the cached NTLM details
ntlmDetails.setDetails(userName, workstation, domain, false, srvName);
ntlmDetails.setNTLMHashedPassword(type3Msg.getNTLMHash());
if (logger.isDebugEnabled())
logger.debug("Updated cached NTLM details");
}
if (logger.isDebugEnabled())
logger.debug("User logged on via NTLM, " + ntlmDetails);
if (onLoginComplete(context, req, res, userInit)) {
// Allow the user to access the requested page
return true;
}
} else {
restartLoginChallenge(context, req, res);
}
}
return false;
}
Aggregations