]> granicus.if.org Git - apache/blob - modules/proxy/ajp_msg.c
167619d399f71e0e1aae6990a07cd8237be7cbfe
[apache] / modules / proxy / ajp_msg.c
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "ajp.h"
18
19 APLOG_USE_MODULE(proxy_ajp);
20
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 .") + \
25                                      strlen("XXXX    ") + \
26                                      strlen(" - ") + 1)
27
28 static char *hex_table = "0123456789ABCDEF";
29
30 /**
31  * Dump the given number of bytes on an AJP Message
32  *
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
39  */
40 apr_status_t ajp_msg_dump(apr_pool_t *pool, ajp_msg_t *msg, char *err,
41                           apr_size_t count, char **buf)
42 {
43     apr_size_t  i, j;
44     char        *current;
45     apr_size_t  bl, rl;
46     apr_byte_t  x;
47     apr_size_t  len = msg->len;
48     apr_size_t  line_len;
49
50     /* Display only first "count" bytes */
51     if (len > count)
52         len = count;
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);
58     if (!*buf)
59         return APR_ENOMEM;
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';
70             return APR_ENOMEM;
71         }
72         apr_snprintf(current, rl, "%.4lx    ", (unsigned long)i);
73         line_len = len - i;
74         if (line_len > AJP_MSG_DUMP_BYTES_PER_LINE) {
75             line_len = AJP_MSG_DUMP_BYTES_PER_LINE;
76         }
77         for (j = 0; j < line_len; j++) {
78              x = msg->buf[i + j];
79
80             *current++ = hex_table[x >> 4];
81             *current++ = hex_table[x & 0x0f];
82             *current++ = ' ';
83         }
84         *current++ = ' ';
85         *current++ = '-';
86         *current++ = ' ';
87         for (j = 0; j < line_len; j++) {
88             x = msg->buf[i + j];
89
90             if (x > 0x20 && x < 0x7F) {
91                 *current++ = x;
92             }
93             else {
94                 *current++ = '.';
95             }
96         }
97         *current++ = '\n';
98     }
99     *(current - 1) = '\0';
100
101     return APR_SUCCESS;
102 }
103
104 /**
105  * Log an AJP message
106  *
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
111  */
112 apr_status_t ajp_msg_log(request_rec *r, ajp_msg_t *msg, char *err)
113 {
114     int level;
115     apr_size_t count;
116     char *buf, *next;
117     apr_status_t rc = APR_SUCCESS;
118
119     if (APLOGrtrace7(r)) {
120         level = APLOG_TRACE7;
121         count = 1024;
122         if (APLOGrtrace8(r)) {
123             level = APLOG_TRACE8;
124             count = AJP_MAX_BUFFER_SZ;
125         }
126         rc = ajp_msg_dump(r->pool, msg, err, count, &buf);
127         if (rc == APR_SUCCESS) {
128             while ((next = ap_strchr_c(buf, '\n'))) {
129                 *next = '\0';
130                 ap_log_rerror(APLOG_MARK, level, 0, r, "%s", buf);
131                 buf = next + 1;
132             }
133             ap_log_rerror(APLOG_MARK, level, 0, r, "%s", buf);
134         }
135     }
136     return rc;
137 }
138
139 /**
140  * Check a new AJP Message by looking at signature and return its size
141  *
142  * @param msg       AJP Message to check
143  * @param len       Pointer to returned len
144  * @return          APR_SUCCESS or error
145  */
146 apr_status_t ajp_msg_check_header(ajp_msg_t *msg, apr_size_t *len)
147 {
148     apr_byte_t *head = msg->buf;
149     apr_size_t msglen;
150
151     if (!((head[0] == 0x41 && head[1] == 0x42) ||
152           (head[0] == 0x12 && head[1] == 0x34))) {
153
154         ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
155                       "ajp_msg_check_header() got bad signature %02x%02x",
156                       head[0], head[1]);
157
158         return AJP_EBAD_SIGNATURE;
159     }
160
161     msglen  = ((head[2] & 0xff) << 8);
162     msglen += (head[3] & 0xFF);
163
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);
169         return AJP_ETOBIG;
170     }
171
172     msg->len = msglen + AJP_HEADER_LEN;
173     msg->pos = AJP_HEADER_LEN;
174     *len     = msglen;
175
176     return APR_SUCCESS;
177 }
178
179 /**
180  * Reset an AJP Message
181  *
182  * @param msg       AJP Message to reset
183  * @return          APR_SUCCESS or error
184  */
185 apr_status_t ajp_msg_reset(ajp_msg_t *msg)
186 {
187     msg->len = AJP_HEADER_LEN;
188     msg->pos = AJP_HEADER_LEN;
189
190     return APR_SUCCESS;
191 }
192
193 /**
194  * Reuse an AJP Message
195  *
196  * @param msg       AJP Message to reuse
197  * @return          APR_SUCCESS or error
198  */
199 apr_status_t ajp_msg_reuse(ajp_msg_t *msg)
200 {
201     apr_byte_t *buf;
202     apr_size_t max_size;
203
204     buf = msg->buf;
205     max_size = msg->max_size;
206     memset(msg, 0, sizeof(ajp_msg_t));
207     msg->buf = buf;
208     msg->max_size = max_size;
209     msg->header_len = AJP_HEADER_LEN;
210     ajp_msg_reset(msg);
211     return APR_SUCCESS;
212 }
213
214 /**
215  * Mark the end of an AJP Message
216  *
217  * @param msg       AJP Message to end
218  * @return          APR_SUCCESS or error
219  */
220 apr_status_t ajp_msg_end(ajp_msg_t *msg)
221 {
222     apr_size_t len = msg->len - AJP_HEADER_LEN;
223
224     if (msg->server_side) {
225         msg->buf[0] = 0x41;
226         msg->buf[1] = 0x42;
227     }
228     else {
229         msg->buf[0] = 0x12;
230         msg->buf[1] = 0x34;
231     }
232
233     msg->buf[2] = (apr_byte_t)((len >> 8) & 0xFF);
234     msg->buf[3] = (apr_byte_t)(len & 0xFF);
235
236     return APR_SUCCESS;
237 }
238
239 static APR_INLINE int ajp_log_overflow(ajp_msg_t *msg, const char *context)
240 {
241     ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
242                  "%s(): BufferOverflowException %" APR_SIZE_T_FMT
243                  " %" APR_SIZE_T_FMT,
244                  context, msg->pos, msg->len);
245     return AJP_EOVERFLOW;
246 }
247
248 /**
249  * Add an unsigned 32bits value to AJP Message
250  *
251  * @param msg       AJP Message to get value from
252  * @param value     value to add to AJP Message
253  * @return          APR_SUCCESS or error
254  */
255 apr_status_t ajp_msg_append_uint32(ajp_msg_t *msg, apr_uint32_t value)
256 {
257     apr_size_t len = msg->len;
258
259     if ((len + 4) > msg->max_size) {
260         return ajp_log_overflow(msg, "ajp_msg_append_uint32");
261     }
262
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);
267
268     msg->len += 4;
269
270     return APR_SUCCESS;
271 }
272
273 /**
274  * Add an unsigned 16bits value to AJP Message
275  *
276  * @param msg       AJP Message to get value from
277  * @param value     value to add to AJP Message
278  * @return          APR_SUCCESS or error
279  */
280 apr_status_t ajp_msg_append_uint16(ajp_msg_t *msg, apr_uint16_t value)
281 {
282     apr_size_t len = msg->len;
283
284     if ((len + 2) > msg->max_size) {
285         return ajp_log_overflow(msg, "ajp_msg_append_uint16");
286     }
287
288     msg->buf[len]     = (apr_byte_t)((value >> 8) & 0xFF);
289     msg->buf[len + 1] = (apr_byte_t)(value & 0xFF);
290
291     msg->len += 2;
292
293     return APR_SUCCESS;
294 }
295
296 /**
297  * Add an unsigned 8bits value to AJP Message
298  *
299  * @param msg       AJP Message to get value from
300  * @param value     value to add to AJP Message
301  * @return          APR_SUCCESS or error
302  */
303 apr_status_t ajp_msg_append_uint8(ajp_msg_t *msg, apr_byte_t value)
304 {
305     apr_size_t len = msg->len;
306
307     if ((len + 1) > msg->max_size) {
308         return ajp_log_overflow(msg, "ajp_msg_append_uint8");
309     }
310
311     msg->buf[len] = value;
312     msg->len += 1;
313
314     return APR_SUCCESS;
315 }
316
317 /**
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
320  *
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
325  */
326 apr_status_t ajp_msg_append_string_ex(ajp_msg_t *msg, const char *value,
327                                       int convert)
328 {
329     size_t len;
330
331     if (value == NULL) {
332         return(ajp_msg_append_uint16(msg, 0xFFFF));
333     }
334
335     len = strlen(value);
336     if ((msg->len + len + 3) > msg->max_size) {
337         return ajp_log_overflow(msg, "ajp_msg_append_cvt_string");
338     }
339
340     /* ignore error - we checked once */
341     ajp_msg_append_uint16(msg, (apr_uint16_t)len);
342
343     /* We checked for space !!  */
344     memcpy(msg->buf + msg->len, value, len + 1); /* including \0 */
345
346     if (convert) {
347         /* convert from EBCDIC if needed */
348         ap_xlate_proto_to_ascii((char *)msg->buf + msg->len, len + 1);
349     }
350
351     msg->len += len + 1;
352
353     return APR_SUCCESS;
354 }
355
356 /**
357  * Add a Byte array to AJP Message
358  *
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
363  */
364 apr_status_t ajp_msg_append_bytes(ajp_msg_t *msg, const apr_byte_t *value,
365                                   apr_size_t valuelen)
366 {
367     if (! valuelen) {
368         return APR_SUCCESS; /* Shouldn't we indicate an error ? */
369     }
370
371     if ((msg->len + valuelen) > msg->max_size) {
372         return ajp_log_overflow(msg, "ajp_msg_append_bytes");
373     }
374
375     /* We checked for space !!  */
376     memcpy(msg->buf + msg->len, value, valuelen);
377     msg->len += valuelen;
378
379     return APR_SUCCESS;
380 }
381
382 /**
383  * Get a 32bits unsigned value from AJP Message
384  *
385  * @param msg       AJP Message to get value from
386  * @param rvalue    Pointer where value will be returned
387  * @return          APR_SUCCESS or error
388  */
389 apr_status_t ajp_msg_get_uint32(ajp_msg_t *msg, apr_uint32_t *rvalue)
390 {
391     apr_uint32_t value;
392
393     if ((msg->pos + 3) > msg->len) {
394         return ajp_log_overflow(msg, "ajp_msg_get_uint32");
395     }
396
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));
401
402     *rvalue = value;
403     return APR_SUCCESS;
404 }
405
406
407 /**
408  * Get a 16bits unsigned value from AJP Message
409  *
410  * @param msg       AJP Message to get value from
411  * @param rvalue    Pointer where value will be returned
412  * @return          APR_SUCCESS or error
413  */
414 apr_status_t ajp_msg_get_uint16(ajp_msg_t *msg, apr_uint16_t *rvalue)
415 {
416     apr_uint16_t value;
417
418     if ((msg->pos + 1) > msg->len) {
419         return ajp_log_overflow(msg, "ajp_msg_get_uint16");
420     }
421
422     value  = ((msg->buf[(msg->pos++)] & 0xFF) << 8);
423     value += ((msg->buf[(msg->pos++)] & 0xFF));
424
425     *rvalue = value;
426     return APR_SUCCESS;
427 }
428
429 /**
430  * Peek a 16bits unsigned value from AJP Message, position in message
431  * is not updated
432  *
433  * @param msg       AJP Message to get value from
434  * @param rvalue    Pointer where value will be returned
435  * @return          APR_SUCCESS or error
436  */
437 apr_status_t ajp_msg_peek_uint16(ajp_msg_t *msg, apr_uint16_t *rvalue)
438 {
439     apr_uint16_t value;
440
441     if ((msg->pos + 1) > msg->len) {
442         return ajp_log_overflow(msg, "ajp_msg_peek_uint16");
443     }
444
445     value = ((msg->buf[(msg->pos)] & 0xFF) << 8);
446     value += ((msg->buf[(msg->pos + 1)] & 0xFF));
447
448     *rvalue = value;
449     return APR_SUCCESS;
450 }
451
452 /**
453  * Peek a 8bits unsigned value from AJP Message, position in message
454  * is not updated
455  *
456  * @param msg       AJP Message to get value from
457  * @param rvalue    Pointer where value will be returned
458  * @return          APR_SUCCESS or error
459  */
460 apr_status_t ajp_msg_peek_uint8(ajp_msg_t *msg, apr_byte_t *rvalue)
461 {
462     if (msg->pos > msg->len) {
463         return ajp_log_overflow(msg, "ajp_msg_peek_uint8");
464     }
465
466     *rvalue = msg->buf[msg->pos];
467     return APR_SUCCESS;
468 }
469
470 /**
471  * Get a 8bits unsigned value from AJP Message
472  *
473  * @param msg       AJP Message to get value from
474  * @param rvalue    Pointer where value will be returned
475  * @return          APR_SUCCESS or error
476  */
477 apr_status_t ajp_msg_get_uint8(ajp_msg_t *msg, apr_byte_t *rvalue)
478 {
479
480     if (msg->pos > msg->len) {
481         return ajp_log_overflow(msg, "ajp_msg_get_uint8");
482     }
483
484     *rvalue = msg->buf[msg->pos++];
485     return APR_SUCCESS;
486 }
487
488
489 /**
490  * Get a String value from AJP Message
491  *
492  * @param msg       AJP Message to get value from
493  * @param rvalue    Pointer where value will be returned
494  * @return          APR_SUCCESS or error
495  */
496 apr_status_t ajp_msg_get_string(ajp_msg_t *msg, const char **rvalue)
497 {
498     apr_uint16_t size;
499     apr_size_t   start;
500     apr_status_t status;
501
502     status = ajp_msg_get_uint16(msg, &size);
503     start = msg->pos;
504
505     if ((status != APR_SUCCESS) || (size + start > msg->max_size)) {
506         return ajp_log_overflow(msg, "ajp_msg_get_string");
507     }
508
509     msg->pos += (apr_size_t)size;
510     msg->pos++;                   /* a String in AJP is NULL terminated */
511
512     *rvalue = (const char *)(msg->buf + start);
513     return APR_SUCCESS;
514 }
515
516
517 /**
518  * Get a Byte array from AJP Message
519  *
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
524  */
525 apr_status_t ajp_msg_get_bytes(ajp_msg_t *msg, apr_byte_t **rvalue,
526                                apr_size_t *rvalue_len)
527 {
528     apr_uint16_t size;
529     apr_size_t   start;
530     apr_status_t status;
531
532     status = ajp_msg_get_uint16(msg, &size);
533     /* save the current position */
534     start = msg->pos;
535
536     if ((status != APR_SUCCESS) || (size + start > msg->max_size)) {
537         return ajp_log_overflow(msg, "ajp_msg_get_bytes");
538     }
539     msg->pos += (apr_size_t)size;   /* only bytes, no trailer */
540
541     *rvalue     = msg->buf + start;
542     *rvalue_len = size;
543
544     return APR_SUCCESS;
545 }
546
547
548 /**
549  * Create an AJP Message from pool
550  *
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
555  */
556 apr_status_t ajp_msg_create(apr_pool_t *pool, apr_size_t size, ajp_msg_t **rmsg)
557 {
558     ajp_msg_t *msg = (ajp_msg_t *)apr_pcalloc(pool, sizeof(ajp_msg_t));
559
560     msg->server_side = 0;
561
562     msg->buf = (apr_byte_t *)apr_palloc(pool, size);
563     msg->len = 0;
564     msg->header_len = AJP_HEADER_LEN;
565     msg->max_size = size;
566     *rmsg = msg;
567
568     return APR_SUCCESS;
569 }
570
571 /**
572  * Recopy an AJP Message to another
573  *
574  * @param smsg      source AJP message
575  * @param dmsg      destination AJP message
576  * @return          APR_SUCCESS or error
577  */
578 apr_status_t ajp_msg_copy(ajp_msg_t *smsg, ajp_msg_t *dmsg)
579 {
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);
585         return  AJP_ETOSMALL;
586     }
587
588     memcpy(dmsg->buf, smsg->buf, smsg->len);
589     dmsg->len = smsg->len;
590     dmsg->pos = smsg->pos;
591
592     return APR_SUCCESS;
593 }
594
595
596 /**
597  * Serialize in an AJP Message a PING command
598  *
599  * +-----------------------+
600  * | PING CMD (1 byte)     |
601  * +-----------------------+
602  *
603  * @param smsg      AJP message to put serialized message
604  * @return          APR_SUCCESS or error
605  */
606 apr_status_t ajp_msg_serialize_ping(ajp_msg_t *msg)
607 {
608     apr_status_t rc;
609     ajp_msg_reset(msg);
610
611     if ((rc = ajp_msg_append_uint8(msg, CMD_AJP13_PING)) != APR_SUCCESS)
612         return rc;
613
614     return APR_SUCCESS;
615 }
616
617 /**
618  * Serialize in an AJP Message a CPING command
619  *
620  * +-----------------------+
621  * | CPING CMD (1 byte)    |
622  * +-----------------------+
623  *
624  * @param smsg      AJP message to put serialized message
625  * @return          APR_SUCCESS or error
626  */
627 apr_status_t ajp_msg_serialize_cping(ajp_msg_t *msg)
628 {
629     apr_status_t rc;
630     ajp_msg_reset(msg);
631
632     if ((rc = ajp_msg_append_uint8(msg, CMD_AJP13_CPING)) != APR_SUCCESS)
633         return rc;
634
635     return APR_SUCCESS;
636 }