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