]> granicus.if.org Git - apache/blob - modules/proxy/ajp_msg.c
Use plain apr/apr-util for ajp.
[apache] / modules / proxy / ajp_msg.c
1 /* Copyright 1999-2004 The Apache Software Foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include "ajp.h"
17
18
19 static char *hex_table = "0123456789ABCDEF";
20
21 /**
22  * Dump up to the first 1024 bytes on an AJP Message
23  *
24  * @param pool      pool to allocate from
25  * @param msg       AJP Message to dump
26  * @param err       error string to display
27  * @return          dump message
28  */
29 char * ajp_msg_dump(apr_pool_t *pool, ajp_msg_t *msg, char *err)
30 {
31     apr_size_t  i, j;
32     char        line[80];
33     char        *current;
34     char        *rv, *p;
35     apr_size_t  bl = 8192;
36     apr_byte_t  x;
37     apr_size_t  len = msg->len;
38
39     /* Display only first 1024 bytes */
40     if (len > 1024)
41         len = 1024;
42     rv = apr_palloc(pool, bl);
43     apr_snprintf(rv, bl,
44                  "ajp_msg_dump(): %s pos=%" APR_SIZE_T_FMT 
45                  " len=%" APR_SIZE_T_FMT " max=%d\n",
46                  err, msg->pos, msg->len, AJP_MSG_BUFFER_SZ);
47     bl -= strlen(rv);
48     p = rv + strlen(rv);
49     for (i = 0; i < len; i += 16) {
50         current = line;
51
52         for (j = 0; j < 16; j++) {
53              x = msg->buf[i + j];
54
55             *current++ = hex_table[x >> 4];
56             *current++ = hex_table[x & 0x0f];
57             *current++ = ' ';
58         }
59         *current++ = ' ';
60         *current++ = '-';
61         *current++ = ' ';
62         for (j = 0; j < 16; j++) {
63             x = msg->buf[i + j];
64
65             if (x > 0x20 && x < 0x7F) {
66                 *current++ = x;
67             }
68             else {
69                 *current++ = '.';
70             }
71         }
72
73         *current++ = '\0';
74         apr_snprintf(p, bl,
75                      "ajp_msg_dump(): %.4lx    %s\n",
76                      (unsigned long)i, line);
77         bl -= strlen(rv);
78         p = rv + strlen(rv);
79
80     }
81     
82     return rv;
83 }
84
85
86 /**
87  * Check a new AJP Message by looking at signature and return its size
88  *
89  * @param msg       AJP Message to check
90  * @param len       Pointer to returned len
91  * @return          APR_SUCCESS or error
92  */
93 apr_status_t ajp_msg_check_header(ajp_msg_t *msg, apr_size_t *len)
94 {
95     apr_byte_t *head = msg->buf;
96     apr_size_t msglen;
97
98     if (!((head[0] == 0x41 && head[1] == 0x42) ||
99           (head[0] == 0x12 && head[1] == 0x34))) {
100
101         ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
102                       "ajp_check_msg_header() got bad signature %x%x",
103                       head[0], head[1]);
104
105         return AJP_EBAD_SIGNATURE;
106     }
107
108     msglen  = ((head[2] & 0xff) << 8);
109     msglen += (head[3] & 0xFF);
110
111     if (msglen > AJP_MSG_BUFFER_SZ) {
112         ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
113                      "ajp_check_msg_header() incoming message is "
114                      "too big %" APR_SIZE_T_FMT ", max is %d",
115                      msglen, AJP_MSG_BUFFER_SZ);
116         return AJP_ETOBIG;
117     }
118
119     msg->len = msglen + AJP_HEADER_LEN;
120     msg->pos = AJP_HEADER_LEN;
121     *len     = msglen;
122     
123     return APR_SUCCESS;
124 }
125
126 /**
127  * Reset an AJP Message
128  *
129  * @param msg       AJP Message to reset
130  * @return          APR_SUCCESS or error
131  */
132 apr_status_t ajp_msg_reset(ajp_msg_t *msg)
133 {
134     msg->len = AJP_HEADER_LEN;
135     msg->pos = AJP_HEADER_LEN;
136     
137     return APR_SUCCESS;
138 }
139
140 /**
141  * Mark the end of an AJP Message
142  *
143  * @param msg       AJP Message to end
144  * @return          APR_SUCCESS or error
145  */
146 apr_status_t ajp_msg_end(ajp_msg_t *msg)
147 {
148     apr_size_t len = msg->len - AJP_HEADER_LEN;
149
150     if (msg->server_side) {
151         msg->buf[0] = 0x41;
152         msg->buf[1] = 0x42;
153     }
154     else {
155         msg->buf[0] = 0x12;
156         msg->buf[1] = 0x34;
157     }
158
159     msg->buf[2] = (apr_byte_t)((len >> 8) & 0xFF);
160     msg->buf[3] = (apr_byte_t)(len & 0xFF);
161     
162     return APR_SUCCESS;
163 }
164
165 static APR_INLINE int ajp_log_overflow(ajp_msg_t *msg, const char *context)
166 {
167     ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
168                  "%s(): BufferOverflowException %" APR_SIZE_T_FMT 
169                  " %" APR_SIZE_T_FMT,
170                  context, msg->pos, msg->len);
171     return AJP_EOVERFLOW;
172 }
173
174 /**
175  * Add an unsigned 32bits value to AJP Message
176  *
177  * @param msg       AJP Message to get value from
178  * @param value     value to add to AJP Message
179  * @return          APR_SUCCESS or error
180  */
181 apr_status_t ajp_msg_append_uint32(ajp_msg_t *msg, apr_uint32_t value)
182 {
183     apr_size_t len = msg->len;
184
185     if ((len + 4) > AJP_MSG_BUFFER_SZ) {
186         return ajp_log_overflow(msg, "ajp_msg_append_uint32");
187     }
188
189     msg->buf[len]     = (apr_byte_t)((value >> 24) & 0xFF);
190     msg->buf[len + 1] = (apr_byte_t)((value >> 16) & 0xFF);
191     msg->buf[len + 2] = (apr_byte_t)((value >> 8) & 0xFF);
192     msg->buf[len + 3] = (apr_byte_t)(value & 0xFF);
193
194     msg->len += 4;
195
196     return APR_SUCCESS;
197 }
198
199 /**
200  * Add an unsigned 16bits value to AJP Message
201  *
202  * @param msg       AJP Message to get value from
203  * @param value     value to add to AJP Message
204  * @return          APR_SUCCESS or error
205  */
206 apr_status_t ajp_msg_append_uint16(ajp_msg_t *msg, apr_uint16_t value)
207 {
208     apr_size_t len = msg->len;
209
210     if ((len + 2) > AJP_MSG_BUFFER_SZ) {
211         return ajp_log_overflow(msg, "ajp_msg_append_uint16");
212     }
213
214     msg->buf[len]     = (apr_byte_t)((value >> 8) & 0xFF);
215     msg->buf[len + 1] = (apr_byte_t)(value & 0xFF);
216
217     msg->len += 2;
218
219     return APR_SUCCESS;
220 }
221
222 /**
223  * Add an unsigned 8bits value to AJP Message
224  *
225  * @param msg       AJP Message to get value from
226  * @param value     value to add to AJP Message
227  * @return          APR_SUCCESS or error
228  */
229 apr_status_t ajp_msg_append_uint8(ajp_msg_t *msg, apr_byte_t value)
230 {
231     apr_size_t len = msg->len;
232
233     if ((len + 1) > AJP_MSG_BUFFER_SZ) {
234         return ajp_log_overflow(msg, "ajp_msg_append_uint8");
235     }
236
237     msg->buf[len] = value;
238     msg->len += 1;
239
240     return APR_SUCCESS;
241 }
242
243 /**
244  *  Add a String in AJP message, and transform the String in ASCII 
245  *  if convert is set and we're on an EBCDIC machine    
246  *
247  * @param msg       AJP Message to get value from
248  * @param value     Pointer to String
249  * @param convert   When set told to convert String to ASCII
250  * @return          APR_SUCCESS or error
251  */
252 apr_status_t ajp_msg_append_string_ex(ajp_msg_t *msg, const char *value,
253                                       int convert)
254 {
255     size_t len;
256
257     if (value == NULL) {
258         return(ajp_msg_append_uint16(msg, 0xFFFF));
259     }
260
261     len = strlen(value);
262     if ((msg->len + len + 2) > AJP_MSG_BUFFER_SZ) {
263         return ajp_log_overflow(msg, "ajp_msg_append_cvt_string");
264     }
265
266     /* ignore error - we checked once */
267     ajp_msg_append_uint16(msg, (apr_uint16_t)len);
268
269     /* We checked for space !!  */
270     memcpy(msg->buf + msg->len, value, len + 1); /* including \0 */
271
272     if (convert)   /* convert from EBCDIC if needed */
273         ajp_xlate_to_ascii((char *)msg->buf + msg->len, len + 1);
274
275     msg->len += len + 1;
276
277     return APR_SUCCESS;
278 }
279
280 /**
281  * Add a Byte array to AJP Message
282  *
283  * @param msg       AJP Message to get value from
284  * @param value     Pointer to Byte array
285  * @param valuelen  Byte array len
286  * @return          APR_SUCCESS or error
287  */
288 apr_status_t ajp_msg_append_bytes(ajp_msg_t *msg, const apr_byte_t *value,
289                                   apr_size_t valuelen)
290 {
291     if (! valuelen) {
292         return APR_SUCCESS; /* Shouldn't we indicate an error ? */
293     }
294
295     if ((msg->len + valuelen) > AJP_MSG_BUFFER_SZ) {
296         return ajp_log_overflow(msg, "ajp_msg_append_bytes");
297     }
298
299     /* We checked for space !!  */
300     memcpy(msg->buf + msg->len, value, valuelen);
301     msg->len += valuelen;
302
303     return APR_SUCCESS;
304 }
305
306 /**
307  * Get a 32bits unsigned value from AJP Message
308  *
309  * @param msg       AJP Message to get value from
310  * @param rvalue    Pointer where value will be returned
311  * @return          APR_SUCCESS or error
312  */
313 apr_status_t ajp_msg_get_uint32(ajp_msg_t *msg, apr_uint32_t *rvalue)
314 {
315     apr_uint32_t value;
316
317     if ((msg->pos + 3) > msg->len) {
318         return ajp_log_overflow(msg, "ajp_msg_get_uint32");
319     }
320
321     value  = ((msg->buf[(msg->pos++)] & 0xFF) << 24);
322     value |= ((msg->buf[(msg->pos++)] & 0xFF) << 16);
323     value |= ((msg->buf[(msg->pos++)] & 0xFF) << 8);
324     value |= ((msg->buf[(msg->pos++)] & 0xFF));
325     
326     *rvalue = value;
327     return APR_SUCCESS;
328 }
329
330
331 /**
332  * Get a 16bits unsigned value from AJP Message
333  *
334  * @param msg       AJP Message to get value from
335  * @param rvalue    Pointer where value will be returned
336  * @return          APR_SUCCESS or error
337  */
338 apr_status_t ajp_msg_get_uint16(ajp_msg_t *msg, apr_uint16_t *rvalue)
339 {
340     apr_uint16_t value;
341     
342     if ((msg->pos + 1) > msg->len) {
343         return ajp_log_overflow(msg, "ajp_msg_get_uint16");
344     }
345
346     value  = ((msg->buf[(msg->pos++)] & 0xFF) << 8);
347     value += ((msg->buf[(msg->pos++)] & 0xFF));
348
349     *rvalue = value;
350     return APR_SUCCESS;
351 }
352
353 /**
354  * Peek a 16bits unsigned value from AJP Message, position in message
355  * is not updated
356  *
357  * @param msg       AJP Message to get value from
358  * @param rvalue    Pointer where value will be returned
359  * @return          APR_SUCCESS or error
360  */
361 apr_status_t ajp_msg_peek_uint16(ajp_msg_t *msg, apr_uint16_t *rvalue)
362 {
363     apr_uint16_t value;
364
365     if ((msg->pos + 1) > msg->len) {
366         return ajp_log_overflow(msg, "ajp_msg_peek_uint16");
367     }
368     
369     value = ((msg->buf[(msg->pos)] & 0xFF) << 8);
370     value += ((msg->buf[(msg->pos + 1)] & 0xFF));
371     
372     *rvalue = value;
373     return APR_SUCCESS;
374 }
375
376 /**
377  * Peek a 8bits unsigned value from AJP Message, position in message
378  * is not updated
379  *
380  * @param msg       AJP Message to get value from
381  * @param rvalue    Pointer where value will be returned
382  * @return          APR_SUCCESS or error
383  */
384 apr_status_t ajp_msg_peek_uint8(ajp_msg_t *msg, apr_byte_t *rvalue)
385 {
386     if (msg->pos > msg->len) {
387         return ajp_log_overflow(msg, "ajp_msg_peek_uint8");
388     }
389     
390     *rvalue = msg->buf[msg->pos];
391     return APR_SUCCESS;
392 }
393
394 /**
395  * Get a 8bits unsigned value from AJP Message
396  *
397  * @param msg       AJP Message to get value from
398  * @param rvalue    Pointer where value will be returned
399  * @return          APR_SUCCESS or error
400  */
401 apr_status_t ajp_msg_get_uint8(ajp_msg_t *msg, apr_byte_t *rvalue)
402 {
403
404     if (msg->pos > msg->len) {
405         return ajp_log_overflow(msg, "ajp_msg_get_uint8");
406     }
407     
408     *rvalue = msg->buf[msg->pos++];
409     return APR_SUCCESS;
410 }
411
412
413 /**
414  * Get a String value from AJP Message
415  *
416  * @param msg       AJP Message to get value from
417  * @param rvalue    Pointer where value will be returned
418  * @return          APR_SUCCESS or error
419  */
420 apr_status_t ajp_msg_get_string(ajp_msg_t *msg, char **rvalue)
421 {
422     apr_uint16_t size;
423     apr_size_t   start;
424     apr_status_t status;
425        
426     status = ajp_msg_get_uint16(msg, &size);
427     start = msg->pos;
428
429     if ((status != APR_SUCCESS) || (size + start > AJP_MSG_BUFFER_SZ)) {
430         return ajp_log_overflow(msg, "ajp_msg_get_string");
431     }
432
433     msg->pos += (apr_size_t)size;
434     msg->pos++;                   /* a String in AJP is NULL terminated */
435
436     *rvalue = (char *)(msg->buf + start);
437     return APR_SUCCESS;
438 }
439
440
441 /**
442  * Get a Byte array from AJP Message
443  *
444  * @param msg       AJP Message to get value from
445  * @param rvalue    Pointer where value will be returned
446  * @param rvalueLen Pointer where Byte array len will be returned
447  * @return          APR_SUCCESS or error
448  */
449 apr_status_t ajp_msg_get_bytes(ajp_msg_t *msg, apr_byte_t **rvalue,
450                                apr_size_t *rvalue_len)
451 {
452     apr_uint16_t size;
453     apr_size_t   start;
454     apr_status_t status;
455
456     status = ajp_msg_get_uint16(msg, &size);
457     /* save the current position */
458     start = msg->pos;
459
460     if ((status != APR_SUCCESS) || (size + start > AJP_MSG_BUFFER_SZ)) {
461         return ajp_log_overflow(msg, "ajp_msg_get_bytes");
462     }
463     msg->pos += (apr_size_t)size;   /* only bytes, no trailer */
464
465     *rvalue     = msg->buf + start;
466     *rvalue_len = size;
467
468     return APR_SUCCESS;
469 }
470
471
472 /**
473  * Create an AJP Message from pool
474  *
475  * @param pool      memory pool to allocate AJP message from
476  * @param rmsg      Pointer to newly created AJP message
477  * @return          APR_SUCCESS or error
478  */
479 apr_status_t ajp_msg_create(apr_pool_t *pool, ajp_msg_t **rmsg)
480 {
481     ajp_msg_t *msg = (ajp_msg_t *)apr_pcalloc(pool, sizeof(ajp_msg_t));
482
483     if (!msg) {
484         ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
485                       "ajp_msg_create(): can't allocate AJP message memory");
486         return APR_ENOPOOL;
487     }
488     
489     msg->server_side = 0;
490
491     msg->buf = (apr_byte_t *)apr_palloc(pool, AJP_MSG_BUFFER_SZ);
492     
493     /* XXX: This should never happen
494      * In case if the OS cannont allocate 8K of data
495      * we are in serious trouble
496      * No need to check the alloc return value, cause the
497      * core dump is probably the best solution anyhow.
498      */
499     if (msg->buf == NULL) {
500         ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
501                       "ajp_msg_create(): can't allocate AJP message memory");
502         return APR_ENOPOOL;
503     }
504
505     msg->len = 0;
506     msg->header_len = AJP_HEADER_LEN;
507     *rmsg = msg;
508     
509     return APR_SUCCESS;
510 }
511
512 /**
513  * Recopy an AJP Message to another
514  *
515  * @param smsg      source AJP message
516  * @param dmsg      destination AJP message
517  * @return          APR_SUCCESS or error
518  */
519 apr_status_t ajp_msg_copy(ajp_msg_t *smsg, ajp_msg_t *dmsg)
520 {
521     if (dmsg == NULL) {
522         ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
523                      "ajp_msg_copy(): destination msg is null");
524         return AJP_EINVAL;
525     }
526     
527     if (smsg->len > AJP_MSG_BUFFER_SZ) {
528         ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
529                      "ajp_msg_copy(): destination buffer too "
530                      "small %" APR_SIZE_T_FMT ", max size is %d",
531                      smsg->len, AJP_MSG_BUFFER_SZ);
532         return  AJP_ETOSMALL;
533     }
534
535     memcpy(dmsg->buf, smsg->buf, smsg->len);
536     dmsg->len = smsg->len;
537     dmsg->pos = smsg->pos;
538
539     return APR_SUCCESS;
540 }
541
542
543 /**
544  * Serialize in an AJP Message a PING command
545  *
546  * +-----------------------+
547  * | PING CMD (1 byte)     |
548  * +-----------------------+
549  *
550  * @param smsg      AJP message to put serialized message
551  * @return          APR_SUCCESS or error
552  */
553 apr_status_t ajp_msg_serialize_ping(ajp_msg_t *msg)
554 {
555     apr_status_t rc;
556     ajp_msg_reset(msg);
557
558     if ((rc = ajp_msg_append_uint8(msg, CMD_AJP13_PING)) != APR_SUCCESS)
559         return rc;
560         
561     return APR_SUCCESS;
562 }
563
564 /** 
565  * Serialize in an AJP Message a CPING command
566  *
567  * +-----------------------+
568  * | CPING CMD (1 byte)    |
569  * +-----------------------+
570  *
571  * @param smsg      AJP message to put serialized message
572  * @return          APR_SUCCESS or error
573  */
574 apr_status_t ajp_msg_serialize_cping(ajp_msg_t *msg)
575 {
576     apr_status_t rc;
577     ajp_msg_reset(msg);
578
579     if ((rc = ajp_msg_append_uint8(msg, CMD_AJP13_CPING)) != APR_SUCCESS)
580         return rc;
581         
582     return APR_SUCCESS;
583 }