File: AJPv2.html

package info (click to toggle)
jserv 1.1-3
  • links: PTS
  • area: contrib
  • in suites: potato
  • size: 4,616 kB
  • ctags: 3,003
  • sloc: sh: 7,718; java: 6,652; ansic: 4,755; makefile: 816; perl: 39; xml: 32
file content (1077 lines) | stat: -rw-r--r-- 44,982 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>

<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
<meta NAME="Author" CONTENT="Ian Kluft">
<title>Apache JServ Protocol Version 2 (AJPv2) - February 15, 1998 - Obsolete Draft</title>
</head>

<body BGCOLOR="#FFFFFF">

<p align="center"><a href="http://java.apache.org/" target="_top"><img SRC="../images/java-apache-project.gif" BORDER="0" WIDTH="609"
HEIGHT="100" ALT="The Java Apache Project"></a></p>

<h1 ALIGN="CENTER">Apache JServ Protocol Version 2 (AJPv2)</h1>

<p ALIGN="CENTER">Obsolete Draft - February 15, 1998</p>
<div align="center"><center>

<table border="0" width="80%">
  <tr>
    <td width="100%" colspan="3"><h3 align="center">Authors</h3>
    </td>
  </tr>
  <tr>
    <td width="33%">Ian Kluft <br>
    Cisco Systems <br>
    San Jose, California, USA</td>
    <td width="33%">Ed Korthof <br>
    Organic Online <br>
    San Francisco, California, USA</td>
    <td width="34%">Stefano Mazzocchi <br>
    Beta Version Productions <br>
    Pavia, Italy </td>
  </tr>
</table>
</center></div>

<h1>Status of this Document</h1>

<p>This is a pre-implementation draft of the AJPv2 protocol specification, a subject under
current discussion within the <a HREF="http://java.apache.org/" target="_top">Java Apache Project</a>.
This is a work in progress subject to revision. </p>

<blockquote>
  <p>This specification is undergoing implementation experiments but performance tests will
  guide further changes to the specs. The implementations at the time will need to adjust to
  those changes. </p>
</blockquote>

<p>This document describes an experimental design for a request protocol intended for but
not restricted to use with the Apache JServ, which runs Java Servlets as defined by
JavaSoft's Java Development Kit. </p>

<hr ALIGN="CENTER">

<h1>Abstract</h1>

<p>The original protocol that was built into Apache HTTPD's mod_jserv was purposely kept
simple for the first implementations of the module. Usage and continuing development have
led to experience indicating needs for significant new features.</p>

<p>The Apache JServ Protocol Version 2 (AJPv2) provides new features such as
keepalive-like performance improvements and the ability for the Servlet Engine to make
intermediate requests back to the HTTP for more information about its environment. The
protocol is kept sufficiently generalized that the back-end process does not necessarily
have to run Java. (The original JServ protocol had only modest dependencies on connecting
to a Java back-end, though the mod_jserv module has strong dependencies on Java.) Although
both the client and server must have prior agreement about which language is in use. </p>

<hr ALIGN="CENTER">

<h1>Table of Contents</h1>

<ul>
  <li><a HREF="#intro">Introduction</a> <ul>
      <li><a HREF="#orig-ajp">The Original JServ Protocol</a> </li>
      <li><a HREF="#improving-ajp">Improving Upon the Original JServ Protocol</a> </li>
      <li><a HREF="#ajpv2">Overview of Apache JServ Protocol Version 2 (AJPv2)</a> </li>
      <li><a HREF="#glossary">Glossary</a> </li>
    </ul>
  </li>
  <li><a HREF="#ajpv2-header">The AJPv2 Header</a> <ul>
      <li><a HREF="#ajpv2-types">The AJPv2 Packet Types and Subtypes</a> </li>
      <li><a HREF="#ajpv2-challenge">Challenge Packets</a> </li>
      <li><a HREF="#ajpv2-init">Initialization Packets</a> </li>
      <li><a HREF="#ajpv2-func">Function Packets</a> </li>
      <li><a HREF="#ajpv2-req">Request Packets</a> </li>
      <li><a HREF="#ajpv2-resp">Response Packets</a> </li>
      <li><a HREF="#ajpv2-async-event">Asynchronous Event Packets</a> </li>
      <li><a HREF="#ajpv2-proto-ctl">Protocol Control Packets</a> </li>
    </ul>
  </li>
  <li><a HREF="#ajpv2-client-state">Client-side State Transitions</a> </li>
  <li><a HREF="#ajpv2-server-state">Server-side State Transitions</a> </li>
  <li><a HREF="#ajpv2-auth">Authentication Algorithm</a> <ul>
      <li><a HREF="#ajpv2-client-config">Impacts of Pseudorandom Number Generation on Security</a>
      </li>
    </ul>
  </li>
  <li><a HREF="#ajpv2-client-config">Client-Side Protocol Configuration Parameters</a> </li>
  <li><a HREF="#ajpv2-server-config">Server-Side Protocol Configuration Parameters</a> </li>
  <li><a HREF="#implementation">Implementation Notes</a> </li>
  <li><a HREF="#refs">References</a> </li>
</ul>

<hr ALIGN="CENTER">

<h1><a NAME="intro"></a>Introduction</h1>

<p>The Apache JServ Protocol Version 2 (AJPv2) is designed as a replacement for the
original experimental protocol used by Apache HTTPD's mod_jserv module, which is used to
communicate with a separate Java servlet engine. With experience using the original JServ
protocol, the Java Apache Project is ready to develop a second-generation servlet engine
protocol. </p>

<h2><a NAME="orig-ajp"></a>The Original JServ Protocol</h2>

<p>The original protocol, written by Alexei Kosut at Organic Online in July 1997, was
deliberately kept simple according to the needs of the project at the time.</p>

<p>The protocol included a &quot;startup&quot; phase where the Apache HTTPD would start
the Java Servlet Engine process and give it an initial setting for the authentication that
will be used thereafter by all servlet requests. There was also a standalone
&quot;manual&quot; mode for the servlet engine, where no authentication would be required.
This is potentially dangerous if used without providing other protection against
intruders.</p>

<p>Then for each request, the HTTPD process would connect to the Servlet Engine via a
socket, and then send a series of ASCII text lines with request headers. The Servlet
Engine would then respond with the entire response when it was done. </p>

<h2><a NAME="improving-ajp"></a>Improving Upon the Original JServ Protocol</h2>

<p>Usage of the JServ protocol has brought about more experience in this problem domain
and the following needs: 

<ul>
  <li>The servlet output is always buffered. But unbuffered output is desirable in many cases.
  </li>
  <li>Developers have expressed a desire to be able to send requests back to the Apache HTTPD
    process for various processing with configuration information only available to the HTTPD.
    (i.e. subrequest handling, URL/path evaluation) </li>
  <li>The single-connection-per-request has been identified as a potential performance
    bottleneck. Although some sites may not be able to significantly avoid this, at sites
    which can, it should simulate the advantages of HTTP's keepalives for reducing or
    eliminating additional socket setup overhead while a client is waiting for an HTTP
    request. </li>
  <li>Logging messages for the Apache HTTPD can only be sent with the request headers. If
    they're not ready at that time for one request, they must be saved and sent during the
    header phase of the next request, guaranteeing that any late log messages for the last
    request will be lost. </li>
</ul>

<p>One option for the multiple-requests-per-session (MRPS) goal was the W3C's <a HREF="#ref-mux">MUX</a> protocol. However, since the Apache HTTPD needs to keep open for
some platforms which run single-threaded (and will continue well into the future on the
more obscure ones), MUX was determined to have excessive overhead for this purpose because
the support for arbitrary protocols introduces generalization not necessary in this
environment.</p>

<h2><a NAME="ajpv2"></a>Overview of Apache JServ Protocol Version 2 (AJPv2)</h2>

<p>The lifetime of an AJPv2 connection begins when the socket is established and may last
for one or more sessions that each represent an HTTP request forwarded from the HTTP
server to the Servlet Engine. For purposes of this specification, the HTTP server is the
client in this exchange because it initiates the request and waits for results.
Conversely, the Servlet Engine performs the server role in this context. The terms
&quot;client&quot; and &quot;server&quot; will be used in this way.</p>

<p>Each session begins with the request environment, including information analogous to
what is found in a CGI request's environment. During the course of processing the request,
either the server or client may send some &quot;function requests&quot; to each other.
These will be met with &quot;function responses&quot;.</p>

<p>As the server completes parts of the primary request's result, it will send them as
response packets. When the server completes its processing, it signals the end of the
processing by closing the session.</p>

<p>At any point when there are no open sessions, it is the option of both the client and
the server to close the connection for resource management, because file descriptors are
assumed to be a finite resource on both sides. </p>

<h2><a NAME="glossary"></a>Glossary</h2>

<dl>
  <dt>Client</dt>
  <dd>The HTTP server process becomes the &quot;client&quot; in the context of the AJPv2
    protocol because it initiates the request and waits for the response. </dd>
  <dt>Connection</dt>
  <dd>A finite-duration link between the AJPv2 client and server, upon which all AJPv2
    transmissions occur. This can theoretically be over any reliable ordered-stream transport
    but is expected to usually be delivered over a TCP-based socket. </dd>
  <dt>Error</dt>
  <dd>A fatal condition forcing termination of the request. Errors reported to the client
    SHOULD be logged by the client. </dd>
  <dt>Octet</dt>
  <dd>An 8-bit quantity, or byte. </dd>
  <dt>Server</dt>
  <dd>The Servlet Engine performs the server function in the context of the AJPv2 protocol. </dd>
  <dt>Session</dt>
  <dd>AJPv2 borrows the term &quot;session&quot; from the W3C MUX protocol and its
    predecessor, Simon Spero's Session Control Protocol (SCP) proposal. In this context, it
    refers to a multiplexed channel within the larger connection that contains this protocol.
    There may be multiple sessions on a single connection. <table BORDER="1">
      <tr>
        <td><em>Note that this is unrelated to the use of &quot;sessions&quot; in the Java
        Development Kit's (JDK) 1.2 servlet classes, which track application-layer inter-request
        information that are outside the scope of this protocol. It is possible (and unfortunate)
        for terminology collisions such as this to occur at different layers of a protocol suite.
        But realizing they are at different layers allows them to be clearly differentiated.</em></td>
      </tr>
    </table>
  </dd>
  <dt>Warning</dt>
  <dd>An abnormal but non-fatal condition which allows processing of the request to continue.
    Warnings reported to the client SHOULD be logged by the client. </dd>
</dl>

<p>The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;,
&quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;,
&quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to
be interpreted as described in <a HREF="#ref-rfc2119">RFC 2119</a>. </p>

<hr ALIGN="CENTER">

<h1><a NAME="ajpv2-header"></a>The AJPv2 Header</h1>

<p>All data sent on the full duplex connection between the client and server MUST follow
this structure: 

<ul>
  <li>Data is sent in packets formed by a header describing some info about the packet and a
    data length and data payload. </li>
  <li>All packets MUST be 32-bit aligned and MUST always follow big endian style
    (&quot;network order&quot;). </li>
  <li>The packet header is either 64 bits long so that the data payload is also 32 bit aligned
    inside the packet. </li>
  <li>Octet 0 (8 bits) contains the packet type and subtype <ul>
      <li>The least significant 5 bits (Bits 0-4) indicate the &quot;packet type&quot; of the
        packet using an unsigned value. </li>
      <li>The most significant 3 bits (Bits 5-7) indicate the subtype of the packet using an
        unsigned value. </li>
    </ul>
  </li>
  <li>Octet 1 (8 bits) contains flag bits. <ul>
      <li>Bit 0 (the least significant bit) contains the &quot;Session Data End&quot; flag. </li>
      <li>Bit 1 contains the &quot;Session Close&quot; flag. </li>
      <li>Bit 2 contains the &quot;Connection Close&quot; flag. </li>
      <li>Bits 3-7 are reserved for future expansion. They MUST currently be set to zero by the
        sender and ignored by the receiver. </li>
    </ul>
  </li>
  <li>Octet 2-3 (16 bits) give the session to which the packet applies. </li>
  <li>Octet 4-7 of the packet (32 bits), set the length of the data payload carried by the
    packet itself and MAY be zero. (This value may be also calculated like this: data length =
    packet length - 8.) Note that since packet must be 32-bit aligned, 0-3 octets of padding
    MUST be added after the length indicated in the packet to make the next packet begin on a
    32-bit boundary. </li>
  <li>Octet 8 is &quot;data octet 0&quot; and Octet &quot;data length + 7&quot; is the last
    &quot;data octet&quot;. </li>
</ul>

<p>The AJPv2 packet header can be represented by this diagram. </p>

<table BORDER="1" width="100%">
  <tr>
    <th align="center">Octet</th>
    <td COLSPAN="2" align="center">0</td>
    <td align="center">1</td>
    <td align="center">2 - 3</td>
    <td align="center">4 - 7</td>
    <td align="center">8 - &lt;n+7&gt;</td>
  </tr>
  <tr>
    <th align="center">Contents</th>
    <td align="center">bits 0-4: Type</td>
    <td align="center">bits 5-7: Subtype</td>
    <td align="center">Flags</td>
    <td align="center">Session</td>
    <td align="center">Data Length</td>
    <td align="center">Data</td>
  </tr>
</table>

<p>Session ID numbers MUST be unique within a connection. On connection-oriented packets,
a Session ID MUST be ignored by the receiver and set to 0 by the originator. Session ID 0
is reserved for filler on connection-oriented packets and MUST NOT be used for an actual
session.</p>

<p><em>Implementation note: When a server handles multiple connections at a time, it is
only necessary to make ID's unique within each connection, not across all connections.</em>
</p>

<h2><a NAME="ajpv2-types"></a>The AJPv2 Packet Types and Subtypes</h2>

<p>Packet types MUST have a corresponding subtype. Valid values are shown in the following
table: </p>

<table BORDER="1" width="100%">
  <tr>
    <th>Type #</th>
    <th>Type Description</th>
    <th>Context</th>
    <th>Originator</th>
    <th>Subtype #</th>
    <th>Subtype Description</th>
  </tr>
  <tr>
    <td>0</td>
    <td>Challenge</td>
    <td>Connection</td>
    <td>Server</td>
    <td>0</td>
    <td>Server-initiated authentication challenge</td>
  </tr>
  <tr>
    <td ROWSPAN="2">1</td>
    <td ROWSPAN="2">Initialization</td>
    <td ROWSPAN="2">Connection</td>
    <td ROWSPAN="2">Client</td>
    <td>0</td>
    <td>Client authentication, response to challenge</td>
  </tr>
  <tr>
    <td>1</td>
    <td>Configuration commands in servlet native language</td>
  </tr>
  <tr>
    <td ROWSPAN="3">2</td>
    <td ROWSPAN="3">Function Call</td>
    <td ROWSPAN="3">Session</td>
    <td ROWSPAN="3">Either</td>
    <td>0</td>
    <td>Function Request</td>
  </tr>
  <tr>
    <td>1</td>
    <td>Function Response</td>
  </tr>
  <tr>
    <td>2</td>
    <td>&quot;No-op&quot; (process flags only)</td>
  </tr>
  <tr>
    <td ROWSPAN="2">3</td>
    <td ROWSPAN="2">Request</td>
    <td ROWSPAN="2">Session</td>
    <td ROWSPAN="2">Client</td>
    <td>0</td>
    <td>Request Start</td>
  </tr>
  <tr>
    <td>1</td>
    <td>Request Entity</td>
  </tr>
  <tr>
    <td ROWSPAN="5">4</td>
    <td ROWSPAN="5">Response</td>
    <td ROWSPAN="5">Session</td>
    <td ROWSPAN="5">Server</td>
    <td>0</td>
    <td>Response Header(s) (newline-delimited)</td>
  </tr>
  <tr>
    <td>1</td>
    <td>Response Entity</td>
  </tr>
  <tr>
    <td>2</td>
    <td>Request log entries (newline-delimited)</td>
  </tr>
  <tr>
    <td>3</td>
    <td>Warning (newline-delimited)</td>
  </tr>
  <tr>
    <td>4</td>
    <td>Fatal error (newline-delimited)</td>
  </tr>
  <tr>
    <td ROWSPAN="2">5</td>
    <td ROWSPAN="2">Asynchronous Event</td>
    <td ROWSPAN="2">Connection</td>
    <td ROWSPAN="2">Client</td>
    <td>0</td>
    <td>Restart (SIGHUP)</td>
  </tr>
  <tr>
    <td>1</td>
    <td>Shutdown (SIGTERM)</td>
  </tr>
  <tr>
    <td>6</td>
    <td>Protocol Control</td>
    <td>Connection</td>
    <td>Either</td>
    <td>0</td>
    <td>Protocol Error</td>
  </tr>
</table>

<p><em>Implementation note:</em> Each Packet type has uniform settings across all subtypes
for direction of travel and session/connection context. These may be determined using the
type only, without regard to the subtype. Some further type divisions were made by
groupings of related functions so that the type has additional semantic value than just
these three attributes.</p>

<p>The tables fields are as follows. </p>

<blockquote>
  <p>The &quot;<em>Type #</em>&quot; contains the the numbers to be used in the packet type
  field of the AJPv2 header.</p>
  <p>The &quot;<em>Type Description</em>&quot; contains a one-word description which will be
  used as a name for that type of packet in following sections.</p>
  <p>The &quot;<em>Originator</em>&quot; field states whether combination of packet type and
  subtype may originate with the client, server or either one. A packet with that type and
  subtype combination MUST originate on the side(s) allows in the table.</p>
  <p>The &quot;<em>Subtype #</em>&quot; contains the the numbers to be used in the packet
  subtype field of the AJPv2 header.</p>
  <p>The &quot;<em>Subtype Description</em>&quot; contains a description of the meaning of a
  packet with that specific combination of type and subtype. </p>
</blockquote>

<p>Any packet with packet type, subtype and origination not as shown in the table above
constitutes a fatal protocol error. </p>

<h2><a NAME="ajpv2-challenge"></a>Challenge Packets</h2>

<p>A challenge packet contains a random-length array of random-value octets. This is the
first packet sent by the server upon establishment of each connection. The length MUST be
between 5 and 63 octets, inclusive. A new random challenge must be chosen for each
connection. This challenge value MUST be saved by the server and associated with this
connection for use in verifying the authentication of the client. See the section on the
authentication algorithm for more details. </p>

<h2><a NAME="ajpv2-init"></a>Initialization Packets</h2>

<p>A Subtype 0 authentication packet is used as a response to the server's challenge. See
the section on the authentication algorithm for more details.</p>

<p>A Subtype 1 initialization packet is used in cases when the client starts the server.
It contains commands in the native language of the Servlet Engine. For the initial Apache
JServ implementation, the language is Java. But any specific language is NOT REQUIRED for
future uses of the protocol, and may be viewed as a higher-level protocol. </p>

<h2><a NAME="ajpv2-func"></a>Function Call Packets</h2>

<p>The Subtype 0 Function Request packet contains a request to be processed by the
receiver, containing a request that will generate a Function Response packet. The AJPv2
protocol does not impose restrictions on the contents of these packets, which may be
viewed as a higher-level protocol. Per-language function-call definitions will be
maintained separately from this protocol and may be revised at different rates, but must
be registered with the Java Apache Project and listed on the java.apache.org web site.</p>

<p>A Subtype 1 Function Response packet contains a response to a previous Function
Request. The AJPv2 protocol does not impose restrictions on the contents of these packets,
which may be viewed as a higher-level protocol. Per-language definitions will be
maintained separately from this protocol and may be revised at different rates, but must
be registered with the Java Apache Project and listed on the java.apache.org web site.</p>

<p>A Subtype 2 No-op packet has no activity associated with it specifically. It is
reserved for any circumstances when the actions in the flag bits of the packet header are
needed without actions of other packet types. </p>

<h2><a NAME="ajpv2-req"></a>Request Packets</h2>

<p>A Subtype 0 Request Start packet contains HTTP-style newline-delimited headers followed
by a blank line and the beginning of the request entity. The headers in this request MUST
included the same variables that are provided in the environment by the <a HREF="#ref-cgi">Common
Gateway Interface</a>. Receipt of this packet subtype MUST create a new session, and MUST
NOT be sent more than once per session. Request Entity packets may follow to send
additional portions of the request data.</p>

<p>A Subtype 1 request entity is a binary object. The type of the data will be provided in
the environment variables if it is available. The handling of the type or any type errors
is the responsibility of the servlet. </p>

<h2><a NAME="ajpv2-resp"></a>Response Packets</h2>

<p>A Subtype 0 response packet contains one or more HTTP response headers. There MAY be
more than one response header per packet, delimited by newlines. And there MAY be more
than one response header packet sent from the server to the client within a session.</p>

<p>A Subtype 1 responses entity is a binary object. The type of the entity should have
been provided in the response headers but is the responsibility of the servlet that
generated it.</p>

<p>A Subtype 2 request log entry packet contains one or more log entry lines from the
server to the client. This is intended as routine per-request logging. Warnings and errors
should use the packets listed below specifically for those purposes. There MAY be more
than one log entry per packet, delimited by newlines. And there MAY be more than one
response header packet sent from the server to the client within a session.</p>

<p>A Subtype 3 warning packet contains a text message describing the warning condition.
This intended for logging on the client. There MAY be more than one warning per packet,
delimited by newlines.</p>

<p>A Subtype 4 fatal error packet contains a text message describing why a request failed.
This intended for logging on the client and may be used to describe the error on any error
messages forwarded to the user by the client. There MAY be more than one error line per
packet, delimited by newlines. </p>

<h2><a NAME="ajpv2-async-event"></a>Asynchronous Event Packets</h2>

<p>A Subtype 0 restart signal packet indicates a Servlet Engine restart MUST take place if
the session is properly authenticated. Any data placed in an asynchronous event packet is
OPTIONAL but MAY be used for debugging purposes.</p>

<p>A Subtype 1 shutdown signal packet indicates the Servlet Engine MUST shut down if the
session is properly authenticated. Any data placed in an asynchronous event packet is
OPTIONAL but MAY be used for debugging purposes. </p>

<h2><a NAME="ajpv2-proto-ctl"></a>Protocol Control Packets</h2>

<p>A Subtype 0 protocol error packet indicates a fatal failure due to a protocol error,
indicating that the originating process is closing the connection. Any data placed in a
protocol error packet is OPTIONAL but MAY be used for debugging purposes. </p>

<hr ALIGN="CENTER">

<h1><a NAME="ajpv2-client-state"></a>Client-side State Transitions</h1>

<p>AJPv2 allows for multiple sessions within a connection so there is separate state
information and state-transition rules for the connection and for each session. If
authentication is configured to be enabled, the client side of the connection begins in
the &quot;Unauthenticated&quot; state. Otherwise the initial state is &quot;Open&quot;.</p>

<p>Due to the presence of flag bits, packets may contain more than one event applicable to
the state tables. In such cases, the first event processed is based on the packet type and
subtype. Then the flag bits are processed. A Close Connection flag supersedes and
pre-empts the Session End Data and Session Close flags. A Session Close supersedes and
pre-empts the Session End Data flag. Session Close and Session End Data flags MUST NOT be
set on connection-oriented packets. </p>

<table BORDER="1" width="100%">
  <tr>
    <th COLSPAN="4">Client Per-Connection State Transitions</th>
  </tr>
  <tr>
    <th>State</th>
    <th>Event</th>
    <th>Action</th>
    <th>New State</th>
  </tr>
  <tr>
    <td ROWSPAN="3">Unauthenticated</td>
    <td>receive Challenge</td>
    <td>Generate response (see authentication algorithm)</td>
    <td>Open</td>
  </tr>
  <tr>
    <td>receive Protocol Error</td>
    <td>close connection</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td>receive other</td>
    <td>return Protocol Error, close connection</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td ROWSPAN="4">Open</td>
    <td>receive any server-to-client per-session packet</td>
    <td>pass to session handler</td>
    <td>Open</td>
  </tr>
  <tr>
    <td>flag set - Close Connection</td>
    <td>terminate all sessions and connection</td>
    <td>Open</td>
  </tr>
  <tr>
    <td>receive Protocol Error</td>
    <td>close connection, terminate all sessions</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td>receive other</td>
    <td>return Protocol Error, close connection</td>
    <td>N/A</td>
  </tr>
</table>

<p>The client side of is where each session begins. The client creates a new session with
a Request Start packet that contains an ID for a session which is not currently open. The
new session is placed in the &quot;Open-Data&quot; state </p>

<table BORDER="1" width="100%">
  <tr>
    <th COLSPAN="4">Client Per-Session State Transitions</th>
  </tr>
  <tr>
    <th>State</th>
    <th>Event</th>
    <th>Action</th>
    <th>New State</th>
  </tr>
  <tr>
    <td>New</td>
    <td>send Request Start to server</td>
    <td>create session record</td>
    <td>Open-Data</td>
  </tr>
  <tr>
    <td ROWSPAN="10">Open-Data</td>
    <td>receive Function Request</td>
    <td>parse message, dispatch requested function, send result to server</td>
    <td>Open-Data</td>
  </tr>
  <tr>
    <td>receive Response Header</td>
    <td>pass header to upper layer</td>
    <td>Open-Data</td>
  </tr>
  <tr>
    <td>receive Response Entity</td>
    <td>pass entity to upper layer</td>
    <td>Open-Data</td>
  </tr>
  <tr>
    <td>receive Log entry</td>
    <td>pass log entry to upper layer</td>
    <td>Open-Data</td>
  </tr>
  <tr>
    <td>flag set - Session Data End</td>
    <td>complete response processing</td>
    <td>Control-Only</td>
  </tr>
  <tr>
    <td>flag set - Session Close</td>
    <td>close session</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td>receive Warning</td>
    <td>pass warning (log w/ appropriate severity) to upper layer</td>
    <td>Open-Data</td>
  </tr>
  <tr>
    <td>receive Error</td>
    <td>pass error (log w/ appropriate severity) to upper layer</td>
    <td>Open-Data</td>
  </tr>
  <tr>
    <td>receive other</td>
    <td>return Protocol Error, close connection</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td>client initiated close session</td>
    <td>send No-op with Close Session flag, close session</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td ROWSPAN="7">Control-Only</td>
    <td>receive Function Request</td>
    <td>parse message, dispatch requested function, send result to server</td>
    <td>Control-Only</td>
  </tr>
  <tr>
    <td>receive Log entry</td>
    <td>pass log entry to upper layer</td>
    <td>Control-Only</td>
  </tr>
  <tr>
    <td>receive Session Close</td>
    <td>close session</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td>receive Warning</td>
    <td>pass warning (log w/ appropriate severity) to upper layer</td>
    <td>Control-Only</td>
  </tr>
  <tr>
    <td>receive Error</td>
    <td>pass error (log w/ appropriate severity) to upper layer</td>
    <td>Control-Only</td>
  </tr>
  <tr>
    <td>receive other</td>
    <td>return Protocol Error, close connection</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td>client initiated close session</td>
    <td>send No-op with Close Session flag, close session</td>
    <td>N/A</td>
  </tr>
</table>

<hr ALIGN="CENTER">

<h1><a NAME="ajpv2-server-state"></a>Server-side State Transitions</h1>

<p>AJPv2 allows for multiple sessions within a connection so there is separate state
information and state-transition rules for the connection and for each session. If
authentication is configured to be enabled, the server begins by generating and sending a
Challenge packet, then entering the &quot;Unauthenticated&quot; state. Otherwise, the
initial state is &quot;Open&quot;.</p>

<p>Due to the presence of flag bits, packets may contain more than one event applicable to
the state tables. In such cases, the first event processed is based on the packet type and
subtype. Then the flag bits are processed. A Close Connection flag supersedes and
pre-empts the Session End Data and Session Close flags. A Session Close supersedes and
pre-empts the Session End Data flag. Session Close and Session End Data flags MUST NOT be
set on connection-oriented packets. </p>

<table BORDER="1" width="100%">
  <tr>
    <th COLSPAN="4">Server Per-Connection State Transitions</th>
  </tr>
  <tr>
    <th>State</th>
    <th>Event</th>
    <th>Action</th>
    <th>New State</th>
  </tr>
  <tr>
    <td ROWSPAN="4">Unauthenticated</td>
    <td ROWSPAN="2">receive Authentication</td>
    <td>if verification fails, close connection</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td>if verification succeeds, continue</td>
    <td>Open</td>
  </tr>
  <tr>
    <td>receive Protocol Error</td>
    <td>close connection</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td>receive other</td>
    <td>return Protocol Error, close connection</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
  <tr>
    <td ROWSPAN="10">Open</td>
    <td>receive any client-to-server per-session packet</td>
    <td>pass to session handler</td>
    <td>Open</td>
  </tr>
  <tr>
    <td>receive Initialization</td>
    <td>process initialization commands</td>
    <td>Open</td>
  </tr>
  <tr>
    <td ROWSPAN="2">receive Restart</td>
    <td>if allowed by remote, run restart (closes connection)</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td>if not allowed by remote, ignore</td>
    <td>Open</td>
  </tr>
  <tr>
    <td ROWSPAN="2">receive Shutdown</td>
    <td>if allowed by remote, shut down (closes connection)</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td>if not allowed by remote, ignore</td>
    <td>Open</td>
  </tr>
  <tr>
    <td>receive Close Connection</td>
    <td>close connection, terminate all sessions</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td>receive Protocol Error</td>
    <td>close connection, terminate all sessions</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td>receive other</td>
    <td>return Protocol Error, close connection</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
</table>

<p>The server creates a new session when a Request Start packet is received that contains
an ID for a session which is not currently open. The new session starts in the
&quot;New&quot; state </p>

<table BORDER="1">
  <tr>
    <th COLSPAN="4">Server Per-Session State Transitions</th>
  </tr>
  <tr>
    <th>State</th>
    <th>Event</th>
    <th>Action</th>
    <th>New State</th>
  </tr>
  <tr>
    <td ROWSPAN="2">New</td>
    <td>receive Request Start</td>
    <td>open new session</td>
    <td>Open-Data</td>
  </tr>
  <tr>
    <td>receive other</td>
    <td>send Protocol Error, close connection</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td ROWSPAN="6">Open-Data</td>
    <td>receive Function Response</td>
    <td>pass on to upper layer</td>
    <td>Open-Data</td>
  </tr>
  <tr>
    <td>receive Request Start</td>
    <td>process request headers and save entity fragment in servlet connection info, or pass
    to upper layer if accepted in fragments</td>
    <td>Open-Data</td>
  </tr>
  <tr>
    <td>receive Request Entity</td>
    <td>save entity fragment in servlet connection info, or pass to upper layer if accepted in
    fragments</td>
    <td>Open-Data</td>
  </tr>
  <tr>
    <td>flag set - Session Data End</td>
    <td>close request stream to servlet, leave it open for response</td>
    <td>Control-Only</td>
  </tr>
  <tr>
    <td>flag set - Session Close</td>
    <td>close session, cancel request to servlet</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td>receive other</td>
    <td>send Protocol Error, close connection</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td ROWSPAN="3">Control-Only</td>
    <td>receive Function Response</td>
    <td>pass on to upper layer</td>
    <td>Control-Only</td>
  </tr>
  <tr>
    <td>receive Session Close</td>
    <td>close session, cancel request to servlet</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td>receive other</td>
    <td>send Protocol Error, close connection</td>
    <td>N/A</td>
  </tr>
</table>

<hr ALIGN="CENTER">

<h1><a NAME="ajpv2-auth"></a>Authentication Algorithm</h1>

<p>The &quot;secret integer&quot; authentication algorithm of the original Apache JServ
protocol has not been carried forward to AJPv2.</p>

<p>The AJPv2 authentication algorithm was inspired by the MD5 Digest Authentication
algorithm for HTTP. (MD5 is defined in <a HREF="#ref-md5">RFC1321</a>.) However, unlike
HTTP, this algorithm depends on all clients and the server having access to a secret file
or string with identical contents, and system clocks that can be kept in sync within a
configurable number of seconds. This is based on the assumption that the administration of
the AJPv2 client and server systems are either the same or in cooperation with each other.</p>

<p>This algorithm uses MD5 hashing but no strong cryptography, and is therefore exportable
under cryptography restrictions for the United States, France and Russia in effect as of
January, 1998. It is able to verify that both sides posses secret text (analogous to a
password) without passing any of it in the clear over the network. 

<ul>
  <li>Client side: <ul>
      <li>receive a 5-63 octet challenge C from the server </li>
      <li>generate a 4-octet T from 4 bytes in big-endian order of the current Unix-style time (a
        32-bit quantity with seconds since January 1, 1970 midnight GMT) </li>
      <li>obtain the shared secret S from a file or the client configuration </li>
      <li>concatenate C, T and S </li>
      <li>compute the MD5 hash of the resulting string </li>
      <li>send T and the MD5 hash to the server in the authentication string </li>
    </ul>
  </li>
  <li>Server side: <ul>
      <li>generate a challenge string C with 5-63 random octets (if present, use local
        configuration parameters to set the length) </li>
      <li>save C when it is sent to the client </li>
      <li>receive T and the MD5 hash from the client </li>
      <li>make sure T is within the time tolerance (in seconds), it must be no farther in the past
        or future than the number of seconds configured for the server </li>
      <li>obtain the shared secret S from a file or the server configuration </li>
      <li>concatenate C, T and S </li>
      <li>compute the MD5 hash of the resulting string </li>
      <li>for validity, the resulting MD5 hash and the received MD5 hash MUST be the same </li>
    </ul>
  </li>
</ul>

<p>The shared secret is an arbitrary-length string (which does not necessarily need to be
ASCII text - it could be an image file.) The only limitation on the shared secret is that
the longer the string, the more processing will be necessary to compute an MD5 hash with
it. Note: this algorithm is as vulnerable as the secret file or string contents - they
SHOULD be adequately protected from unauthorized users by any security measures available.</p>

<p>It also has limited vulnerability to packet-sniffing attacks. Secret files or strings
are not sent in the clear. The use of the challenge-response and time-checking means that
sniffed hashes only respond to specific challenges and expire within seconds. Sniffed
authentication strings cannot be re-used after they expire.</p>

<p>There is a small chance (estimated at less than 1 in 1,000,000,000,000 for each
connection, with even smaller chances for longer challenge strings, with good pseudorandom
number generation) that any given challenge could be used again for another connection. If
this were to occur in less than the expiration time, a sniffed packet could be used to
answer the authentication. </p>

<h2><a NAME="ajpv2-client-config"></a>Impacts of Pseudorandom Number Generation on
Security</h2>

<p>The authentication algorithm depends on good pseudorandom number generation and random
number keys. Pseudorandom numbers, by definition, are not completely random and may fail
in some ways to be able to cover all possible bit patterns, or may not cover them in
completely unpredictable sequences. As one important example, the time in seconds MUST NOT
be used alone for random number keys because, even though it contains 32 bits on Unix and
other systems, it does not have 32 bits of variability each time it is used. So any
knowledge of the time frame a seed was chosen allows a relatively small window of numbers
from which to base an attack. Additional sources of randomness for seeds can be obtained
from the process ID, parent process ID process group ID, microseconds since boot, contents
of rapidly-changing buffers, and others. The more bits of variability (unpredictability)
in the seed, the better.</p>

<p>Since some common random number libraries only use 15 bits of precision on random
numbers returned with each pseudorandom number request, an authentication challenge string
SHOULD be generated by separate calls to the pseudorandom number generator for each byte,
using some transformation or truncation to take it down to 8 bits each time. The only
exceptions would be when the implementor knows there are enough bits in use to cover all
possible combinations within a 16- or 32-bit quantity.</p>

<p>Many more recommendations and ideas in this area can be found in <a HREF="#ref-rfc-random">RFC 1750, &quot;Randomness Recommendations for Security&quot;</a>. </p>

<hr ALIGN="CENTER">

<h1><a NAME="ajpv2-client-config"></a>Client-Side Protocol Configuration Parameters</h1>

<p>The following protocol parameters are configurable on the client side. 

<dl>
  <dt>authentication</dt>
  <dd>This setting determines whether authentication is in use on the server. <em>The default
    value MUST be to enable authentication.</em> Implementors SHOULD warn administrators to
    ensure the client's authentication configuration matches the server's. </dd>
  <dt>secret file or string</dt>
  <dd>This must be configured to the same contents as used on the server which will
    interoperate with the client. </dd>
</dl>

<hr ALIGN="CENTER">

<h1><a NAME="ajpv2-server-config"></a>Server-Side Protocol Configuration Parameters</h1>

<p>The following protocol parameters are configurable on the server side. 

<dl>
  <dt>authentication</dt>
  <dd>This setting determines whether authentication is in use on the server. <em>The default
    value MUST be to enable authentication.</em> Administrators who choose to disable
    authentication SHOULD be warned by the implementor to provide their own security (such as
    a firewall or router with filtering) to protect the server from intruders. </dd>
  <dt>secret file or string</dt>
  <dd>This must be configured to the same contents as used on all clients which will
    interoperate with the server. </dd>
  <dt>challenge minimum length</dt>
  <dd>The protocol-enforced minimum challenge length of 5 octets will (with proper
    pseudorandom number generation) approximate 1 in 1 quadrillion odds of any given challenge
    being chosen. For each octet in length added, this minimum figure is multiplied by 256. If
    computing power increases at current rates (which has doubled every 18 months for over 30
    years, according to Moore's Law), this number will need to be increased at least by one
    every 4 years computed from 1998 to maintain wide margins of safety over potential
    intruders' computational processing availability. <em>The recommended default is 5 plus
    one for every two years since 1998.</em> </dd>
  <dt>challenge maximum length</dt>
  <dd>The protocol-enforced maximum challenge length of 63 octets is considered an estimated
    maximum need throughout the lifetime of the protocol. To cut the connection-establishment
    overhead, this number can be reduced to 16 plus one for every two years since 1998. <em>The
    recommended default is 63.</em> </dd>
  <dt>challenge expiration interval</dt>
  <dd>This value MUST BE used to reject old authentication strings, which could have been
    sniffed from network packets in attempts to re-use them. It SHOULD be set to a number
    slightly larger than the maximum number of seconds that client and server system clocks
    would be expected to differ with normal drifting and re-setting. If the client and server
    are always on the same system, a value of 5 seconds should be enough allowance for the
    heaviest system loads. For sites running NTP (Network Time Protocol) and connected via a
    LAN, a value of 15 seconds would work. Other sites might choose 300 seconds (5 minutes) to
    600 seconds (10 minutes). If the client and server clocks drift to a greater difference
    than this parameter toward either the past or future, all client connections will be
    rejected by the server until the clocks are sufficiently synchronized again. <em>The
    recommended default is 300.</em> </dd>
</dl>

<hr ALIGN="CENTER">

<h1><a NAME="implementation"></a>Implementation Notes</h1>

<p>The following are some additional notes for implementors: 

<ul>
  <li>The server is assumed to be multithreaded, since this is originally intended for
    implementation with the Apache JServ servlet engine, and Java is multithreaded. </li>
  <li>Since the client could be single-threaded, it controls the number of threads in use by
    the number of connections it opens simultaneously. </li>
  <li>The server MUST NOT perform more than one Function Request to the client at a time due
    to the potential for a single-threaded client. Instead, the server MUST wait for a
    Function Response before sending a new Function Request. </li>
  <li>The client MAY send Function Requests while it has Requests and other Function Requests
    pending. </li>
  <li>While sessions are open, both the client and server SHOULD refrain from closing the
    connection (which would terminate all open sessions) except in urgent situations, such as
    a server shutdown. Resource management SHOULD favor existing connections over new ones,
    i.e. refuse to open a new connection when it would have to close an open and active one to
    free the resources. </li>
</ul>

<hr ALIGN="CENTER">

<h1><a NAME="refs"></a>References</h1>

<ul>
  <li>S. Bradner, <a HREF="ftp://ftp.isi.edu/in-notes/rfc2119.txt">&quot;Key words for use in
    RFCs to Indicate Requirement Levels&quot;, RFC 2119,</a> Harvard University, March 1997 </li>
  <li>D. Eastlake, S. Crocker, and J. Schiller, <a HREF="ftp://ftp.isi.edu/in-notes/rfc1750.txt">&quot;Randomness Recommendations for
    Security&quot;, RFC 1750,</a> IETF Network Working Group, December 1994 </li>
  <li>J. Gettys and H. Nielsen, <a HREF="http://www.w3.org/Protocols/MUX/WD-mux-970825.html" target="_top">&quot;Simple
    Multiplexing Protocol&quot;, W3C Working Draft 25-August-97</a>, World Wide Web Consortium
    (W3C), August 1997 </li>
  <li>A. Kosut, &quot;Apache JServ Protocol&quot;, Version 1.0, Java Apache Project, July 1997
  </li>
  <li>R. McCool, <a HREF="http://hoohoo.ncsa.uiuc.edu/cgi/" target="_top">&quot;The Common Gateway
    Interface&quot;, Version 1.1,</a> National Center for Supercomputing Applications (NCSA),
    1994. </li>
  <li>R. Rivest <a HREF="ftp://ftp.isi.edu/in-notes/rfc1321.txt" target="_top">&quot;The MD5 Message-Digest
    Algorithm&quot;, RFC 1321,</a> MIT Laboratory for Computer Science, April 1992 </li>
</ul>

<hr ALIGN="CENTER">

<h1><a NAME="acks"></a>Acknowledgements</h1>

<p>This specification was developed through discussion and consensus on the Java Apache
Project's mail list. The original idea for this model was evolved from ideas proposed by
Ed Korthof, who continued to provide input throughout its development. The authentication
algorithm and numerous modifications were provided by Ian Kluft. Stefano Mazzocchi also
provided technical review and suggestions for nearly all parts of the spec.</p>

<p ALIGN="CENTER"><font SIZE="2">Copyright (c) 1997-98 <a HREF="http://java.apache.org/" target="_top">The
Java Apache Project</a>.<br>
</font><font SIZE="-1">$Id: AJPv2.html,v 1.3 1999/06/09 05:21:29 jonbolt Exp $</font><font SIZE="2"><br>
All rights reserved.</font></p>
</body>
</html>