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