martin 97/11/11 14:43:27
Modified: src/main http_core.c
Log:
New check routine check_cmd_context() -- controls whether a particular
directive is allowed in <Directory/Files/Location>, <Limit> or
<VirtualHost> context and complains if it isn't.
Reviewed by: Dean Gaudet, Jim Jagielski, Ken Coar
Revision Changes Path
1.137 +171 -56 apachen/src/main/http_core.c
Index: http_core.c
===================================================================
RCS file: /home/cvs/apachen/src/main/http_core.c,v
retrieving revision 1.136
retrieving revision 1.137
diff -u -u -r1.136 -r1.137
--- http_core.c 1997/11/11 22:36:22 1.136
+++ http_core.c 1997/11/11 22:43:26 1.137
@@ -564,11 +564,40 @@
* commands, but most of the old srm.conf is in the the modules.
*/
+/* check_cmd_context(): Forbidden in: */
+#define NOT_IN_VIRTUALHOST 0x01U /* <Virtualhost> */
+#define NOT_IN_LIMIT 0x02U /* <Limit> */
+#define NOT_IN_DIR_LOC_FILE 0x04U /* <Directory>/<Location>/<Files>*/
+
+
+static const char *check_cmd_context(cmd_parms *cmd, unsigned forbidden)
+{
+ const char *gt = (cmd->cmd->name[0] == '<'
+ && cmd->cmd->name[strlen(cmd->cmd->name)-1] != '>') ? ">" :
"";
+
+ if ((forbidden & NOT_IN_VIRTUALHOST) && cmd->server->is_virtual)
+ return pstrcat(cmd->pool, cmd->cmd->name, gt,
+ " cannot occur within <VirtualHost> section", NULL);
+
+ if ((forbidden & NOT_IN_LIMIT) && cmd->limited != -1)
+ return pstrcat(cmd->pool, cmd->cmd->name, gt,
+ " cannot occur within <Limit> section", NULL);
+
+ if ((forbidden & NOT_IN_DIR_LOC_FILE) && cmd->path != NULL)
+ return pstrcat(cmd->pool, cmd->cmd->name, gt,
+ " cannot occur within <Directory/Location/Files>
section", NULL);
+
+ return NULL;
+}
+
const char *set_access_name (cmd_parms *cmd, void *dummy, char *arg)
{
void *sconf = cmd->server->module_config;
core_server_config *conf = get_module_config (sconf, &core_module);
-
+
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
conf->access_name = pstrdup(cmd->pool, arg);
return NULL;
}
@@ -578,6 +607,9 @@
void *sconf = cmd->server->module_config;
core_server_config *conf = get_module_config (sconf, &core_module);
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
if (!is_directory (arg))
if (cmd->server->is_virtual)
fprintf (stderr, "Warning: DocumentRoot [%s] does not exist\n",
arg);
@@ -594,6 +626,9 @@
int error_number, index_number, idx500;
char *w;
+ const char *err = check_cmd_context(cmd, NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
/* 1st parameter should be a 3 digit number, which we recognize;
* convert it into an array index
*/
@@ -632,6 +667,9 @@
{
char *w;
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
d->override = OR_NONE;
while(l[0]) {
w = getword_conf (cmd->pool, &l);
@@ -736,7 +774,13 @@
const char *limited_methods = getword(cmd->pool,&arg,'>');
int limited = 0;
- if (cmd->limited > 0) return "Can't nest <Limit> sections";
+ const char *err = check_cmd_context(cmd, NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
+ /* XXX: NB: Currently, we have no way of checking
+ * whether <Limit> sections are closed properly.
+ * (If we would add a srm_command_loop() here we might...)
+ */
while(limited_methods[0]) {
char *method = getword_conf (cmd->pool, &limited_methods);
@@ -765,18 +809,18 @@
* When a section is not closed properly when end-of-file is reached,
* then an error message should be printed:
*/
-static const char *missing_endsection (pool *p, const char *secname, int
nest)
+static const char *missing_endsection (cmd_parms *cmd, int nest)
{
char rply[100];
if (nest < 2)
ap_snprintf(rply, sizeof rply, "Missing </%s> directive at end-of-file",
- secname);
+ &cmd->cmd->name[1]);
else
ap_snprintf(rply, sizeof rply, "%d missing </%s> directives at
end-of-file",
- nest, secname);
+ nest, &cmd->cmd->name[1]);
- return pstrdup(p, rply);
+ return pstrdup(cmd->pool, rply);
}
/* We use this in <DirectoryMatch> and <FilesMatch>, to ensure that
@@ -805,10 +849,10 @@
void *new_dir_conf = create_per_dir_config (cmd->pool);
regex_t *r = NULL;
- if (endp) *endp = '\0';
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
- if (cmd->path) return "<Directory> sections don't nest";
- if (cmd->limited != -1) return "Can't have <Directory> within <Limit>";
+ if (endp) *endp = '\0';
cmd->path = getword_conf (cmd->pool, &arg);
#ifdef __EMX__
@@ -831,9 +875,9 @@
errmsg = srm_command_loop (cmd, new_dir_conf);
if (errmsg == NULL)
- return missing_endsection(cmd->pool,
- (cmd->info) ? "DirectoryMatch" : "Directory", 1);
- if (errmsg != end_dir_magic) return errmsg;
+ return missing_endsection(cmd, 1);
+ else if (errmsg != end_dir_magic)
+ return errmsg;
conf = (core_dir_config *)get_module_config(new_dir_conf, &core_module);
conf->r = r;
@@ -867,11 +911,11 @@
void *new_url_conf = create_per_dir_config (cmd->pool);
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
if (endp) *endp = '\0';
- if (cmd->path) return "<Location> sections don't nest";
- if (cmd->limited != -1) return "Can't have <Location> within <Limit>";
-
cmd->path = getword_conf (cmd->pool, &arg);
cmd->override = OR_ALL|ACCESS_CONF;
@@ -885,9 +929,9 @@
errmsg = srm_command_loop (cmd, new_url_conf);
if (errmsg == NULL)
- return missing_endsection(cmd->pool,
- (cmd->info) ? "LocationMatch" : "Location", 1);
- if (errmsg != end_url_magic) return errmsg;
+ return missing_endsection(cmd, 1);
+ else if (errmsg != end_url_magic)
+ return errmsg;
conf = (core_dir_config *)get_module_config(new_url_conf, &core_module);
conf->d = pstrdup(cmd->pool, cmd->path); /* No mangling, please */
@@ -923,6 +967,9 @@
void *new_file_conf = create_per_dir_config (cmd->pool);
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
if (endp) *endp = '\0';
if (cmd->limited != -1) return "Can't have <Files> within <Limit>";
@@ -953,9 +1000,9 @@
errmsg = srm_command_loop (cmd, new_file_conf);
if (errmsg == NULL)
- return missing_endsection(cmd->pool,
- (cmd->info) ? "FilesMatch" : "Files", 1);
- if (errmsg != end_file_magic) return errmsg;
+ return missing_endsection(cmd, 1);
+ else if (errmsg != end_file_magic)
+ return errmsg;
conf = (core_dir_config *)get_module_config(new_file_conf, &core_module);
conf->d = pstrdup(cmd->pool, cmd->path);
@@ -1001,7 +1048,7 @@
nest--;
}
- return (nest == 0) ? NULL : missing_endsection(cmd->pool, "IfModule",
nest);
+ return (nest == 0) ? NULL : missing_endsection(cmd, nest);
}
/* httpd.conf commands... beginning with the <VirtualHost> business */
@@ -1020,6 +1067,9 @@
char *endp = strrchr (arg, '>');
pool *p = cmd->pool, *ptemp = cmd->temp_pool;
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
if (endp) *endp = '\0';
/* FIXME: There's another feature waiting to happen here -- since you
@@ -1048,13 +1098,17 @@
process_resource_config (s, s->access_confname, p, ptemp);
if (errmsg == NULL)
- return missing_endsection(cmd->pool, "Virtualhost", 1);
- if (errmsg == end_virthost_magic) return NULL;
+ return missing_endsection(cmd, 1);
+ else if (errmsg == end_virthost_magic)
+ return NULL;
return errmsg;
}
const char *add_module_command (cmd_parms *cmd, void *dummy, char *arg)
{
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
if (add_named_module (arg))
return NULL;
return "required module not found";
@@ -1062,6 +1116,9 @@
const char *clear_module_list_command (cmd_parms *cmd, void *dummy)
{
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
clear_module_list ();
return NULL;
}
@@ -1073,14 +1130,18 @@
int offset = (int)(long)cmd->info;
char *struct_ptr = (char *)cmd->server;
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
*(char **)(struct_ptr + offset) = pstrdup (cmd->pool, arg);
return NULL;
}
const char *server_type (cmd_parms *cmd, void *dummy, char *arg)
{
- if (cmd->server->is_virtual)
- return "ServerType directive not allowed in <VirtualHost>";
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
if (!strcasecmp (arg, "inetd")) standalone = 0;
else if (!strcasecmp (arg, "standalone")) standalone = 1;
else return "ServerType must be either 'inetd' or 'standalone'";
@@ -1089,15 +1150,18 @@
}
const char *server_port (cmd_parms *cmd, void *dummy, char *arg) {
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
cmd->server->port = atoi (arg);
return NULL;
}
const char *set_send_buffer_size (cmd_parms *cmd, void *dummy, char *arg) {
int s = atoi (arg);
- if (cmd->server->is_virtual) {
- return "SendBufferSize directive can not be used in <VirtualHost>";
- }
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
if (s < 512 && s != 0) {
return "SendBufferSize must be >= 512 bytes, or 0 for system
default.";
}
@@ -1107,6 +1171,9 @@
const char *set_user (cmd_parms *cmd, void *dummy, char *arg)
{
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
if (!cmd->server->is_virtual) {
user_name = pstrdup (cmd->pool, arg);
cmd->server->server_uid = user_id = uname2id(arg);
@@ -1140,6 +1207,9 @@
const char *set_group (cmd_parms *cmd, void *dummy, char *arg)
{
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
if (!cmd->server->is_virtual)
cmd->server->server_gid = group_id = gname2id(arg);
else {
@@ -1156,8 +1226,9 @@
}
const char *set_server_root (cmd_parms *cmd, void *dummy, char *arg) {
- if (cmd->server->is_virtual)
- return "ServerRoot directive not allowed in <VirtualHost>";
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
if (!is_directory (arg)) return "ServerRoot must be a valid directory";
strncpy (server_root, arg, sizeof(server_root)-1);
server_root[sizeof(server_root)-1] = '\0';
@@ -1165,16 +1236,25 @@
}
const char *set_timeout (cmd_parms *cmd, void *dummy, char *arg) {
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
cmd->server->timeout = atoi (arg);
return NULL;
}
const char *set_keep_alive_timeout (cmd_parms *cmd, void *dummy, char *arg) {
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
cmd->server->keep_alive_timeout = atoi (arg);
return NULL;
}
const char *set_keep_alive (cmd_parms *cmd, void *dummy, char *arg) {
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
/* We've changed it to On/Off, but used to use numbers
* so we accept anything but "Off" or "0" as "On"
*/
@@ -1186,11 +1266,17 @@
}
const char *set_keep_alive_max (cmd_parms *cmd, void *dummy, char *arg) {
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
cmd->server->keep_alive_max = atoi (arg);
return NULL;
}
const char *set_pidfile (cmd_parms *cmd, void *dummy, char *arg) {
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
if (cmd->server->is_virtual)
return "PidFile directive not allowed in <VirtualHost>";
pid_fname = pstrdup (cmd->pool, arg);
@@ -1198,26 +1284,34 @@
}
const char *set_scoreboard (cmd_parms *cmd, void *dummy, char *arg) {
- if (cmd->server->is_virtual)
- return "ScoreBoardFile directive not allowed in <VirtualHost>";
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
scoreboard_fname = pstrdup (cmd->pool, arg);
return NULL;
}
const char *set_lockfile (cmd_parms *cmd, void *dummy, char *arg) {
- if (cmd->server->is_virtual)
- return "LockFile directive not allowed in <VirtualHost>";
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
lock_fname = pstrdup (cmd->pool, arg);
return NULL;
}
const char *set_idcheck (cmd_parms *cmd, core_dir_config *d, int arg) {
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
d->do_rfc1413 = arg != 0;
return NULL;
}
const char *set_hostname_lookups (cmd_parms *cmd, core_dir_config *d, char
*arg)
{
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
if (!strcasecmp (arg, "on")) {
d->hostname_lookups = HOSTNAME_LOOKUP_ON;
} else if (!strcasecmp (arg, "off")) {
@@ -1231,26 +1325,34 @@
}
const char *set_serverpath (cmd_parms *cmd, void *dummy, char *arg) {
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
cmd->server->path = pstrdup (cmd->pool, arg);
cmd->server->pathlen = strlen (arg);
return NULL;
}
const char *set_content_md5 (cmd_parms *cmd, core_dir_config *d, int arg) {
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
d->content_md5 = arg != 0;
return NULL;
}
const char *set_daemons_to_start (cmd_parms *cmd, void *dummy, char *arg) {
- if (cmd->server->is_virtual)
- return "StartServers directive not allowed in <VirtualHost>";
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
daemons_to_start = atoi (arg);
return NULL;
}
const char *set_min_free_servers (cmd_parms *cmd, void *dummy, char *arg) {
- if (cmd->server->is_virtual)
- return "MinSpareServers directive not allowed in <VirtualHost>";
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
daemons_min_free = atoi (arg);
if (daemons_min_free <= 0) {
fprintf(stderr, "WARNING: detected MinSpareServers set to
non-positive.\n");
@@ -1263,15 +1365,17 @@
}
const char *set_max_free_servers (cmd_parms *cmd, void *dummy, char *arg) {
- if (cmd->server->is_virtual)
- return "MaxSpareServers directive not allowed in <VirtualHost>";
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
daemons_max_free = atoi (arg);
return NULL;
}
const char *set_server_limit (cmd_parms *cmd, void *dummy, char *arg) {
- if (cmd->server->is_virtual)
- return "MaxClients directive not allowed in <VirtualHost>";
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
daemons_limit = atoi (arg);
if (daemons_limit > HARD_SERVER_LIMIT) {
fprintf(stderr, "WARNING: MaxClients of %d exceeds compile time limit
"
@@ -1288,22 +1392,25 @@
}
const char *set_max_requests (cmd_parms *cmd, void *dummy, char *arg) {
- if (cmd->server->is_virtual)
- return "MaxRequestsPerChild directive not allowed in <VirtualHost>";
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
max_requests_per_child = atoi (arg);
return NULL;
}
const char *set_threads (cmd_parms *cmd, void *dummy, char *arg) {
- if (cmd->server->is_virtual)
- return "ThreadsPerChild directive not allowed in <VirtualHost>";
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
threads_per_child = atoi (arg);
return NULL;
}
const char *set_excess_requests (cmd_parms *cmd, void *dummy, char *arg) {
- if (cmd->server->is_virtual)
- return "ExcessRequestsPerChild directive not allowed in <VirtualHost>";
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
excess_requests_per_child = atoi (arg);
return NULL;
}
@@ -1397,8 +1504,9 @@
#endif
const char *set_bind_address (cmd_parms *cmd, void *dummy, char *arg) {
- if (cmd->server->is_virtual)
- return "BindAddress directive not allowed in <VirtualHost>";
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
bind_address.s_addr = get_virthost_addr (arg, NULL);
return NULL;
}
@@ -1409,7 +1517,9 @@
char *ports;
unsigned short port;
- if (cmd->server->is_virtual) return "Listen not allowed in
<VirtualHost>";
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
ports=strchr(ips, ':');
if (ports != NULL)
{
@@ -1440,8 +1550,9 @@
const char *set_listenbacklog (cmd_parms *cmd, void *dummy, char *arg) {
int b;
- if (cmd->server->is_virtual)
- return "ListenBacklog not allowed in <VirtualHost>";
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
b = atoi (arg);
if (b < 1) return "ListenBacklog must be > 0";
listenbacklog = b;
@@ -1450,8 +1561,9 @@
const char *set_coredumpdir (cmd_parms *cmd, void *dummy, char *arg) {
struct stat finfo;
- if (cmd->server->is_virtual)
- return "CoreDumpDirectory not allowed in <VirtualHost>";
+ const char *err = check_cmd_context(cmd,
NOT_IN_VIRTUALHOST|NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
if ((stat(arg, &finfo) == -1) || !S_ISDIR(finfo.st_mode)) {
return pstrcat(cmd->pool, "CoreDumpDirectory ", arg,
" does not exist or is not a directory", NULL);
@@ -1474,6 +1586,9 @@
{
char *str;
+ const char *err = check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) return err;
+
if ((str = getword_conf(cmd->pool, &arg))) {
if (!strcasecmp(str, "emerg"))
cmd->server->loglevel = APLOG_EMERG;