KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sslexplorer > replacementproxy > ProxiedRequestDispatcher


1 /*
2  * SSL-Explorer
3  *
4  * Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */

19             
20 package com.sslexplorer.replacementproxy;
21
22 import java.io.ByteArrayInputStream JavaDoc;
23 import java.io.OutputStream JavaDoc;
24 import java.net.MalformedURLException JavaDoc;
25 import java.net.URL JavaDoc;
26 import java.util.Enumeration JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.StringTokenizer JavaDoc;
30
31 import javax.servlet.http.HttpSession JavaDoc;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.mortbay.util.MultiMap;
36
37 import com.maverick.http.HttpAuthenticatorFactory;
38 import com.maverick.http.HttpClient;
39 import com.maverick.http.HttpResponse;
40 import com.maverick.http.PasswordCredentials;
41 import com.sslexplorer.boot.CaseInsensitiveMap;
42 import com.sslexplorer.boot.HttpConstants;
43 import com.sslexplorer.boot.Util;
44 import com.sslexplorer.core.CookieItem;
45 import com.sslexplorer.core.CookieMap;
46 import com.sslexplorer.core.stringreplacement.SessionInfoReplacer;
47 import com.sslexplorer.core.stringreplacement.VariableReplacement;
48 import com.sslexplorer.policyframework.LaunchSession;
49 import com.sslexplorer.reverseproxy.SessionClients;
50 import com.sslexplorer.security.Constants;
51 import com.sslexplorer.util.ProxiedHttpMethod;
52 import com.sslexplorer.webforwards.WebForwardDatabaseFactory;
53 import com.sslexplorer.webforwards.WebForwardTypes;
54
55 /**
56  * @author Brett Smith <brett@3sp.com>
57  */

58 public class ProxiedRequestDispatcher {
59     final static Log log = LogFactory.getLog(ProxiedRequestDispatcher.class);
60     static CaseInsensitiveMap ignoreHeaders = new CaseInsensitiveMap();
61
62     final static String JavaDoc sessionIdCookieName = System.getProperty("sslexplorer.cookie", "JSESSIONID");
63     
64     /**
65      * Launch session attribute for storing whether authentication has been
66      * posted yet
67      */

68     public static final String JavaDoc LAUNCH_ATTR_AUTH_POSTED = "authPosted";
69
70     static {
71
72         ignoreHeaders.put(HttpConstants.HDR_PROXY_CONNECTION, Boolean.TRUE);
73         ignoreHeaders.put(HttpConstants.HDR_ACCEPT_ENCODING, Boolean.TRUE);
74         ignoreHeaders.put(HttpConstants.HDR_TRANSFER_ENCODING, Boolean.TRUE);
75         ignoreHeaders.put(HttpConstants.HDR_TE, Boolean.TRUE);
76         ignoreHeaders.put(HttpConstants.HDR_TRAILER, Boolean.TRUE);
77         ignoreHeaders.put(HttpConstants.HDR_PROXY_AUTHORIZATION, Boolean.TRUE);
78         ignoreHeaders.put(HttpConstants.HDR_PROXY_AUTHENTICATE, Boolean.TRUE);
79         ignoreHeaders.put(HttpConstants.HDR_UPGRADE, Boolean.TRUE);
80
81     }
82
83     private RequestProcessor requestProcessor;
84     private LaunchSession launchSession;
85     private HttpResponse serverResponse;
86     private int responseCode;
87     private String JavaDoc responseMessage;
88     private CookieMap cookieMap;
89
90     public ProxiedRequestDispatcher(RequestProcessor requestProcessor, LaunchSession launchSession, CookieMap cookieMap) {
91         this.launchSession = launchSession;
92         this.requestProcessor = requestProcessor;
93         this.cookieMap = cookieMap;
94     }
95
96     /**
97      * Send the request to the target server.
98      *
99      * @return request successful
100      * @throws Exception on any error
101      */

102     public boolean sendProxiedRequest() throws Exception JavaDoc {
103
104         byte[] content = null;
105         OutputStream JavaDoc serverOut = null;
106         HttpClient client;
107         SessionClients clients = null;
108         HttpSession JavaDoc session = requestProcessor.getSession();
109
110         // Manage the sessions clients
111
synchronized (session) {
112             clients = (SessionClients) session.getAttribute(Constants.HTTP_CLIENTS);
113             if (clients == null) {
114                 clients = new SessionClients();
115                 session.setAttribute(Constants.HTTP_CLIENTS, clients);
116             }
117         }
118         
119         URL JavaDoc proxiedURL = requestProcessor.getRequestParameters().getProxiedURL();
120
121         synchronized (clients) {
122             String JavaDoc key = proxiedURL.getHost() + ":"
123                 + (proxiedURL.getPort() > 0 ? proxiedURL.getPort() : proxiedURL.getProtocol().equals("https") ? 443 : 80)
124                 + ":"
125                 + proxiedURL.getProtocol().equals("https")
126                 + ":"
127                 + requestProcessor.getWebForward().getResourceId()
128                 + Thread.currentThread().getName();
129             client = (HttpClient) clients.get(key);
130
131             if (client == null) {
132                 client = new HttpClient(proxiedURL.getHost(), (proxiedURL.getPort() > 0 ? proxiedURL.getPort()
133                     : proxiedURL.getProtocol().equals("https") ? 443 : 80), proxiedURL.getProtocol().equals("https"));
134
135                 if (!requestProcessor.getWebForward().getPreferredAuthenticationScheme().equals(HttpAuthenticatorFactory.NONE) && !requestProcessor.getWebForward()
136                                 .getAuthenticationUsername()
137                                 .equals("")
138                     && !requestProcessor.getWebForward().getAuthenticationPassword().equals("")) {
139                     PasswordCredentials pwd = new PasswordCredentials();
140                     pwd.setUsername(SessionInfoReplacer.replace(requestProcessor.getSessionInfo(), requestProcessor.getWebForward()
141                                     .getAuthenticationUsername()));
142                     pwd.setPassword(SessionInfoReplacer.replace(requestProcessor.getSessionInfo(), requestProcessor.getWebForward()
143                                     .getAuthenticationPassword()));
144                     client.setCredentials(pwd);
145                 }
146
147                 // Set the preferred scheme
148
client.setPreferredAuthentication(requestProcessor.getWebForward().getPreferredAuthenticationScheme());
149
150                 // Do not track cookies, browser will instead
151
client.setIncludeCookies(false);
152                 
153                 // If we're using basic authentication then preempt the 401
154
// response
155
client.setPreemtiveAuthentication(requestProcessor.getWebForward()
156                                 .getPreferredAuthenticationScheme()
157                                 .equalsIgnoreCase("BASIC"));
158                 clients.put(key, client);
159             }
160         }
161
162         if (log.isDebugEnabled())
163             log.debug("Connecting to [" + requestProcessor.getRequestParameters().getProxiedURL() + "] ");
164
165         ProxiedHttpMethod method;
166
167         if (!requestProcessor.getWebForward().getFormType().equals(WebForwardTypes.FORM_SUBMIT_NONE) &&
168                 !requestProcessor.getWebForward().getFormType().equals("") &&
169                 !requestProcessor.getWebForward().getFormType().equals(WebForwardTypes.FORM_SUBMIT_JAVASCRIPT) &&
170                 !Boolean.TRUE.equals(launchSession.getAttribute(LAUNCH_ATTR_AUTH_POSTED))) {
171
172             /**
173              * This code will automatically submit form parameters.
174              *
175              * LDP - Use the full URI with parameters as we need to ensure parameters are sent as they are received.
176              */

177             method = new ProxiedHttpMethod(requestProcessor.getWebForward().getFormType(),
178                     SessionInfoReplacer.replace(requestProcessor.getSessionInfo(), requestProcessor.getUriEncoded()),
179                     requestProcessor.getWebForward().getFormType().equals(WebForwardTypes.FORM_SUBMIT_POST)? new MultiMap() : requestProcessor.getRequestParameters(),
180                     requestProcessor.getSessionInfo(),
181                     requestProcessor.getWebForward().getFormType().equals(WebForwardTypes.FORM_SUBMIT_POST));
182
183             if (requestProcessor.getWebForward().getEncoding() != null && !requestProcessor.getWebForward().getEncoding().equals(WebForwardTypes.DEFAULT_ENCODING))
184                 method.setCharsetEncoding(requestProcessor.getWebForward().getEncoding());
185
186             StringTokenizer JavaDoc tokens = new StringTokenizer JavaDoc(requestProcessor.getWebForward().getFormParameters(), "\n");
187             int idx;
188             String JavaDoc param;
189             while (tokens.hasMoreTokens()) {
190                 param = SessionInfoReplacer.replace(requestProcessor.getLaunchSession().getSession(), tokens.nextToken().trim());
191                 idx = param.indexOf('=');
192                 if (idx > -1 && idx < param.length()-1) {
193                     method.addParameter(param.substring(0, idx), param.substring(idx + 1));
194                 } else
195                     method.addParameter(param, "");
196             }
197             
198             launchSession.setAttribute(LAUNCH_ATTR_AUTH_POSTED, Boolean.TRUE);
199         } else {
200             /**
201              * LDP - Use the full URI with parameters as we need to ensure parameters are sent as they are received.
202              */

203             method = new ProxiedHttpMethod(requestProcessor.getMethod(),
204                     SessionInfoReplacer.replace(requestProcessor.getSessionInfo(), requestProcessor.getUriEncoded()),
205                     requestProcessor.getRequestParameters(),
206                     requestProcessor.getSessionInfo(),
207                     requestProcessor.getRequest().getContentType()!=null &&
208                     requestProcessor.getRequest().getContentType().startsWith("application/x-www-form-urlencoded"));
209
210             if (requestProcessor.getWebForward().getEncoding() != null && !requestProcessor.getWebForward().getEncoding().equals(WebForwardTypes.DEFAULT_ENCODING))
211                 method.setCharsetEncoding(requestProcessor.getWebForward().getEncoding());
212         }
213
214         int contentLength = 0;
215         String JavaDoc contentType = null;
216         
217         for (Enumeration JavaDoc e = requestProcessor.getHeaderNames(); e.hasMoreElements();) {
218
219             String JavaDoc hdr = (String JavaDoc) e.nextElement();
220
221             if (ignoreHeaders.containsKey(hdr)) {
222                 if (log.isDebugEnabled())
223                     log.debug("Ignoring " + hdr + " = " + requestProcessor.getHeader(hdr));
224                 continue;
225             }
226
227             // See if there any replacements for this header
228
List JavaDoc replacements = WebForwardDatabaseFactory.getInstance().getReplacementsForContent(launchSession.getSession().getUser().getPrincipalName(),
229                 Replacement.REPLACEMENT_TYPE_SENT_HEADER,
230                 hdr,
231                 proxiedURL.toExternalForm());
232
233             Enumeration JavaDoc vals = requestProcessor.getHeaders(hdr);
234             while (vals.hasMoreElements()) {
235                 String JavaDoc val = (String JavaDoc) vals.nextElement();
236
237                 // Do the replacements
238
for (Iterator JavaDoc i = replacements.iterator(); i.hasNext();) {
239                     Replacement r = (Replacement) i.next();
240                     val = val.replaceAll(r.getMatchPattern(), r.getReplacePattern());
241                 }
242
243                 if (val != null) {
244                     if (hdr.equalsIgnoreCase(HttpConstants.HDR_HOST)) {
245                         if (proxiedURL.getPort() == -1) {
246                             val = proxiedURL.getHost();
247                         } else {
248                             val = proxiedURL.getHost() + ":" + proxiedURL.getPort();
249                         }
250                     } else if (hdr.equalsIgnoreCase(HttpConstants.HDR_COOKIE)) {
251                         // We shouldnt supply our local cookies
252
if (log.isDebugEnabled())
253                             log.debug(" Splitting cookie " + val);
254                         String JavaDoc[] cookieVals = val.split("\\;");
255                         StringBuffer JavaDoc newVal = new StringBuffer JavaDoc();
256                         for (int i = 0; i < cookieVals.length; i++) {
257                             if (log.isDebugEnabled())
258                                 log.debug("Cookie = " + cookieVals[i]);
259                             int idx = cookieVals[i].indexOf('=');
260                             String JavaDoc cn = "";
261                             String JavaDoc cv = "";
262                             if(idx==-1) {
263                                 cn = Util.trimBoth(cookieVals[i]);
264                             } else if(idx < cookieVals[i].length()-1) {
265                                 cn = Util.trimBoth(cookieVals[i].substring(0, idx));
266                                 cv = Util.trimBoth(cookieVals[i].substring(idx + 1));
267                             } else {
268                                 cn = Util.trimBoth(cookieVals[i].substring(0, idx));
269                             }
270                             if (cn.equals("webForward") || cn.equals(Constants.LOGON_TICKET)
271                                 || cn.equals(Constants.DOMAIN_LOGON_TICKET)
272                                 || (cn.equals(sessionIdCookieName) && cv.equals(requestProcessor.getSession().getId()))) {
273                                 if (log.isDebugEnabled())
274                                     log.debug(" Omiting cookie " + cn + "=" + cv);
275                             } else {
276                                 // TODO is it ok to store the cookie map in
277
// memory?
278
CookieItem cookie = cookieMap.getByFakeCookieName(cn);
279                                 if (cookie == null) {
280                                     if (log.isDebugEnabled())
281                                         log.debug(" Cookie " + cn + " unmapped, ignoring");
282                                     // Un-mapped cookie, ignore
283
} else {
284                                     if (log.isDebugEnabled())
285                                         log.debug(" Including cookie " + cn + "=" + cv);
286                                     if (newVal.length() > 0) {
287                                         newVal.append("; ");
288                                     }
289                                     newVal.append(cookie.getRealCookieName());
290                                     newVal.append("=");
291                                     newVal.append(Util.urlDecode(cv));
292                                 }
293                             }
294                         }
295                         if (newVal.length() == 0) {
296                             if (log.isDebugEnabled())
297                                 log.debug("Send no cookies");
298                             val = null;
299                         } else {
300                             val = newVal.toString();
301                             if (log.isDebugEnabled())
302                                 log.debug("Using cooking val of " + val);
303                         }
304                     }
305                     // Change the refererer
306
else if (hdr.equalsIgnoreCase(HttpConstants.HDR_REFERER)) {
307                         try {
308                             URL JavaDoc refUrl = new URL JavaDoc(val);
309                             refUrl.getQuery();
310                             if (log.isDebugEnabled())
311                                 log.debug("Splitting refererer query string [" + val + "] " + refUrl.getQuery());
312                             if (refUrl.getQuery() != null) {
313                                 String JavaDoc[] refParms = refUrl.getQuery().split("&");
314                                 String JavaDoc sslexUrlRef = null;
315                                 String JavaDoc destUrlRef = null;
316                                 for (int i = 0; i < refParms.length; i++) {
317                                     // System.err.println("Refparms[" + i +
318
// "]=" + refParms[i]);
319
if (refParms[i].startsWith("sslex_url=")) {
320                                         sslexUrlRef = Util.urlDecode(refParms[i].substring(10));
321                                     } else if (refParms[i].startsWith("dest_url=")) {
322                                         destUrlRef = Util.urlDecode(refParms[i].substring(9));
323                                     }
324                                 }
325                                 if (sslexUrlRef != null) {
326                                     val = Util.urlDecode(sslexUrlRef);
327                                     if (log.isDebugEnabled())
328                                         log.debug("Changed referer to " + val);
329                                 } else if (destUrlRef != null) {
330                                     val = Util.urlDecode(destUrlRef);
331                                     if (log.isDebugEnabled())
332                                         log.debug("Changed referer to " + val);
333                                 } else {
334                                     VariableReplacement r = new VariableReplacement();
335                                     r.setRequest(requestProcessor.getRequest());
336                                     r.setSession(requestProcessor.getSessionInfo());
337                                     val = r.replace(val);
338                                 }
339                             }
340                         } catch (MalformedURLException JavaDoc murle) {
341
342                         }
343                     } else if (hdr.equalsIgnoreCase(HttpConstants.HDR_CONTENT_LENGTH)) {
344                         contentLength = Integer.parseInt(val);
345                         continue;
346                     } else if(hdr.equalsIgnoreCase(HttpConstants.HDR_CONTENT_TYPE)) {
347                         contentType = val;
348                         continue;
349                     } else if (hdr.equalsIgnoreCase(HttpConstants.HDR_CONNECTION)) {
350                         // Handled by the Maverick HTTP client
351
continue;
352                     }
353
354                     if (val != null) {
355                         method.getProxiedRequest().addHeaderField(hdr, val);
356                     }
357
358                     if (log.isDebugEnabled())
359                         log.debug("Adding request property " + hdr + " = " + val);
360                 }
361             }
362         }
363
364         // Proxy headers
365
method.getProxiedRequest().setHeaderField("Via", "SSL Explorer");
366
367         if(requestProcessor.getRequestParameters().isFormData() && contentLength > 0) {
368             method.setContent(requestProcessor.getRequestParameters().getFormData(), requestProcessor.getRequestParameters().getFormDataLength(), contentType);
369         } else if(contentLength > 0) {
370             method.setContent(requestProcessor.getRequest().getInputStream(), contentLength, contentType);
371         }
372
373         // Execute the request
374
if (log.isDebugEnabled())
375             log.debug("Connecting to " + client.getHost() + ":" + client.getPort() + " (Secure = " + client.isSecure() + ")");
376
377         serverResponse = client.execute(method);
378
379         responseCode = serverResponse.getStatus();
380         responseMessage = serverResponse.getReason();
381
382         return true;
383     }
384
385     public int getResponseCode() {
386         return responseCode;
387     }
388
389     public HttpResponse getServerResponse() {
390         return serverResponse;
391     }
392
393     public String JavaDoc getResponseMessage() {
394         return responseMessage;
395     }
396 }
397
Popular Tags