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
31
32 package org.apache.commons.httpclient.server;
33
34 import java.io.IOException;
35
36 import org.apache.commons.httpclient.Credentials;
37 import org.apache.commons.httpclient.Header;
38 import org.apache.commons.httpclient.auth.AuthenticationException;
39 import org.apache.commons.httpclient.auth.BasicScheme;
40 import org.apache.commons.httpclient.auth.HttpAuthenticator;
41 import org.apache.commons.httpclient.auth.MalformedChallengeException;
42
43 /***
44 * This request handler guards access to a proxy when used in a
45 * request handler chain. It checks the headers for valid credentials
46 * and performs the authentication handshake if necessary.
47 *
48 * @author Ortwin Glueck
49 */
50 public class ProxyAuthRequestHandler implements HttpRequestHandler {
51 private Credentials credentials;
52
53 /***
54 * TODO replace creds parameter with a class specific to an auth scheme encapsulating all required information for a specific scheme
55 * @param creds
56 */
57 public ProxyAuthRequestHandler(Credentials creds) {
58 if (creds == null) throw new IllegalArgumentException("Credentials can not be null");
59 this.credentials = creds;
60 }
61
62 public boolean processRequest(SimpleHttpServerConnection conn)
63 throws IOException {
64 Header[] headers = conn.getHeaders();
65 Header clientAuth = findHeader(headers, HttpAuthenticator.PROXY_AUTH_RESP);
66 if (clientAuth != null) {
67 boolean ok = checkAuthorization(clientAuth);
68 if (ok) conn.connectionKeepAlive();
69 return !ok;
70 } else {
71 performHandshake(conn);
72 }
73 return true;
74 }
75
76 /***
77 * @param conn
78 */
79 private void performHandshake(SimpleHttpServerConnection conn) throws IOException {
80 Header challenge = createChallenge();
81 ResponseWriter out = conn.getWriter();
82 out.println("HTTP/1.1 407 Proxy Authentication Required");
83 out.print(challenge.toExternalForm());
84 out.print(new Header("Proxy-Connection", "Keep-Alive").toExternalForm());
85 out.print(new Header("Content-Length", "0").toExternalForm());
86 out.println();
87 out.flush();
88 conn.connectionKeepAlive();
89 }
90
91 /***
92 *
93 * @return
94 */
95 private Header createChallenge() {
96 Header header = new Header();
97 header.setName(HttpAuthenticator.PROXY_AUTH);
98
99 String challenge = "basic realm=test";
100 header.setValue(challenge);
101 return header;
102 }
103
104 /***
105 * Checks if the credentials provided by the client match the required credentials
106 * @return true if the client is authorized, false if not.
107 * @param clientAuth
108 */
109 private boolean checkAuthorization(Header clientAuth) {
110
111 BasicScheme scheme;
112 try {
113 scheme = new BasicScheme("basic realm=test");
114 String expectedAuthString = scheme.authenticate(credentials, null, null);
115 return expectedAuthString.equals(clientAuth.getValue());
116 } catch (MalformedChallengeException e) {
117
118 e.printStackTrace();
119 } catch (AuthenticationException e) {
120
121 e.printStackTrace();
122 }
123 return false;
124 }
125
126 private Header findHeader(Header[] headers, String name) {
127 for(int i=0; i<headers.length; i++) {
128 Header header = headers[i];
129 if (header.getName().equalsIgnoreCase(name)) return header;
130 }
131 return null;
132 }
133
134 }