Standard - September 9, 1998
describes the protocol used to communicate between a web server module
and the Apache JServ servlet engine over a TCP socket.
The authentication scheme used for AJPv1.0 (used by Apache JServ 0.9.xx) was considered too simple and worked only on local environments. For this reason, while the request/response phase of the protocol were kept unchanged, authentication handshake was ported from higher versions of the protocol (proposed as a future extension) and implemented here for security reasons.
This will also provide more feedback to developers for newer revisions of the AJP protocol.
A request is made by requesting a TCP connection to the port Apache JServ is listening to.
If authentication is enabled (authentication must be enabled or disabled on both sides) the authentication handshake is performed (see Authentication), otherwise authentication is skipped and request metadata is sent right away.
The client sends the request metadata to the servlet engine (see Request) and waits for response metadata (see Response).
When finished, the servlet engine closes the connection, indicating that the request has been completed.
The AJPv1.1 authentication algorithm depends on all clients and the servlet engine having access to a secret file or string with identical contents. This is based on the assumption that the administration of both sides are either the same or in cooperation with each other.
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 July, 1998. It is able to verify that both sides possess secret text (analogous to a password) without passing any of it in the clear over the network.
Note: all numbers are sent on the connection streams using big endian format (network order), where most significant bits come first.
- Client side
- receive 4 octects (32 bits) from the server indicating the challenge string length.
- receive as many octects as specified by the octects above.
- obtain the shared secret S from a client configured file.
- concatenate C and S
- compute the MD5 hash of the resulting string
- send the MD5 hash to the server
- Server side:
- generate a challenge string of random octets R with length defined using local configuration parameters (minimum length is forced for security reasons to be at least 5 octets)
- obtain a 64 bit system time T using milliseconds since 01/01/1970
- concatenate C and T and save it as R
- send length of R to client using 4 octets (32 bits)
- send R to client.
- obtain the shared secret S from a file or the server configuration
- concatenate R and S
- compute the MD5 hash of the resulting string
- receive the MD5 hash from the client (16 octets)
- if the resulting MD5 hash and the received MD5 hash ARE NOT the same, close the connection.
The shared secret is an arbitrary-length string (which does not necessarily need to be ASCII text - it could be any binary 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, so, since authentication must be performed on every request and MD5 strength does not depend very much on string length, this could as small as a few lines of text.
The server does not acknowledge the authentication success to the client to avoid round trip time and speed up the request process. For this reason, the client must control the availability of the connection while writing the request, since this indicates the success of that operation.
Authentication may be disabled to increment performance. If this is done, both client and server must disable the authentication handshake and skip the authentication phase. Systems administrators that want to avoid untrusted execution of servlets, should secure their networks using other systems.
The module sends the request metadata to the servlet engine. These are sent as lines, with two parts: a one-character identifier, and the data. This is preceded with a four-digit hex number indicating the length of the following string (with leading 0s), e.g. "000dHDate Friday", where "000d" is the length, "H" is the identifier, and "Date Friday" is the data.
AUTH_TYPE(*): The type of authentication used
CONTENT_LENGTH(*): The length of the request entity
CONTENT_TYPE(*): The media type of the request entity
DOCUMENT_ROOT: The server's main document root
PATH_INFO(*): Extra URI path information
PATH_TRANSLATED(*): The translated path info
QUERY_STRING(*): The query arguments
REQUEST_METHOD: The method used for the request
REMOTE_USER(*): The authenticated username used for the request
REMOTE_ADDR: The IP address of the requesting host
REMOTE_HOST: The hostname of the requesting host (if available)
SCRIPT_NAME: The URI portion that refers to the servlet
SERVER_NAME: The hostname of the server
SERVER_PORT: The port number of the server
SERVER_PROTOCOL: The protocol used for the request
SERVER_SOFTWARE: The name of the server software
The response consists of two parts, response headers and the response entity. This is sent basically the same way CGI responses are sent:
Copyright (c) 1997-98 The
Java Apache Project.
$Id: AJPv11.html,v 1.3 1999/06/09 05:21:29 jonbolt Exp $
All rights reserved.