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.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 private Credentials credentials;
51
52 /***
53 * The proxy authenticate challange header.
54 */
55 public static final String PROXY_AUTH = "Proxy-Authenticate";
56
57 /***
58 * The proxy authenticate response header.
59 */
60 public static final String PROXY_AUTH_RESP = "Proxy-Authorization";
61
62 /***
63 * TODO replace creds parameter with a class specific to an auth scheme
64 * encapsulating all required information for a specific scheme
65 *
66 * @param creds
67 */
68 public ProxyAuthRequestHandler(Credentials creds) {
69 if (creds == null)
70 throw new IllegalArgumentException("Credentials can not be null");
71 this.credentials = creds;
72 }
73
74 public boolean processRequest(
75 final SimpleHttpServerConnection conn,
76 final SimpleRequest request) throws IOException
77 {
78 Header clientAuth = request.getFirstHeader(PROXY_AUTH_RESP);
79 if (clientAuth != null) {
80 boolean ok = checkAuthorization(clientAuth);
81 if (ok)
82 conn.connectionKeepAlive();
83 return !ok;
84 } else {
85 performHandshake(conn);
86 }
87 return true;
88 }
89
90 /***
91 * @param conn
92 */
93 private void performHandshake(SimpleHttpServerConnection conn) throws IOException {
94 Header challenge = createChallenge();
95 ResponseWriter out = conn.getWriter();
96 out.println("HTTP/1.1 407 Proxy Authentication Required");
97 out.print(challenge.toExternalForm());
98 out.print(new Header("Proxy-Connection", "Keep-Alive").toExternalForm());
99 out.print(new Header("Content-Length", "0").toExternalForm());
100 out.println();
101 out.flush();
102 conn.connectionKeepAlive();
103 }
104
105 /***
106 * @return
107 */
108 private Header createChallenge() {
109 Header header = new Header();
110 header.setName(PROXY_AUTH);
111
112 String challenge = "basic realm=test";
113 header.setValue(challenge);
114 return header;
115 }
116
117 /***
118 * Checks if the credentials provided by the client match the required
119 * credentials
120 *
121 * @return true if the client is authorized, false if not.
122 * @param clientAuth
123 */
124 private boolean checkAuthorization(Header clientAuth) {
125 String expectedAuthString = BasicScheme.authenticate(
126 (UsernamePasswordCredentials)credentials,
127 "ISO-8859-1");
128 return expectedAuthString.equals(clientAuth.getValue());
129 }
130
131 }