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