001: /*
002: * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/BasicAuthenticator.java,v 1.12 2002/03/23 17:52:16 remm Exp $
003: * $Revision: 1.12 $
004: * $Date: 2002/03/23 17:52:16 $
005: *
006: * ====================================================================
007: *
008: * The Apache Software License, Version 1.1
009: *
010: * Copyright (c) 1999 The Apache Software Foundation. All rights
011: * reserved.
012: *
013: * Redistribution and use in source and binary forms, with or without
014: * modification, are permitted provided that the following conditions
015: * are met:
016: *
017: * 1. Redistributions of source code must retain the above copyright
018: * notice, this list of conditions and the following disclaimer.
019: *
020: * 2. Redistributions in binary form must reproduce the above copyright
021: * notice, this list of conditions and the following disclaimer in
022: * the documentation and/or other materials provided with the
023: * distribution.
024: *
025: * 3. The end-user documentation included with the redistribution, if
026: * any, must include the following acknowlegement:
027: * "This product includes software developed by the
028: * Apache Software Foundation (http://www.apache.org/)."
029: * Alternately, this acknowlegement may appear in the software itself,
030: * if and wherever such third-party acknowlegements normally appear.
031: *
032: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
033: * Foundation" must not be used to endorse or promote products derived
034: * from this software without prior written permission. For written
035: * permission, please contact apache@apache.org.
036: *
037: * 5. Products derived from this software may not be called "Apache"
038: * nor may "Apache" appear in their names without prior written
039: * permission of the Apache Group.
040: *
041: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
042: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
043: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
044: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
045: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
046: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
047: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
048: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
049: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
050: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
051: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
052: * SUCH DAMAGE.
053: * ====================================================================
054: *
055: * This software consists of voluntary contributions made by many
056: * individuals on behalf of the Apache Software Foundation. For more
057: * information on the Apache Software Foundation, please see
058: * <http://www.apache.org/>.
059: *
060: * [Additional notices, if required by prior licensing conditions]
061: *
062: */
063:
064: package org.apache.catalina.authenticator;
065:
066: import java.io.IOException;
067: import java.security.Principal;
068: import javax.servlet.http.HttpServletRequest;
069: import javax.servlet.http.HttpServletResponse;
070: import org.apache.catalina.HttpRequest;
071: import org.apache.catalina.HttpResponse;
072: import org.apache.catalina.Realm;
073: import org.apache.catalina.Session;
074: import org.apache.catalina.deploy.LoginConfig;
075: import org.apache.catalina.util.Base64;
076:
077: /**
078: * An <b>Authenticator</b> and <b>Valve</b> implementation of HTTP BASIC
079: * Authentication, as outlined in RFC 2617: "HTTP Authentication: Basic
080: * and Digest Access Authentication."
081: *
082: * @author Craig R. McClanahan
083: * @version $Revision: 1.12 $ $Date: 2002/03/23 17:52:16 $
084: */
085:
086: public class BasicAuthenticator extends AuthenticatorBase {
087:
088: // ----------------------------------------------------- Instance Variables
089:
090: /**
091: * The Base64 helper object for this class.
092: */
093: protected static final Base64 base64Helper = new Base64();
094:
095: /**
096: * Descriptive information about this implementation.
097: */
098: protected static final String info = "org.apache.catalina.authenticator.BasicAuthenticator/1.0";
099:
100: // ------------------------------------------------------------- Properties
101:
102: /**
103: * Return descriptive information about this Valve implementation.
104: */
105: public String getInfo() {
106:
107: return (this .info);
108:
109: }
110:
111: // --------------------------------------------------------- Public Methods
112:
113: /**
114: * Authenticate the user making this request, based on the specified
115: * login configuration. Return <code>true</code> if any specified
116: * constraint has been satisfied, or <code>false</code> if we have
117: * created a response challenge already.
118: *
119: * @param request Request we are processing
120: * @param response Response we are creating
121: * @param login Login configuration describing how authentication
122: * should be performed
123: *
124: * @exception IOException if an input/output error occurs
125: */
126: public boolean authenticate(HttpRequest request,
127: HttpResponse response, LoginConfig config)
128: throws IOException {
129:
130: // Have we already authenticated someone?
131: Principal principal = ((HttpServletRequest) request
132: .getRequest()).getUserPrincipal();
133: if (principal != null) {
134: if (debug >= 1)
135: log("Already authenticated '" + principal.getName()
136: + "'");
137: return (true);
138: }
139:
140: // Validate any credentials already included with this request
141: HttpServletRequest hreq = (HttpServletRequest) request
142: .getRequest();
143: HttpServletResponse hres = (HttpServletResponse) response
144: .getResponse();
145: String authorization = request.getAuthorization();
146: String username = parseUsername(authorization);
147: String password = parsePassword(authorization);
148: principal = context.getRealm().authenticate(username, password);
149: if (principal != null) {
150: register(request, response, principal,
151: Constants.BASIC_METHOD, username, password);
152: return (true);
153: }
154:
155: // Send an "unauthorized" response and an appropriate challenge
156: String realmName = config.getRealmName();
157: if (realmName == null)
158: realmName = hreq.getServerName() + ":"
159: + hreq.getServerPort();
160: // if (debug >= 1)
161: // log("Challenging for realm '" + realmName + "'");
162: hres.setHeader("WWW-Authenticate", "Basic realm=\"" + realmName
163: + "\"");
164: hres.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
165: // hres.flushBuffer();
166: return (false);
167:
168: }
169:
170: // ------------------------------------------------------ Protected Methods
171:
172: /**
173: * Parse the username from the specified authorization credentials.
174: * If none can be found, return <code>null</code>.
175: *
176: * @param authorization Authorization credentials from this request
177: */
178: protected String parseUsername(String authorization) {
179:
180: if (authorization == null)
181: return (null);
182: if (!authorization.toLowerCase().startsWith("basic "))
183: return (null);
184: authorization = authorization.substring(6).trim();
185:
186: // Decode and parse the authorization credentials
187: String unencoded = new String(base64Helper.decode(authorization
188: .getBytes()));
189: int colon = unencoded.indexOf(':');
190: if (colon < 0)
191: return (null);
192: String username = unencoded.substring(0, colon).trim();
193: // String password = unencoded.substring(colon + 1).trim();
194: return (username);
195:
196: }
197:
198: /**
199: * Parse the password from the specified authorization credentials.
200: * If none can be found, return <code>null</code>.
201: *
202: * @param authorization Authorization credentials from this request
203: */
204: protected String parsePassword(String authorization) {
205:
206: if (authorization == null)
207: return (null);
208: if (!authorization.startsWith("Basic "))
209: return (null);
210: authorization = authorization.substring(6).trim();
211:
212: // Decode and parse the authorization credentials
213: String unencoded = new String(base64Helper.decode(authorization
214: .getBytes()));
215: int colon = unencoded.indexOf(':');
216: if (colon < 0)
217: return (null);
218: // String username = unencoded.substring(0, colon).trim();
219: String password = unencoded.substring(colon + 1).trim();
220: return (password);
221:
222: }
223:
224: }
|