1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.jetty.ajp;
16
17 import java.io.IOException;
18 import java.io.InterruptedIOException;
19
20 import javax.servlet.ServletInputStream;
21
22 import org.mortbay.io.Buffer;
23 import org.mortbay.io.BufferUtil;
24 import org.mortbay.io.Buffers;
25 import org.mortbay.io.EndPoint;
26 import org.mortbay.io.View;
27 import org.mortbay.jetty.EofException;
28 import org.mortbay.jetty.HttpTokens;
29 import org.mortbay.jetty.Parser;
30 import org.mortbay.log.Log;
31
32
33
34
35 public class Ajp13Parser implements Parser
36 {
37 private final static int STATE_START = -1;
38 private final static int STATE_END = 0;
39 private final static int STATE_AJP13CHUNK_START = 1;
40 private final static int STATE_AJP13CHUNK = 2;
41
42 private int _state = STATE_START;
43 private long _contentLength;
44 private long _contentPosition;
45 private int _chunkLength;
46 private int _chunkPosition;
47 private int _headers;
48 private Buffers _buffers;
49 private EndPoint _endp;
50 private Buffer _buffer;
51 private Buffer _header;
52 private Buffer _body;
53 private View _contentView = new View();
54 private EventHandler _handler;
55 private Ajp13Generator _generator;
56 private View _tok0;
57 private View _tok1;
58 protected int _length;
59 protected int _packetLength;
60
61
62
63 public Ajp13Parser(Buffers buffers, EndPoint endPoint, EventHandler handler, Ajp13Generator generator)
64 {
65 _buffers = buffers;
66 _endp = endPoint;
67 _handler = handler;
68 _generator = generator;
69
70 }
71
72
73 public long getContentLength()
74 {
75 return _contentLength;
76 }
77
78
79 public int getState()
80 {
81 return _state;
82 }
83
84
85 public boolean inContentState()
86 {
87 return _state > 0;
88 }
89
90
91 public boolean inHeaderState()
92 {
93 return _state < 0;
94 }
95
96
97 public boolean isIdle()
98 {
99 return _state == STATE_START;
100 }
101
102
103 public boolean isComplete()
104 {
105 return _state == STATE_END;
106 }
107
108
109 public boolean isMoreInBuffer()
110 {
111
112 if (_header != null && _header.hasContent() || _body != null && _body.hasContent())
113 return true;
114
115 return false;
116 }
117
118
119 public boolean isState(int state)
120 {
121 return _state == state;
122 }
123
124
125 public void parse() throws IOException
126 {
127 if (_state == STATE_END)
128 reset(false);
129 if (_state != STATE_START)
130 throw new IllegalStateException("!START");
131
132
133 while (!isComplete())
134 {
135 parseNext();
136 }
137 }
138
139
140 public long parseAvailable() throws IOException
141 {
142 long len = parseNext();
143 long total = len > 0 ? len : 0;
144
145
146 while (!isComplete() && _buffer != null && _buffer.length() > 0)
147 {
148 len = parseNext();
149 if (len > 0)
150 total += len;
151 else
152 break;
153 }
154 return total;
155 }
156
157
158 private int fill() throws IOException
159 {
160 int filled = -1;
161 if (_body != null && _buffer != _body)
162 {
163
164
165
166 if(_header.length() > 0)
167 {
168
169 _body.put(_header);
170 }
171
172 _buffer = _body;
173
174 if (_buffer.length()>0)
175 {
176 filled = _buffer.length();
177 return filled;
178 }
179 }
180
181 if (_buffer.markIndex() == 0 && _buffer.putIndex() == _buffer.capacity())
182 throw new IOException("FULL");
183 if (_endp != null && filled <= 0)
184 {
185
186
187 if (_buffer == _body)
188 _buffer.compact();
189
190 if (_buffer.space() == 0)
191 throw new IOException("FULL");
192
193 try
194 {
195 filled = _endp.fill(_buffer);
196 }
197 catch (IOException e)
198 {
199
200 Log.debug(e);
201 reset(true);
202 throw (e instanceof EofException) ? e : new EofException(e);
203 }
204 }
205
206 if (filled < 0)
207 {
208 if (_state > STATE_END)
209 {
210 _state = STATE_END;
211 _handler.messageComplete(_contentPosition);
212 return filled;
213 }
214 reset(true);
215 throw new EofException();
216 }
217
218 return filled;
219 }
220
221
222 public long parseNext() throws IOException
223 {
224 long total_filled = -1;
225
226 if (_buffer == null)
227 {
228 if (_header == null)
229 {
230 _header = _buffers.getBuffer(Ajp13Packet.MAX_PACKET_SIZE);
231 _header.clear();
232 }
233 _buffer = _header;
234 _tok0 = new View(_header);
235 _tok1 = new View(_header);
236 _tok0.setPutIndex(_tok0.getIndex());
237 _tok1.setPutIndex(_tok1.getIndex());
238 }
239
240 if (_state == STATE_END)
241 throw new IllegalStateException("STATE_END");
242 if (_state > STATE_END && _contentPosition == _contentLength)
243 {
244 _state = STATE_END;
245 _handler.messageComplete(_contentPosition);
246 return total_filled;
247 }
248
249 if (_state < 0)
250 {
251
252 if (_packetLength<=0)
253 {
254 if (_buffer.length()<4)
255 {
256 if (total_filled<0)
257 total_filled=0;
258 total_filled+=fill();
259 if (_buffer.length()<4)
260 return total_filled;
261 }
262
263 _contentLength = HttpTokens.UNKNOWN_CONTENT;
264 int _magic = Ajp13RequestPacket.getInt(_buffer);
265 if (_magic != Ajp13RequestHeaders.MAGIC)
266 throw new IOException("Bad AJP13 rcv packet: " + "0x" + Integer.toHexString(_magic) + " expected " + "0x" + Integer.toHexString(Ajp13RequestHeaders.MAGIC) + " " + this);
267
268
269 _packetLength = Ajp13RequestPacket.getInt(_buffer);
270 if (_packetLength > Ajp13Packet.MAX_PACKET_SIZE)
271 throw new IOException("AJP13 packet (" + _packetLength + "bytes) too large for buffer");
272
273 }
274
275 if (_buffer.length() < _packetLength)
276 {
277 if (total_filled<0)
278 total_filled=0;
279 total_filled+=fill();
280 if (_buffer.length() < _packetLength)
281 return total_filled;
282 }
283
284
285 Buffer bufHeaderName = null;
286 Buffer bufHeaderValue = null;
287 int attr_type = 0;
288
289 byte packetType = Ajp13RequestPacket.getByte(_buffer);
290
291 switch (packetType)
292 {
293 case Ajp13Packet.FORWARD_REQUEST_ORDINAL:
294 _handler.startForwardRequest();
295 break;
296 case Ajp13Packet.CPING_REQUEST_ORDINAL:
297 ((Ajp13Generator) _generator).sendCPong();
298
299 if(_header != null)
300 {
301 _buffers.returnBuffer(_header);
302 _header = null;
303 }
304
305 if(_body != null)
306 {
307 _buffers.returnBuffer(_body);
308 _body = null;
309 }
310
311 _buffer= null;
312
313 reset(true);
314
315 return -1;
316 case Ajp13Packet.SHUTDOWN_ORDINAL:
317 shutdownRequest();
318
319 return -1;
320
321 default:
322
323
324 Log.warn("AJP13 message type ({PING}: "+packetType+" ) not supported/recognized as an AJP request");
325 throw new IllegalStateException("PING is not implemented");
326 }
327
328
329 _handler.parsedMethod(Ajp13RequestPacket.getMethod(_buffer));
330 _handler.parsedProtocol(Ajp13RequestPacket.getString(_buffer, _tok0));
331 _handler.parsedUri(Ajp13RequestPacket.getString(_buffer, _tok1));
332 _handler.parsedRemoteAddr(Ajp13RequestPacket.getString(_buffer, _tok1));
333 _handler.parsedRemoteHost(Ajp13RequestPacket.getString(_buffer, _tok1));
334 _handler.parsedServerName(Ajp13RequestPacket.getString(_buffer, _tok1));
335 _handler.parsedServerPort(Ajp13RequestPacket.getInt(_buffer));
336 _handler.parsedSslSecure(Ajp13RequestPacket.getBool(_buffer));
337
338
339 _headers = Ajp13RequestPacket.getInt(_buffer);
340
341 for (int h=0;h<_headers;h++)
342 {
343 bufHeaderName = Ajp13RequestPacket.getHeaderName(_buffer, _tok0);
344 bufHeaderValue = Ajp13RequestPacket.getString(_buffer, _tok1);
345
346 if (bufHeaderName != null && bufHeaderName.toString().equals(Ajp13RequestHeaders.CONTENT_LENGTH))
347 {
348 _contentLength = BufferUtil.toLong(bufHeaderValue);
349 if (_contentLength == 0)
350 _contentLength = HttpTokens.NO_CONTENT;
351 }
352
353 _handler.parsedHeader(bufHeaderName, bufHeaderValue);
354 }
355
356
357
358 attr_type = Ajp13RequestPacket.getByte(_buffer) & 0xff;
359 while (attr_type != 0xFF)
360 {
361
362 switch (attr_type)
363 {
364
365
366
367
368 case Ajp13RequestHeaders.REMOTE_USER_ATTR:
369 _handler.parsedRemoteUser(Ajp13RequestPacket.getString(_buffer, _tok1));
370 break;
371 case Ajp13RequestHeaders.AUTH_TYPE_ATTR:
372 _handler.parsedAuthorizationType(Ajp13RequestPacket.getString(_buffer, _tok1));
373 break;
374
375 case Ajp13RequestHeaders.QUERY_STRING_ATTR:
376 _handler.parsedQueryString(Ajp13RequestPacket.getString(_buffer, _tok1));
377 break;
378
379 case Ajp13RequestHeaders.JVM_ROUTE_ATTR:
380
381
382
383
384 _handler.parsedRequestAttribute("org.mortbay.http.ajp.JVMRoute", Ajp13RequestPacket.getString(_buffer, _tok1));
385 break;
386
387 case Ajp13RequestHeaders.SSL_CERT_ATTR:
388 _handler.parsedSslCert(Ajp13RequestPacket.getString(_buffer, _tok1));
389 break;
390
391 case Ajp13RequestHeaders.SSL_CIPHER_ATTR:
392 _handler.parsedSslCipher(Ajp13RequestPacket.getString(_buffer, _tok1));
393
394 break;
395
396 case Ajp13RequestHeaders.SSL_SESSION_ATTR:
397 _handler.parsedSslSession(Ajp13RequestPacket.getString(_buffer, _tok1));
398 break;
399
400 case Ajp13RequestHeaders.REQUEST_ATTR:
401 _handler.parsedRequestAttribute(Ajp13RequestPacket.getString(_buffer, _tok0).toString(), Ajp13RequestPacket.getString(_buffer, _tok1));
402 break;
403
404
405
406
407
408
409 case Ajp13RequestHeaders.SSL_KEYSIZE_ATTR:
410
411
412
413
414 int length = Ajp13RequestPacket.getInt(_buffer);
415
416 if (length>0 && length<16)
417 {
418
419 _buffer.skip(-2);
420 _handler.parsedRequestAttribute("javax.servlet.request.key_size", Ajp13RequestPacket.getString(_buffer, _tok1));
421 }
422 else
423 _handler.parsedRequestAttribute("javax.servlet.request.key_size",length);
424
425 break;
426
427
428
429
430
431
432 case Ajp13RequestHeaders.SECRET_ATTR:
433
434
435
436
437
438 break;
439
440 case Ajp13RequestHeaders.STORED_METHOD_ATTR:
441
442
443
444
445 break;
446
447
448 case Ajp13RequestHeaders.CONTEXT_ATTR:
449 _handler.parsedContextPath(Ajp13RequestPacket.getString(_buffer, _tok1));
450 break;
451 case Ajp13RequestHeaders.SERVLET_PATH_ATTR:
452 _handler.parsedServletPath(Ajp13RequestPacket.getString(_buffer, _tok1));
453
454 break;
455 default:
456 Log.warn("Unsupported Ajp13 Request Attribute {}", new Integer(attr_type));
457 break;
458 }
459
460 attr_type = Ajp13RequestPacket.getByte(_buffer) & 0xff;
461 }
462
463
464
465
466
467
468 _contentPosition = 0;
469 switch ((int) _contentLength)
470 {
471
472 case HttpTokens.NO_CONTENT:
473 _state = STATE_END;
474 _handler.headerComplete();
475 _handler.messageComplete(_contentPosition);
476
477 break;
478
479 case HttpTokens.UNKNOWN_CONTENT:
480
481 _generator.getBodyChunk();
482 if (_buffers != null && _body == null && _buffer == _header && _header.length() <= 0)
483 {
484 _body = _buffers.getBuffer(Ajp13Packet.MAX_PACKET_SIZE);
485 _body.clear();
486 }
487 _state = STATE_AJP13CHUNK_START;
488 _handler.headerComplete();
489
490 return total_filled;
491
492 default:
493
494 if (_buffers != null && _body == null && _buffer == _header && _contentLength > (_header.capacity() - _header.getIndex()))
495 {
496 _body = _buffers.getBuffer(Ajp13Packet.MAX_PACKET_SIZE);
497 _body.clear();
498
499 }
500 _state = STATE_AJP13CHUNK_START;
501 _handler.headerComplete();
502 return total_filled;
503 }
504 }
505
506
507 Buffer chunk;
508
509 while (_state>STATE_END)
510 {
511 switch (_state)
512 {
513 case STATE_AJP13CHUNK_START:
514 if (_buffer.length()<6)
515 {
516 if (total_filled<0)
517 total_filled=0;
518 total_filled+=fill();
519 if (_buffer.length()<6)
520 return total_filled;
521 }
522 int _magic=Ajp13RequestPacket.getInt(_buffer);
523 if (_magic!=Ajp13RequestHeaders.MAGIC)
524 {
525 throw new IOException("Bad AJP13 rcv packet: "+"0x"+Integer.toHexString(_magic)+" expected "+"0x"
526 +Integer.toHexString(Ajp13RequestHeaders.MAGIC)+" "+this);
527 }
528 _chunkPosition=0;
529 _chunkLength=Ajp13RequestPacket.getInt(_buffer)-2;
530 Ajp13RequestPacket.getInt(_buffer);
531 if (_chunkLength==0)
532 {
533 _state=STATE_END;
534 _generator.gotBody();
535 _handler.messageComplete(_contentPosition);
536 return total_filled;
537 }
538 _state=STATE_AJP13CHUNK;
539
540 case STATE_AJP13CHUNK:
541 if (_buffer.length()<_chunkLength)
542 {
543 if (total_filled<0)
544 total_filled=0;
545 total_filled+=fill();
546 if (_buffer.length()<_chunkLength)
547 return total_filled;
548 }
549
550 int remaining=_chunkLength-_chunkPosition;
551
552 if (remaining==0)
553 {
554 _state=STATE_AJP13CHUNK_START;
555 if (_contentPosition<_contentLength)
556 {
557 _generator.getBodyChunk();
558 }
559 else
560 {
561 _generator.gotBody();
562 }
563
564 return total_filled;
565 }
566
567 if (_buffer.length()<remaining)
568 {
569 remaining=_buffer.length();
570 }
571
572 chunk=Ajp13RequestPacket.get(_buffer,(int)remaining);
573 _contentPosition+=chunk.length();
574 _chunkPosition+=chunk.length();
575 _contentView.update(chunk);
576
577 remaining=_chunkLength-_chunkPosition;
578
579 if (remaining==0)
580 {
581 _state=STATE_AJP13CHUNK_START;
582 if (_contentPosition<_contentLength || _contentLength == HttpTokens.UNKNOWN_CONTENT)
583 {
584 _generator.getBodyChunk();
585 }
586 else
587 {
588 _generator.gotBody();
589 }
590 }
591
592 _handler.content(chunk);
593
594 return total_filled;
595
596 default:
597 throw new IllegalStateException("Invalid Content State");
598
599 }
600
601 }
602
603 return total_filled;
604 }
605
606
607 public void reset(boolean returnBuffers)
608 {
609 _state = STATE_START;
610 _contentLength = HttpTokens.UNKNOWN_CONTENT;
611 _contentPosition = 0;
612 _length = 0;
613 _packetLength = 0;
614
615 if (_body != null)
616 {
617 if (_body.hasContent())
618 {
619 _header.setMarkIndex(-1);
620 _header.compact();
621
622
623 _body.skip(_header.put(_body));
624
625 }
626
627 if (_body.length() == 0)
628 {
629 if (_buffers != null && returnBuffers)
630 _buffers.returnBuffer(_body);
631 _body = null;
632 }
633 else
634 {
635 _body.setMarkIndex(-1);
636 _body.compact();
637 }
638 }
639
640 if (_header != null)
641 {
642 _header.setMarkIndex(-1);
643 if (!_header.hasContent() && _buffers != null && returnBuffers)
644 {
645 _buffers.returnBuffer(_header);
646 _header = null;
647 _buffer = null;
648 }
649 else
650 {
651 _header.compact();
652 _tok0.update(_header);
653 _tok0.update(0, 0);
654 _tok1.update(_header);
655 _tok1.update(0, 0);
656 }
657 }
658
659 _buffer = _header;
660 }
661
662
663 Buffer getHeaderBuffer()
664 {
665 return _buffer;
666 }
667
668 private void shutdownRequest()
669 {
670 _state = STATE_END;
671
672 if(!Ajp13SocketConnector.__allowShutdown)
673 {
674 Log.warn("AJP13: Shutdown Request is Denied, allowShutdown is set to false!!!");
675 return;
676 }
677
678 if(Ajp13SocketConnector.__secretWord != null)
679 {
680 Log.warn("AJP13: Validating Secret Word");
681 try
682 {
683 String secretWord = Ajp13RequestPacket.getString(_buffer, _tok1).toString();
684
685 if(!Ajp13SocketConnector.__secretWord.equals(secretWord))
686 {
687 Log.warn("AJP13: Shutdown Request Denied, Invalid Sercret word!!!");
688 throw new IllegalStateException("AJP13: Secret Word is Invalid: Peer has requested shutdown but, Secret Word did not match");
689 }
690 }
691 catch (Exception e)
692 {
693 Log.warn("AJP13: Secret Word is Required!!!");
694 Log.debug(e);
695 throw new IllegalStateException("AJP13: Secret Word is Required: Peer has requested shutdown but, has not provided a Secret Word");
696 }
697
698
699 Log.warn("AJP13: Shutdown Request is Denied, allowShutdown is set to false!!!");
700 return;
701 }
702
703 Log.warn("AJP13: Peer Has Requested for Shutdown!!!");
704 Log.warn("AJP13: Jetty 6 is shutting down !!!");
705 System.exit(0);
706 }
707
708
709 public interface EventHandler
710 {
711
712
713
714
715 public void content(Buffer ref) throws IOException;
716
717 public void headerComplete() throws IOException;
718
719 public void messageComplete(long contextLength) throws IOException;
720
721 public void parsedHeader(Buffer name, Buffer value) throws IOException;
722
723 public void parsedMethod(Buffer method) throws IOException;
724
725 public void parsedProtocol(Buffer protocol) throws IOException;
726
727 public void parsedQueryString(Buffer value) throws IOException;
728
729 public void parsedRemoteAddr(Buffer addr) throws IOException;
730
731 public void parsedRemoteHost(Buffer host) throws IOException;
732
733 public void parsedRequestAttribute(String key, Buffer value) throws IOException;
734
735 public void parsedRequestAttribute(String key, int value) throws IOException;
736
737 public void parsedServerName(Buffer name) throws IOException;
738
739 public void parsedServerPort(int port) throws IOException;
740
741 public void parsedSslSecure(boolean secure) throws IOException;
742
743 public void parsedUri(Buffer uri) throws IOException;
744
745 public void startForwardRequest() throws IOException;
746
747 public void parsedAuthorizationType(Buffer authType) throws IOException;
748
749 public void parsedRemoteUser(Buffer remoteUser) throws IOException;
750
751 public void parsedServletPath(Buffer servletPath) throws IOException;
752
753 public void parsedContextPath(Buffer context) throws IOException;
754
755 public void parsedSslCert(Buffer sslCert) throws IOException;
756
757 public void parsedSslCipher(Buffer sslCipher) throws IOException;
758
759 public void parsedSslSession(Buffer sslSession) throws IOException;
760
761
762
763
764
765
766
767 }
768
769
770
771
772
773
774 public static class Input extends ServletInputStream
775 {
776 private Ajp13Parser _parser;
777 private EndPoint _endp;
778 private long _maxIdleTime;
779 private View _content;
780
781
782 public Input(Ajp13Parser parser, long maxIdleTime)
783 {
784 _parser = parser;
785 _endp = parser._endp;
786 _maxIdleTime = maxIdleTime;
787 _content = _parser._contentView;
788 }
789
790
791 public int read() throws IOException
792 {
793 int c = -1;
794 if (blockForContent())
795 c = 0xff & _content.get();
796 return c;
797 }
798
799
800
801
802
803 public int read(byte[] b, int off, int len) throws IOException
804 {
805 int l = -1;
806 if (blockForContent())
807 l = _content.get(b, off, len);
808 return l;
809 }
810
811
812 private boolean blockForContent() throws IOException
813 {
814 if (_content.length() > 0)
815 return true;
816 if (_parser.isState(Ajp13Parser.STATE_END))
817 return false;
818
819
820 if (_endp == null)
821 _parser.parseNext();
822
823
824 else if (_endp.isBlocking())
825 {
826 _parser.parseNext();
827
828
829 while (_content.length() == 0 && !_parser.isState(Ajp13Parser.STATE_END))
830 {
831
832 _parser.parseNext();
833 }
834 }
835 else
836 {
837 long filled = _parser.parseNext();
838 boolean blocked = false;
839
840
841
842 while (_content.length() == 0 && !_parser.isState(Ajp13Parser.STATE_END))
843 {
844
845
846 if (filled > 0)
847 blocked = false;
848 else if (filled == 0)
849 {
850 if (blocked)
851 throw new InterruptedIOException("timeout");
852
853 blocked = true;
854 _endp.blockReadable(_maxIdleTime);
855 }
856
857
858 filled = _parser.parseNext();
859 }
860 }
861
862 return _content.length() > 0;
863 }
864
865 }
866 }