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;