Shugo Maeda wrote:
> Can you make a patch? Or may I implement it?
I'm not adept in C and I'm not yet familiar with Apache2 API, but here's
my attempt. Please review it. Some notes about this patch:
- I've only tested it with Apache 1.3.33;
- The Japanese directives documentation (directives.ja.euc.rd) has not
been updated.
- With this patch, everytime we add a new directive that can be put in
dir-specific config, we must add check_restrict_directives() to it.
Regards,
dave
diff -ruN --exclude='*~' mod_ruby-1.2.4.orig/doc/directives.en.rd mod_ruby-1.2.4+rubyrestrictdirectives/doc/directives.en.rd
--- mod_ruby-1.2.4.orig/doc/directives.en.rd Thu Jul 1 10:49:24 2004
+++ mod_ruby-1.2.4+rubyrestrictdirectives/doc/directives.en.rd Thu Nov 18 13:01:04 2004
@@ -24,6 +24,7 @@
* ((<RubyTimeOut|RubyTimeOut sec>))
* ((<RubySafeLevel|RubySafeLevel level>))
* ((<RubyOutputMode|RubyOutputMode mode>))
+* ((<RubyRestrictDirectives|RubyRestrictDirectives flag>))
* ((<RubyKanjiCode|RubyKanjiCode kcode>))
--- RubyAddPath directory...
@@ -258,6 +259,19 @@
RubyOutputMode syncheader
+--- RubyRestrictDirectives flag
+ Specifies whether all the other Ruby* directives (like
+ RubyHandler, RubySetEnv, etc.) are restricted from being
+ specified in .htaccess files. Default is (({off})). Setting this
+ to (({on})) can be useful in some multi-user situations
+ (e.g. shared webhosting), in which the server admin wants to use
+ mod_ruby but does not want to allow normal users to get access
+ to it. Only available in server config.
+
+ example:
+
+ RubyRestrictDirectives on
+
--- RubyKanjiCode kcode
Specifies the value of ((|$KCODE|)).
diff -ruN --exclude='*~' mod_ruby-1.2.4.orig/mod_ruby.c mod_ruby-1.2.4+rubyrestrictdirectives/mod_ruby.c
--- mod_ruby-1.2.4.orig/mod_ruby.c Mon Sep 27 12:02:36 2004
+++ mod_ruby-1.2.4+rubyrestrictdirectives/mod_ruby.c Thu Nov 18 10:12:43 2004
@@ -164,6 +164,9 @@
"set default $SAFE"},
{"RubyOutputMode", ruby_cmd_output_mode, NULL, OR_ALL, TAKE1,
"set output mode (nosync|sync|syncheader)"},
+ {"RubyRestrictDirectives", ruby_cmd_restrict_directives, NULL,
+ RSRC_CONF, FLAG,
+ "whether Ruby* directives are restricted from .htaccess"},
{"RubyHandler", ruby_cmd_handler, NULL, OR_ALL, TAKE1,
"set ruby handler object"},
{"RubyTransHandler", ruby_cmd_trans_handler, NULL, RSRC_CONF, TAKE1,
diff -ruN --exclude='*~' mod_ruby-1.2.4.orig/mod_ruby.h mod_ruby-1.2.4+rubyrestrictdirectives/mod_ruby.h
--- mod_ruby-1.2.4.orig/mod_ruby.h Mon Sep 27 12:11:32 2004
+++ mod_ruby-1.2.4+rubyrestrictdirectives/mod_ruby.h Thu Nov 18 07:19:20 2004
@@ -133,6 +133,7 @@
table *env;
int timeout;
array_header *ruby_child_init_handler;
+ int restrict_directives;
} ruby_server_config;
typedef struct {
@@ -163,6 +164,7 @@
#define MR_DEFAULT_TIMEOUT 270
#define MR_DEFAULT_SAFE_LEVEL 1
+#define MR_DEFAULT_RESTRICT_DIRECTIVES 0
#define MR_OUTPUT_DEFAULT 0
#define MR_OUTPUT_NOSYNC 1
diff -ruN --exclude='*~' mod_ruby-1.2.4.orig/ruby_config.c mod_ruby-1.2.4+rubyrestrictdirectives/ruby_config.c
--- mod_ruby-1.2.4.orig/ruby_config.c Wed Aug 18 23:23:43 2004
+++ mod_ruby-1.2.4+rubyrestrictdirectives/ruby_config.c Thu Nov 18 12:54:41 2004
@@ -27,10 +27,14 @@
* SUCH DAMAGE.
*/
+#define CORE_PRIVATE
#include "mod_ruby.h"
#include "ruby_config.h"
static int default_safe_level = MR_DEFAULT_SAFE_LEVEL;
+static char restrict_directives_error_msg[] =
+ "RubyRestrictDirectives is enabled, directives not available in "
+ ".htaccess";
#define push_handler(p, handler, arg) { \
if ((handler) == NULL) \
@@ -46,6 +50,7 @@
conf->load_path = ap_make_array(p, 1, sizeof(char*));
conf->env = ap_make_table(p, 1);
conf->timeout = MR_DEFAULT_TIMEOUT;
+ conf->restrict_directives = MR_DEFAULT_RESTRICT_DIRECTIVES;
conf->ruby_child_init_handler = NULL;
return conf;
}
@@ -79,6 +84,8 @@
}
new->env = ap_overlay_tables(p, add->env, base->env);
new->timeout = add->timeout ? add->timeout : base->timeout;
+ new->restrict_directives = add->restrict_directives ?
+ add->restrict_directives : base->restrict_directives;
new->ruby_child_init_handler =
merge_handlers(p, base->ruby_child_init_handler,
add->ruby_child_init_handler);
@@ -167,8 +174,41 @@
return (void *) new;
}
+int is_from_htaccess(cmd_parms *cmd, ruby_dir_config *conf)
+{
+ core_server_config *sconf;
+ int access_name_len;
+ int config_file_path_len;
+
+ if (cmd->path == NULL || conf == NULL) return 0;
+ sconf = ap_get_module_config(cmd->server->module_config, &core_module);
+
+ access_name_len = strlen(sconf->access_name);
+ config_file_path_len = strlen(cmd->config_file->name);
+ if (config_file_path_len < access_name_len) return 0;
+ if (strcmp(cmd->config_file->name + config_file_path_len - access_name_len,
+ sconf->access_name) != 0)
+ return 0;
+
+ return 1;
+}
+
+int is_restrict_directives(server_rec *server)
+{
+ ruby_server_config *sconf = get_server_config(server);
+
+ return sconf->restrict_directives != 0 ? 1 : 0;
+}
+
+#define check_restrict_directives(cmd, dconf) { \
+ if (is_from_htaccess((cmd), (dconf)) && \
+ is_restrict_directives((cmd)->server)) \
+ return restrict_directives_error_msg; \
+}
+
const char *ruby_cmd_kanji_code(cmd_parms *cmd, ruby_dir_config *conf, char *arg)
{
+ check_restrict_directives(cmd, conf);
conf->kcode = ap_pstrdup(cmd->pool, arg);
return NULL;
}
@@ -177,6 +217,7 @@
{
ruby_server_config *sconf;
+ check_restrict_directives(cmd, dconf);
if (cmd->path == NULL) {
sconf = get_server_config(cmd->server);
*(char **) ap_push_array(sconf->load_path) = arg;
@@ -260,6 +301,7 @@
ruby_server_config *sconf = get_server_config(cmd->server);
ruby_library_context *lib;
+ check_restrict_directives(cmd, dconf);
if (ruby_running()) {
ruby_require(cmd->pool, arg, cmd->server, sconf, dconf);
}
@@ -296,6 +338,7 @@
const char *ruby_cmd_set_env(cmd_parms *cmd, ruby_dir_config *conf,
char *key, char *val)
{
+ check_restrict_directives(cmd, conf);
ap_table_set(conf->env, key, val);
if (cmd->path == NULL) {
ruby_server_config *sconf = get_server_config(cmd->server);
@@ -304,6 +347,13 @@
return NULL;
}
+const char *ruby_cmd_restrict_directives(cmd_parms *cmd, void *dummy, int flag)
+{
+ ruby_server_config *sconf = get_server_config(cmd->server);
+ sconf->restrict_directives = flag;
+ return NULL;
+}
+
const char *ruby_cmd_timeout(cmd_parms *cmd, void *dummy, char *arg)
{
ruby_server_config *conf = get_server_config(cmd->server);
@@ -314,6 +364,7 @@
const char *ruby_cmd_safe_level(cmd_parms *cmd, ruby_dir_config *conf, char *arg)
{
+ check_restrict_directives(cmd, conf);
if (cmd->path == NULL && !cmd->server->is_virtual) {
conf->safe_level = default_safe_level = atoi(arg);
}
@@ -325,6 +376,7 @@
const char *ruby_cmd_output_mode(cmd_parms *cmd, ruby_dir_config *conf, char *arg)
{
+ check_restrict_directives(cmd, conf);
if (strcasecmp(arg, "nosync") == 0) {
conf->output_mode = MR_OUTPUT_NOSYNC;
}
@@ -342,48 +394,56 @@
const char *ruby_cmd_handler(cmd_parms *cmd, ruby_dir_config *conf, char *arg)
{
+ check_restrict_directives(cmd, conf);
push_handler(cmd->pool, conf->ruby_handler, arg);
return NULL;
}
const char *ruby_cmd_trans_handler(cmd_parms *cmd, ruby_dir_config *conf, char *arg)
{
+ check_restrict_directives(cmd, conf);
push_handler(cmd->pool, conf->ruby_trans_handler, arg);
return NULL;
}
const char *ruby_cmd_authen_handler(cmd_parms *cmd, ruby_dir_config *conf, char *arg)
{
+ check_restrict_directives(cmd, conf);
push_handler(cmd->pool, conf->ruby_authen_handler, arg);
return NULL;
}
const char *ruby_cmd_authz_handler(cmd_parms *cmd, ruby_dir_config *conf, char *arg)
{
+ check_restrict_directives(cmd, conf);
push_handler(cmd->pool, conf->ruby_authz_handler, arg);
return NULL;
}
const char *ruby_cmd_access_handler(cmd_parms *cmd, ruby_dir_config *conf, char *arg)
{
+ check_restrict_directives(cmd, conf);
push_handler(cmd->pool, conf->ruby_access_handler, arg);
return NULL;
}
const char *ruby_cmd_type_handler(cmd_parms *cmd, ruby_dir_config *conf, char *arg)
{
+ check_restrict_directives(cmd, conf);
push_handler(cmd->pool, conf->ruby_type_handler, arg);
return NULL;
}
const char *ruby_cmd_fixup_handler(cmd_parms *cmd, ruby_dir_config *conf, char *arg)
{
+ check_restrict_directives(cmd, conf);
push_handler(cmd->pool, conf->ruby_fixup_handler, arg);
return NULL;
}
const char *ruby_cmd_log_handler(cmd_parms *cmd, ruby_dir_config *conf, char *arg)
{
+ check_restrict_directives(cmd, conf);
push_handler(cmd->pool, conf->ruby_log_handler, arg);
return NULL;
}
@@ -391,6 +451,7 @@
const char *ruby_cmd_header_parser_handler(cmd_parms *cmd,
ruby_dir_config *conf, char *arg)
{
+ check_restrict_directives(cmd, conf);
push_handler(cmd->pool, conf->ruby_header_parser_handler, arg);
return NULL;
}
@@ -398,6 +459,7 @@
const char *ruby_cmd_post_read_request_handler(cmd_parms *cmd,
ruby_dir_config *conf, char *arg)
{
+ check_restrict_directives(cmd, conf);
push_handler(cmd->pool, conf->ruby_post_read_request_handler, arg);
return NULL;
}
@@ -405,6 +467,7 @@
const char *ruby_cmd_init_handler(cmd_parms *cmd,
ruby_dir_config *conf, char *arg)
{
+ check_restrict_directives(cmd, conf);
push_handler(cmd->pool, conf->ruby_init_handler, arg);
return NULL;
}
@@ -412,6 +475,7 @@
const char *ruby_cmd_cleanup_handler(cmd_parms *cmd,
ruby_dir_config *conf, char *arg)
{
+ check_restrict_directives(cmd, conf);
push_handler(cmd->pool, conf->ruby_cleanup_handler, arg);
return NULL;
}
diff -ruN --exclude='*~' mod_ruby-1.2.4.orig/ruby_config.h mod_ruby-1.2.4+rubyrestrictdirectives/ruby_config.h
--- mod_ruby-1.2.4.orig/ruby_config.h Sun Aug 8 05:40:25 2004
+++ mod_ruby-1.2.4+rubyrestrictdirectives/ruby_config.h Thu Nov 18 10:34:31 2004
@@ -30,6 +30,8 @@
#ifndef RUBY_CONFIG_H
#define RUBY_CONFIG_H
+extern char restrict_directives_error_msg[];
+
void *ruby_create_server_config(pool*, server_rec*);
void *ruby_merge_server_config(pool*, void*, void*);
void *ruby_create_dir_config (pool*, char*);
@@ -42,6 +44,7 @@
const char *ruby_cmd_timeout(cmd_parms*, void*, char*);
const char *ruby_cmd_safe_level(cmd_parms*, ruby_dir_config*, char*);
const char *ruby_cmd_output_mode(cmd_parms*, ruby_dir_config*, char*);
+const char *ruby_cmd_restrict_directives(cmd_parms*, void*, int);
const char *ruby_cmd_handler(cmd_parms*, ruby_dir_config*, char*);
const char *ruby_cmd_trans_handler(cmd_parms*, ruby_dir_config*, char*);
const char *ruby_cmd_authen_handler(cmd_parms*, ruby_dir_config*, char*);