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