2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 /***************************************************************************
19 * Description: Next generation bi-directional protocol handler. *
20 * Author: Henri Gomez <hgomez@apache.org> *
21 * Version: $Revision: 466585 $ *
22 ***************************************************************************/
25 #include "jk_global.h"
28 #include "jk_ajp_common.h"
33 * Compute the MD5 with ENTROPY / SECRET KEY
36 void ajp14_compute_md5(jk_login_service_t *s, jk_logger_t *l)
39 jk_md5((const unsigned char *)s->entropy,
40 (const unsigned char *)s->secret_key, s->computed_key);
42 if (JK_IS_DEBUG_LEVEL(l))
43 jk_log(l, JK_LOG_DEBUG, "(%s/%s) -> (%s)",
44 s->entropy, s->secret_key, s->computed_key);
50 * Build the Login Init Command
52 * +-------------------------+---------------------------+---------------------------+
53 * | LOGIN INIT CMD (1 byte) | NEGOCIATION DATA (32bits) | WEB SERVER INFO (CString) |
54 * +-------------------------+---------------------------+---------------------------+
58 int ajp14_marshal_login_init_into_msgb(jk_msg_buf_t *msg,
59 jk_login_service_t *s, jk_logger_t *l)
62 /* To be on the safe side */
68 if (jk_b_append_byte(msg, AJP14_LOGINIT_CMD)) {
75 if (jk_b_append_long(msg, s->negociation)) {
82 if (jk_b_append_string(msg, s->web_server_name)) {
83 jk_log(l, JK_LOG_ERROR,
84 "failed appending the web_server_name string");
95 * Decode the Login Seed Command
97 * +-------------------------+---------------------------+
98 * | LOGIN SEED CMD (1 byte) | MD5 of entropy (32 chars) |
99 * +-------------------------+---------------------------+
103 int ajp14_unmarshal_login_seed(jk_msg_buf_t *msg,
104 jk_login_service_t *s, jk_logger_t *l)
109 (msg, (unsigned char *)s->entropy, AJP14_ENTROPY_SEED_LEN) < 0) {
110 jk_log(l, JK_LOG_ERROR,
116 s->entropy[AJP14_ENTROPY_SEED_LEN] = 0; /* Just to have a CString */
122 * Build the Login Computed Command
124 * +-------------------------+---------------------------------------+
125 * | LOGIN COMP CMD (1 byte) | MD5 of RANDOM + SECRET KEY (32 chars) |
126 * +-------------------------+---------------------------------------+
130 int ajp14_marshal_login_comp_into_msgb(jk_msg_buf_t *msg,
131 jk_login_service_t *s, jk_logger_t *l)
135 /* To be on the safe side */
141 if (jk_b_append_byte(msg, AJP14_LOGCOMP_CMD)) {
148 if (jk_b_append_bytes
149 (msg, (const unsigned char *)s->computed_key,
150 AJP14_COMPUTED_KEY_LEN)) {
151 jk_log(l, JK_LOG_ERROR,
152 "failed appending the COMPUTED MD5 bytes");
163 * Decode the LogOk Command
165 * +--------------------+------------------------+-------------------------------+
166 * | LOGOK CMD (1 byte) | NEGOCIED DATA (32bits) | SERVLET ENGINE INFO (CString) |
167 * +--------------------+------------------------+-------------------------------+
171 int ajp14_unmarshal_log_ok(jk_msg_buf_t *msg,
172 jk_login_service_t *s, jk_logger_t *l)
179 nego = jk_b_get_long(msg);
181 if (nego == 0xFFFFFFFF) {
182 jk_log(l, JK_LOG_ERROR,
183 "can't get negociated data");
188 sname = (char *)jk_b_get_string(msg);
191 jk_log(l, JK_LOG_ERROR,
192 "can't get servlet engine name");
197 if (s->servlet_engine_name) /* take care of removing previously allocated data */
198 free(s->servlet_engine_name);
200 s->servlet_engine_name = strdup(sname);
202 if (!s->servlet_engine_name) {
203 jk_log(l, JK_LOG_ERROR,
204 "can't malloc servlet engine name");
215 * Decode the Log Nok Command
217 * +---------------------+-----------------------+
218 * | LOGNOK CMD (1 byte) | FAILURE CODE (32bits) |
219 * +---------------------+-----------------------+
223 int ajp14_unmarshal_log_nok(jk_msg_buf_t *msg, jk_logger_t *l)
225 unsigned long status;
229 status = jk_b_get_long(msg);
231 if (status == 0xFFFFFFFF) {
232 jk_log(l, JK_LOG_ERROR,
233 "can't get failure code");
238 jk_log(l, JK_LOG_INFO, "Can't Log with servlet engine - code %08lx",
246 * Build the Shutdown Cmd
248 * +-----------------------+---------------------------------------+
249 * | SHUTDOWN CMD (1 byte) | MD5 of RANDOM + SECRET KEY (32 chars) |
250 * +-----------------------+---------------------------------------+
254 int ajp14_marshal_shutdown_into_msgb(jk_msg_buf_t *msg,
255 jk_login_service_t *s, jk_logger_t *l)
260 /* To be on the safe side */
266 if (jk_b_append_byte(msg, AJP14_SHUTDOWN_CMD)) {
273 if (jk_b_append_bytes
274 (msg, (const unsigned char *)s->computed_key,
275 AJP14_COMPUTED_KEY_LEN)) {
276 jk_log(l, JK_LOG_ERROR,
277 "failed appending the COMPUTED MD5 bytes");
287 * Decode the Shutdown Nok Command
289 * +----------------------+-----------------------+
290 * | SHUTNOK CMD (1 byte) | FAILURE CODE (32bits) |
291 * +----------------------+-----------------------+
294 int ajp14_unmarshal_shutdown_nok(jk_msg_buf_t *msg, jk_logger_t *l)
296 unsigned long status;
299 status = jk_b_get_long(msg);
301 if (status == 0xFFFFFFFF) {
302 jk_log(l, JK_LOG_ERROR,
303 "can't get failure code");
308 jk_log(l, JK_LOG_INFO, "Can't shutdown servlet engine - code %08lx",
315 * Build the Unknown Packet
317 * +-----------------------------+---------------------------------+------------------------------+
318 * | UNKNOWN PACKET CMD (1 byte) | UNHANDLED MESSAGE SIZE (16bits) | UNHANDLED MESSAGE (bytes...) |
319 * +-----------------------------+---------------------------------+------------------------------+
323 int ajp14_marshal_unknown_packet_into_msgb(jk_msg_buf_t *msg,
324 jk_msg_buf_t *unk, jk_logger_t *l)
328 /* To be on the safe side */
334 if (jk_b_append_byte(msg, AJP14_UNKNOW_PACKET_CMD)) {
339 * UNHANDLED MESSAGE SIZE
341 if (jk_b_append_int(msg, (unsigned short)unk->len)) {
346 * UNHANDLED MESSAGE (Question : Did we have to send all the message or only part of)
347 * ( ie: only 1k max )
349 if (jk_b_append_bytes(msg, unk->buf, unk->len)) {
350 jk_log(l, JK_LOG_ERROR,
351 "failed appending the UNHANDLED MESSAGE");
361 * Build the Context Query Cmd (autoconf)
363 * +--------------------------+---------------------------------+
364 * | CONTEXT QRY CMD (1 byte) | VIRTUAL HOST NAME (CString (*)) |
365 * +--------------------------+---------------------------------+
369 int ajp14_marshal_context_query_into_msgb(jk_msg_buf_t *msg,
370 char *virtual, jk_logger_t *l)
374 /* To be on the safe side */
380 if (jk_b_append_byte(msg, AJP14_CONTEXT_QRY_CMD)) {
385 * VIRTUAL HOST CSTRING
387 if (jk_b_append_string(msg, virtual)) {
388 jk_log(l, JK_LOG_ERROR,
389 "failed appending the virtual host string");
400 * Decode the Context Info Cmd (Autoconf)
402 * The Autoconf feature of AJP14, let us know which URL/URI could
403 * be handled by the servlet-engine
405 * +---------------------------+---------------------------------+----------------------------+-------------------------------+-----------+
406 * | CONTEXT INFO CMD (1 byte) | VIRTUAL HOST NAME (CString (*)) | CONTEXT NAME (CString (*)) | URL1 [\n] URL2 [\n] URL3 [\n] | NEXT CTX. |
407 * +---------------------------+---------------------------------+----------------------------+-------------------------------+-----------+
410 int ajp14_unmarshal_context_info(jk_msg_buf_t *msg,
411 jk_context_t *c, jk_logger_t *l)
417 vname = (char *)jk_b_get_string(msg);
420 jk_log(l, JK_LOG_DEBUG,
421 "get virtual %s for virtual %s",
425 jk_log(l, JK_LOG_ERROR,
426 "can't get virtual hostname");
431 /* Check if we get the correct virtual host */
432 if (c->virt != NULL && vname != NULL && strcmp(c->virt, vname)) {
433 /* set the virtual name, better to add to a virtual list ? */
435 if (context_set_virtual(c, vname) == JK_FALSE) {
436 jk_log(l, JK_LOG_ERROR,
437 "can't malloc virtual hostname");
445 cname = (char *)jk_b_get_string(msg);
448 jk_log(l, JK_LOG_ERROR,
449 "can't get context");
454 jk_log(l, JK_LOG_DEBUG,
455 "get context %s for virtual %s",
458 /* grab all contexts up to empty one which indicate end of contexts */
462 /* create new context base (if needed) */
464 if (context_add_base(c, cname) == JK_FALSE) {
465 jk_log(l, JK_LOG_ERROR,
466 "can't add/set context %s",
474 uri = (char *)jk_b_get_string(msg);
477 jk_log(l, JK_LOG_ERROR,
484 jk_log(l, JK_LOG_DEBUG, "No more URI for context %s", cname);
488 jk_log(l, JK_LOG_INFO,
489 "Got URI (%s) for virtualhost %s and context %s", uri,
492 if (context_add_uri(c, cname, uri) == JK_FALSE) {
493 jk_log(l, JK_LOG_ERROR,
494 "can't add/set uri (%s) for context %s",
508 * Build the Context State Query Cmd
510 * We send the list of contexts where we want to know state, empty string end context list*
511 * If cname is set, only ask about THIS context
513 * +----------------------------+----------------------------------+----------------------------+----+
514 * | CONTEXT STATE CMD (1 byte) | VIRTUAL HOST NAME (CString (*)) | CONTEXT NAME (CString (*)) | .. |
515 * +----------------------------+----------------------------------+----------------------------+----+
519 int ajp14_marshal_context_state_into_msgb(jk_msg_buf_t *msg,
521 char *cname, jk_logger_t *l)
523 jk_context_item_t *ci;
528 /* To be on the safe side */
534 if (jk_b_append_byte(msg, AJP14_CONTEXT_STATE_CMD)) {
539 * VIRTUAL HOST CSTRING
541 if (jk_b_append_string(msg, c->virt)) {
542 jk_log(l, JK_LOG_ERROR,
543 "failed appending the virtual host string");
550 ci = context_find_base(c, cname);
553 jk_log(l, JK_LOG_ERROR,
554 "unknown context %s",
564 if (jk_b_append_string(msg, cname)) {
565 jk_log(l, JK_LOG_ERROR,
566 "failed appending the context string %s",
572 else { /* Grab all contexts name */
574 for (i = 0; i < c->size; i++) {
579 if (jk_b_append_string(msg, c->contexts[i]->cbase)) {
580 jk_log(l, JK_LOG_ERROR,
581 "failed appending the context string %s",
582 c->contexts[i]->cbase);
589 /* End of context list, an empty string */
591 if (jk_b_append_string(msg, "")) {
592 jk_log(l, JK_LOG_ERROR,
593 "failed appending end of contexts");
604 * Decode the Context State Reply Cmd
606 * We get update of contexts list, empty string end context list*
608 * +----------------------------------+---------------------------------+----------------------------+------------------+----+
609 * | CONTEXT STATE REPLY CMD (1 byte) | VIRTUAL HOST NAME (CString (*)) | CONTEXT NAME (CString (*)) | UP/DOWN (1 byte) | .. |
610 * +----------------------------------+---------------------------------+----------------------------+------------------+----+
614 int ajp14_unmarshal_context_state_reply(jk_msg_buf_t *msg,
615 jk_context_t *c, jk_logger_t *l)
619 jk_context_item_t *ci;
622 /* get virtual name */
623 vname = (char *)jk_b_get_string(msg);
626 jk_log(l, JK_LOG_ERROR,
627 "can't get virtual hostname");
632 /* Check if we speak about the correct virtual */
633 if (strcmp(c->virt, vname)) {
634 jk_log(l, JK_LOG_ERROR,
635 "incorrect virtual %s instead of %s",
643 /* get context name */
644 cname = (char *)jk_b_get_string(msg);
647 jk_log(l, JK_LOG_ERROR,
648 "can't get context");
656 ci = context_find_base(c, cname);
659 jk_log(l, JK_LOG_ERROR,
660 "unknow context %s for virtual %s",
666 ci->status = jk_b_get_int(msg);
668 if (JK_IS_DEBUG_LEVEL(l))
669 jk_log(l, JK_LOG_DEBUG,
670 "updated context %s to state %d",
679 * Decode the Context Update Cmd
681 * +-----------------------------+---------------------------------+----------------------------+------------------+
682 * | CONTEXT UPDATE CMD (1 byte) | VIRTUAL HOST NAME (CString (*)) | CONTEXT NAME (CString (*)) | UP/DOWN (1 byte) |
683 * +-----------------------------+---------------------------------+----------------------------+------------------+
687 int ajp14_unmarshal_context_update_cmd(jk_msg_buf_t *msg,
688 jk_context_t *c, jk_logger_t *l)
692 rc = ajp14_unmarshal_context_state_reply(msg, c, l);