1 /* 2 * mod_ajp13 - Apache JServ Protocol version 1.3 (AJP13) gateway 3 * 4 * Copyright(c) 2021 Glenn Strauss gstrauss()gluelogic.com All rights reserved 5 * License: BSD 3-clause (same as lighttpd) 6 * 7 * AJPv13 protocol reference: 8 * https://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html 9 * 10 * Note: connection pool (and connection reuse) is not implemented 11 */ 12 #include "first.h" 13 14 #include <sys/types.h> 15 #include <limits.h> 16 #include <stdlib.h> 17 #include <string.h> 18 19 #include "gw_backend.h" 20 typedef gw_plugin_config plugin_config; 21 typedef gw_plugin_data plugin_data; 22 typedef gw_handler_ctx handler_ctx; 23 24 #include "base.h" 25 #include "buffer.h" 26 #include "chunk.h" 27 #include "fdevent.h" 28 #include "http_chunk.h" 29 #include "http_header.h" 30 #include "http_kv.h" 31 #include "log.h" 32 33 #define AJP13_MAX_PACKET_SIZE 8192 34 35 36 static void 37 mod_ajp13_merge_config_cpv (plugin_config * const pconf, const config_plugin_value_t * const cpv) 38 { 39 switch (cpv->k_id) { /* index into static config_plugin_keys_t cpk[] */ 40 case 0: /* ajp13.server */ 41 if (cpv->vtype == T_CONFIG_LOCAL) { 42 gw_plugin_config * const gw = cpv->v.v; 43 pconf->exts = gw->exts; 44 pconf->exts_auth = gw->exts_auth; 45 pconf->exts_resp = gw->exts_resp; 46 } 47 break; 48 case 1: /* ajp13.balance */ 49 /*if (cpv->vtype == T_CONFIG_LOCAL)*//*always true here for this param*/ 50 pconf->balance = (int)cpv->v.u; 51 break; 52 case 2: /* ajp13.debug */ 53 pconf->debug = (int)cpv->v.u; 54 break; 55 case 3: /* ajp13.map-extensions */ 56 pconf->ext_mapping = cpv->v.a; 57 break; 58 default:/* should not happen */ 59 return; 60 } 61 } 62 63 64 static void 65 mod_ajp13_merge_config (plugin_config * const pconf, const config_plugin_value_t *cpv) 66 { 67 do { 68 mod_ajp13_merge_config_cpv(pconf, cpv); 69 } while ((++cpv)->k_id != -1); 70 } 71 72 73 static void 74 mod_ajp13_patch_config (request_st * const r, plugin_data * const p) 75 { 76 memcpy(&p->conf, &p->defaults, sizeof(plugin_config)); 77 for (int i = 1, used = p->nconfig; i < used; ++i) { 78 if (config_check_cond(r, (uint32_t)p->cvlist[i].k_id)) 79 mod_ajp13_merge_config(&p->conf,p->cvlist + p->cvlist[i].v.u2[0]); 80 } 81 } 82 83 84 SETDEFAULTS_FUNC(mod_ajp13_set_defaults) 85 { 86 static const config_plugin_keys_t cpk[] = { 87 { CONST_STR_LEN("ajp13.server"), 88 T_CONFIG_ARRAY_KVARRAY, 89 T_CONFIG_SCOPE_CONNECTION } 90 ,{ CONST_STR_LEN("ajp13.balance"), 91 T_CONFIG_STRING, 92 T_CONFIG_SCOPE_CONNECTION } 93 ,{ CONST_STR_LEN("ajp13.debug"), 94 T_CONFIG_INT, 95 T_CONFIG_SCOPE_CONNECTION } 96 ,{ CONST_STR_LEN("ajp13.map-extensions"), 97 T_CONFIG_ARRAY_KVSTRING, 98 T_CONFIG_SCOPE_CONNECTION } 99 ,{ NULL, 0, 100 T_CONFIG_UNSET, 101 T_CONFIG_SCOPE_UNSET } 102 }; 103 104 plugin_data * const p = p_d; 105 if (!config_plugin_values_init(srv, p, cpk, "mod_ajp13")) 106 return HANDLER_ERROR; 107 108 /* process and validate config directives 109 * (init i to 0 if global context; to 1 to skip empty global context) */ 110 for (int i = !p->cvlist[0].v.u2[1]; i < p->nconfig; ++i) { 111 config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0]; 112 gw_plugin_config *gw = NULL; 113 for (; -1 != cpv->k_id; ++cpv) { 114 switch (cpv->k_id) { 115 case 0:{/* ajp13.server */ 116 gw = ck_calloc(1, sizeof(gw_plugin_config)); 117 if (!gw_set_defaults_backend(srv, p, cpv->v.a, gw, 0, 118 cpk[cpv->k_id].k)) { 119 gw_plugin_config_free(gw); 120 return HANDLER_ERROR; 121 } 122 cpv->v.v = gw; 123 cpv->vtype = T_CONFIG_LOCAL; 124 break; 125 } 126 case 1: /* ajp13.balance */ 127 cpv->v.u = (unsigned int)gw_get_defaults_balance(srv, cpv->v.b); 128 break; 129 case 2: /* ajp13.debug */ 130 case 3: /* ajp13.map-extensions */ 131 break; 132 default:/* should not happen */ 133 break; 134 } 135 } 136 137 /* disable check-local for all exts (default enabled) */ 138 if (gw && gw->exts) { /*(check after gw_set_defaults_backend())*/ 139 gw_exts_clear_check_local(gw->exts); 140 } 141 } 142 143 /* default is 0 */ 144 /*p->defaults.balance = (unsigned int)gw_get_defaults_balance(srv, NULL);*/ 145 146 /* initialize p->defaults from global config context */ 147 if (p->nconfig > 0 && p->cvlist->v.u2[1]) { 148 const config_plugin_value_t *cpv = p->cvlist + p->cvlist->v.u2[0]; 149 if (-1 != cpv->k_id) 150 mod_ajp13_merge_config(&p->defaults, cpv); 151 } 152 153 return HANDLER_GO_ON; 154 } 155 156 157 __attribute_pure__ 158 static inline uint32_t 159 ajp13_dec_uint16 (const uint8_t * const x) 160 { 161 return (x[0] << 8) | x[1]; 162 } 163 164 165 static inline void 166 ajp13_enc_uint16_nc (uint8_t * const x, const uint32_t v) 167 { 168 /*(_nc = no check; caller must check for sufficient space in x)*/ 169 x[0] = 0xFF & (v >> 8); 170 x[1] = 0xFF & (v); 171 } 172 173 174 static uint32_t 175 ajp13_enc_uint16 (uint8_t * const x, const uint32_t n, const uint32_t v) 176 { 177 if (n + 2 > AJP13_MAX_PACKET_SIZE) return 0; 178 ajp13_enc_uint16_nc(x+n, v); 179 return n+2; 180 } 181 182 183 static uint32_t 184 ajp13_enc_byte (uint8_t * const x, const uint32_t n, const uint32_t v) 185 { 186 if (n + 1 > AJP13_MAX_PACKET_SIZE) return 0; 187 x[n] = v; 188 return n+1; 189 } 190 191 192 static uint32_t 193 ajp13_enc_string (uint8_t * const x, uint32_t n, const char * const s, const uint32_t len) 194 { 195 /*assert(AJP13_MAX_PACKET_SIZE <= UINT16_MAX);*//*(max is 8k in practice)*/ 196 if (0 == len || len == UINT16_MAX) 197 return ajp13_enc_uint16(x, n, 0xFFFF); 198 199 if (n + 2 + len + 1 > AJP13_MAX_PACKET_SIZE) return 0; 200 ajp13_enc_uint16_nc(x+n, len); 201 n += 2; 202 memcpy(x+n, s, len); 203 n += len; 204 x[n] = '\0'; 205 return n+1; 206 } 207 208 209 static handler_t 210 ajp13_stdin_append (handler_ctx * const hctx) 211 { 212 chunkqueue * const req_cq = &hctx->r->reqbody_queue; 213 const off_t req_cqlen = chunkqueue_length(req_cq); 214 const off_t max_bytes = hctx->request_id < req_cqlen 215 ? hctx->request_id < MAX_WRITE_LIMIT ? hctx->request_id : MAX_WRITE_LIMIT 216 : req_cqlen; 217 off_t sent = 0; 218 uint8_t hdr[4] = { 0x12, 0x34, 0, 0 }; 219 220 for (off_t dlen; sent < max_bytes; sent += dlen) { 221 dlen = max_bytes - sent > AJP13_MAX_PACKET_SIZE - 4 222 ? AJP13_MAX_PACKET_SIZE - 4 223 : max_bytes - sent; 224 225 if (-1 != hctx->wb_reqlen) { 226 if (hctx->wb_reqlen >= 0) 227 hctx->wb_reqlen += sizeof(hdr); 228 else 229 hctx->wb_reqlen -= sizeof(hdr); 230 } 231 232 ajp13_enc_uint16_nc(hdr+2, (uint32_t)dlen); 233 (chunkqueue_is_empty(&hctx->wb) || hctx->wb.first->type == MEM_CHUNK) 234 /* else FILE_CHUNK for temp file */ 235 ? chunkqueue_append_mem(&hctx->wb, (char *)&hdr, sizeof(hdr)) 236 : chunkqueue_append_mem_min(&hctx->wb, (char *)&hdr, sizeof(hdr)); 237 chunkqueue_steal(&hctx->wb, req_cq, dlen); 238 /*(hctx->wb_reqlen already includes reqbody_length)*/ 239 } 240 241 hctx->request_id -= (int)sent; 242 return HANDLER_GO_ON; 243 } 244 245 246 static void 247 ajp13_stdin_append_n (handler_ctx * const hctx, const uint32_t n) 248 { 249 if (hctx->wb.bytes_in == hctx->wb_reqlen) { 250 /*(no additional request body to be sent; send empty packet)*/ 251 uint8_t hdr[4] = { 0x12, 0x34, 0, 0 }; 252 hctx->wb_reqlen += sizeof(hdr); 253 chunkqueue_append_mem(&hctx->wb, (char *)hdr, sizeof(hdr)); 254 } 255 256 /* AJP13 connections can be reused, so server and backend must agree on how 257 * much data is sent for each serialized request, especially if backend 258 * chooses not to read (and use or discard) entire request body from server. 259 * If server sent excess data, data might be interpreted as a subsequent 260 * request, which might be abused for request smuggling (security). */ 261 262 /* overload hctx->request_id to track bytes requested by backend. 263 * Value must stay >= 0, since -1 is used to flag end of request */ 264 if (n <= (uint32_t)(INT_MAX - hctx->request_id)) 265 hctx->request_id += (int)n; 266 else /* unexpected; misbehaving backend sent MANY Get Body Chunk requests */ 267 hctx->request_id = INT_MAX; /*(limitation of overloaded struct member)*/ 268 269 ajp13_stdin_append(hctx); 270 } 271 272 273 __attribute_pure__ 274 static uint8_t 275 ajp13_method_byte (const http_method_t m) 276 { 277 /* map lighttpd http_method_t to ajp13 method byte */ 278 279 #if (defined(__STDC_VERSION__) && __STDC_VERSION__-0 >= 199901L) /* C99 */ 280 281 static const uint8_t ajp13_methods[] = { 282 [HTTP_METHOD_GET] = 2, 283 [HTTP_METHOD_HEAD] = 3, 284 [HTTP_METHOD_POST] = 4, 285 [HTTP_METHOD_PUT] = 5, 286 [HTTP_METHOD_DELETE] = 6, 287 [HTTP_METHOD_OPTIONS] = 1, 288 [HTTP_METHOD_TRACE] = 7, 289 [HTTP_METHOD_ACL] = 15, 290 [HTTP_METHOD_BASELINE_CONTROL] = 26, 291 [HTTP_METHOD_CHECKIN] = 18, 292 [HTTP_METHOD_CHECKOUT] = 19, 293 [HTTP_METHOD_COPY] = 11, 294 [HTTP_METHOD_LABEL] = 24, 295 [HTTP_METHOD_LOCK] = 13, 296 [HTTP_METHOD_MERGE] = 25, 297 [HTTP_METHOD_MKACTIVITY] = 27, 298 [HTTP_METHOD_MKCOL] = 10, 299 [HTTP_METHOD_MKWORKSPACE] = 22, 300 [HTTP_METHOD_MOVE] = 12, 301 [HTTP_METHOD_PROPFIND] = 8, 302 [HTTP_METHOD_PROPPATCH] = 9, 303 [HTTP_METHOD_REPORT] = 16, 304 [HTTP_METHOD_SEARCH] = 21, 305 [HTTP_METHOD_UNCHECKOUT] = 20, 306 [HTTP_METHOD_UNLOCK] = 14, 307 [HTTP_METHOD_UPDATE] = 23, 308 [HTTP_METHOD_VERSION_CONTROL] = 17 309 }; 310 311 return m >= 0 && m < (http_method_t)sizeof(ajp13_methods) 312 ? ajp13_methods[m] 313 : 0; 314 315 #else /*(array position is ajp13 method identifier byte)*/ 316 317 static const uint8_t ajp13_methods[] = { 318 0, 319 HTTP_METHOD_OPTIONS, 320 HTTP_METHOD_GET, 321 HTTP_METHOD_HEAD, 322 HTTP_METHOD_POST, 323 HTTP_METHOD_PUT, 324 HTTP_METHOD_DELETE, 325 HTTP_METHOD_TRACE, 326 HTTP_METHOD_PROPFIND, 327 HTTP_METHOD_PROPPATCH, 328 HTTP_METHOD_MKCOL, 329 HTTP_METHOD_COPY, 330 HTTP_METHOD_MOVE, 331 HTTP_METHOD_LOCK, 332 HTTP_METHOD_UNLOCK, 333 HTTP_METHOD_ACL, 334 HTTP_METHOD_REPORT, 335 HTTP_METHOD_VERSION_CONTROL, 336 HTTP_METHOD_CHECKIN, 337 HTTP_METHOD_CHECKOUT, 338 HTTP_METHOD_UNCHECKOUT, 339 HTTP_METHOD_SEARCH, 340 HTTP_METHOD_MKWORKSPACE, 341 HTTP_METHOD_UPDATE, 342 HTTP_METHOD_LABEL, 343 HTTP_METHOD_MERGE, 344 HTTP_METHOD_BASELINE_CONTROL, 345 HTTP_METHOD_MKACTIVITY 346 }; 347 348 uint8_t method; 349 for (method = 1; method < sizeof(ajp13_methods); ++method) { 350 if (ajp13_methods[method] == m) break; 351 } 352 return (method < sizeof(ajp13_methods)) ? method : 0; 353 354 #endif 355 } 356 357 358 static uint32_t 359 ajp13_enc_request_headers (uint8_t * const x, uint32_t n, const request_st * const r) 360 { 361 const array * const rqst_headers = &r->rqst_headers; 362 const int add_content_length = 363 (!light_btst(r->rqst_htags, HTTP_HEADER_CONTENT_LENGTH)); 364 /* num_headers */ 365 n = ajp13_enc_uint16(x, n, rqst_headers->used + add_content_length); 366 if (0 == n) return n; 367 /* request_headers */ 368 if (add_content_length) { 369 /* (gw_backend.c sends 411 Length Required if Content-Length not 370 * provided and request body is being streamed to backend. Add 371 * Content-Length if not provided and request body was collected.) */ 372 n = ajp13_enc_uint16(x, n, 0xA008); 373 if (0 == n) return n; 374 char buf[LI_ITOSTRING_LENGTH]; 375 n = ajp13_enc_string(x, n, buf, 376 li_itostrn(buf, sizeof(buf), r->reqbody_length)); 377 if (0 == n) return n; 378 } 379 for (uint32_t i = 0, num = rqst_headers->used; i < num; ++i) { 380 const data_string * const ds = (data_string *)rqst_headers->data[i]; 381 uint8_t code = 0x00; 382 switch (ds->ext) { /* map request header to ajp13 SC_REQ_* code */ 383 case HTTP_HEADER_ACCEPT: code = 0x01; break; 384 case HTTP_HEADER_ACCEPT_ENCODING: code = 0x03; break; 385 case HTTP_HEADER_ACCEPT_LANGUAGE: code = 0x04; break; 386 case HTTP_HEADER_AUTHORIZATION: code = 0x05; break; 387 case HTTP_HEADER_CONNECTION: code = 0x06; break; 388 case HTTP_HEADER_CONTENT_TYPE: code = 0x07; break; 389 case HTTP_HEADER_CONTENT_LENGTH: code = 0x08; break; 390 case HTTP_HEADER_COOKIE: code = 0x09; break; 391 case HTTP_HEADER_HOST: code = 0x0B; break; 392 case HTTP_HEADER_PRAGMA: code = 0x0C; break; 393 case HTTP_HEADER_REFERER: code = 0x0D; break; 394 case HTTP_HEADER_USER_AGENT: code = 0x0E; break; 395 case HTTP_HEADER_OTHER: 396 if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Accept-Charset"))) 397 code = 0x02; 398 else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Cookie2"))) 399 code = 0x0A; 400 break; 401 default: 402 break; 403 } 404 405 n = (code) 406 ? ajp13_enc_uint16(x, n, 0xA000 | code) 407 : ajp13_enc_string(x, n, BUF_PTR_LEN(&ds->key)); 408 if (0 == n) return n; 409 n = ajp13_enc_string(x, n, BUF_PTR_LEN(&ds->value)); 410 if (0 == n) return n; 411 } 412 return n; 413 } 414 415 416 #if 0 417 static uint32_t 418 ajp13_enc_req_attribute (uint8_t * const x, uint32_t n, const char * const k, const uint32_t klen, const char * const v, const uint32_t vlen) 419 { 420 n = ajp13_enc_byte(x, n, 0x0A); 421 if (0 == n) return n; 422 n = ajp13_enc_string(x, n, k, klen); 423 if (0 == n) return n; 424 return ajp13_enc_string(x, n, v, vlen); 425 } 426 #endif 427 428 429 static uint32_t 430 ajp13_enc_attribute (uint8_t * const x, uint32_t n, const buffer * const b, uint8_t code) 431 { 432 if (NULL == b) return n; 433 n = ajp13_enc_byte(x, n, code); 434 if (0 == n) return n; 435 return ajp13_enc_string(x, n, BUF_PTR_LEN(b)); 436 } 437 438 439 static uint32_t 440 ajp13_enc_attributes (uint8_t * const x, uint32_t n, request_st * const r) 441 { 442 const buffer *vb; 443 444 vb = http_header_env_get(r, CONST_STR_LEN("REMOTE_USER")); 445 n = ajp13_enc_attribute(x, n, vb, 0x03); 446 if (0 == n) return n; 447 vb = http_header_env_get(r, CONST_STR_LEN("AUTH_TYPE")); 448 n = ajp13_enc_attribute(x, n, vb, 0x04); 449 if (0 == n) return n; 450 451 if (!buffer_is_blank(&r->uri.query)) { 452 n = ajp13_enc_attribute(x, n, &r->uri.query, 0x05); 453 if (0 == n) return n; 454 } 455 456 if (buffer_is_equal_string(&r->uri.scheme, CONST_STR_LEN("https"))) { 457 /* XXX: might have config to avoid this overhead if not needed */ 458 459 r->con->srv->request_env(r); 460 461 vb = http_header_env_get(r, CONST_STR_LEN("SSL_CLIENT_CERT")); 462 n = ajp13_enc_attribute(x, n, vb, 0x07); 463 if (0 == n) return n; 464 vb = http_header_env_get(r, CONST_STR_LEN("SSL_CIPHER")); 465 n = ajp13_enc_attribute(x, n, vb, 0x08); 466 if (0 == n) return n; 467 vb = http_header_env_get(r, CONST_STR_LEN("SSL_CIPHER_USE_KEYSIZE")); 468 n = ajp13_enc_attribute(x, n, vb, 0x0B); 469 if (0 == n) return n; 470 } 471 472 #if 0 473 /* req_attribute */ /*(what is often included by convention?)*/ 474 n = ajp13_enc_req_attribute(x, n, CONST_STR_LEN("REDIRECT_URI"), 475 BUF_PTR_LEN(&r->target_orig)); 476 if (0 == n) return n; 477 if (!buffer_is_equal(&r->target, &r->target_orig)) { 478 n = ajp13_enc_req_attribute(x, n, CONST_STR_LEN("REDIRECT_URI"), 479 BUF_PTR_LEN(&r->target)); 480 if (0 == n) return n; 481 } 482 /* Note: if this is extended to pass all env; must not pass HTTP_PROXY */ 483 #endif 484 485 #if 1 /*(experimental) (???) (XXX: create separate config option?)*/ 486 /*(use mod_setenv to set value)*/ 487 vb = http_header_env_get(r, CONST_STR_LEN("AJP13_SECRET")); 488 n = ajp13_enc_attribute(x, n, vb, 0x0C); 489 if (0 == n) return n; 490 #endif 491 492 return n; 493 } 494 495 496 static uint32_t 497 ajp13_enc_server_name (uint8_t * const x, const uint32_t n, const request_st * const r) 498 { 499 #if 0 500 const data_string * const ds = 501 array_get_element_klen(cgienv, CONST_STR_LEN("SERVER_NAME")); 502 return (ds) 503 ? ajp13_enc_string(x, n, BUF_PTR_LEN(&ds->value)) 504 : ajp13_enc_string(x, n, NULL, 0); 505 #else 506 /* copied and modified from http_cgi.c:http_cgi_headers() */ 507 uint32_t len = buffer_clen(r->server_name); 508 if (len) { 509 const char * const ptr = r->server_name->ptr; 510 if (ptr[0] == '[') { 511 const char *colon = strstr(ptr, "]:"); 512 if (colon) len = (colon + 1) - ptr; 513 } 514 else { 515 const char *colon = strchr(ptr, ':'); 516 if (colon) len = colon - ptr; 517 } 518 return ajp13_enc_string(x, n, ptr, len); 519 } 520 else { 521 /* SERVER_ADDR is generated in http_cgi_headers() 522 * if the listen addr is, for example, a wildcard addr. 523 * XXX: For now, just send an empty string in this case 524 * instead of duplicating that code */ 525 return ajp13_enc_string(x, n, NULL, 0); 526 } 527 #endif 528 } 529 530 531 #if 0 532 static int 533 ajp13_env_add (void *venv, const char *k, size_t klen, const char *v, size_t vlen) 534 { 535 /*(might be more efficient to store list rather than lighttpd array)*/ 536 array_set_key_value((array *)venv, k, klen, v, vlen); 537 return 0; 538 } 539 #endif 540 541 542 static handler_t 543 ajp13_create_env (handler_ctx * const hctx) 544 { 545 request_st * const r = hctx->r; 546 /* AJP13_MAX_PACKET_SIZE currently matches default 8k chunk_buf_sz */ 547 buffer * const b = 548 chunkqueue_prepend_buffer_open_sz(&hctx->wb, AJP13_MAX_PACKET_SIZE); 549 550 #if 0 /*(elide if used only for SERVER_NAME, as is current case)*/ 551 /* Note: while it might be slightly more efficient to special-case ajp13 552 * request creation here (reduce string copy), it is not worth duplicating 553 * the logic centralized in http-header-glue.c:http_cgi_headers() */ 554 array * const cgienv = array_init(64); 555 #endif 556 557 do { 558 #if 0 559 #if 0 /* XXX: potential future extension */ 560 gw_host * const host = hctx->host; 561 http_cgi_opts opts = { 562 (hctx->gw_mode == FCGI_AUTHORIZER), 563 host->break_scriptfilename_for_php, 564 host->docroot, 565 host->strip_request_uri 566 }; 567 #else 568 http_cgi_opts opts = { 0, 0, NULL, NULL }; 569 #endif 570 if (0 != http_cgi_headers(r, &opts, ajp13_env_add, cgienv)) break; 571 #endif 572 573 uint32_t n = 6; 574 uint8_t * const x = (uint8_t *)b->ptr; 575 576 x[0] = 0x12; 577 x[1] = 0x34; 578 x[2] = 0; 579 x[3] = 0; 580 x[4] = 0x02; /* JK_AJP13_FORWARD_REQUEST */ 581 /* method */ 582 const uint8_t method_byte = ajp13_method_byte(r->http_method); 583 if (0 == method_byte) break; 584 x[5] = method_byte; 585 /* protocol */ 586 const char * const proto = get_http_version_name(r->http_version); 587 n = ajp13_enc_string(x, n, proto, strlen(proto)); 588 if (0 == n) break; 589 /* req_uri */ 590 n = ajp13_enc_string(x, n, BUF_PTR_LEN(&r->uri.path)); 591 if (0 == n) break; 592 /* remote_addr */ 593 n = ajp13_enc_string(x, n, BUF_PTR_LEN(&r->con->dst_addr_buf)); 594 if (0 == n) break; 595 /* remote_host *//*(skip DNS lookup)*/ 596 n = ajp13_enc_string(x, n, NULL, 0); 597 if (0 == n) break; 598 /* server_name */ 599 n = ajp13_enc_server_name(x, n, r); 600 if (0 == n) break; 601 /* server_port */ 602 unsigned short port = sock_addr_get_port(&r->con->srv_socket->addr); 603 n = ajp13_enc_uint16(x, n, port); 604 if (0 == n) break; 605 /* is_ssl */ 606 n = ajp13_enc_byte(x,n,buffer_is_equal_string(&r->uri.scheme, 607 CONST_STR_LEN("https"))); 608 if (0 == n) break; 609 /* num_headers */ 610 /* request_headers */ 611 n = ajp13_enc_request_headers(x, n, r); 612 if (0 == n) break; 613 /* attributes */ 614 n = ajp13_enc_attributes(x, n, r); 615 if (0 == n) break; 616 /* request_terminator */ 617 n = ajp13_enc_byte(x, n, 0xFF); 618 if (0 == n) break; 619 /* payload length (overwrite in header) */ 620 ajp13_enc_uint16_nc(x+2, n-4); 621 622 #if 0 623 array_free(cgienv); 624 #endif 625 626 /* (buffer is reallocated only if n is exactly AJP13_MAX_PACKET_SIZE) */ 627 /* (could check for one-off; limit to 8k-1 to avoid resizing buffer) */ 628 buffer_extend(b, n);/*(buffer_commit but extend +1 for '\0' as needed)*/ 629 chunkqueue_prepend_buffer_commit(&hctx->wb); 630 hctx->wb_reqlen = (off_t)n; 631 632 if (r->reqbody_length) { 633 /*chunkqueue_append_chunkqueue(&hctx->wb, &r->reqbody_queue);*/ 634 if (r->reqbody_length > 0) 635 hctx->wb_reqlen += r->reqbody_length; 636 /* (eventual) (minimal) total request size, not necessarily 637 * including all ajp13 framing around content length yet */ 638 else /* as-yet-unknown total rqst sz (Transfer-Encoding: chunked)*/ 639 hctx->wb_reqlen = -hctx->wb_reqlen; 640 } 641 /* send single data packet, then wait for Get Body Chunk from backend */ 642 ajp13_stdin_append_n(hctx, AJP13_MAX_PACKET_SIZE-4); 643 hctx->request_id = 0; /* overloaded value; see ajp13_stdin_append_n() */ 644 645 plugin_stats_inc("ajp13.requests"); 646 return HANDLER_GO_ON; 647 } while (0); 648 649 #if 0 650 array_free(cgienv); 651 #endif 652 653 r->http_status = 400; 654 r->handler_module = NULL; 655 buffer_clear(b); 656 chunkqueue_remove_finished_chunks(&hctx->wb); 657 return HANDLER_FINISHED; 658 } 659 660 661 static void 662 ajp13_expand_headers (buffer * const b, handler_ctx * const hctx, uint32_t plen) 663 { 664 /* hctx->rb must contain at least plen content 665 * and all chunks expected to be MEM_CHUNK */ 666 chunkqueue_compact_mem(hctx->rb, plen); 667 668 /* expect all headers in single AJP13 packet; 669 * not handling multiple AJP13_SEND_HEADERS packets 670 * (expecting single MEM_CHUNK <= 8k with AJP13 headers) */ 671 672 chunk * const c = hctx->rb->first; 673 uint8_t *ptr = 674 (uint8_t *)c->mem->ptr + c->offset + 5; /* +5 for (4 hdr + 1 type) */ 675 plen -= 5; 676 677 /* expand headers into buffer to be parsed by common code for responses 678 * (parsing might be slightly faster if AJP13-specific, but then would have 679 * to duplicate all http_response_parse_headers() policy)*/ 680 681 do { 682 uint32_t len; 683 if (plen < 2) break; 684 plen -= 2; 685 buffer_append_string_len(b, CONST_STR_LEN("HTTP/1.1 ")); 686 buffer_append_int(b, ajp13_dec_uint16(ptr)); 687 ptr += 2; 688 689 if (plen < 2) break; 690 plen -= 2; 691 len = ajp13_dec_uint16(ptr); 692 ptr += 2; 693 if (plen < len+1) break; 694 plen -= len+1; /* include -1 for ending '\0' */ 695 buffer_append_char(b, ' '); 696 if (len) buffer_append_string_len(b, (char *)ptr, len); 697 ptr += len+1; 698 699 if (plen < 2) break; 700 plen -= 2; 701 ptr += 2; 702 for (uint32_t nhdrs = ajp13_dec_uint16(ptr); nhdrs; --nhdrs) { 703 if (plen < 2) break; 704 plen -= 2; 705 len = ajp13_dec_uint16(ptr); 706 ptr += 2; 707 if (len >= 0xA000) { 708 if (len == 0xA000 || len > 0xA00B) break; 709 static const struct { 710 const char *h; 711 uint32_t len; 712 } hcode[] = { 713 { CONST_STR_LEN("\nContent-Type: ") } 714 ,{ CONST_STR_LEN("\nContent-Language: ") } 715 ,{ CONST_STR_LEN("\nContent-Length: ") } 716 ,{ CONST_STR_LEN("\nDate: ") } 717 ,{ CONST_STR_LEN("\nLast-Modified: ") } 718 ,{ CONST_STR_LEN("\nLocation: ") } 719 ,{ CONST_STR_LEN("\nSet-Cookie: ") } 720 ,{ CONST_STR_LEN("\nSet-Cookie2: ") } 721 ,{ CONST_STR_LEN("\nServlet-Engine: ") } 722 ,{ CONST_STR_LEN("\nStatus: ") } 723 ,{ CONST_STR_LEN("\nWWW-Authenticate: ") } 724 }; 725 const uint32_t idx = (len & 0xF) - 1; 726 buffer_append_string_len(b, hcode[idx].h, hcode[idx].len); 727 } 728 else { 729 if (plen < len+1) break; 730 plen -= len+1; 731 buffer_append_str3(b, CONST_STR_LEN("\n"), 732 (char *)ptr, len, 733 CONST_STR_LEN(": ")); 734 ptr += len+1; 735 } 736 737 if (plen < 2) break; 738 plen -= 2; 739 len = ajp13_dec_uint16(ptr); 740 ptr += 2; 741 if (plen < len+1) break; 742 plen -= len+1; 743 buffer_append_string_len(b, (char *)ptr, len); 744 ptr += len+1; 745 } 746 } while (0); 747 748 buffer_append_string_len(b, CONST_STR_LEN("\n\n")); 749 } 750 751 752 enum { 753 AJP13_FORWARD_REQUEST = 2 754 ,AJP13_SEND_BODY_CHUNK = 3 755 ,AJP13_SEND_HEADERS = 4 756 ,AJP13_END_RESPONSE = 5 757 ,AJP13_GET_BODY_CHUNK = 6 758 ,AJP13_SHUTDOWN = 7 759 ,AJP13_PING = 8 760 ,AJP13_CPONG_REPLY = 9 761 ,AJP13_CPING = 10 762 }; 763 764 765 __attribute_cold__ 766 static handler_t 767 ajp13_recv_0(const request_st * const r, const handler_ctx * const hctx) 768 { 769 if (-1 == hctx->request_id) /*(flag request ended)*/ 770 return HANDLER_FINISHED; 771 if (!(fdevent_fdnode_interest(hctx->fdn) & FDEVENT_IN) 772 && !(r->conf.stream_response_body 773 & FDEVENT_STREAM_RESPONSE_POLLRDHUP)) 774 return HANDLER_GO_ON; 775 log_error(r->conf.errh, __FILE__, __LINE__, 776 "unexpected end-of-file (perhaps the ajp13 process died):" 777 "pid: %d socket: %s", 778 hctx->proc->pid, hctx->proc->connection_name->ptr); 779 780 return HANDLER_ERROR; 781 } 782 783 784 static handler_t 785 ajp13_recv_parse_loop (request_st * const r, handler_ctx * const hctx) 786 { 787 log_error_st * const errh = r->conf.errh; 788 int fin = 0; 789 do { 790 uint8_t header[7]; 791 const off_t rblen = chunkqueue_length(hctx->rb); 792 if (rblen < 5) 793 break; /* incomplete packet header + min response payload */ 794 char *ptr = (char *)&header; 795 uint32_t pklen = 5; 796 if (chunkqueue_peek_data(hctx->rb, &ptr, &pklen, errh) < 0) 797 break; 798 if (pklen != 5) 799 break; 800 if (ptr[0] != 'A' || ptr[1] != 'B') { 801 log_error(errh, __FILE__, __LINE__, 802 "invalid packet prefix sent from container:" 803 "pid: %d socket: %s", 804 hctx->proc->pid, hctx->proc->connection_name->ptr); 805 return HANDLER_ERROR; 806 } 807 uint32_t plen = ajp13_dec_uint16((uint8_t *)ptr+2); 808 if (plen > (unsigned int)rblen - 4) 809 break; /* incomplete packet */ 810 811 switch(ptr[4]) { 812 case AJP13_SEND_HEADERS: 813 if (0 == r->resp_body_started) { 814 if (plen < 3) { 815 log_error(errh, __FILE__, __LINE__, 816 "AJP13: headers packet received with invalid length"); 817 return HANDLER_FINISHED; 818 } 819 820 buffer *hdrs = hctx->response; 821 if (NULL == hdrs) { 822 hdrs = r->tmp_buf; 823 buffer_clear(hdrs); 824 } 825 826 ajp13_expand_headers(hdrs, hctx, 4 + plen); 827 828 if (HANDLER_GO_ON != 829 http_response_parse_headers(r, &hctx->opts, hdrs)) { 830 hctx->send_content_body = 0; 831 return HANDLER_FINISHED; 832 } 833 if (0 == r->resp_body_started) { 834 if (!hctx->response) { 835 hctx->response = chunk_buffer_acquire(); 836 buffer_copy_buffer(hctx->response, hdrs); 837 } 838 } 839 else if (hctx->gw_mode == GW_AUTHORIZER && 840 (r->http_status == 0 || r->http_status == 200)) { 841 /* authorizer approved request; ignore the content here */ 842 hctx->send_content_body = 0; 843 hctx->opts.authorizer |= /*(save response streaming flags)*/ 844 (r->conf.stream_response_body 845 & (FDEVENT_STREAM_RESPONSE 846 |FDEVENT_STREAM_RESPONSE_BUFMIN)) << 1; 847 r->conf.stream_response_body &= 848 ~(FDEVENT_STREAM_RESPONSE|FDEVENT_STREAM_RESPONSE_BUFMIN); 849 } 850 #if 0 851 else if ((r->conf.stream_response_body & 852 (FDEVENT_STREAM_RESPONSE|FDEVENT_STREAM_RESPONSE_BUFMIN)) 853 && ( r->http_status == 204 854 || r->http_status == 205 855 || r->http_status == 304 856 || r->http_method == HTTP_METHOD_HEAD)) { 857 /* disable streaming to wait for backend protocol to signal 858 * end of response (prevent http_response_write_prepare() 859 * from short-circuiting and finishing responses without 860 * response body) */ 861 r->conf.stream_response_body &= 862 ~(FDEVENT_STREAM_RESPONSE|FDEVENT_STREAM_RESPONSE_BUFMIN); 863 } 864 #endif 865 } 866 else { 867 log_error(errh, __FILE__, __LINE__, 868 "AJP13: headers received after body started"); 869 /* ignore; discard packet */ 870 } 871 break; 872 case AJP13_SEND_BODY_CHUNK: 873 if (0 == r->resp_body_started) { /* header not finished */ 874 log_error(errh, __FILE__, __LINE__, 875 "AJP13: body received before headers"); 876 return HANDLER_FINISHED; 877 } 878 else if (hctx->send_content_body) { 879 ptr = (char *)&header; 880 pklen = 7; 881 if (chunkqueue_peek_data(hctx->rb, &ptr, &pklen, errh) < 0) 882 return HANDLER_GO_ON; 883 if (pklen != 7) 884 return HANDLER_GO_ON; 885 uint32_t len = ajp13_dec_uint16((uint8_t *)ptr+5); 886 if (0 == len) break; /*(skip "flush" packet of 0-length data)*/ 887 if (len > plen - 3) { 888 log_error(errh, __FILE__, __LINE__, 889 "AJP13: body packet received with invalid length"); 890 return HANDLER_FINISHED; 891 } 892 chunkqueue_mark_written(hctx->rb, 7); 893 if (0 == http_response_transfer_cqlen(r, hctx->rb, len)) { 894 if (len != plen - 3) 895 chunkqueue_mark_written(hctx->rb, plen - 3 - len); 896 continue; 897 } 898 else { 899 /* error writing to tempfile; 900 * truncate response or send 500 if nothing sent yet */ 901 hctx->send_content_body = 0; 902 return HANDLER_FINISHED; 903 } 904 } 905 else { 906 /* ignore; discard packet */ 907 } 908 break; 909 case AJP13_GET_BODY_CHUNK: 910 /*assert(3 == plen);*/ 911 ptr = (char *)&header; 912 pklen = 7; 913 if (chunkqueue_peek_data(hctx->rb, &ptr, &pklen, errh) < 0) 914 return HANDLER_GO_ON; 915 if (pklen != 7) 916 return HANDLER_GO_ON; 917 ajp13_stdin_append_n(hctx, ajp13_dec_uint16((uint8_t *)ptr+5)); 918 break; 919 case AJP13_END_RESPONSE: 920 /*assert(2 == plen);*/ 921 #if 0 922 ptr = (char *)&header; 923 pklen = 6; 924 if (chunkqueue_peek_data(hctx->rb, &ptr, &pklen, errh) < 0) 925 return HANDLER_GO_ON; 926 if (pklen != 6) 927 return HANDLER_GO_ON; 928 if (ptr[5]) { 929 /* future: add connection to pool if 'reuse' flag is set */ 930 } 931 #endif 932 hctx->request_id = -1; /*(flag request ended)*/ 933 fin = 1; 934 break; 935 case AJP13_CPONG_REPLY: 936 /*assert(1 == plen);*/ 937 break; 938 default: 939 log_error(errh, __FILE__, __LINE__, 940 "AJP13: packet type not handled: %d", ptr[4]); 941 /* discard packet */ 942 break; 943 } 944 945 chunkqueue_mark_written(hctx->rb, 4 + plen); 946 } while (0 == fin); 947 948 return 0 == fin ? HANDLER_GO_ON : HANDLER_FINISHED; 949 } 950 951 952 static handler_t 953 ajp13_recv_parse (request_st * const r, struct http_response_opts_t * const opts, buffer * const b, size_t n) 954 { 955 handler_ctx * const hctx = (handler_ctx *)opts->pdata; 956 if (0 == n) return ajp13_recv_0(r, hctx); 957 /* future: might try to elide copying if buffer contains full packet(s) 958 * and prior read did not end in a partial packet */ 959 chunkqueue_append_buffer(hctx->rb, b); 960 return ajp13_recv_parse_loop(r, hctx); 961 } 962 963 964 static handler_t 965 ajp13_check_extension (request_st * const r, void *p_d) 966 { 967 if (NULL != r->handler_module) return HANDLER_GO_ON; 968 969 plugin_data * const p = p_d; 970 mod_ajp13_patch_config(r, p); 971 if (NULL == p->conf.exts) return HANDLER_GO_ON; 972 973 handler_t rc = gw_check_extension(r, p, 1, 0); 974 if (HANDLER_GO_ON != rc) return rc; 975 976 if (r->handler_module == p->self) { 977 handler_ctx *hctx = r->plugin_ctx[p->id]; 978 hctx->opts.backend = BACKEND_AJP13; 979 hctx->opts.parse = ajp13_recv_parse; 980 hctx->opts.pdata = hctx; 981 hctx->stdin_append = ajp13_stdin_append; 982 hctx->create_env = ajp13_create_env; 983 if (!hctx->rb) 984 hctx->rb = chunkqueue_init(NULL); 985 else 986 chunkqueue_reset(hctx->rb); 987 } 988 989 return HANDLER_GO_ON; 990 } 991 992 993 __attribute_cold__ 994 int mod_ajp13_plugin_init (plugin *p); 995 int mod_ajp13_plugin_init (plugin *p) 996 { 997 p->version = LIGHTTPD_VERSION_ID; 998 p->name = "ajp13"; 999 1000 p->init = gw_init; 1001 p->cleanup = gw_free; 1002 p->set_defaults = mod_ajp13_set_defaults; 1003 p->handle_request_reset = gw_handle_request_reset; 1004 p->handle_uri_clean = ajp13_check_extension; 1005 p->handle_subrequest = gw_handle_subrequest; 1006 p->handle_trigger = gw_handle_trigger; 1007 p->handle_waitpid = gw_handle_waitpid_cb; 1008 1009 return 0; 1010 } 1011