You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by Dean Gaudet <dg...@hyperreal.com> on 1997/06/27 04:21:25 UTC
cvs commit: apache/src http_request.c mod_cern_meta.c mod_dir.c
dgaudet 97/06/26 19:21:25
Modified: src Tag: APACHE_1_2_X http_request.c mod_cern_meta.c
mod_dir.c
Log:
Ugh I messed up the security fixes commit.
Revision Changes Path
No revision
No revision
1.50.2.1 +41 -4 apache/src/http_request.c
Index: http_request.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_request.c,v
retrieving revision 1.50
retrieving revision 1.50.2.1
diff -C3 -r1.50 -r1.50.2.1
*** http_request.c 1997/05/14 19:22:52 1.50
--- http_request.c 1997/06/27 02:21:21 1.50.2.1
***************
*** 85,90 ****
--- 85,108 ----
* they change, all the way down.
*/
+
+ /*
+ * We don't want people able to serve up pipes, or unix sockets, or other
+ * scary things. Note that symlink tests are performed later.
+ */
+ static int check_safe_file(request_rec *r)
+ {
+ if (r->finfo.st_mode == 0 /* doesn't exist */
+ || S_ISDIR (r->finfo.st_mode)
+ || S_ISREG (r->finfo.st_mode)
+ || S_ISLNK (r->finfo.st_mode)) {
+ return OK;
+ }
+ log_reason("object is not a file, directory or symlink", r->filename, r);
+ return HTTP_FORBIDDEN;
+ }
+
+
int check_symlinks (char *d, int opts)
{
struct stat lfi, fi;
***************
*** 310,320 ****
if (res != OK) {
return res;
}
!
if (test_filename[strlen(test_filename)-1] == '/')
--num_dirs;
! if (S_ISDIR (r->finfo.st_mode)) ++num_dirs;
for (i = 1; i <= num_dirs; ++i) {
core_dir_config *core_dir =
--- 328,344 ----
if (res != OK) {
return res;
}
!
! if ((res = check_safe_file(r))) {
! return res;
! }
!
if (test_filename[strlen(test_filename)-1] == '/')
--num_dirs;
! if (S_ISDIR (r->finfo.st_mode)) {
! ++num_dirs;
! }
for (i = 1; i <= num_dirs; ++i) {
core_dir_config *core_dir =
***************
*** 399,406 ****
r->per_dir_config = per_dir_defaults;
! if ((res = check_symlinks (r->filename, allow_options(r))))
! {
log_reason("Symbolic link not allowed", r->filename, r);
return res;
}
--- 423,438 ----
r->per_dir_config = per_dir_defaults;
! /* Symlink permissions are determined by the parent. If the request is for
! * a directory then applying the symlink test here would use the
! * permissions of the directory as opposed to its parent. Consider a
! * symlink pointing to a dir with a .htaccess disallowing symlinks. If you
! * access /symlink (or /symlink/) you would get a 403 without this S_ISDIR
! * test. But if you accessed /symlink/index.html, for example, you would
! * *not* get the 403.
! */
! if (!S_ISDIR (r->finfo.st_mode)
! && (res = check_symlinks (r->filename, allow_options(r)))) {
log_reason("Symbolic link not allowed", r->filename, r);
return res;
}
***************
*** 667,672 ****
--- 699,709 ----
rnew->filename = make_full_path (rnew->pool, fdir, new_file);
if (stat (rnew->filename, &rnew->finfo) < 0) {
rnew->finfo.st_mode = 0;
+ }
+
+ if ((res = check_safe_file(rnew))) {
+ rnew->status = res;
+ return rnew;
}
rnew->per_dir_config = r->per_dir_config;
1.10.2.1 +14 -20 apache/src/mod_cern_meta.c
Index: mod_cern_meta.c
===================================================================
RCS file: /export/home/cvs/apache/src/mod_cern_meta.c,v
retrieving revision 1.10
retrieving revision 1.10.2.1
diff -C3 -r1.10 -r1.10.2.1
*** mod_cern_meta.c 1997/03/07 14:15:39 1.10
--- mod_cern_meta.c 1997/06/27 02:21:22 1.10.2.1
***************
*** 131,136 ****
--- 131,137 ----
#include <sys/stat.h>
#include "util_script.h"
#include "http_log.h"
+ #include "http_request.h"
#define DEFAULT_METADIR ".web"
#define DEFAULT_METASUFFIX ".meta"
***************
*** 238,247 ****
char *last_slash;
char *real_file;
char *scrap_book;
- struct stat meta_stat;
FILE *f;
cern_meta_config *cmc ;
int rv;
cmc = get_module_config (r->server->module_config,
&cern_meta_module);
--- 239,248 ----
char *last_slash;
char *real_file;
char *scrap_book;
FILE *f;
cern_meta_config *cmc ;
int rv;
+ request_rec *rr;
cmc = get_module_config (r->server->module_config,
&cern_meta_module);
***************
*** 276,305 ****
metafilename = pstrcat(r->pool, "/", scrap_book, "/", cmc->metadir, "/", real_file, cmc->metasuffix, NULL);
! /*
! * stat can legitimately fail for a bewildering number of reasons,
! * only one of which implies the file isn't there. A hardened
! * version of this module should test for all conditions, but later...
*/
! if (stat(metafilename, &meta_stat) == -1) {
! /* stat failed, possibly file missing */
return DECLINED;
! };
!
! /*
! * this check is to be found in other Jan/96 Apache code, I've
! * not been able to find any corroboration in the man pages but
! * I've been wrong before so I'll put it in anyway. Never
! * admit to being clueless...
! */
! if ( meta_stat.st_mode == 0 ) {
! /* stat failed, definately file missing */
! return DECLINED;
! };
f = pfopen (r->pool, metafilename, "r");
-
if (f == NULL) {
log_reason("meta file permissions deny server access", metafilename, r);
return FORBIDDEN;
};
--- 277,299 ----
metafilename = pstrcat(r->pool, "/", scrap_book, "/", cmc->metadir, "/", real_file, cmc->metasuffix, NULL);
! /* XXX: it sucks to require this subrequest to complete, because this
! * means people must leave their meta files accessible to the world.
! * A better solution might be a "safe open" feature of pfopen to avoid
! * pipes, symlinks, and crap like that.
*/
! rr = sub_req_lookup_file (metafilename, r);
! if (rr->status != HTTP_OK) {
! destroy_sub_req (rr);
return DECLINED;
! }
! destroy_sub_req (rr);
f = pfopen (r->pool, metafilename, "r");
if (f == NULL) {
+ if (errno == ENOENT) {
+ return DECLINED;
+ }
log_reason("meta file permissions deny server access", metafilename, r);
return FORBIDDEN;
};
1.26.2.1 +19 -0 apache/src/mod_dir.c
Index: mod_dir.c
===================================================================
RCS file: /export/home/cvs/apache/src/mod_dir.c,v
retrieving revision 1.26
retrieving revision 1.26.2.1
diff -C3 -r1.26 -r1.26.2.1
*** mod_dir.c 1997/05/13 04:01:50 1.26
--- mod_dir.c 1997/06/27 02:21:22 1.26.2.1
***************
*** 164,174 ****
--- 164,180 ----
}
const char *add_header(cmd_parms *cmd, void *d, char *name) {
+ if (strchr (name, '/')) {
+ return "HeaderName cannot contain a /";
+ }
push_item(((dir_config_rec *)d)->hdr_list, 0, NULL, cmd->path, name);
return NULL;
}
const char *add_readme(cmd_parms *cmd, void *d, char *name) {
+ if (strchr (name, '/')) {
+ return "ReadmeName cannot contain a /";
+ }
push_item(((dir_config_rec *)d)->rdme_list, 0, NULL, cmd->path, name);
return NULL;
}
***************
*** 408,414 ****
--- 414,422 ----
FILE *f;
struct stat finfo;
int plaintext=0;
+ request_rec *rr;
+ /* XXX: this is a load of crap, it needs to do a full sub_req_lookup_uri */
fn = make_full_path(r->pool, name, readme_fname);
fn = pstrcat(r->pool, fn, ".html", NULL);
if(stat(fn,&finfo) == -1) {
***************
*** 421,426 ****
--- 429,442 ----
rputs("<PRE>\n", r);
}
else if (rule) rputs("<HR>\n", r);
+ /* XXX: when the above is rewritten properly, this necessary security
+ * check will be redundant. -djg */
+ rr = sub_req_lookup_file (fn, r);
+ if (rr->status != HTTP_OK) {
+ destroy_sub_req (rr);
+ return 0;
+ }
+ destroy_sub_req (rr);
if(!(f = pfopen(r->pool,fn,"r")))
return 0;
if (!plaintext)
***************
*** 462,467 ****
--- 478,486 ----
FILE *thefile = NULL;
int x,y,n,p;
+ if (r->status != HTTP_OK) {
+ return NULL;
+ }
if (r->content_type && !strcmp(r->content_type,"text/html") && !r->content_encoding) {
if(!(thefile = pfopen(r->pool, r->filename,"r")))
return NULL;