1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.apache.commons.httpclient.server;
31
32 import java.io.IOException;
33
34 import org.apache.commons.httpclient.Credentials;
35 import org.apache.commons.httpclient.Header;
36 import org.apache.commons.httpclient.HttpStatus;
37 import org.apache.commons.httpclient.UsernamePasswordCredentials;
38 import org.apache.commons.httpclient.auth.BasicScheme;
39
40 /***
41 * This request handler guards access to a proxy when used in a request handler
42 * chain. It checks the headers for valid credentials and performs the
43 * authentication handshake if necessary.
44 *
45 * @author Ortwin Glueck
46 * @author Oleg Kalnichevski
47 */
48 public class ProxyAuthRequestHandler implements HttpRequestHandler {
49
50 private Credentials credentials = null;
51 private String realm = null;
52 private boolean keepalive = true;
53
54 /***
55 * The proxy authenticate response header.
56 */
57 public static final String PROXY_AUTH_RESP = "Proxy-Authorization";
58
59 /***
60 * TODO replace creds parameter with a class specific to an auth scheme
61 * encapsulating all required information for a specific scheme
62 *
63 * @param creds
64 */
65 public ProxyAuthRequestHandler(final Credentials creds, final String realm, boolean keepalive) {
66 if (creds == null)
67 throw new IllegalArgumentException("Credentials may not be null");
68 this.credentials = creds;
69 this.keepalive = keepalive;
70 if (realm != null) {
71 this.realm = realm;
72 } else {
73 this.realm = "test";
74 }
75 }
76
77 public ProxyAuthRequestHandler(final Credentials creds, final String realm) {
78 this(creds, realm, true);
79 }
80
81 public ProxyAuthRequestHandler(final Credentials creds) {
82 this(creds, null, true);
83 }
84
85 public boolean processRequest(
86 final SimpleHttpServerConnection conn,
87 final SimpleRequest request) throws IOException
88 {
89 Header clientAuth = request.getFirstHeader(PROXY_AUTH_RESP);
90 if (clientAuth != null && checkAuthorization(clientAuth)) {
91 return false;
92 } else {
93 SimpleResponse response = performBasicHandshake(conn, request);
94
95 request.getBodyBytes();
96 conn.writeResponse(response);
97 return true;
98 }
99 }
100
101
102 private SimpleResponse performBasicHandshake(
103 final SimpleHttpServerConnection conn,
104 final SimpleRequest request) {
105
106 SimpleResponse response = new SimpleResponse();
107 response.setStatusLine(
108 request.getRequestLine().getHttpVersion(),
109 HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED);
110 if (!request.getRequestLine().getMethod().equalsIgnoreCase("HEAD")) {
111 response.setBodyString("unauthorized");
112 }
113 response.addHeader(new Header("Proxy-Authenticate", "basic realm=\"" + this.realm + "\""));
114 if (this.keepalive) {
115 response.addHeader(new Header("Proxy-Connection", "keep-alive"));
116 conn.setKeepAlive(true);
117 } else {
118 response.addHeader(new Header("Proxy-Connection", "close"));
119 conn.setKeepAlive(false);
120 }
121 return response;
122 }
123
124 /***
125 * Checks if the credentials provided by the client match the required
126 * credentials
127 *
128 * @return true if the client is authorized, false if not.
129 * @param clientAuth
130 */
131 private boolean checkAuthorization(Header clientAuth) {
132 String expectedAuthString = BasicScheme.authenticate(
133 (UsernamePasswordCredentials)credentials,
134 "ISO-8859-1");
135 return expectedAuthString.equals(clientAuth.getValue());
136 }
137
138 }