1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 APLOG_USE_MODULE(proxy_ajp);
21 #define AJP_MSG_DUMP_BYTES_PER_LINE 16
22 /* 2 hex digits plus space plus one char per dumped byte */
23 /* plus prefix plus separator plus '\0' */
24 #define AJP_MSG_DUMP_LINE_LENGTH (strlen("XX .") + \
28 static char *hex_table = "0123456789ABCDEF";
31 * Dump the given number of bytes on an AJP Message
33 * @param pool pool to allocate from
34 * @param msg AJP Message to dump
35 * @param err error string to display
36 * @param count the number of bytes to dump
37 * @param buf buffer pointer for dump message
38 * @return APR_SUCCESS or error
40 apr_status_t ajp_msg_dump(apr_pool_t *pool, ajp_msg_t *msg, char *err,
41 apr_size_t count, char **buf)
47 apr_size_t len = msg->len;
50 /* Display only first "count" bytes */
53 /* First the space needed for the first line */
54 bl = strlen(err) + 3 * (strlen(" XXX=") + 20) + 1 +
55 /* Now for the data lines */
56 (len + 15) / 16 * AJP_MSG_DUMP_LINE_LENGTH;
57 *buf = apr_palloc(pool, bl);
60 apr_snprintf(*buf, bl,
61 "%s pos=%" APR_SIZE_T_FMT
62 " len=%" APR_SIZE_T_FMT " max=%" APR_SIZE_T_FMT "\n",
63 err, msg->pos, msg->len, msg->max_size);
64 current = *buf + strlen(*buf);
65 for (i = 0; i < len; i += AJP_MSG_DUMP_BYTES_PER_LINE) {
66 /* Safety check: do we have enough buffer for another line? */
67 rl = bl - (current - *buf);
68 if (AJP_MSG_DUMP_LINE_LENGTH > rl) {
69 *(current - 1) = '\0';
72 apr_snprintf(current, rl, "%.4lx ", (unsigned long)i);
74 if (line_len > AJP_MSG_DUMP_BYTES_PER_LINE) {
75 line_len = AJP_MSG_DUMP_BYTES_PER_LINE;
77 for (j = 0; j < line_len; j++) {
80 *current++ = hex_table[x >> 4];
81 *current++ = hex_table[x & 0x0f];
87 for (j = 0; j < line_len; j++) {
90 if (x > 0x20 && x < 0x7F) {
99 *(current - 1) = '\0';
107 * @param request The current request
108 * @param msg AJP Message to dump
109 * @param err error string to display
110 * @return APR_SUCCESS or error
112 apr_status_t ajp_msg_log(request_rec *r, ajp_msg_t *msg, char *err)
117 apr_status_t rc = APR_SUCCESS;
119 if (APLOGrtrace7(r)) {
120 level = APLOG_TRACE7;
122 if (APLOGrtrace8(r)) {
123 level = APLOG_TRACE8;
124 count = AJP_MAX_BUFFER_SZ;
126 rc = ajp_msg_dump(r->pool, msg, err, count, &buf);
127 if (rc == APR_SUCCESS) {
128 while ((next = ap_strchr_c(buf, '\n'))) {
130 ap_log_rerror(APLOG_MARK, level, 0, r, "%s", buf);
133 ap_log_rerror(APLOG_MARK, level, 0, r, "%s", buf);
140 * Check a new AJP Message by looking at signature and return its size
142 * @param msg AJP Message to check
143 * @param len Pointer to returned len
144 * @return APR_SUCCESS or error
146 apr_status_t ajp_msg_check_header(ajp_msg_t *msg, apr_size_t *len)
148 apr_byte_t *head = msg->buf;
151 if (!((head[0] == 0x41 && head[1] == 0x42) ||
152 (head[0] == 0x12 && head[1] == 0x34))) {
154 ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
155 "ajp_msg_check_header() got bad signature %02x%02x",
158 return AJP_EBAD_SIGNATURE;
161 msglen = ((head[2] & 0xff) << 8);
162 msglen += (head[3] & 0xFF);
164 if (msglen > msg->max_size) {
165 ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
166 "ajp_msg_check_header() incoming message is "
167 "too big %" APR_SIZE_T_FMT ", max is %" APR_SIZE_T_FMT,
168 msglen, msg->max_size);
172 msg->len = msglen + AJP_HEADER_LEN;
173 msg->pos = AJP_HEADER_LEN;
180 * Reset an AJP Message
182 * @param msg AJP Message to reset
183 * @return APR_SUCCESS or error
185 apr_status_t ajp_msg_reset(ajp_msg_t *msg)
187 msg->len = AJP_HEADER_LEN;
188 msg->pos = AJP_HEADER_LEN;
194 * Reuse an AJP Message
196 * @param msg AJP Message to reuse
197 * @return APR_SUCCESS or error
199 apr_status_t ajp_msg_reuse(ajp_msg_t *msg)
205 max_size = msg->max_size;
206 memset(msg, 0, sizeof(ajp_msg_t));
208 msg->max_size = max_size;
209 msg->header_len = AJP_HEADER_LEN;
215 * Mark the end of an AJP Message
217 * @param msg AJP Message to end
218 * @return APR_SUCCESS or error
220 apr_status_t ajp_msg_end(ajp_msg_t *msg)
222 apr_size_t len = msg->len - AJP_HEADER_LEN;
224 if (msg->server_side) {
233 msg->buf[2] = (apr_byte_t)((len >> 8) & 0xFF);
234 msg->buf[3] = (apr_byte_t)(len & 0xFF);
239 static APR_INLINE int ajp_log_overflow(ajp_msg_t *msg, const char *context)
241 ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
242 "%s(): BufferOverflowException %" APR_SIZE_T_FMT
244 context, msg->pos, msg->len);
245 return AJP_EOVERFLOW;
249 * Add an unsigned 32bits value to AJP Message
251 * @param msg AJP Message to get value from
252 * @param value value to add to AJP Message
253 * @return APR_SUCCESS or error
255 apr_status_t ajp_msg_append_uint32(ajp_msg_t *msg, apr_uint32_t value)
257 apr_size_t len = msg->len;
259 if ((len + 4) > msg->max_size) {
260 return ajp_log_overflow(msg, "ajp_msg_append_uint32");
263 msg->buf[len] = (apr_byte_t)((value >> 24) & 0xFF);
264 msg->buf[len + 1] = (apr_byte_t)((value >> 16) & 0xFF);
265 msg->buf[len + 2] = (apr_byte_t)((value >> 8) & 0xFF);
266 msg->buf[len + 3] = (apr_byte_t)(value & 0xFF);
274 * Add an unsigned 16bits value to AJP Message
276 * @param msg AJP Message to get value from
277 * @param value value to add to AJP Message
278 * @return APR_SUCCESS or error
280 apr_status_t ajp_msg_append_uint16(ajp_msg_t *msg, apr_uint16_t value)
282 apr_size_t len = msg->len;
284 if ((len + 2) > msg->max_size) {
285 return ajp_log_overflow(msg, "ajp_msg_append_uint16");
288 msg->buf[len] = (apr_byte_t)((value >> 8) & 0xFF);
289 msg->buf[len + 1] = (apr_byte_t)(value & 0xFF);
297 * Add an unsigned 8bits value to AJP Message
299 * @param msg AJP Message to get value from
300 * @param value value to add to AJP Message
301 * @return APR_SUCCESS or error
303 apr_status_t ajp_msg_append_uint8(ajp_msg_t *msg, apr_byte_t value)
305 apr_size_t len = msg->len;
307 if ((len + 1) > msg->max_size) {
308 return ajp_log_overflow(msg, "ajp_msg_append_uint8");
311 msg->buf[len] = value;
318 * Add a String in AJP message, and transform the String in ASCII
319 * if convert is set and we're on an EBCDIC machine
321 * @param msg AJP Message to get value from
322 * @param value Pointer to String
323 * @param convert When set told to convert String to ASCII
324 * @return APR_SUCCESS or error
326 apr_status_t ajp_msg_append_string_ex(ajp_msg_t *msg, const char *value,
332 return(ajp_msg_append_uint16(msg, 0xFFFF));
336 if ((msg->len + len + 3) > msg->max_size) {
337 return ajp_log_overflow(msg, "ajp_msg_append_cvt_string");
340 /* ignore error - we checked once */
341 ajp_msg_append_uint16(msg, (apr_uint16_t)len);
343 /* We checked for space !! */
344 memcpy(msg->buf + msg->len, value, len + 1); /* including \0 */
347 /* convert from EBCDIC if needed */
348 ap_xlate_proto_to_ascii((char *)msg->buf + msg->len, len + 1);
357 * Add a Byte array to AJP Message
359 * @param msg AJP Message to get value from
360 * @param value Pointer to Byte array
361 * @param valuelen Byte array len
362 * @return APR_SUCCESS or error
364 apr_status_t ajp_msg_append_bytes(ajp_msg_t *msg, const apr_byte_t *value,
368 return APR_SUCCESS; /* Shouldn't we indicate an error ? */
371 if ((msg->len + valuelen) > msg->max_size) {
372 return ajp_log_overflow(msg, "ajp_msg_append_bytes");
375 /* We checked for space !! */
376 memcpy(msg->buf + msg->len, value, valuelen);
377 msg->len += valuelen;
383 * Get a 32bits unsigned value from AJP Message
385 * @param msg AJP Message to get value from
386 * @param rvalue Pointer where value will be returned
387 * @return APR_SUCCESS or error
389 apr_status_t ajp_msg_get_uint32(ajp_msg_t *msg, apr_uint32_t *rvalue)
393 if ((msg->pos + 3) > msg->len) {
394 return ajp_log_overflow(msg, "ajp_msg_get_uint32");
397 value = ((msg->buf[(msg->pos++)] & 0xFF) << 24);
398 value |= ((msg->buf[(msg->pos++)] & 0xFF) << 16);
399 value |= ((msg->buf[(msg->pos++)] & 0xFF) << 8);
400 value |= ((msg->buf[(msg->pos++)] & 0xFF));
408 * Get a 16bits unsigned value from AJP Message
410 * @param msg AJP Message to get value from
411 * @param rvalue Pointer where value will be returned
412 * @return APR_SUCCESS or error
414 apr_status_t ajp_msg_get_uint16(ajp_msg_t *msg, apr_uint16_t *rvalue)
418 if ((msg->pos + 1) > msg->len) {
419 return ajp_log_overflow(msg, "ajp_msg_get_uint16");
422 value = ((msg->buf[(msg->pos++)] & 0xFF) << 8);
423 value += ((msg->buf[(msg->pos++)] & 0xFF));
430 * Peek a 16bits unsigned value from AJP Message, position in message
433 * @param msg AJP Message to get value from
434 * @param rvalue Pointer where value will be returned
435 * @return APR_SUCCESS or error
437 apr_status_t ajp_msg_peek_uint16(ajp_msg_t *msg, apr_uint16_t *rvalue)
441 if ((msg->pos + 1) > msg->len) {
442 return ajp_log_overflow(msg, "ajp_msg_peek_uint16");
445 value = ((msg->buf[(msg->pos)] & 0xFF) << 8);
446 value += ((msg->buf[(msg->pos + 1)] & 0xFF));
453 * Peek a 8bits unsigned value from AJP Message, position in message
456 * @param msg AJP Message to get value from
457 * @param rvalue Pointer where value will be returned
458 * @return APR_SUCCESS or error
460 apr_status_t ajp_msg_peek_uint8(ajp_msg_t *msg, apr_byte_t *rvalue)
462 if (msg->pos > msg->len) {
463 return ajp_log_overflow(msg, "ajp_msg_peek_uint8");
466 *rvalue = msg->buf[msg->pos];
471 * Get a 8bits unsigned value from AJP Message
473 * @param msg AJP Message to get value from
474 * @param rvalue Pointer where value will be returned
475 * @return APR_SUCCESS or error
477 apr_status_t ajp_msg_get_uint8(ajp_msg_t *msg, apr_byte_t *rvalue)
480 if (msg->pos > msg->len) {
481 return ajp_log_overflow(msg, "ajp_msg_get_uint8");
484 *rvalue = msg->buf[msg->pos++];
490 * Get a String value from AJP Message
492 * @param msg AJP Message to get value from
493 * @param rvalue Pointer where value will be returned
494 * @return APR_SUCCESS or error
496 apr_status_t ajp_msg_get_string(ajp_msg_t *msg, const char **rvalue)
502 status = ajp_msg_get_uint16(msg, &size);
505 if ((status != APR_SUCCESS) || (size + start > msg->max_size)) {
506 return ajp_log_overflow(msg, "ajp_msg_get_string");
509 msg->pos += (apr_size_t)size;
510 msg->pos++; /* a String in AJP is NULL terminated */
512 *rvalue = (const char *)(msg->buf + start);
518 * Get a Byte array from AJP Message
520 * @param msg AJP Message to get value from
521 * @param rvalue Pointer where value will be returned
522 * @param rvalueLen Pointer where Byte array len will be returned
523 * @return APR_SUCCESS or error
525 apr_status_t ajp_msg_get_bytes(ajp_msg_t *msg, apr_byte_t **rvalue,
526 apr_size_t *rvalue_len)
532 status = ajp_msg_get_uint16(msg, &size);
533 /* save the current position */
536 if ((status != APR_SUCCESS) || (size + start > msg->max_size)) {
537 return ajp_log_overflow(msg, "ajp_msg_get_bytes");
539 msg->pos += (apr_size_t)size; /* only bytes, no trailer */
541 *rvalue = msg->buf + start;
549 * Create an AJP Message from pool
551 * @param pool memory pool to allocate AJP message from
552 * @param size size of the buffer to create
553 * @param rmsg Pointer to newly created AJP message
554 * @return APR_SUCCESS or error
556 apr_status_t ajp_msg_create(apr_pool_t *pool, apr_size_t size, ajp_msg_t **rmsg)
558 ajp_msg_t *msg = (ajp_msg_t *)apr_pcalloc(pool, sizeof(ajp_msg_t));
560 msg->server_side = 0;
562 msg->buf = (apr_byte_t *)apr_palloc(pool, size);
564 msg->header_len = AJP_HEADER_LEN;
565 msg->max_size = size;
572 * Recopy an AJP Message to another
574 * @param smsg source AJP message
575 * @param dmsg destination AJP message
576 * @return APR_SUCCESS or error
578 apr_status_t ajp_msg_copy(ajp_msg_t *smsg, ajp_msg_t *dmsg)
580 if (smsg->len > smsg->max_size) {
581 ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
582 "ajp_msg_copy(): destination buffer too "
583 "small %" APR_SIZE_T_FMT ", max size is %" APR_SIZE_T_FMT,
584 smsg->len, smsg->max_size);
588 memcpy(dmsg->buf, smsg->buf, smsg->len);
589 dmsg->len = smsg->len;
590 dmsg->pos = smsg->pos;
597 * Serialize in an AJP Message a PING command
599 * +-----------------------+
600 * | PING CMD (1 byte) |
601 * +-----------------------+
603 * @param smsg AJP message to put serialized message
604 * @return APR_SUCCESS or error
606 apr_status_t ajp_msg_serialize_ping(ajp_msg_t *msg)
611 if ((rc = ajp_msg_append_uint8(msg, CMD_AJP13_PING)) != APR_SUCCESS)
618 * Serialize in an AJP Message a CPING command
620 * +-----------------------+
621 * | CPING CMD (1 byte) |
622 * +-----------------------+
624 * @param smsg AJP message to put serialized message
625 * @return APR_SUCCESS or error
627 apr_status_t ajp_msg_serialize_cping(ajp_msg_t *msg)
632 if ((rc = ajp_msg_append_uint8(msg, CMD_AJP13_CPING)) != APR_SUCCESS)