/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.web.tomcat.security.jaspi.modules;
import java.io.IOException;
import java.security.Principal;
import javax.security.auth.Subject;
import javax.security.auth.message.AuthException;
import javax.security.auth.message.AuthStatus;
import javax.security.auth.message.MessageInfo;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.Context;
import org.apache.catalina.authenticator.Constants;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.util.Base64;
import org.apache.catalina.util.StringManager;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.CharChunk;
import org.apache.tomcat.util.buf.MessageBytes;
import org.jboss.logging.Logger;
/**
* Server auth module for Basic authentication
* @author Anil.Saldhana@redhat.com
* @since Oct 7, 2008
*/
public class HTTPBasicServerAuthModule extends TomcatServerAuthModule
{
private static Logger log = Logger.getLogger(HTTPBasicServerAuthModule.class);
protected Context context;
protected boolean cache = false;
protected static final StringManager sm =
StringManager.getManager(Constants.Package);
/**
* Authenticate bytes.
*/
public static final byte[] AUTHENTICATE_BYTES = {
(byte) 'W',
(byte) 'W',
(byte) 'W',
(byte) '-',
(byte) 'A',
(byte) 'u',
(byte) 't',
(byte) 'h',
(byte) 'e',
(byte) 'n',
(byte) 't',
(byte) 'i',
(byte) 'c',
(byte) 'a',
(byte) 't',
(byte) 'e'
};
/**
* The number of random bytes to include when generating a
* session identifier.
*/
protected static final int SESSION_ID_BYTES = 16;
protected String delgatingLoginContextName = null;
public HTTPBasicServerAuthModule()
{
}
public HTTPBasicServerAuthModule(String delgatingLoginContextName)
{
super();
this.delgatingLoginContextName = delgatingLoginContextName;
}
public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject)
throws AuthException
{
throw new RuntimeException("Not Applicable");
}
public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject,
Subject serviceSubject) throws AuthException
{
Request request = (Request) messageInfo.getRequestMessage();
Response response = (Response) messageInfo.getResponseMessage();
Principal principal;
context = request.getContext();
LoginConfig config = context.getLoginConfig();
// Validate any credentials already included with this request
String username = null;
String password = null;
MessageBytes authorization =
request.getCoyoteRequest().getMimeHeaders()
.getValue("authorization");
if (authorization != null) {
authorization.toBytes();
ByteChunk authorizationBC = authorization.getByteChunk();
if (authorizationBC.startsWithIgnoreCase("basic ", 0)) {
authorizationBC.setOffset(authorizationBC.getOffset() + 6);
// FIXME: Add trimming
// authorizationBC.trim();
CharChunk authorizationCC = authorization.getCharChunk();
Base64.decode(authorizationBC, authorizationCC);
// Get username and password
int colon = authorizationCC.indexOf(':');
if (colon < 0) {
username = authorizationCC.toString();
} else {
char[] buf = authorizationCC.getBuffer();
username = new String(buf, 0, colon);
password = new String(buf, colon + 1,
authorizationCC.getEnd() - colon - 1);
}
authorizationBC.setOffset(authorizationBC.getOffset() - 6);
}
principal = context.getRealm().authenticate(username, password);
if (principal != null) {
registerWithCallbackHandler(principal, username, password);
/*register(request, response, principal, Constants.BASIC_METHOD,
username, password);*/
return AuthStatus.SUCCESS;
}
}
// Send an "unauthorized" response and an appropriate challenge
MessageBytes authenticate =
response.getCoyoteResponse().getMimeHeaders()
.addValue(AUTHENTICATE_BYTES, 0, AUTHENTICATE_BYTES.length);
CharChunk authenticateCC = authenticate.getCharChunk();
try
{
authenticateCC.append("Basic realm=\"");
if (config.getRealmName() == null) {
authenticateCC.append(request.getServerName());
authenticateCC.append(':');
authenticateCC.append(Integer.toString(request.getServerPort()));
} else {
authenticateCC.append(config.getRealmName());
}
authenticateCC.append('\"');
authenticate.toChars();
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
catch (IOException e)
{
log.error("IOException ", e);
}
//response.flushBuffer();
return AuthStatus.FAILURE;
}
}