hgomez 01/05/21 08:20:34
Modified: jk/src/native/apache-2.0 mod_jk.c
Log:
mod_jk should be passing the raw, possibly encoded URI to Tomcat;
see <http://java.sun.com/products/servlet/errata_042700.html>
for this requirement. Standalone Tomcat is compliant, only
mod_jk needed to be changed. (Provided by Keith Wannamaker)
also updated configuration, put EnvVars and SSL stuff that's in
Apache 1.3 mod_jk but not in 2.0.
WARNING: mod_jk didn't works with latest Apache 2.0.18, currently investigated.
Revision Changes Path
1.3 +400 -41 jakarta-tomcat-connectors/jk/src/native/apache-2.0/mod_jk.c
Index: mod_jk.c
===================================================================
RCS file: /home/cvs/jakarta-tomcat-connectors/jk/src/native/apache-2.0/mod_jk.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- mod_jk.c 2001/05/18 14:49:24 1.2
+++ mod_jk.c 2001/05/21 15:20:28 1.3
@@ -103,9 +103,29 @@
char *worker_file;
int mountcopy;
jk_map_t *uri_to_context;
+
+ char * secret_key;
+ jk_map_t *automount;
+
jk_uri_worker_map_t *uw_map;
int was_initialized;
+
+ /*
+ * SSL Support
+ */
+ int ssl_enable;
+ char *https_indicator;
+ char *certs_indicator;
+ char *cipher_indicator;
+ char *session_indicator;
+
+ /*
+ * Environment variables support
+ */
+ int envvars_in_use;
+ apr_table_t * envvars;
+
server_rec *s;
} jk_server_conf_t;
@@ -191,6 +211,15 @@
return JK_FALSE;
}
+/*
+ * Read a chunk of the request body into a buffer. Attempt to read len
+ * bytes into the buffer. Write the number of bytes actually read into
+ * actually_read.
+ *
+ * Think of this function as a method of the apache1.3-specific subclass of
+ * the jk_ws_service class. Think of the *s param as a "this" or "self"
+ * pointer.
+ */
static int JK_METHOD ws_read(jk_ws_service_t *s,
void *b,
unsigned l,
@@ -214,6 +243,17 @@
return JK_FALSE;
}
+/*
+ * Write a chunk of response data back to the browser. If the headers
+ * haven't yet been sent over, send over default header values (Status =
+ * 200, basically).
+ *
+ * Write len bytes from buffer b.
+ *
+ * Think of this function as a method of the apache1.3-specific subclass of
+ * the jk_ws_service class. Think of the *s param as a "this" or "self"
+ * pointer.
+ */
/* Works with 4096, fails with 8192 */
#define CHUNK_SIZE 4096
@@ -275,12 +315,13 @@
/* ========================================================================= */
/* ========================================================================= */
-/* Log something to JServ log file then exit */
+/* Log something to Jk log file then exit */
static void jk_error_exit(const char *file,
- int line,
- int level,
- server_rec *s,
- const char *fmt, ...)
+ int line,
+ int level,
+ const server_rec *s,
+ apr_pool_t *p,
+ const char *fmt, ...)
{
va_list ap;
char *res;
@@ -314,10 +355,14 @@
}
static int init_ws_service(apache_private_data_t *private_data,
- jk_ws_service_t *s)
+ jk_ws_service_t *s,
+ jk_server_conf_t *conf)
{
request_rec *r = private_data->r;
- s->jvm_route = NULL;
+ char *ssl_temp = NULL;
+ s->jvm_route = NULL; /* Used for sticky session routing */
+
+ /* Copy in function pointers (which are really methods) */
s->start_response = ws_start_response;
s->read = ws_read;
s->write = ws_write;
@@ -375,14 +420,63 @@
s->method = (char *)r->method;
s->content_length = get_content_length(r);
s->query_string = r->args;
- s->req_uri = r->uri;
-
+
+ /*
+ * The 2.2 servlet spec errata says the uri from
+ * HttpServletRequest.getRequestURI() should remain encoded.
+ * [http://java.sun.com/products/servlet/errata_042700.html]
+ */
+ s->req_uri = r->unparsed_uri;
+ if (s->req_uri != NULL) {
+ char *query_str = strchr(s->req_uri, '?');
+ if (query_str != NULL) {
+ *query_str = 0;
+ }
+ }
+
s->is_ssl = JK_FALSE;
s->ssl_cert = NULL;
s->ssl_cert_len = 0;
s->ssl_cipher = NULL;
s->ssl_session = NULL;
+ if(conf->ssl_enable || conf->envvars_in_use) {
+ ap_add_common_vars(r);
+
+ if(conf->ssl_enable) {
+ ssl_temp = (char *)apr_table_get(r->subprocess_env,
conf->https_indicator);
+ if(ssl_temp && !strcasecmp(ssl_temp, "on")) {
+ s->is_ssl = JK_TRUE;
+ s->ssl_cert = (char *)apr_table_get(r->subprocess_env,
conf->certs_indicator);
+ if(s->ssl_cert) {
+ s->ssl_cert_len = strlen(s->ssl_cert);
+ }
+ s->ssl_cipher = (char *)apr_table_get(r->subprocess_env,
conf->cipher_indicator);
+ s->ssl_session = (char *)apr_table_get(r->subprocess_env,
conf->session_indicator);
+ }
+ }
+
+ if(conf->envvars_in_use) {
+ apr_array_header_t *t = apr_table_elts(conf->envvars);
+ if(t && t->nelts) {
+ int i;
+ apr_table_entry_t *elts = (apr_table_entry_t *)t->elts;
+ s->attributes_names = apr_palloc(r->pool, sizeof(char *) *
t->nelts);
+ s->attributes_values = apr_palloc(r->pool, sizeof(char *) *
t->nelts);
+
+ for(i = 0 ; i < t->nelts ; i++) {
+ s->attributes_names[i] = elts[i].key;
+ s->attributes_values[i] = (char
*)apr_table_get(r->subprocess_env, elts[i].key);
+ if(!s->attributes_values[i]) {
+ s->attributes_values[i] = elts[i].val;
+ }
+ }
+
+ s->num_attributes = t->nelts;
+ }
+ }
+ }
+
s->headers_names = NULL;
s->headers_values = NULL;
s->num_headers = 0;
@@ -409,9 +503,22 @@
return JK_TRUE;
}
-/* ========================================================================= */
-/* The JK module command processors */
-/* ========================================================================= */
+/*
+ * The JK module command processors
+ *
+ * The below are all installed so that Apache calls them while it is
+ * processing its config files. This allows configuration info to be
+ * copied into a jk_server_conf_t object, which is then used for request
+ * filtering/processing.
+ *
+ * See jk_cmds definition below for explanations of these options.
+ */
+
+/*
+ * JkMountCopy directive handling
+ *
+ * JkMountCopy Yes/No
+ */
static const char *jk_set_mountcopy(cmd_parms *cmd,
void *dummy,
@@ -427,6 +534,12 @@
return NULL;
}
+/*
+ * JkMount directive handling
+ *
+ * JkMount URI(context) worker
+ */
+
static const char *jk_mount_context(cmd_parms *cmd,
void *dummy,
char *context,
@@ -445,6 +558,47 @@
return NULL;
}
+/*
+ * JkSecretKey directive handling
+ *
+ * JkSecretKey defaultsecretkey
+ */
+
+static const char *jk_secret_key(cmd_parms *cmd,
+ void *dummy,
+ char *secret_key)
+{
+ server_rec *s = cmd->server;
+ jk_server_conf_t *conf =
+ (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
+
+ conf->secret_key = secret_key;
+ return NULL;
+}
+
+/*
+ * JkAutoMount directive handling
+ *
+ * JkAutoMount worker secretkey
+ */
+
+static const char *jk_automount_context(cmd_parms *cmd,
+ void *dummy,
+ char *worker,
+ char *secret_key)
+{
+ server_rec *s = cmd->server;
+ jk_server_conf_t *conf =
+ (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
+
+ /*
+ * Add the new automount to the auto map.
+ */
+ char * old;
+ map_put(conf->automount, worker, secret_key, (void **)&old);
+ return NULL;
+}
+
static const char *jk_set_worker_file(cmd_parms *cmd,
void *dummy,
char *worker_file)
@@ -490,27 +644,176 @@
}
static const char * jk_set_log_fmt(cmd_parms *cmd,
- void *dummy,
- char * log_format)
+ void *dummy,
+ char * log_format)
{
- jk_set_log_format(log_format);
- return NULL;
+ jk_set_log_format(log_format);
+ return NULL;
}
+
+static const char *jk_set_enable_ssl(cmd_parms *cmd,
+ void *dummy,
+ int flag)
+{
+ server_rec *s = cmd->server;
+ jk_server_conf_t *conf =
+ (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
+
+ /* Set up our value */
+ conf->ssl_enable = flag ? JK_TRUE : JK_FALSE;
+
+ return NULL;
+}
+
+static const char *jk_set_https_indicator(cmd_parms *cmd,
+ void *dummy,
+ char *indicator)
+{
+ server_rec *s = cmd->server;
+ jk_server_conf_t *conf =
+ (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
+
+ conf->https_indicator = indicator;
+
+ return NULL;
+}
+
+static const char *jk_set_certs_indicator(cmd_parms *cmd,
+ void *dummy,
+ char *indicator)
+{
+ server_rec *s = cmd->server;
+ jk_server_conf_t *conf =
+ (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
+
+ conf->certs_indicator = indicator;
+
+ return NULL;
+}
+
+static const char *jk_set_cipher_indicator(cmd_parms *cmd,
+ void *dummy,
+ char *indicator)
+{
+ server_rec *s = cmd->server;
+ jk_server_conf_t *conf =
+ (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
+
+ conf->cipher_indicator = indicator;
+
+ return NULL;
+}
+
+static const char *jk_set_session_indicator(cmd_parms *cmd,
+ void *dummy,
+ char *indicator)
+{
+ server_rec *s = cmd->server;
+ jk_server_conf_t *conf =
+ (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
+
+ conf->session_indicator = indicator;
+
+ return NULL;
+}
+
+static const char *jk_add_env_var(cmd_parms *cmd,
+ void *dummy,
+ char *env_name,
+ char *default_value)
+{
+ server_rec *s = cmd->server;
+ jk_server_conf_t *conf =
+ (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
+
+ conf->envvars_in_use = JK_TRUE;
+
+ apr_table_add(conf->envvars, env_name, default_value);
+
+ return NULL;
+}
static const command_rec jk_cmds[] =
{
+ /*
+ * JkWorkersFile specifies a full path to the location of the worker
+ * properties file.
+ *
+ * This file defines the different workers used by apache to redirect
+ * servlet requests.
+ */
{"JkWorkersFile", jk_set_worker_file, NULL, RSRC_CONF, TAKE1,
"the name of a worker file for the Jakarta servlet containers"},
+
+ /*
+ * JkSecretKey specifies the default (common) secret key to works with
+ * workers in AJP14 protocol
+ */
+ {"JkSecretKey", jk_secret_key, NULL, RSRC_CONF, TAKE1,
+ "the default secret key to works with workers"},
+
+ /*
+ * JkAutoMount specifies that the list of handled URLs must be
+ * asked to the servlet engine (autoconf feature)
+ */
+ {"JkAutoMount", jk_automount_context, NULL, RSRC_CONF, TAKE12,
+ "automatic mount points to a Tomcat worker"},
+
+ /*
+ * JkMount mounts a url prefix to a worker (the worker need to be
+ * defined in the worker properties file.
+ */
{"JkMount", jk_mount_context, NULL, RSRC_CONF, TAKE23,
"A mount point from a context to a Tomcat worker"},
+
+ /*
+ * JkMountCopy specifies if mod_jk should copy the mount points
+ * from the main server to the virtual servers.
+ */
{"JkMountCopy", jk_set_mountcopy, NULL, RSRC_CONF, FLAG,
"Should the base server mounts be copied to the virtual server"},
+
+ /*
+ * JkLogFile & JkLogLevel specifies to where should the plugin log
+ * its information and how much.
+ * JkLogStampFormat specify the time-stamp to be used on log
+ */
{"JkLogFile", jk_set_log_file, NULL, RSRC_CONF, TAKE1,
"Full path to the Jakarta Tomcat module log file"},
{"JkLogLevel", jk_set_log_level, NULL, RSRC_CONF, TAKE1,
"The Jakarta Tomcat module log level, can be debug, info, error or emerg"},
{"JkLogStampFormat", jk_set_log_fmt, NULL, RSRC_CONF, TAKE1,
"The Jakarta Tomcat module log format, follow strftime synthax"},
+
+ /*
+ * Apache has multiple SSL modules (for example apache_ssl, stronghold
+ * IHS ...). Each of these can have a different SSL environment names
+ * The following properties let the administrator specify the envoiroment
+ * variables names.
+ *
+ * HTTPS - indication for SSL
+ * CERTS - Base64-Der-encoded client certificates.
+ * CIPHER - A string specifing the ciphers suite in use.
+ * SESSION - A string specifing the current SSL session.
+ */
+ {"JkHTTPSIndicator", jk_set_https_indicator, NULL, RSRC_CONF, TAKE1,
+ "Name of the Apache environment that contains SSL indication"},
+ {"JkCERTSIndicator", jk_set_certs_indicator, NULL, RSRC_CONF, TAKE1,
+ "Name of the Apache environment that contains SSL client certificates"},
+ {"JkCIPHERIndicator", jk_set_cipher_indicator, NULL, RSRC_CONF, TAKE1,
+ "Name of the Apache environment that contains SSL client cipher"},
+ {"JkSESSIONIndicator", jk_set_session_indicator, NULL, RSRC_CONF, TAKE1,
+ "Name of the Apache environment that contains SSL session"},
+ {"JkExtractSSL", jk_set_enable_ssl, NULL, RSRC_CONF, FLAG,
+ "Turns on SSL processing and information gathering by mod_jk"},
+
+ /*
+ * JkEnvVar let user defines envs var passed from WebServer to
+ * Servlet Engine
+ */
+ {"JkEnvVar", jk_add_env_var, NULL, RSRC_CONF, TAKE2,
+ "Adds a name of environment variable that should be sent to servlet-engine"},
+
{NULL}
};
@@ -570,7 +873,7 @@
s.ws_private = &private_data;
s.pool = &private_data.p;
- if(init_ws_service(&private_data, &s)) {
+ if(init_ws_service(&private_data, &s, conf)) {
jk_endpoint_t *end = NULL;
/* Use per/thread pool ( or "context" ) to reuse the
@@ -635,16 +938,69 @@
c->mountcopy = JK_FALSE;
c->was_initialized = JK_FALSE;
+ /*
+ * By default we will try to gather SSL info.
+ * Disable this functionality through JkExtractSSL
+ */
+ c->ssl_enable = JK_TRUE;
+ /*
+ * The defaults ssl indicators match those in mod_ssl (seems
+ * to be in more use).
+ */
+ c->https_indicator = "HTTPS";
+ c->certs_indicator = "SSL_CLIENT_CERT";
+
+ /*
+ * The following (comented out) environment variables match apache_ssl!
+ * If you are using apache_sslapache_ssl uncomment them (or use the
+ * configuration directives to set them.
+ *
+ c->cipher_indicator = "HTTPS_CIPHER";
+ c->session_indicator = NULL;
+ */
+
+ /*
+ * The following environment variables match mod_ssl! If you
+ * are using another module (say apache_ssl) comment them out.
+ */
+ c->cipher_indicator = "SSL_CIPHER";
+ c->session_indicator = "SSL_SESSION_ID";
+
if(!map_alloc(&(c->uri_to_context))) {
- jk_error_exit(APLOG_MARK, APLOG_EMERG, s, "Memory error");
+ jk_error_exit(APLOG_MARK, APLOG_EMERG, s, p, "Memory error");
}
+ if(!map_alloc(&(c->automount))) {
+ jk_error_exit(APLOG_MARK, APLOG_EMERG, s, p, "Memory error");
+ }
+
c->uw_map = NULL;
+ c->secret_key = NULL;
+
+ c->envvars_in_use = JK_FALSE;
+ c->envvars = apr_table_make(p, 0);
+
c->s = s;
return c;
}
+static void copy_jk_map(apr_pool_t *p, server_rec * s, jk_map_t * src, jk_map_t *
dst)
+{
+ int sz = map_size(src);
+ int i;
+ for(i = 0 ; i < sz ; i++) {
+ void *old;
+ char *name = map_name_at(src, i);
+ if(map_get(src, name, NULL) == NULL) {
+ if(!map_put(dst, name, apr_pstrdup(p, map_get_string(src, name,
NULL)), &old)) {
+ jk_error_exit(APLOG_MARK, APLOG_EMERG, s, p, "Memory error");
+ }
+ }
+ }
+}
+
+
static void *merge_jk_config(apr_pool_t *p,
void *basev,
void *overridesv)
@@ -652,22 +1008,24 @@
jk_server_conf_t *base = (jk_server_conf_t *) basev;
jk_server_conf_t *overrides = (jk_server_conf_t *)overridesv;
+ if(base->ssl_enable) {
+ overrides->ssl_enable = base->ssl_enable;
+ overrides->https_indicator = base->https_indicator;
+ overrides->certs_indicator = base->certs_indicator;
+ overrides->cipher_indicator = base->cipher_indicator;
+ overrides->session_indicator = base->session_indicator;
+ }
+
if(overrides->mountcopy) {
- int sz = map_size(base->uri_to_context);
- int i;
- for(i = 0 ; i < sz ; i++) {
- void *old;
- char *name = map_name_at(base->uri_to_context, i);
- if(NULL == map_get(overrides->uri_to_context, name, NULL)) {
- if(!map_put(overrides->uri_to_context,
- name,
- apr_pstrdup(p, map_get_string(base->uri_to_context,
name, NULL)),
- &old)) {
- jk_error_exit(APLOG_MARK, APLOG_EMERG, overrides->s, "Memory
error");
- }
- }
- }
+ copy_jk_map(p, overrides->s, base->uri_to_context,
overrides->uri_to_context);
+ copy_jk_map(p, overrides->s, base->automount, overrides->automount);
+ }
+
+ if(base->envvars_in_use) {
+ overrides->envvars_in_use = JK_TRUE;
+ overrides->envvars = apr_table_overlay(p, overrides->envvars,
base->envvars);
}
+
if(overrides->log_file && overrides->log_level >= 0) {
if(!jk_open_file_logger(&(overrides->log), overrides->log_file,
overrides->log_level)) {
overrides->log = NULL;
@@ -676,9 +1034,12 @@
if(!uri_worker_map_alloc(&(overrides->uw_map),
overrides->uri_to_context,
overrides->log)) {
- jk_error_exit(APLOG_MARK, APLOG_EMERG, overrides->s, "Memory error");
+ jk_error_exit(APLOG_MARK, APLOG_EMERG, overrides->s,
overrides->s->process->pool, "Memory error");
}
+ if (base->secret_key)
+ overrides->secret_key = base->secret_key;
+
return overrides;
}
@@ -698,7 +1059,7 @@
}
if(!uri_worker_map_alloc(&(conf->uw_map), conf->uri_to_context, conf->log)) {
- jk_error_exit(APLOG_MARK, APLOG_EMERG, s, "Memory error");
+ jk_error_exit(APLOG_MARK, APLOG_EMERG, s, pconf, "Memory error");
}
if(map_alloc(&init_map)) {
@@ -709,7 +1070,7 @@
}
}
- jk_error_exit(APLOG_MARK, APLOG_EMERG, s, "Error while opening the workers");
+ jk_error_exit(APLOG_MARK, APLOG_EMERG, s, pconf, "Error while opening the
workers");
}
static void jk_post_config(apr_pool_t *pconf,
@@ -732,19 +1093,19 @@
}
if(!uri_worker_map_alloc(&(conf->uw_map), conf->uri_to_context,
conf->log)) {
- jk_error_exit(APLOG_MARK, APLOG_EMERG, s, "Memory error");
+ jk_error_exit(APLOG_MARK, APLOG_EMERG, s, plog, "Memory error");
}
if(map_alloc(&init_map)) {
if(map_read_properties(init_map, conf->worker_file)) {
- ap_add_version_component(pconf, JK_EXPOSED_VERSION);
+ ap_add_version_component(pconf,
JK_EXPOSED_VERSION);
if(wc_open(init_map, conf->log)) {
return;
}
}
}
- jk_error_exit(APLOG_MARK, APLOG_EMERG, s, "Error while opening the
workers");
+ jk_error_exit(APLOG_MARK, APLOG_EMERG, s, plog, "Error while opening
the workers");
}
}
}
@@ -756,9 +1117,7 @@
(jk_server_conf_t *)ap_get_module_config(r->server->module_config,
&jk_module);
if(conf) {
- char *worker = map_uri_to_worker(conf->uw_map,
- r->uri,
- conf->log ? conf->log : main_log);
+ char *worker = map_uri_to_worker(conf->uw_map, r->uri, conf->log ?
conf->log : main_log);
if(worker) {
r->handler=apr_pstrdup(r->pool,JK_HANDLER);