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
31
32
33
34 public class Ajp13Parser implements Parser
35 {
36 private final static int STATE_START = -1;
37 private final static int STATE_END = 0;
38 private final static int STATE_AJP13CHUNK_START = 1;
39 private final static int STATE_AJP13CHUNK = 2;
40
41 private int _state = STATE_START;
42 private long _contentLength;
43 private long _contentPosition;
44 private int _chunkLength;
45 private int _chunkPosition;
46 private int _headers;
47 private Buffers _buffers;
48 private EndPoint _endp;
49 private Buffer _buffer;
50 private Buffer _header;
51 private Buffer _body;
52 private View _contentView = new View();
53 private EventHandler _handler;
54 private Ajp13Generator _generator;
55 private View _tok0;
56 private View _tok1;
57 protected int _length;
58 protected int _packetLength;
59
60
61
62 public Ajp13Parser(Buffers buffers, EndPoint endPoint)
63 {
64 _buffers = buffers;
65 _endp = endPoint;
66 }
67
68
69 public void setEventHandler(EventHandler handler)
70 {
71 _handler=handler;
72 }
73
74
75 public void setGenerator(Ajp13Generator generator)
76 {
77 _generator=generator;
78 }
79
80
81 public long getContentLength()
82 {
83 return _contentLength;
84 }
85
86
87 public int getState()
88 {
89 return _state;
90 }
91
92
93 public boolean inContentState()
94 {
95 return _state > 0;
96 }
97
98
99 public boolean inHeaderState()
100 {
101 return _state < 0;
102 }
103
104
105 public boolean isIdle()
106 {
107 return _state == STATE_START;
108 }
109
110
111 public boolean isComplete()
112 {
113 return _state == STATE_END;
114 }
115
116
117 public boolean isMoreInBuffer()
118 {
119
120 if (_header != null && _header.hasContent() || _body != null && _body.hasContent())
121 return true;
122
123 return false;
124 }
125
126
127 public boolean isState(int state)
128 {
129 return _state == state;
130 }
131
132
133 public void parse() throws IOException
134 {
135 if (_state == STATE_END)
136 reset();
137 if (_state != STATE_START)
138 throw new IllegalStateException("!START");
139
140
141 while (!isComplete())
142 {
143 parseNext();
144 }
145 }
146
147
148 public int parseAvailable() throws IOException
149 {
150 int len = parseNext();
151 int total = len > 0 ? len : 0;
152
153
154 while (!isComplete() && _buffer != null && _buffer.length() > 0)
155 {
156 len = parseNext();
157 if (len > 0)
158 total += len;
159 else
160 break;
161 }
162 return total;
163 }
164
165
166 private int fill() throws IOException
167 {
168 int filled = -1;
169 if (_body != null && _buffer != _body)
170 {
171
172
173
174 if(_header.length() > 0)
175 {
176
177 _body.put(_header);
178 }
179
180 _buffer = _body;
181
182 if (_buffer.length()>0)
183 {
184 filled = _buffer.length();
185 return filled;
186 }
187 }
188
189 if (_buffer.markIndex() == 0 && _buffer.putIndex() == _buffer.capacity())
190 throw new IOException("FULL");
191 if (_endp != null && filled <= 0)
192 {
193
194
195 if (_buffer == _body)
196 _buffer.compact();
197
198 if (_buffer.space() == 0)
199 throw new IOException("FULL");
200
201 try
202 {
203 filled = _endp.fill(_buffer);
204 }
205 catch (IOException e)
206 {
207
208 Log.debug(e);
209 reset();
210 throw (e instanceof EofException) ? e : new EofException(e);
211 }
212 }
213
214 if (filled < 0)
215 {
216 if (_state > STATE_END)
217 {
218 _state = STATE_END;
219 _handler.messageComplete(_contentPosition);
220 return filled;
221 }
222 reset();
223 throw new EofException();
224 }
225
226 return filled;
227 }
228
229 volatile int _seq=0;
230
231 public int parseNext() throws IOException
232 {
233 int total_filled = 0;
234
235 if (_buffer == null)
236 {
237 if (_header == null)
238 _header = _buffers.getHeader();
239
240 _buffer = _header;
241 _tok0 = new View(_header);
242 _tok1 = new View(_header);
243 _tok0.setPutIndex(_tok0.getIndex());
244 _tok1.setPutIndex(_tok1.getIndex());
245 }
246
247 if (_state == STATE_END)
248 throw new IllegalStateException("STATE_END");
249 if (_state > STATE_END && _contentPosition == _contentLength)
250 {
251 _state = STATE_END;
252 _handler.messageComplete(_contentPosition);
253 return 1;
254 }
255
256 if (_state < 0)
257 {
258
259 if (_packetLength<=0)
260 {
261 if (_buffer.length()<4)
262 {
263 if (total_filled<0)
264 total_filled=0;
265 total_filled+=fill();
266 if (_buffer.length()<4)
267 return total_filled;
268 }
269
270 _contentLength = HttpTokens.UNKNOWN_CONTENT;
271 int _magic = Ajp13RequestPacket.getInt(_buffer);
272 if (_magic != Ajp13RequestHeaders.MAGIC)
273 throw new IOException("Bad AJP13 rcv packet: " + "0x" + Integer.toHexString(_magic) + " expected " + "0x" + Integer.toHexString(Ajp13RequestHeaders.MAGIC) + " " + this);
274
275
276 _packetLength = Ajp13RequestPacket.getInt(_buffer);
277 if (_packetLength > Ajp13Packet.MAX_PACKET_SIZE)
278 throw new IOException("AJP13 packet (" + _packetLength + "bytes) too large for buffer");
279
280 }
281
282 if (_buffer.length() < _packetLength)
283 {
284 if (total_filled<0)
285 total_filled=0;
286 total_filled+=fill();
287 if (_buffer.length() < _packetLength)
288 return total_filled;
289 }
290
291
292 Buffer bufHeaderName = null;
293 Buffer bufHeaderValue = null;
294 int attr_type = 0;
295
296 byte packetType = Ajp13RequestPacket.getByte(_buffer);
297
298 switch (packetType)
299 {
300 case Ajp13Packet.FORWARD_REQUEST_ORDINAL:
301 _handler.startForwardRequest();
302 break;
303 case Ajp13Packet.CPING_REQUEST_ORDINAL:
304 (_generator).sendCPong();
305
306 if(_header != null)
307 {
308 _buffers.returnBuffer(_header);
309 _header = null;
310 }
311
312 if(_body != null)
313 {
314 _buffers.returnBuffer(_body);
315 _body = null;
316 }
317
318 _buffer= null;
319
320 reset();
321
322 return -1;
323 case Ajp13Packet.SHUTDOWN_ORDINAL:
324 shutdownRequest();
325
326 return -1;
327
328 default:
329
330
331 Log.warn("AJP13 message type ({PING}: "+packetType+" ) not supported/recognized as an AJP request");
332 throw new IllegalStateException("PING is not implemented");
333 }
334
335
336 _handler.parsedMethod(Ajp13RequestPacket.getMethod(_buffer));
337 _handler.parsedProtocol(Ajp13RequestPacket.getString(_buffer, _tok0));
338 _handler.parsedUri(Ajp13RequestPacket.getString(_buffer, _tok1));
339 _handler.parsedRemoteAddr(Ajp13RequestPacket.getString(_buffer, _tok1));
340 _handler.parsedRemoteHost(Ajp13RequestPacket.getString(_buffer, _tok1));
341 _handler.parsedServerName(Ajp13RequestPacket.getString(_buffer, _tok1));
342 _handler.parsedServerPort(Ajp13RequestPacket.getInt(_buffer));
343 _handler.parsedSslSecure(Ajp13RequestPacket.getBool(_buffer));
344
345
346 _headers = Ajp13RequestPacket.getInt(_buffer);
347
348 for (int h=0;h<_headers;h++)
349 {
350 bufHeaderName = Ajp13RequestPacket.getHeaderName(_buffer, _tok0);
351 bufHeaderValue = Ajp13RequestPacket.getString(_buffer, _tok1);
352
353 if (bufHeaderName != null && bufHeaderName.toString().equals(Ajp13RequestHeaders.CONTENT_LENGTH))
354 {
355 _contentLength = BufferUtil.toLong(bufHeaderValue);
356 if (_contentLength == 0)
357 _contentLength = HttpTokens.NO_CONTENT;
358 }
359
360 _handler.parsedHeader(bufHeaderName, bufHeaderValue);
361 }
362
363
364
365 attr_type = Ajp13RequestPacket.getByte(_buffer) & 0xff;
366 while (attr_type != 0xFF)
367 {
368 switch (attr_type)
369 {
370
371
372
373
374 case Ajp13RequestHeaders.REMOTE_USER_ATTR:
375 _handler.parsedRemoteUser(Ajp13RequestPacket.getString(_buffer, _tok1));
376 break;
377 case Ajp13RequestHeaders.AUTH_TYPE_ATTR:
378
379 _handler.parsedAuthorizationType(Ajp13RequestPacket.getString(_buffer, _tok1));
380 break;
381
382 case Ajp13RequestHeaders.QUERY_STRING_ATTR:
383 _handler.parsedQueryString(Ajp13RequestPacket.getString(_buffer, _tok1));
384 break;
385
386 case Ajp13RequestHeaders.JVM_ROUTE_ATTR:
387
388
389 _handler.parsedRequestAttribute("org.eclipse.jetty.ajp.JVMRoute", Ajp13RequestPacket.getString(_buffer, _tok1));
390 break;
391
392 case Ajp13RequestHeaders.SSL_CERT_ATTR:
393 _handler.parsedSslCert(Ajp13RequestPacket.getString(_buffer, _tok1));
394 break;
395
396 case Ajp13RequestHeaders.SSL_CIPHER_ATTR:
397 _handler.parsedSslCipher(Ajp13RequestPacket.getString(_buffer, _tok1));
398
399 break;
400
401 case Ajp13RequestHeaders.SSL_SESSION_ATTR:
402 _handler.parsedSslSession(Ajp13RequestPacket.getString(_buffer, _tok1));
403 break;
404
405 case Ajp13RequestHeaders.REQUEST_ATTR:
406 _handler.parsedRequestAttribute(Ajp13RequestPacket.getString(_buffer, _tok0).toString(), Ajp13RequestPacket.getString(_buffer, _tok1));
407 break;
408
409
410
411
412
413
414 case Ajp13RequestHeaders.SSL_KEYSIZE_ATTR:
415
416
417
418
419
420 int length = Ajp13RequestPacket.getInt(_buffer);
421
422 if (length>0 && length<16)
423 {
424
425 _buffer.skip(-2);
426 _handler.parsedSslKeySize(Integer.parseInt(Ajp13RequestPacket.getString(_buffer, _tok1).toString()));
427 }
428 else
429 _handler.parsedSslKeySize(length);
430
431 break;
432
433
434
435
436
437
438 case Ajp13RequestHeaders.SECRET_ATTR:
439
440
441
442
443
444 break;
445
446 case Ajp13RequestHeaders.STORED_METHOD_ATTR:
447
448
449
450
451 break;
452
453
454 case Ajp13RequestHeaders.CONTEXT_ATTR:
455 _handler.parsedContextPath(Ajp13RequestPacket.getString(_buffer, _tok1));
456 break;
457 case Ajp13RequestHeaders.SERVLET_PATH_ATTR:
458 _handler.parsedServletPath(Ajp13RequestPacket.getString(_buffer, _tok1));
459
460 break;
461 default:
462 Log.warn("Unsupported Ajp13 Request Attribute {}", new Integer(attr_type));
463 break;
464 }
465
466 attr_type = Ajp13RequestPacket.getByte(_buffer) & 0xff;
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();
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();
498 _body.clear();
499
500 }
501 _state = STATE_AJP13CHUNK_START;
502 _handler.headerComplete();
503 return total_filled;
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 break;
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,remaining);
574
575 _contentPosition+=chunk.length();
576 _chunkPosition+=chunk.length();
577 _contentView.update(chunk);
578
579 remaining=_chunkLength-_chunkPosition;
580
581 if (remaining==0)
582 {
583 _state=STATE_AJP13CHUNK_START;
584 if (_contentPosition<_contentLength || _contentLength == HttpTokens.UNKNOWN_CONTENT)
585 {
586 _generator.getBodyChunk();
587 }
588 else
589 {
590 _generator.gotBody();
591 }
592 }
593
594 _handler.content(chunk);
595
596 return total_filled;
597
598 default:
599 throw new IllegalStateException("Invalid Content State");
600
601 }
602
603 }
604
605 return total_filled;
606 }
607
608
609 public void reset()
610 {
611 _state = STATE_START;
612 _contentLength = HttpTokens.UNKNOWN_CONTENT;
613 _contentPosition = 0;
614 _length = 0;
615 _packetLength = 0;
616
617 if (_body!=null && _body.hasContent())
618 {
619
620
621
622 if (_header==null)
623 {
624 _header=_buffers.getHeader();
625 _tok0.update(_header);
626 _tok0.update(0,0);
627 _tok1.update(_header);
628 _tok1.update(0,0);
629 }
630 else
631 {
632 _header.setMarkIndex(-1);
633 _header.compact();
634 }
635 int take=_header.space();
636 if (take>_body.length())
637 take=_body.length();
638 _body.peek(_body.getIndex(),take);
639 _body.skip(_header.put(_body.peek(_body.getIndex(),take)));
640 }
641
642 if (_header!=null)
643 _header.setMarkIndex(-1);
644 if (_body!=null)
645 _body.setMarkIndex(-1);
646
647 _buffer=_header;
648 }
649
650
651
652 public void returnBuffers()
653 {
654 if (_body!=null && !_body.hasContent() && _body.markIndex()==-1)
655 {
656 if (_buffer==_body)
657 _buffer=_header;
658 if (_buffers!=null)
659 _buffers.returnBuffer(_body);
660 _body=null;
661 }
662
663 if (_header!=null && !_header.hasContent() && _header.markIndex()==-1)
664 {
665 if (_buffer==_header)
666 _buffer=null;
667 _buffers.returnBuffer(_header);
668 _header=null;
669 }
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 @Override
802 public int read() throws IOException
803 {
804 int c = -1;
805 if (blockForContent())
806 c = 0xff & _content.get();
807 return c;
808 }
809
810
811
812
813
814 @Override
815 public int read(byte[] b, int off, int len) throws IOException
816 {
817 int l = -1;
818 if (blockForContent())
819 l = _content.get(b, off, len);
820 return l;
821 }
822
823
824 private boolean blockForContent() throws IOException
825 {
826 if (_content.length() > 0)
827 return true;
828 if (_parser.isState(Ajp13Parser.STATE_END) || _parser.isState(Ajp13Parser.STATE_START))
829 return false;
830
831
832 if (_endp == null)
833 _parser.parseNext();
834
835
836 else if (_endp.isBlocking())
837 {
838 _parser.parseNext();
839
840
841 while (_content.length() == 0 && !_parser.isState(Ajp13Parser.STATE_END))
842 {
843
844 _parser.parseNext();
845 }
846 }
847 else
848 {
849 long filled = _parser.parseNext();
850 boolean blocked = false;
851
852
853
854 while (_content.length() == 0 && !_parser.isState(Ajp13Parser.STATE_END))
855 {
856
857
858 if (filled > 0)
859 blocked = false;
860 else if (filled == 0)
861 {
862 if (blocked)
863 throw new InterruptedIOException("timeout");
864
865 blocked = true;
866 _endp.blockReadable(_maxIdleTime);
867 }
868
869
870 filled = _parser.parseNext();
871 }
872 }
873
874 return _content.length() > 0;
875 }
876
877 }
878 }