/*
* Copyright (c) 2013, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. 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.wso2.carbon.identity.oauth2.token.handlers.grant.iwa.ntlm;
import com.sun.jna.platform.win32.Sspi;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.identity.base.IdentityConstants;
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.identity.oauth2.token.handlers.grant.AbstractAuthorizationGrantHandler;
import org.wso2.carbon.identity.oauth2.token.handlers.grant.iwa.ntlm.util.SimpleFilterChain;
import org.wso2.carbon.identity.oauth2.token.handlers.grant.iwa.ntlm.util.SimpleHttpRequest;
import org.wso2.carbon.identity.oauth2.token.handlers.grant.iwa.ntlm.util.SimpleHttpResponse;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import waffle.servlet.NegotiateSecurityFilter;
import waffle.util.Base64;
import waffle.windows.auth.IWindowsCredentialsHandle;
import waffle.windows.auth.impl.WindowsAccountImpl;
import waffle.windows.auth.impl.WindowsAuthProviderImpl;
import waffle.windows.auth.impl.WindowsCredentialsHandleImpl;
import waffle.windows.auth.impl.WindowsSecurityContextImpl;
import javax.security.auth.Subject;
import javax.servlet.ServletException;
import java.io.IOException;
public class NTLMAuthenticationGrantHandler extends AbstractAuthorizationGrantHandler {
private static Log log = LogFactory.getLog(NTLMAuthenticationGrantHandler.class);
String securityPackage = "Negotiate";
@Override
public boolean validateGrant(OAuthTokenReqMessageContext tokReqMsgCtx) throws IdentityOAuth2Exception {
if(!super.validateGrant(tokReqMsgCtx)){
return false;
}
NegotiateSecurityFilter filter;
filter = new NegotiateSecurityFilter();
filter.setAuth(new WindowsAuthProviderImpl());
try {
filter.init(null);
} catch (ServletException e) {
log.error("Error while initializing Negotiate Security Filter", e);
throw new IdentityOAuth2Exception("Error while initializing Negotiate Security Filter", e);
}
String token = tokReqMsgCtx.getOauth2AccessTokenReqDTO().getWindowsToken();
boolean authenticated;
IWindowsCredentialsHandle clientCredentials;
WindowsSecurityContextImpl clientContext;
filter.setRoleFormat("both");
if (token != null) {
// Logging the windows authentication object
if (log.isDebugEnabled() && IdentityUtil.isTokenLoggable(IdentityConstants.IdentityTokens.NTLM_TOKEN)) {
log.debug("Received NTLM Token : " +
tokReqMsgCtx.getOauth2AccessTokenReqDTO().getWindowsToken()
);
}
// client credentials handle
clientCredentials = WindowsCredentialsHandleImpl.getCurrent(securityPackage);
clientCredentials.initialize();
// initial client security context
clientContext = new WindowsSecurityContextImpl();
clientContext.setPrincipalName(WindowsAccountImpl.getCurrentUsername());
clientContext.setCredentialsHandle(clientCredentials.getHandle());
clientContext.setSecurityPackage(securityPackage);
clientContext.initialize(null, null, WindowsAccountImpl.getCurrentUsername());
SimpleHttpRequest request = new SimpleHttpRequest();
SimpleFilterChain filterChain = new SimpleFilterChain();
while (true) {
try {
request.addHeader("Authorization", securityPackage + " " + token);
SimpleHttpResponse response = new SimpleHttpResponse();
try {
filter.doFilter(request, response, filterChain);
} catch (IOException e) {
log.error("You have been given wrong inputs to negotiate filter", e);
throw new IdentityOAuth2Exception("Error while processing negotiate the filter.", e);
}
Subject subject = (Subject) request.getSession().getAttribute("javax.security.auth.subject");
authenticated = (subject != null && subject.getPrincipals().size() > 0);
if (authenticated) {
if (log.isDebugEnabled()) {
log.debug("NTLM token is authenticated");
}
String resourceOwnerUserNameWithDomain = WindowsAccountImpl.getCurrentUsername();
String resourceOwnerUserName = resourceOwnerUserNameWithDomain.split("\\\\")[1];
tokReqMsgCtx.setAuthorizedUser(OAuth2Util.getUserFromUserName(resourceOwnerUserName));
break;
}
String continueToken = response.getHeader("WWW-Authenticate").
substring(securityPackage.length() + 1);
byte[] continueTokenBytes = Base64.decode(continueToken);
Sspi.SecBufferDesc continueTokenBuffer = new Sspi.
SecBufferDesc(Sspi.SECBUFFER_TOKEN, continueTokenBytes);
clientContext.initialize(clientContext.getHandle(), continueTokenBuffer, "localhost");
token = Base64.encode(clientContext.getToken());
} catch (Exception e) {
log.error("Error while validating the NTLM authentication grant", e);
throw new IdentityOAuth2Exception("Error while validating the NTLM authentication grant", e);
}
}
} else {
if (log.isDebugEnabled()) {
log.debug("NTLM token is null");
}
throw new IdentityOAuth2Exception("NTLM token is null");
}
return authenticated;
}
}