1 16 17 package org.apache.ajp; 18 19 import java.io.ByteArrayInputStream ; 20 import java.io.IOException ; 21 import java.security.cert.CertificateFactory ; 22 import java.security.cert.X509Certificate ; 23 24 import org.apache.tomcat.util.buf.ByteChunk; 25 import org.apache.tomcat.util.buf.MessageBytes; 26 import org.apache.tomcat.util.http.BaseRequest; 27 import org.apache.tomcat.util.http.HttpMessages; 28 import org.apache.tomcat.util.http.MimeHeaders; 29 30 31 51 public class RequestHandler extends AjpHandler 52 { 53 55 public static final byte JK_AJP13_FORWARD_REQUEST = 2; 57 public static final byte JK_AJP13_SHUTDOWN = 7; 58 public static final byte JK_AJP13_PING_REQUEST = 8; 59 public static final byte JK_AJP13_CPING_REQUEST = 10; 60 61 public static final byte JK_AJP13_SEND_BODY_CHUNK = 3; 63 public static final byte JK_AJP13_SEND_HEADERS = 4; 64 public static final byte JK_AJP13_END_RESPONSE = 5; 65 public static final byte JK_AJP13_GET_BODY_CHUNK = 6; 66 public static final byte JK_AJP13_CPONG_REPLY = 9; 67 68 public static final int SC_RESP_CONTENT_TYPE = 0xA001; 70 public static final int SC_RESP_CONTENT_LANGUAGE = 0xA002; 71 public static final int SC_RESP_CONTENT_LENGTH = 0xA003; 72 public static final int SC_RESP_DATE = 0xA004; 73 public static final int SC_RESP_LAST_MODIFIED = 0xA005; 74 public static final int SC_RESP_LOCATION = 0xA006; 75 public static final int SC_RESP_SET_COOKIE = 0xA007; 76 public static final int SC_RESP_SET_COOKIE2 = 0xA008; 77 public static final int SC_RESP_SERVLET_ENGINE = 0xA009; 78 public static final int SC_RESP_STATUS = 0xA00A; 79 public static final int SC_RESP_WWW_AUTHENTICATE = 0xA00B; 80 81 public static final byte SC_A_CONTEXT = 1; public static final byte SC_A_SERVLET_PATH = 2; public static final byte SC_A_REMOTE_USER = 3; 85 public static final byte SC_A_AUTH_TYPE = 4; 86 public static final byte SC_A_QUERY_STRING = 5; 87 public static final byte SC_A_JVM_ROUTE = 6; 88 public static final byte SC_A_SSL_CERT = 7; 89 public static final byte SC_A_SSL_CIPHER = 8; 90 public static final byte SC_A_SSL_SESSION = 9; 91 public static final byte SC_A_SSL_KEY_SIZE = 11; public static final byte SC_A_SECRET = 12; 93 public static final byte SC_A_STORED_METHOD = 13; 94 95 public static final byte SC_A_REQ_ATTRIBUTE = 10; 97 98 public static final byte SC_A_ARE_DONE = (byte)0xFF; 100 101 public static final String []methodTransArray = { 103 "OPTIONS", 104 "GET", 105 "HEAD", 106 "POST", 107 "PUT", 108 "DELETE", 109 "TRACE", 110 "PROPFIND", 111 "PROPPATCH", 112 "MKCOL", 113 "COPY", 114 "MOVE", 115 "LOCK", 116 "UNLOCK", 117 "ACL", 118 "REPORT", 119 "VERSION-CONTROL", 120 "CHECKIN", 121 "CHECKOUT", 122 "UNCHECKOUT", 123 "SEARCH", 124 "MKWORKSPACE", 125 "UPDATE", 126 "LABEL", 127 "MERGE", 128 "BASELINE-CONTROL", 129 "MKACTIVITY" 130 }; 131 public static final int SC_M_JK_STORED = (byte) 0xFF; 132 133 134 public static final int SC_REQ_ACCEPT = 1; 136 public static final int SC_REQ_ACCEPT_CHARSET = 2; 137 public static final int SC_REQ_ACCEPT_ENCODING = 3; 138 public static final int SC_REQ_ACCEPT_LANGUAGE = 4; 139 public static final int SC_REQ_AUTHORIZATION = 5; 140 public static final int SC_REQ_CONNECTION = 6; 141 public static final int SC_REQ_CONTENT_TYPE = 7; 142 public static final int SC_REQ_CONTENT_LENGTH = 8; 143 public static final int SC_REQ_COOKIE = 9; 144 public static final int SC_REQ_COOKIE2 = 10; 145 public static final int SC_REQ_HOST = 11; 146 public static final int SC_REQ_PRAGMA = 12; 147 public static final int SC_REQ_REFERER = 13; 148 public static final int SC_REQ_USER_AGENT = 14; 149 150 public static final String []headerTransArray = { 152 "accept", 153 "accept-charset", 154 "accept-encoding", 155 "accept-language", 156 "authorization", 157 "connection", 158 "content-type", 159 "content-length", 160 "cookie", 161 "cookie2", 162 "host", 163 "pragma", 164 "referer", 165 "user-agent" 166 }; 167 168 public RequestHandler() 169 { 170 } 171 172 public void init( Ajp13 ajp14 ) { 173 ajp14.registerMessageType( JK_AJP13_FORWARD_REQUEST, 175 "JK_AJP13_FORWARD_REQUEST", 176 this, null); ajp14.registerMessageType( JK_AJP13_SEND_BODY_CHUNK, "JK_AJP13_SEND_BODY_CHUNK", 180 this,null ); 181 ajp14.registerMessageType( JK_AJP13_SEND_HEADERS, "JK_AJP13_SEND_HEADERS", 183 this,null ); 184 ajp14.registerMessageType( JK_AJP13_END_RESPONSE, "JK_AJP13_END_RESPONSE", 186 this,null ); 187 ajp14.registerMessageType( JK_AJP13_GET_BODY_CHUNK, "JK_AJP13_GET_BODY_CHUNK", 189 this, null ); 190 ajp14.registerMessageType( JK_AJP13_CPING_REQUEST, 191 "JK_AJP13_PING_REQUEST", 192 this, null); ajp14.registerMessageType( JK_AJP13_CPONG_REPLY, 194 "JK_AJP13_PONG_REPLY", 195 this, null); } 197 198 204 public int sendCPong(Ajp13 ch, Ajp13Packet outBuf) 205 { 206 outBuf.reset(); 207 outBuf.appendByte(JK_AJP13_CPONG_REPLY); 208 209 try 210 { 211 ch.send(outBuf); 212 } 213 catch (IOException ioe) 214 { 215 log("can't send pong reply"); 216 } 217 218 return (999); } 220 221 public int handleAjpMessage( int type, Ajp13 channel, 223 Ajp13Packet ajp, BaseRequest req ) 224 throws IOException 225 { 226 switch( type ) { 227 case RequestHandler.JK_AJP13_FORWARD_REQUEST: 228 return decodeRequest(channel, channel.hBuf, req ); 229 230 default: 231 return UNKNOWN; 232 } 233 } 234 235 246 protected int decodeRequest(Ajp13 ch, Ajp13Packet msg, BaseRequest req) 247 throws IOException 248 { 249 250 if (debug > 0) { 251 log("decodeRequest()"); 252 } 253 254 256 boolean isSSL = false; 257 258 byte methodCode = msg.getByte(); 260 if (methodCode != SC_M_JK_STORED) 261 req.method().setString(methodTransArray[(int)methodCode - 1]); 262 263 msg.getMessageBytes(req.protocol()); 264 msg.getMessageBytes(req.requestURI()); 265 266 msg.getMessageBytes(req.remoteAddr()); 267 msg.getMessageBytes(req.remoteHost()); 268 msg.getMessageBytes(req.serverName()); 269 req.setServerPort(msg.getInt()); 270 271 isSSL = msg.getBool(); 272 273 MimeHeaders headers = req.headers(); 275 int hCount = msg.getInt(); 276 for(int i = 0 ; i < hCount ; i++) { 277 String hName = null; 278 279 int isc = msg.peekInt(); 283 int hId = isc & 0xFF; 284 285 MessageBytes vMB=null; 286 isc &= 0xFF00; 287 if(0xA000 == isc) { 288 msg.getInt(); hName = headerTransArray[hId - 1]; 293 vMB= headers.addValue(hName); 294 msg.getMessageBytes(vMB); 295 296 if (hId == SC_REQ_CONTENT_LENGTH) { 297 int contentLength = (vMB == null) ? -1 : vMB.getInt(); 299 req.setContentLength(contentLength); 300 } else if (hId == SC_REQ_CONTENT_TYPE) { 301 ByteChunk bchunk = vMB.getByteChunk(); 303 req.contentType().setBytes(bchunk.getBytes(), 304 bchunk.getOffset(), 305 bchunk.getLength()); 306 } else if (hId == SC_REQ_AUTHORIZATION) { 307 ByteChunk bchunk = vMB.getByteChunk(); 308 req.authorization().setBytes(bchunk.getBytes(), 309 bchunk.getOffset(), 310 bchunk.getLength()); 311 } 312 } else { 313 vMB = msg.addHeader(headers); 318 if (vMB == null) { 319 return 500; } 321 msg.getMessageBytes(vMB); 322 } 323 } 324 325 byte attributeCode; 326 for(attributeCode = msg.getByte() ; 327 attributeCode != SC_A_ARE_DONE ; 328 attributeCode = msg.getByte()) { 329 switch(attributeCode) { 330 case SC_A_CONTEXT : 331 break; 332 333 case SC_A_SERVLET_PATH : 334 break; 335 336 case SC_A_REMOTE_USER : 337 msg.getMessageBytes(req.remoteUser()); 338 break; 339 340 case SC_A_AUTH_TYPE : 341 msg.getMessageBytes(req.authType()); 342 break; 343 344 case SC_A_QUERY_STRING : 345 msg.getMessageBytes(req.queryString()); 346 break; 347 348 case SC_A_JVM_ROUTE : 349 msg.getMessageBytes(req.jvmRoute()); 350 break; 351 352 case SC_A_SSL_CERT : 353 isSSL = true; 354 String certString = msg.getString(); 356 byte[] certData = certString.getBytes(); 357 ByteArrayInputStream bais = new ByteArrayInputStream (certData); 358 359 X509Certificate jsseCerts[] = null; 361 try { 362 CertificateFactory cf = 363 CertificateFactory.getInstance("X.509"); 364 X509Certificate cert = (X509Certificate ) 365 cf.generateCertificate(bais); 366 jsseCerts = new X509Certificate [1]; 367 jsseCerts[0] = cert; 368 } catch(java.security.cert.CertificateException e) { 369 log("Certificate convertion failed" + e ); 370 } 371 372 req.setAttribute("javax.servlet.request.X509Certificate", 373 jsseCerts); 374 break; 375 376 case SC_A_SSL_CIPHER : 377 isSSL = true; 378 req.setAttribute("javax.servlet.request.cipher_suite", 379 msg.getString()); 380 break; 381 382 case SC_A_SECRET : 383 String secret=msg.getString(); 388 if(secret!=null) { 389 ch.setSecret( secret ); 390 } 391 break; 392 393 case SC_A_SSL_SESSION : 394 isSSL = true; 395 req.setAttribute("javax.servlet.request.ssl_session", 396 msg.getString()); 397 break; 398 399 case SC_A_REQ_ATTRIBUTE : 400 req.setAttribute(msg.getString(), 401 msg.getString()); 402 break; 403 404 case SC_A_SSL_KEY_SIZE: isSSL = true; 406 req.setAttribute("javax.servlet.request.key_size", 407 Integer.toString(msg.getInt())); 408 break; 409 410 case SC_A_STORED_METHOD: 411 req.method().setString(msg.getString()); 412 break; 413 414 default: 415 msg.getString(); 418 break; 419 } 420 } 421 422 if(isSSL) { 423 req.setScheme(req.SCHEME_HTTPS); 424 req.setSecure(true); 425 } 426 427 req.cookies().setHeaders(req.headers()); 429 430 if(req.getContentLength() > 0) { 433 434 435 int err = ch.receive(ch.inBuf); 436 if(err < 0) { 437 return 500; 438 } 439 440 ch.blen = ch.inBuf.peekInt(); 441 ch.pos = 0; 442 ch.inBuf.getBytes(ch.bodyBuff); 443 } 444 445 if (debug > 5) { 446 log(req.toString()); 447 } 448 449 return 200; } 451 452 453 455 462 public void sendHeaders(Ajp13 ch, Ajp13Packet outBuf, 463 int status, String statusMessage, 464 MimeHeaders headers) 465 throws IOException 466 { 467 if( statusMessage==null ) statusMessage=HttpMessages.getMessage(status); 469 outBuf.reset(); 470 outBuf.appendByte(JK_AJP13_SEND_HEADERS); 471 outBuf.appendInt(status); 472 473 outBuf.appendString(statusMessage); 474 475 int numHeaders = headers.size(); 476 outBuf.appendInt(numHeaders); 477 478 for( int i=0 ; i < numHeaders ; i++ ) { 479 String headerName = headers.getName(i).toString(); 480 int sc = headerNameToSc(headerName); 481 if(-1 != sc) { 482 outBuf.appendInt(sc); 483 } else { 484 outBuf.appendString(headerName); 485 } 486 outBuf.appendString(headers.getValue(i).toString() ); 487 } 488 489 outBuf.end(); 490 ch.send(outBuf); 491 } 492 493 494 498 public void finish(Ajp13 ch, Ajp13Packet outBuf) throws IOException { 499 if (debug > 0) log("finish()"); 500 501 outBuf.reset(); 502 outBuf.appendByte(JK_AJP13_END_RESPONSE); 503 outBuf.appendBool(true); outBuf.end(); 505 ch.send(outBuf); 506 } 507 508 516 public void doWrite(Ajp13 ch, Ajp13Packet outBuf, 517 byte b[], int off, int len) 518 throws IOException 519 { 520 if (debug > 0) log("doWrite(byte[], " + off + ", " + len + ")"); 521 522 int sent = 0; 523 while(sent < len) { 524 int to_send = len - sent; 525 to_send = to_send > Ajp13.MAX_SEND_SIZE ? Ajp13.MAX_SEND_SIZE : to_send; 526 527 outBuf.reset(); 528 outBuf.appendByte(JK_AJP13_SEND_BODY_CHUNK); 529 outBuf.appendBytes(b, off + sent, to_send); 530 ch.send(outBuf); 531 sent += to_send; 532 } 533 } 534 535 537 545 protected int headerNameToSc(String name) 546 { 547 switch(name.charAt(0)) { 548 case 'c': 549 case 'C': 550 if(name.equalsIgnoreCase("Content-Type")) { 551 return SC_RESP_CONTENT_TYPE; 552 } else if(name.equalsIgnoreCase("Content-Language")) { 553 return SC_RESP_CONTENT_LANGUAGE; 554 } else if(name.equalsIgnoreCase("Content-Length")) { 555 return SC_RESP_CONTENT_LENGTH; 556 } 557 break; 558 559 case 'd': 560 case 'D': 561 if(name.equalsIgnoreCase("Date")) { 562 return SC_RESP_DATE; 563 } 564 break; 565 566 case 'l': 567 case 'L': 568 if(name.equalsIgnoreCase("Last-Modified")) { 569 return SC_RESP_LAST_MODIFIED; 570 } else if(name.equalsIgnoreCase("Location")) { 571 return SC_RESP_LOCATION; 572 } 573 break; 574 575 case 's': 576 case 'S': 577 if(name.equalsIgnoreCase("Set-Cookie")) { 578 return SC_RESP_SET_COOKIE; 579 } else if(name.equalsIgnoreCase("Set-Cookie2")) { 580 return SC_RESP_SET_COOKIE2; 581 } 582 break; 583 584 case 'w': 585 case 'W': 586 if(name.equalsIgnoreCase("WWW-Authenticate")) { 587 return SC_RESP_WWW_AUTHENTICATE; 588 } 589 break; 590 } 591 592 return -1; 593 } 594 595 private int debug=0; 596 private Logger logger = new Logger(); 597 598 public void setDebug(int debug) { 599 this.debug = debug; 600 } 601 602 public void setLogger(Logger l) { 603 this.logger = l; 604 } 605 606 void log(String s) { 607 logger.log("[RequestHandler] " + s ); 608 } 609 610 613 public int available(Ajp13 ch) throws IOException { 614 if (debug > 0) { 615 log("available()"); 616 } 617 618 if (ch.pos >= ch.blen) { 619 if( ! refillReadBuffer(ch)) { 620 return 0; 621 } 622 } 623 return ch.blen - ch.pos; 624 } 625 626 629 public int doRead(Ajp13 ch) throws IOException 630 { 631 if (debug > 0) { 632 log("doRead()"); 633 } 634 635 if(ch.pos >= ch.blen) { 636 if( ! refillReadBuffer(ch)) { 637 return -1; 638 } 639 } 640 return ch.bodyBuff[ch.pos++] & 0xFF; 641 } 642 643 653 public int doRead(Ajp13 ch, byte[] b, int off, int len) throws IOException 654 { 655 if (debug > 0) { 656 log("doRead(byte[], int, int)"); 657 } 658 659 if(ch.pos >= ch.blen) { 660 if( ! refillReadBuffer(ch)) { 661 return -1; 662 } 663 } 664 665 if(ch.pos + len <= ch.blen) { System.arraycopy(ch.bodyBuff, ch.pos, b, off, len); 668 ch.pos += len; 669 return len; 670 } 671 672 int toCopy = len; 674 while(toCopy > 0) { 675 int bytesRemaining = ch.blen - ch.pos; 676 if(bytesRemaining < 0) 677 bytesRemaining = 0; 678 int c = bytesRemaining < toCopy ? bytesRemaining : toCopy; 679 680 System.arraycopy(ch.bodyBuff, ch.pos, b, off, c); 681 682 toCopy -= c; 683 684 off += c; 685 ch.pos += c; 687 if(toCopy > 0) 688 if( ! refillReadBuffer(ch)) { break; 690 } 691 } 692 693 return len - toCopy; 694 } 695 696 702 public boolean refillReadBuffer(Ajp13 ch) throws IOException 703 { 704 if (debug > 0) { 705 log("refillReadBuffer()"); 706 } 707 708 711 ch.inBuf.reset(); 713 ch.inBuf.appendByte(JK_AJP13_GET_BODY_CHUNK); 714 ch.inBuf.appendInt(Ajp13.MAX_READ_SIZE); 715 ch.send(ch.inBuf); 716 717 int err = ch.receive(ch.inBuf); 718 if(err < 0) { 719 throw new IOException (); 720 } 721 722 if (ch.inBuf.getLen() == 0) { 724 if (debug > 0) { 725 log("refillReadBuffer(): " 726 + "received empty packet -> end of stream"); 727 } 728 ch.blen = 0; 729 ch.pos = 0; 730 return false; 731 } 732 733 ch.blen = ch.inBuf.peekInt(); 734 ch.pos = 0; 735 ch.inBuf.getBytes(ch.bodyBuff); 736 737 return (ch.blen > 0); 738 } 739 740 742 744 public void beginSendHeaders(Ajp13 ch, Ajp13Packet outBuf, 745 int status, 746 String statusMessage, 747 int numHeaders) throws IOException { 748 749 if (debug > 0) { 750 log("sendHeaders()"); 751 } 752 753 755 outBuf.reset(); 756 outBuf.appendByte(JK_AJP13_SEND_HEADERS); 757 758 if (debug > 0) { 759 log("status is: " + status + 760 "(" + statusMessage + ")"); 761 } 762 763 outBuf.appendInt(status); 765 outBuf.appendString(statusMessage); 766 767 outBuf.appendInt(numHeaders); 769 } 770 771 public void sendHeader(Ajp13Packet outBuf, 772 String name, String value) 773 throws IOException 774 { 775 int sc = headerNameToSc(name); 776 if(-1 != sc) { 777 outBuf.appendInt(sc); 778 } else { 779 outBuf.appendString(name); 780 } 781 outBuf.appendString(value); 782 } 783 784 public void endSendHeaders(Ajp13 ch, Ajp13Packet outBuf) 785 throws IOException 786 { 787 outBuf.end(); 788 ch.send(outBuf); 789 } 790 791 797 public void sendHeaders(Ajp13 ch, Ajp13Packet outBuf, 798 int status, MimeHeaders headers) 799 throws IOException 800 { 801 sendHeaders(ch, outBuf, status, HttpMessages.getMessage(status), 802 headers); 803 } 804 805 806 } 807 | Popular Tags |