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