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
415 int length = Ajp13RequestPacket.getInt(_buffer);
416
417 if (length>0 && length<16)
418 {
419
420 _buffer.skip(-2);
421 _handler.parsedSslKeySize(Integer.parseInt(Ajp13RequestPacket.getString(_buffer, _tok1).toString()));
422 }
423 else
424 _handler.parsedSslKeySize(length);
425
426 break;
427
428
429
430
431
432
433 case Ajp13RequestHeaders.SECRET_ATTR:
434
435
436
437
438
439 break;
440
441 case Ajp13RequestHeaders.STORED_METHOD_ATTR:
442
443
444
445
446 break;
447
448
449 case Ajp13RequestHeaders.CONTEXT_ATTR:
450 _handler.parsedContextPath(Ajp13RequestPacket.getString(_buffer, _tok1));
451 break;
452 case Ajp13RequestHeaders.SERVLET_PATH_ATTR:
453 _handler.parsedServletPath(Ajp13RequestPacket.getString(_buffer, _tok1));
454
455 break;
456 default:
457 Log.warn("Unsupported Ajp13 Request Attribute {}", new Integer(attr_type));
458 break;
459 }
460
461 attr_type = Ajp13RequestPacket.getByte(_buffer) & 0xff;
462 }
463
464
465
466
467
468
469 _contentPosition = 0;
470 switch ((int) _contentLength)
471 {
472
473 case HttpTokens.NO_CONTENT:
474 _state = STATE_END;
475 _handler.headerComplete();
476 _handler.messageComplete(_contentPosition);
477
478 break;
479
480 case HttpTokens.UNKNOWN_CONTENT:
481
482 _generator.getBodyChunk();
483 if (_buffers != null && _body == null && _buffer == _header && _header.length() <= 0)
484 {
485 _body = _buffers.getBuffer(Ajp13Packet.MAX_PACKET_SIZE);
486 _body.clear();
487 }
488 _state = STATE_AJP13CHUNK_START;
489 _handler.headerComplete();
490
491 return total_filled;
492
493 default:
494
495 if (_buffers != null && _body == null && _buffer == _header && _contentLength > (_header.capacity() - _header.getIndex()))
496 {
497 _body = _buffers.getBuffer(Ajp13Packet.MAX_PACKET_SIZE);
498 _body.clear();
499
500 }
501 _state = STATE_AJP13CHUNK_START;
502 _handler.headerComplete();
503 return total_filled;
504 }
505 }
506
507
508 Buffer chunk;
509
510 while (_state>STATE_END)
511 {
512 switch (_state)
513 {
514 case STATE_AJP13CHUNK_START:
515 if (_buffer.length()<6)
516 {
517 if (total_filled<0)
518 total_filled=0;
519 total_filled+=fill();
520 if (_buffer.length()<6)
521 return total_filled;
522 }
523 int _magic=Ajp13RequestPacket.getInt(_buffer);
524 if (_magic!=Ajp13RequestHeaders.MAGIC)
525 {
526 throw new IOException("Bad AJP13 rcv packet: "+"0x"+Integer.toHexString(_magic)+" expected "+"0x"
527 +Integer.toHexString(Ajp13RequestHeaders.MAGIC)+" "+this);
528 }
529 _chunkPosition=0;
530 _chunkLength=Ajp13RequestPacket.getInt(_buffer)-2;
531 Ajp13RequestPacket.getInt(_buffer);
532 if (_chunkLength==0)
533 {
534 _state=STATE_END;
535 _generator.gotBody();
536 _handler.messageComplete(_contentPosition);
537 return total_filled;
538 }
539 _state=STATE_AJP13CHUNK;
540
541 case STATE_AJP13CHUNK:
542 if (_buffer.length()<_chunkLength)
543 {
544 if (total_filled<0)
545 total_filled=0;
546 total_filled+=fill();
547 if (_buffer.length()<_chunkLength)
548 return total_filled;
549 }
550
551 int remaining=_chunkLength-_chunkPosition;
552
553 if (remaining==0)
554 {
555 _state=STATE_AJP13CHUNK_START;
556 if (_contentPosition<_contentLength)
557 {
558 _generator.getBodyChunk();
559 }
560 else
561 {
562 _generator.gotBody();
563 }
564
565 return total_filled;
566 }
567
568 if (_buffer.length()<remaining)
569 {
570 remaining=_buffer.length();
571 }
572
573 chunk=Ajp13RequestPacket.get(_buffer,(int)remaining);
574 _contentPosition+=chunk.length();
575 _chunkPosition+=chunk.length();
576 _contentView.update(chunk);
577
578 remaining=_chunkLength-_chunkPosition;
579
580 if (remaining==0)
581 {
582 _state=STATE_AJP13CHUNK_START;
583 if (_contentPosition<_contentLength || _contentLength == HttpTokens.UNKNOWN_CONTENT)
584 {
585 _generator.getBodyChunk();
586 }
587 else
588 {
589 _generator.gotBody();
590 }
591 }
592
593 _handler.content(chunk);
594
595 return total_filled;
596
597 default:
598 throw new IllegalStateException("Invalid Content State");
599
600 }
601
602 }
603
604 return total_filled;
605 }
606
607
608 public void reset(boolean returnBuffers)
609 {
610 _state = STATE_START;
611 _contentLength = HttpTokens.UNKNOWN_CONTENT;
612 _contentPosition = 0;
613 _length = 0;
614 _packetLength = 0;
615
616 if (_body != null)
617 {
618 if (_body.hasContent())
619 {
620 _header.setMarkIndex(-1);
621 _header.compact();
622
623
624 _body.skip(_header.put(_body));
625
626 }
627
628 if (_body.length() == 0)
629 {
630 if (_buffers != null && returnBuffers)
631 _buffers.returnBuffer(_body);
632 _body = null;
633 }
634 else
635 {
636 _body.setMarkIndex(-1);
637 _body.compact();
638 }
639 }
640
641 if (_header != null)
642 {
643 _header.setMarkIndex(-1);
644 if (!_header.hasContent() && _buffers != null && returnBuffers)
645 {
646 _buffers.returnBuffer(_header);
647 _header = null;
648 _buffer = null;
649 }
650 else
651 {
652 _header.compact();
653 _tok0.update(_header);
654 _tok0.update(0, 0);
655 _tok1.update(_header);
656 _tok1.update(0, 0);
657 }
658 }
659
660 _buffer = _header;
661 }
662
663
664 Buffer getHeaderBuffer()
665 {
666 return _buffer;
667 }
668
669 private void shutdownRequest()
670 {
671 _state = STATE_END;
672
673 if(!Ajp13SocketConnector.__allowShutdown)
674 {
675 Log.warn("AJP13: Shutdown Request is Denied, allowShutdown is set to false!!!");
676 return;
677 }
678
679 if(Ajp13SocketConnector.__secretWord != null)
680 {
681 Log.warn("AJP13: Validating Secret Word");
682 try
683 {
684 String secretWord = Ajp13RequestPacket.getString(_buffer, _tok1).toString();
685
686 if(!Ajp13SocketConnector.__secretWord.equals(secretWord))
687 {
688 Log.warn("AJP13: Shutdown Request Denied, Invalid Sercret word!!!");
689 throw new IllegalStateException("AJP13: Secret Word is Invalid: Peer has requested shutdown but, Secret Word did not match");
690 }
691 }
692 catch (Exception e)
693 {
694 Log.warn("AJP13: Secret Word is Required!!!");
695 Log.debug(e);
696 throw new IllegalStateException("AJP13: Secret Word is Required: Peer has requested shutdown but, has not provided a Secret Word");
697 }
698
699
700 Log.warn("AJP13: Shutdown Request is Denied, allowShutdown is set to false!!!");
701 return;
702 }
703
704 Log.warn("AJP13: Peer Has Requested for Shutdown!!!");
705 Log.warn("AJP13: Jetty 6 is shutting down !!!");
706 System.exit(0);
707 }
708
709
710 public interface EventHandler
711 {
712
713
714
715
716 public void content(Buffer ref) throws IOException;
717
718 public void headerComplete() throws IOException;
719
720 public void messageComplete(long contextLength) throws IOException;
721
722 public void parsedHeader(Buffer name, Buffer value) throws IOException;
723
724 public void parsedMethod(Buffer method) throws IOException;
725
726 public void parsedProtocol(Buffer protocol) throws IOException;
727
728 public void parsedQueryString(Buffer value) throws IOException;
729
730 public void parsedRemoteAddr(Buffer addr) throws IOException;
731
732 public void parsedRemoteHost(Buffer host) throws IOException;
733
734 public void parsedRequestAttribute(String key, Buffer value) throws IOException;
735
736 public void parsedRequestAttribute(String key, int value) throws IOException;
737
738 public void parsedServerName(Buffer name) throws IOException;
739
740 public void parsedServerPort(int port) throws IOException;
741
742 public void parsedSslSecure(boolean secure) throws IOException;
743
744 public void parsedUri(Buffer uri) throws IOException;
745
746 public void startForwardRequest() throws IOException;
747
748 public void parsedAuthorizationType(Buffer authType) throws IOException;
749
750 public void parsedRemoteUser(Buffer remoteUser) throws IOException;
751
752 public void parsedServletPath(Buffer servletPath) throws IOException;
753
754 public void parsedContextPath(Buffer context) throws IOException;
755
756 public void parsedSslCert(Buffer sslCert) throws IOException;
757
758 public void parsedSslCipher(Buffer sslCipher) throws IOException;
759
760 public void parsedSslSession(Buffer sslSession) throws IOException;
761
762 public void parsedSslKeySize(int keySize) throws IOException;
763
764
765
766
767
768 }
769
770
771
772
773
774
775 public static class Input extends ServletInputStream
776 {
777 private Ajp13Parser _parser;
778 private EndPoint _endp;
779 private long _maxIdleTime;
780 private View _content;
781
782
783 public Input(Ajp13Parser parser, long maxIdleTime)
784 {
785 _parser = parser;
786 _endp = parser._endp;
787 _maxIdleTime = maxIdleTime;
788 _content = _parser._contentView;
789 }
790
791
792 public int read() throws IOException
793 {
794 int c = -1;
795 if (blockForContent())
796 c = 0xff & _content.get();
797 return c;
798 }
799
800
801
802
803
804 public int read(byte[] b, int off, int len) throws IOException
805 {
806 int l = -1;
807 if (blockForContent())
808 l = _content.get(b, off, len);
809 return l;
810 }
811
812
813 private boolean blockForContent() throws IOException
814 {
815 if (_content.length() > 0)
816 return true;
817 if (_parser.isState(Ajp13Parser.STATE_END))
818 return false;
819
820
821 if (_endp == null)
822 _parser.parseNext();
823
824
825 else if (_endp.isBlocking())
826 {
827 _parser.parseNext();
828
829
830 while (_content.length() == 0 && !_parser.isState(Ajp13Parser.STATE_END))
831 {
832
833 _parser.parseNext();
834 }
835 }
836 else
837 {
838 long filled = _parser.parseNext();
839 boolean blocked = false;
840
841
842
843 while (_content.length() == 0 && !_parser.isState(Ajp13Parser.STATE_END))
844 {
845
846
847 if (filled > 0)
848 blocked = false;
849 else if (filled == 0)
850 {
851 if (blocked)
852 throw new InterruptedIOException("timeout");
853
854 blocked = true;
855 _endp.blockReadable(_maxIdleTime);
856 }
857
858
859 filled = _parser.parseNext();
860 }
861 }
862
863 return _content.length() > 0;
864 }
865
866 }
867 }