1 25 26 27 package org.apache.coyote.tomcat5; 28 29 import java.io.IOException ; 30 31 import java.security.cert.X509Certificate ; 33 import java.security.cert.CertificateException ; 34 36 import javax.servlet.http.Cookie ; 37 import javax.servlet.http.HttpServletRequest ; 38 import javax.servlet.http.HttpServletResponse ; 39 import org.apache.catalina.ContainerEvent; 40 import org.apache.catalina.ContainerListener; 41 42 import org.apache.catalina.Context; 43 import org.apache.catalina.Globals; 44 import org.apache.catalina.Wrapper; 45 import org.apache.catalina.core.ContainerBase; 46 import org.apache.catalina.util.StringManager; 47 import com.sun.org.apache.commons.logging.Log; 48 import com.sun.org.apache.commons.logging.LogFactory; 49 import org.apache.coyote.ActionCode; 50 import org.apache.coyote.Adapter; 51 import org.apache.coyote.Request; 52 import org.apache.coyote.Response; 53 56 import org.apache.tomcat.util.buf.ByteChunk; 57 import org.apache.tomcat.util.buf.CharChunk; 58 import org.apache.tomcat.util.buf.MessageBytes; 59 import org.apache.tomcat.util.buf.UEncoder; 61 66 import com.sun.appserv.ProxyHandler; 68 70 71 79 80 public class CoyoteAdapter 81 implements Adapter 82 { 83 private static Log log = LogFactory.getLog(CoyoteAdapter.class); 84 85 87 88 public static final int ADAPTER_NOTES = 1; 89 90 91 93 94 100 public CoyoteAdapter(CoyoteConnector connector) { 101 102 super(); 103 this.connector = connector; 104 this.debug = connector.getDebug(); 105 urlEncoder.addSafeCharacter('/'); 107 } 109 110 111 113 114 117 private CoyoteConnector connector = null; 118 119 120 123 private int debug = 0; 124 125 private UEncoder urlEncoder = new UEncoder(); 127 129 132 136 137 138 141 144 145 146 149 protected StringManager sm = 150 StringManager.getManager(Constants.Package); 151 152 153 155 156 159 public void service(Request req, Response res) 160 throws Exception { 161 162 CoyoteRequest request = (CoyoteRequest) req.getNote(ADAPTER_NOTES); 163 CoyoteResponse response = (CoyoteResponse) res.getNote(ADAPTER_NOTES); 164 165 if (request == null) { 166 167 request = (CoyoteRequest) connector.createRequest(); 169 request.setCoyoteRequest(req); 170 response = (CoyoteResponse) connector.createResponse(); 171 response.setCoyoteResponse(res); 172 173 request.setResponse(response); 175 response.setRequest(request); 176 177 req.setNote(ADAPTER_NOTES, request); 179 res.setNote(ADAPTER_NOTES, response); 180 181 req.getParameters().setQueryStringEncoding 183 (connector.getURIEncoding()); 184 } 185 186 if (!connector.isEnabled()) { 189 String msg = sm.getString("coyoteAdapter.listenerOff", 190 String.valueOf(connector.getPort())); 191 if (log.isDebugEnabled()) { 192 log.debug(msg); 193 } 194 response.sendError(HttpServletResponse.SC_NOT_FOUND, msg); 195 return; 196 } 197 199 if (connector.isXpoweredBy()) { 200 response.addHeader("X-Powered-By", "Servlet/2.5"); 201 } 202 203 try { 204 205 if ( postParseRequest(req, request, res, response) ) { 208 209 boolean authPassthroughEnabled = 211 connector.getAuthPassthroughEnabled(); 212 ProxyHandler proxyHandler = connector.getProxyHandler(); 213 if (authPassthroughEnabled && proxyHandler != null) { 214 215 if (proxyHandler.getSSLKeysize( 217 (HttpServletRequest )request.getRequest()) > 0) { 218 request.setSecure(true); 219 } 220 222 X509Certificate [] certs = null; 223 try { 224 certs = proxyHandler.getSSLClientCertificateChain( 225 request.getRequest()); 226 } catch (CertificateException ce) { 227 log.error(sm.getString( 228 "coyoteAdapter.proxyAuthCertError"), 229 ce); 230 } 231 if (certs != null) { 232 request.setAttribute(Globals.CERTIFICATES_ATTR, 233 certs); 234 } 235 } 236 238 connector.getContainer().invoke(request, response); 240 241 } 242 243 response.finishResponse(); 244 req.action( ActionCode.ACTION_POST_REQUEST , null); 245 246 } catch (IOException e) { 247 ; 248 } catch (Throwable t) { 249 log.error(sm.getString("coyoteAdapter.service"), t); 250 } finally { 251 request.recycle(); 253 response.recycle(); 254 } 255 256 } 257 258 259 261 262 265 protected boolean postParseRequest(Request req, CoyoteRequest request, 266 Response res, CoyoteResponse response) 267 throws Exception { 268 if (! req.scheme().isNull()) { 274 request.setSecure(req.scheme().equals("https")); 276 } else { 277 req.scheme().setString(connector.getScheme()); 280 request.setSecure(connector.getSecure()); 281 } 282 283 String proxyName = connector.getProxyName(); 289 int proxyPort = connector.getProxyPort(); 290 if (proxyPort != 0) { 291 req.setServerPort(proxyPort); 292 } 293 if (proxyName != null) { 294 req.serverName().setString(proxyName); 295 } 296 297 MessageBytes decodedURI = req.decodedURI(); 299 decodedURI.duplicate(req.requestURI()); 300 try { 301 req.getURLDecoder().convert(decodedURI, false); 302 } catch (IOException ioe) { 303 res.setStatus(400); 304 res.setMessage("Invalid URI"); 305 throw ioe; 306 } 307 308 if (!normalize(req.decodedURI())) { 310 res.setStatus(400); 311 res.setMessage("Invalid URI"); 312 return false; 313 } 314 315 String principal = req.getRemoteUser().toString(); 317 if (principal != null) { 318 request.setUserPrincipal(new CoyotePrincipal(principal)); 319 } 320 321 String authtype = req.getAuthType().toString(); 323 if (authtype != null) { 324 request.setAuthType(authtype); 325 } 326 327 334 request.convertURI(decodedURI); 337 338 request.parseSessionId(); 340 342 CharChunk uriCC = decodedURI.getCharChunk(); 346 int semicolon = uriCC.indexOf(';'); 347 if (semicolon > 0) { 348 decodedURI.setChars 349 (uriCC.getBuffer(), uriCC.getStart(), semicolon); 350 } 351 352 connector.getMapper().map(req.serverName(), decodedURI, 354 request.getMappingData()); 355 356 Context ctx = (Context) request.getMappingData().context; 361 request.setContext(ctx); 362 request.setWrapper((Wrapper) request.getMappingData().wrapper); 364 365 if (!connector.getAllowTrace() 367 && req.method().equalsIgnoreCase("TRACE")) { 368 Wrapper wrapper = request.getWrapper(); 369 String header = null; 370 if (wrapper != null) { 371 String [] methods = wrapper.getServletMethods(); 372 if (methods != null) { 373 for (int i=0; i<methods.length; i++) { 374 if ("TRACE".equals(methods[i])) { 376 continue; 377 } 378 if (header == null) { 379 header = methods[i]; 380 } else { 381 header += ", " + methods[i]; 382 } 383 } 384 } 385 } 386 res.setStatus(405); 387 res.addHeader("Allow", header); 388 res.setMessage("TRACE method is not allowed"); 389 return false; 390 } 391 392 MessageBytes redirectPathMB = request.getMappingData().redirectPath; 394 if (!redirectPathMB.isNull() 399 && (!ctx.hasAdHocPaths() 400 || (ctx.getAdHocServletName(((HttpServletRequest ) 401 request.getRequest()).getServletPath()) == null))) { 402 String redirectPath = redirectPathMB.toString(); 404 String query = request.getQueryString(); 405 if (request.isRequestedSessionIdFromURL()) { 406 redirectPath = redirectPath + ";jsessionid=" 409 + request.getRequestedSessionId(); 410 } 411 if (query != null) { 412 redirectPath = redirectPath + "?" + query; 415 } 416 redirectPath = urlEncoder.encodeURL(redirectPath); 418 response.sendRedirect(redirectPath); 420 return false; 421 } 422 423 427 request.parseSessionCookiesId(); 429 431 request.parseJrouteCookie(); 433 435 return true; 436 } 437 438 439 442 496 497 498 501 538 539 540 543 590 591 592 601 public static boolean normalize(MessageBytes uriMB) { 602 603 ByteChunk uriBC = uriMB.getByteChunk(); 604 byte[] b = uriBC.getBytes(); 605 int start = uriBC.getStart(); 606 int end = uriBC.getEnd(); 607 608 if ((end - start == 1) && b[start] == (byte) '*') 610 return true; 611 612 int pos = 0; 613 int index = 0; 614 615 for (pos = start; pos < end; pos++) { 618 if (b[pos] == (byte) '\\') 619 b[pos] = (byte) '/'; 620 if (b[pos] == (byte) 0) 621 return false; 622 } 623 624 if (b[start] != (byte) '/') { 626 return false; 627 } 628 629 for (pos = start; pos < (end - 1); pos++) { 631 if (b[pos] == (byte) '/') { 632 while ((pos + 1 < end) && (b[pos + 1] == (byte) '/')) { 633 copyBytes(b, pos, pos + 1, end - pos - 1); 634 end--; 635 } 636 } 637 } 638 639 if (((end - start) > 2) && (b[end - 1] == (byte) '.')) { 643 if ((b[end - 2] == (byte) '/') 644 || ((b[end - 2] == (byte) '.') 645 && (b[end - 3] == (byte) '/'))) { 646 b[end] = (byte) '/'; 647 end++; 648 } 649 } 650 651 uriBC.setEnd(end); 652 653 index = 0; 654 655 while (true) { 657 index = uriBC.indexOf("/./", 0, 3, index); 658 if (index < 0) 659 break; 660 copyBytes(b, start + index, start + index + 2, 661 end - start - index - 2); 662 end = end - 2; 663 uriBC.setEnd(end); 664 } 665 666 index = 0; 667 668 while (true) { 670 index = uriBC.indexOf("/../", 0, 4, index); 671 if (index < 0) 672 break; 673 if (index == 0) 675 return false; 676 int index2 = -1; 677 for (pos = start + index - 1; (pos >= 0) && (index2 < 0); pos --) { 678 if (b[pos] == (byte) '/') { 679 index2 = pos; 680 } 681 } 682 copyBytes(b, start + index2, start + index + 3, 683 end - start - index - 3); 684 end = end + index2 - index - 3; 685 uriBC.setEnd(end); 686 index = index2; 687 } 688 689 uriBC.setBytes(b, start, end); 690 691 return true; 692 693 } 694 695 696 698 699 703 protected static void copyBytes(byte[] b, int dest, int src, int len) { 704 for (int pos = 0; pos < len; pos++) { 705 b[pos + dest] = b[pos + src]; 706 } 707 } 708 709 710 715 protected void log(String message) { 716 log.info( message ); 717 } 718 719 720 726 protected void log(String message, Throwable throwable) { 727 log.error( message, throwable); 728 } 729 730 731 734 756 757 758 767 public void fireAdapterEvent(String type, Object data) { 768 if ( connector != null && connector.getContainer() != null) { 769 try{ 770 ((ContainerBase)connector.getContainer()) 771 .fireContainerEvent(type,data); 772 } catch (Throwable t){ 773 log.error(sm.getString("coyoteAdapter.service"), t); 774 } 775 } 776 } 777 779 } 780 | Popular Tags |