>Number:         557
>Category:       general
>Synopsis:       ~UserHome directories are not honored in absolute pathname 
>requests (.htaccess)
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    apache (Apache HTTP Project)
>State:          open
>Class:          sw-bug
>Submitter-Id:   apache
>Arrival-Date:   Wed May  7 16:10:01 1997
>Originator:     [EMAIL PROTECTED]
>Organization:
apache
>Release:        1.2b10 and previous
>Environment:
FreeBSD 2.2.1, gcc (testing platform)
>Description:
While it may be a security hole to implement AuthUserFile access to a
relative directory (the reason for the absolute pathname now) it should still
be considered that an active user's home directory is still a valid non-
relative directory.

The implementation is to remove burdens from sysadmins who would have to 
provide end-users full pathnames for their directories.  Also to allow these
directories to be portable in future when the customer/user moves their home
directory.  No need to provide end-users with their absolute directory since
it would equal their username (~username) in this instance.
>How-To-Repeat:
Replication of this problem requires a user called "testing" with a home
directory of "/usr/local/customer/home" and a standard user or group 
configured htaccess/htpasswd file as follows:

----".htaccess" file------
AuthUserFile ~testing/.htpasswd 
AuthGroupFile /dev/null
AuthName Testing Server
AuthType Basic
<limit GET>
require valid-user
</Limit>

---".htpasswd" file------
testing:<standard crypt>
---

Place this file in a user's home directory.  Point apache to it via a 
<VirtualHost> directive with an IP alias, and you will get a failure that it
cannot locate the file "~testing/.htaccess"... while using the full absolute
path works correctly.
>Fix:
The following patch will take a "~" from a filename request and attempt to
resolve the username path.  If it can be resolved, it uses it, otherwise the
filename is used as-is, with the current security provisions remaining.

*** alloc.c     1997/05/04 22:52:59     1.1
--- alloc.c     1997/05/04 23:12:15
***************
*** 828,850 ****
    register_cleanup (p, (void *)fp, file_cleanup, file_child_cleanup);
  }
  
  FILE *pfopen(pool *a, const char *name, const char *mode)
  {
    FILE *fd = NULL;
    int baseFlag, desc;
  
    block_alarms();
  
    if (*mode == 'a') {
      /* Work around faulty implementations of fopen */
      baseFlag = (*(mode+1) == '+') ? O_RDWR : O_WRONLY;
!     desc = open(name, baseFlag | O_APPEND | O_CREAT,
                S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
      if (desc >= 0) {
        fd = fdopen(desc, mode);
      }
    } else {
!     fd = fopen(name, mode);
    }
  
    if (fd != NULL) note_cleanups_for_file (a, fd);
--- 828,876 ----
    register_cleanup (p, (void *)fp, file_cleanup, file_child_cleanup);
  }
  
+ #include <pwd.h>
+ char *get_upath(n)
+ char *n;
+ {
+       char *p;
+       static struct passwd *pw, *getpwnam();
+       if ((pw=getpwnam(n)) != (struct passwd *) NULL) 
+               return(pw->pw_dir);
+       return(n);
+ }
+               
  FILE *pfopen(pool *a, const char *name, const char *mode)
  {
    FILE *fd = NULL;
+   char fname[1024];
+   char tmp[1024];
    int baseFlag, desc;
+   if (*name == '~') { /* assume user name expansion requested */
+       char *p, *r;;
+       strcpy(tmp, name);
+       if ((p=strchr(tmp, '/')) != (char *) NULL ) {
+               *p='\0'; /* null it out*/
+               p++; /* put it on the start of the path */
+               r=tmp; 
+               r++; /* skip past the ~ */
+               sprintf(fname, "%s/%s", get_upath(r), p);
+               } else  /* found no /'s give up */
+                 strcpy(fname, name);
+       } else 
+               strcpy(fname, name);
  
    block_alarms();
  
    if (*mode == 'a') {
      /* Work around faulty implementations of fopen */
      baseFlag = (*(mode+1) == '+') ? O_RDWR : O_WRONLY;
!     desc = open(fname, baseFlag | O_APPEND | O_CREAT,
                S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
      if (desc >= 0) {
        fd = fdopen(desc, mode);
      }
    } else {
!     fd = fopen(fname, mode);
    }
  
    if (fd != NULL) note_cleanups_for_file (a, fd);
%0
>Audit-Trail:
>Unformatted:


Reply via email to