1 19 20 package com.sslexplorer.replacementproxy; 21 22 import java.io.ByteArrayInputStream ; 23 import java.io.OutputStream ; 24 import java.net.MalformedURLException ; 25 import java.net.URL ; 26 import java.util.Enumeration ; 27 import java.util.Iterator ; 28 import java.util.List ; 29 import java.util.StringTokenizer ; 30 31 import javax.servlet.http.HttpSession ; 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 58 public class ProxiedRequestDispatcher { 59 final static Log log = LogFactory.getLog(ProxiedRequestDispatcher.class); 60 static CaseInsensitiveMap ignoreHeaders = new CaseInsensitiveMap(); 61 62 final static String sessionIdCookieName = System.getProperty("sslexplorer.cookie", "JSESSIONID"); 63 64 68 public static final String 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 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 102 public boolean sendProxiedRequest() throws Exception { 103 104 byte[] content = null; 105 OutputStream serverOut = null; 106 HttpClient client; 107 SessionClients clients = null; 108 HttpSession session = requestProcessor.getSession(); 109 110 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 proxiedURL = requestProcessor.getRequestParameters().getProxiedURL(); 120 121 synchronized (clients) { 122 String 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 client.setPreferredAuthentication(requestProcessor.getWebForward().getPreferredAuthenticationScheme()); 149 150 client.setIncludeCookies(false); 152 153 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 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 tokens = new StringTokenizer (requestProcessor.getWebForward().getFormParameters(), "\n"); 187 int idx; 188 String 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 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 contentType = null; 216 217 for (Enumeration e = requestProcessor.getHeaderNames(); e.hasMoreElements();) { 218 219 String hdr = (String ) 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 List replacements = WebForwardDatabaseFactory.getInstance().getReplacementsForContent(launchSession.getSession().getUser().getPrincipalName(), 229 Replacement.REPLACEMENT_TYPE_SENT_HEADER, 230 hdr, 231 proxiedURL.toExternalForm()); 232 233 Enumeration vals = requestProcessor.getHeaders(hdr); 234 while (vals.hasMoreElements()) { 235 String val = (String ) vals.nextElement(); 236 237 for (Iterator 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 if (log.isDebugEnabled()) 253 log.debug(" Splitting cookie " + val); 254 String [] cookieVals = val.split("\\;"); 255 StringBuffer newVal = new StringBuffer (); 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 cn = ""; 261 String 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 CookieItem cookie = cookieMap.getByFakeCookieName(cn); 279 if (cookie == null) { 280 if (log.isDebugEnabled()) 281 log.debug(" Cookie " + cn + " unmapped, ignoring"); 282 } 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 else if (hdr.equalsIgnoreCase(HttpConstants.HDR_REFERER)) { 307 try { 308 URL refUrl = new URL (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 [] refParms = refUrl.getQuery().split("&"); 314 String sslexUrlRef = null; 315 String destUrlRef = null; 316 for (int i = 0; i < refParms.length; i++) { 317 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 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 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 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 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 getResponseMessage() { 394 return responseMessage; 395 } 396 } 397 | Popular Tags |