1 /* 2 * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/test/org/apache/commons/httpclient/server/ProxyAuthRequestHandler.java,v 1.12 2004/11/28 15:44:39 olegk Exp $ 3 * $Revision: 480424 $ 4 * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $ 5 * 6 * ==================================================================== 7 * 8 * Licensed to the Apache Software Foundation (ASF) under one or more 9 * contributor license agreements. See the NOTICE file distributed with 10 * this work for additional information regarding copyright ownership. 11 * The ASF licenses this file to You under the Apache License, Version 2.0 12 * (the "License"); you may not use this file except in compliance with 13 * the License. You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 * ==================================================================== 23 * 24 * This software consists of voluntary contributions made by many 25 * individuals on behalf of the Apache Software Foundation. For more 26 * information on the Apache Software Foundation, please see 27 * <http://www.apache.org/>. 28 * 29 */ 30 31 package org.apache.commons.httpclient.server; 32 33 import java.io.IOException; 34 35 import org.apache.commons.httpclient.Credentials; 36 import org.apache.commons.httpclient.Header; 37 import org.apache.commons.httpclient.HttpStatus; 38 import org.apache.commons.httpclient.UsernamePasswordCredentials; 39 import org.apache.commons.httpclient.auth.BasicScheme; 40 41 /** 42 * This request handler guards access to a proxy when used in a request handler 43 * chain. It checks the headers for valid credentials and performs the 44 * authentication handshake if necessary. 45 * 46 * @author Ortwin Glueck 47 * @author Oleg Kalnichevski 48 */ 49 public class ProxyAuthRequestHandler implements HttpRequestHandler { 50 51 private Credentials credentials = null; 52 private String realm = null; 53 private boolean keepalive = true; 54 55 /** 56 * The proxy authenticate response header. 57 */ 58 public static final String PROXY_AUTH_RESP = "Proxy-Authorization"; 59 60 /** 61 * TODO replace creds parameter with a class specific to an auth scheme 62 * encapsulating all required information for a specific scheme 63 * 64 * @param creds 65 */ ProxyAuthRequestHandler(final Credentials creds, final String realm, boolean keepalive)66 public ProxyAuthRequestHandler(final Credentials creds, final String realm, boolean keepalive) { 67 if (creds == null) 68 throw new IllegalArgumentException("Credentials may not be null"); 69 this.credentials = creds; 70 this.keepalive = keepalive; 71 if (realm != null) { 72 this.realm = realm; 73 } else { 74 this.realm = "test"; 75 } 76 } 77 ProxyAuthRequestHandler(final Credentials creds, final String realm)78 public ProxyAuthRequestHandler(final Credentials creds, final String realm) { 79 this(creds, realm, true); 80 } 81 ProxyAuthRequestHandler(final Credentials creds)82 public ProxyAuthRequestHandler(final Credentials creds) { 83 this(creds, null, true); 84 } 85 processRequest( final SimpleHttpServerConnection conn, final SimpleRequest request)86 public boolean processRequest( 87 final SimpleHttpServerConnection conn, 88 final SimpleRequest request) throws IOException 89 { 90 Header clientAuth = request.getFirstHeader(PROXY_AUTH_RESP); 91 if (clientAuth != null && checkAuthorization(clientAuth)) { 92 return false; 93 } else { 94 SimpleResponse response = performBasicHandshake(conn, request); 95 // Make sure the request body is fully consumed 96 request.getBodyBytes(); 97 conn.writeResponse(response); 98 return true; 99 } 100 } 101 102 //TODO add more auth schemes performBasicHandshake( final SimpleHttpServerConnection conn, final SimpleRequest request)103 private SimpleResponse performBasicHandshake( 104 final SimpleHttpServerConnection conn, 105 final SimpleRequest request) { 106 107 SimpleResponse response = new SimpleResponse(); 108 response.setStatusLine( 109 request.getRequestLine().getHttpVersion(), 110 HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED); 111 if (!request.getRequestLine().getMethod().equalsIgnoreCase("HEAD")) { 112 response.setBodyString("unauthorized"); 113 } 114 response.addHeader(new Header("Proxy-Authenticate", "basic realm=\"" + this.realm + "\"")); 115 if (this.keepalive) { 116 response.addHeader(new Header("Proxy-Connection", "keep-alive")); 117 conn.setKeepAlive(true); 118 } else { 119 response.addHeader(new Header("Proxy-Connection", "close")); 120 conn.setKeepAlive(false); 121 } 122 return response; 123 } 124 125 /** 126 * Checks if the credentials provided by the client match the required 127 * credentials 128 * 129 * @return true if the client is authorized, false if not. 130 * @param clientAuth 131 */ checkAuthorization(Header clientAuth)132 private boolean checkAuthorization(Header clientAuth) { 133 String expectedAuthString = BasicScheme.authenticate( 134 (UsernamePasswordCredentials)credentials, 135 "ISO-8859-1"); 136 return expectedAuthString.equals(clientAuth.getValue()); 137 } 138 139 } 140