httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From wr...@apache.org
Subject cvs commit: apache-1.3/src/os/os2 util_os2.c
Date Thu, 10 May 2001 04:07:58 GMT
wrowe       01/05/09 21:07:58

  Modified:    .        STATUS
               src      CHANGES
               src/os/win32 util_win32.c
               src/os/os2 util_os2.c
  Log:
    *) Correct a vulnerability in the Win32 and OS2 ports, by which a
       client submitting a carefully constructed URI could cause a GP
       (segment) fault in the child process, which would have to be
       cleared by the operator to resume operation.  This vulnerability
       introduced no identified means to comprimize the server's data.
       Reported by Auriemma Luigi <kaino3@genie.it>.
       [William Rowe, Brian Harvard]
  
  PR:  7522
  
  Revision  Changes    Path
  1.936     +12 -19    apache-1.3/STATUS
  
  Index: STATUS
  ===================================================================
  RCS file: /home/cvs/apache-1.3/STATUS,v
  retrieving revision 1.935
  retrieving revision 1.936
  diff -u -r1.935 -r1.936
  --- STATUS	2001/04/02 09:22:02	1.935
  +++ STATUS	2001/05/10 04:07:54	1.936
  @@ -1,9 +1,10 @@
   APACHE 1.3 STATUS:						-*-text-*-
  -  Last modified at [$Date: 2001/04/02 09:22:02 $]
  +  Last modified at [$Date: 2001/05/10 04:07:54 $]
   
   Release:
   
  -   1.3.20-dev: Current version.
  +   1.3.20: In development - security exploit demands a release ASAP.
  +           Will offers to RM, tag and roll 5/10 9:00pm PST.
      1.3.19: Tagged and rolled Feb 26, 2001. Announced Mar 01, 2001.
      1.3.18: Not released.
                (Pulled because of an incorrect unescaping fix. t/r Feb 19, 2001)
  @@ -255,7 +256,8 @@
         the filename (think win32, or samba-mounted filesystems).  There are
         several PR's to this and I don't see for security reasons why we can't
         accomodate it, though it does add complexity to suexec.c.
  -      Accepting quoted executable names solves that issue.
  +      Accepting quoted executable names solves that issue, except that the
  +      exec cmd="" parsing needs to accept escaped quotes.
         PR #1120
         Brian: +1
         
  @@ -303,24 +305,15 @@
   	- mod_log_referer.c
   	- mod_mime_magic.c (needs access to mod_mime API stage...)
   
  -    * do something to disable bogus warnings
  +    * do something to disable bogus warnings ... Will asks "Which warnings?"
   
       * rfc1413.c has static storage which won't work multithreaded
   
  -    * mod_include --> exec cgi, exec cmd, etc. don't work right.
  -      Looks like a code path that isn't run anywhere else that has
  -      something not quite right...  A PR or two on it.
  -
  -    * Currently if you double click on the conf files or the
  -      log files you get a useless dialog offering the set of all
  -      executables, usually after a very long pause.  Ought
  -      to stuff .conf in the registry mapping it to text.
  -
       * apparently either "BrowserMatch" or the "nokeepalive" variable
         cause instability - see PR#1729.
   
   
  -Binaries (1.3.19):
  +Binaries (1.3.20):
   
    Platform                      Avail.  Volunteer
    ------------------------------------------------------------------------------
  @@ -350,7 +343,7 @@
    i386-unknown-netBSD-1.3.2     no      Lars Eilebrecht, Randy Terbush
    i386-unknown-sco3             no      Ben Laurie
    i386-unknown-sco5             no      Ben Laurie
  - i386-siemens-sinix5.4         yes     Martin Kraemer
  + i386-siemens-sinix5.4         no      Martin Kraemer
    i386-dg-dgux5.4R2.01          no      Randy Terbush
    x86-qnx-4.x                   no      Randy Terbush
    x86-bsdos-3.x                 no      Randy Terbush
  @@ -364,9 +357,9 @@
    mips-sgi-irix5.3              no      Mark Imbrianco, Randy Terbush
    mips-sgi-irix6.2              no      Lars Eilebrecht, Randy Terbush
    mips-sgi-irix6.4              no      Lars Eilebrecht
  - mips-siemens-reliantunix5.4   yes     Martin Kraemer
  - netware                       yes     Brad Nicholes <bnicholes@novell.com>
  - OS/2                          yes     Brian Havard
  + mips-siemens-reliantunix5.4   no      Martin Kraemer
  + netware                       no      Brad Nicholes <bnicholes@novell.com>
  + OS/2                          no      Brian Havard
    OS/390-09.00-02               no                     
    powerpc+i386-apple-darwin1.2  no      Wilfredo Sanchez
    powerpc-apple-rhapsody5.5     no      Wilfredo Sanchez
  @@ -379,4 +372,4 @@
    sparc-sun-solaris2.7          no      Cliff Skolnick
    sparc-sun-sunos4.1.3_U1       no      Sameer Parekh
    sparc-unknown-linux           no      Lars Eilebrecht, Randy Terbush
  - win32                         yes     William Rowe
  + win32                         no      William Rowe
  
  
  
  1.1679    +8 -0      apache-1.3/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/CHANGES,v
  retrieving revision 1.1678
  retrieving revision 1.1679
  diff -u -r1.1678 -r1.1679
  --- CHANGES	2001/05/09 05:17:10	1.1678
  +++ CHANGES	2001/05/10 04:07:55	1.1679
  @@ -1,5 +1,13 @@
   Changes with Apache 1.3.20
   
  +  *) Correct a vulnerability in the Win32 and OS2 ports, by which a 
  +     client submitting a carefully constructed URI could cause a GP
  +     (segment) fault in the child process, which would have to be
  +     cleared by the operator to resume operation.  This vulnerability
  +     introduced no identified means to comprimize the server's data.
  +     Reported by Auriemma Luigi <kaino3@genie.it>.
  +     [William Rowe, Brian Harvard]
  +
     *) Resolve the Win32 SSI exec cmd bug, where cmd was not executed
        appropriately against the shell.  [William Rowe]
   
  
  
  
  1.44      +141 -137  apache-1.3/src/os/win32/util_win32.c
  
  Index: util_win32.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/os/win32/util_win32.c,v
  retrieving revision 1.43
  retrieving revision 1.44
  diff -u -r1.43 -r1.44
  --- util_win32.c	2001/03/28 23:17:37	1.43
  +++ util_win32.c	2001/05/10 04:07:57	1.44
  @@ -83,140 +83,185 @@
       return TRUE;
   }
   
  +
   /* Accepts as input a pathname, and tries to match it to an 
    * existing path and return the pathname in the case that
    * is present on the existing path.  This routine also
    * converts alias names to long names.
  + *
  + * WARNING: Folding to systemcase fails when /path/to/foo/../bar
  + * is given and foo does not exist, is not a directory.
    */
   API_EXPORT(char *) ap_os_systemcase_filename(pool *pPool, 
                                                const char *szFile)
   {
  -    char buf[HUGE_STRING_LEN];
  -    char *pInputName;
  -    char *p, *q, *t;
  +    char *buf, *t, *r;
  +    const char *q, *p;
       BOOL bDone = FALSE;
       BOOL bFileExists = TRUE;
       HANDLE hFind;
       WIN32_FIND_DATA wfd;
  +    size_t buflen;
  +    int slack = 0;
   
  -    if (!szFile || strlen(szFile) == 0 || strlen(szFile) >= sizeof(buf))
  +    if (!szFile || strlen(szFile) == 0)
           return ap_pstrdup(pPool, "");
   
  -    t = buf;
  -    pInputName = ap_pstrdup(pPool, szFile);
  +    buflen = strlen(szFile);
  +    t = buf = ap_palloc(pPool, buflen + 1);
  +    q = szFile;
   
  -    /* First convert all slashes to \ so Win32 calls work OK */
  -    for (p = pInputName; *p; p++) {
  -        if (*p == '/')
  -            *p = '\\';
  -    }
  -    
  -    q = p = pInputName;
       /* If there is drive information, copy it over. */ 
  -    if (pInputName[1] == ':') {
  -        /* This is correct - if systemcase is used for
  +    if (szFile[1] == ':') {
  +        /* Lowercase, so that when systemcase is used for
            * comparison, d: designations will match
  -         */                    
  -        *(t++) = tolower(*p++);
  -        *(t++) = *p++;
  -        q = p;
  -
  -        /* If all we have is a drive letter, then we are done */
  -        if (!*p)
  -            bDone = TRUE;
  -    }    
  -
  -    if (*p == '\\') {
  -        ++p;
  -        if (*p == '\\')  /* UNC name */
  +         */                 
  +        *(t++) = tolower(*(q++));
  +        *(t++) = *(q++);
  +    }
  +    else if ((*q == '/') || (*q == '\\')) {
  +        /* Get past the root path (/ or //foo/bar/) so we can go
  +         * on to normalize individual path elements.
  +         */
  +        *(t++) = '\\', ++q;
  +        if ((*q == '/') || (*q == '\\'))  /* UNC name */
           {
  -            /* Get past the machine name.  FindFirstFile */
  -            /* will not find a machine name only */
  -            *(t++) = '\\';
  -            ++q;
  -            p = strchr(p + 1, '\\'); 
  -            if (p)
  +                /* Lower-case the machine name, so compares match.
  +                 * FindFirstFile won't parse \\machine alone
  +                 */
  +            *(t++) = '\\', ++q;
  +            for (p = q; *p && (*p != '/') && (*p != '\\'); ++p)
  +                /* continue */ ;
  +            if (*p || p > q) 
               {
  -                p++;
  -                /* Get past the share name.  FindFirstFile */
  -                /* will not find a \\machine\share name only */
  -                p = strchr(p, '\\'); 
  -                if (p) {
  -                    /* This was faulty - as of 1.3.13 \\machine\share 
  -                     * name is now always lowercased
  -                     */
  -                    strncpy(t,q,p-q);
  -                    strlwr(t);
  -                    t += p - q;
  -                    q = p;
  -                    p++;
  +                /* Lower-case the machine name, so compares match.
  +                 * FindFirstFile won't parse \\machine\share alone
  +                 */
  +                memcpy(t, q, p - q);
  +                t[p - q] = '\0';
  +                strlwr(t);
  +                t += p - q;
  +                q = p;
  +                if (*p) {
  +                    *(t++) = '\\', ++q;
  +                    for (p = q; *p && (*p != '/') && (*p != '\\'); ++p)
  +                        /* continue */ ;
  +                    if (*p || p > q) 
  +                    {
  +                        /* Copy the lower-cased share name.  FindFirstFile 
  +                         * cannot not find a \\machine\share name only 
  +                         */
  +                        memcpy(t, q, p - q);
  +                        t[p - q] = '\0';
  +                        strlwr(t);
  +                        t += p - q;
  +                        q = p;
  +                        if (*p)
  +                            *(t++) = '\\', ++q;
  +                        else
  +                            bFileExists = FALSE;
  +                    }
  +                    else
  +                        bFileExists = FALSE;
                   }
  +                else
  +                    bFileExists = FALSE;
               }
  -
  -            if (!p) {
  +            else
                   bFileExists = FALSE;
  -                p = q;
  -            }
           }
       }
   
  -    p = strchr(p, '\\');
  +    while (bFileExists) {
   
  -    while (!bDone) {
  -        if (p)
  -            *p = '\0';
  +        /* parse past any leading slashes */
  +        for (; (*q == '/') || (*q == '\\'); ++q)
  +            *(t++) = '\\';
   
  -        if (strchr(q, '*') || strchr(q, '?'))
  -            bFileExists = FALSE;
  +        /* break on end of string */
  +        if (!*q)
  +            break;
  +
  +        /* get to the end of this path segment */
  +        for (p = q; *p && (*p != '/') && (*p != '\\'); ++p)
  +            /* continue */ ;
  +                
  +        /* copy the segment */
  +        memcpy(t, q, p - q);
  +        t[p - q] = '\0';
  +
  +        /* Test for nasties that can exhibit undesired effects */
  +        if (strpbrk(t, "?\"<>*|:")) {
  +            t += p - q;
  +            q = p;
  +            break;
  +        }
   
           /* If the path exists so far, call FindFirstFile
            * again.  However, if this portion of the path contains
            * only '.' charaters, skip the call to FindFirstFile
            * since it will convert '.' and '..' to actual names.
  -         * Note: in the call to OnlyDots, we may have to skip
  -         *       a leading slash.
  +         * On win32, '...' is an alias for '..', so we gain 
  +         * a bit of slack.
            */
  -        if (bFileExists && !OnlyDots((*q == '.' ? q : q+1))) {            
  -            hFind = FindFirstFile(pInputName, &wfd);
  -            
  -            if (hFind == INVALID_HANDLE_VALUE) {
  -                bFileExists = FALSE;
  +        if (*t == '.' && OnlyDots(t)) {
  +            if (p - q == 3) {
  +                t += 2;
  +                q = p;
  +                ++slack;
               }
               else {
  -                FindClose(hFind);
  -
  -                if (*q == '\\')
  -                    *(t++) = '\\';
  -                t = strchr(strcpy(t, wfd.cFileName), '\0');
  +                t += p - q;
  +                q = p;
               }
  +            /* Paths of 4 dots or more are invalid */
  +            if (p - q > 3)
  +                break;
           }
  -        
  -        if (!bFileExists || OnlyDots((*q == '.' ? q : q+1))) {
  -            /* XXX: Comparison could be faulty ...\unknown
  -             * names may not match!
  -             */
  -            strcpy(t, q);
  -            t = strchr(t, '\0');
  -        }
  -        
  -        if (p) {
  -            q = p;
  -            *p++ = '\\';
  -            p = strchr(p, '\\');
  -        }
           else {
  -            bDone = TRUE;
  +            if ((hFind = FindFirstFile(buf, &wfd)) == INVALID_HANDLE_VALUE) {
  +                t += p - q;
  +                q = p;
  +                break;
  +            }
  +            else {
  +                size_t fnlen = strlen(wfd.cFileName);
  +                FindClose(hFind);
  +                /* the string length just changed, could have shrunk
  +                 * (trailing spaces or dots) or could have grown 
  +                 * (longer filename aliases).  Realloc as necessary
  +                 */
  +                slack -= fnlen - (p - q);
  +                if (slack < 0) {
  +                    char *n;
  +                    slack += buflen + fnlen - (p - q);
  +                    buflen += buflen + fnlen - (p - q);
  +                    n = ap_palloc(pPool, buflen + 1);
  +                    memcpy (n, buf, t - buf);
  +                    t = n + (t - buf);
  +                    buf = n;
  +                }
  +                memcpy(t, wfd.cFileName, fnlen);
  +                t += fnlen;
  +                q = p;
  +                if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  +                    break;
  +            }
           }
       }
  -    *t = '\0';
  -    
  -    /* Finally, convert all slashes to / so server code handles it ok */
  -    for (p = buf; *p; p++) {
  -        if (*p == '\\')
  -            *p = '/';
  +
  +    /* Convert all parsed '\'s to '/' for canonical form (doesn't touch
  +     * the non-existant portion of the path whatsoever.)
  +     */
  +    for (r = buf; r < t; ++r) {
  +        if (*r == '\\')
  +            *r = '/';
       }
   
  -    return ap_pstrdup(pPool, buf);
  +    /* Copy the non-existant portion (minimally nul-terminates the string) */
  +    strcpy(t, q);
  +    
  +    return buf;
   }
   
   
  @@ -293,56 +338,15 @@
        *  simply truncated, with no embedded '~'.  Further, this behavior
        *  can be modified on WinNT volumes.  This was not a safe test,
        *  therefore exclude the '~' pretest.
  -     */     
  +     */
   #ifdef WIN32_SHORT_FILENAME_INSECURE_BEHAVIOR
        p = strchr(pNewStr, '~');
        if (p != NULL)
   #endif
  -     {
  -        char *pConvertedName, *pQstr, *pPstr;
  -        char buf[HUGE_STRING_LEN];
  -        /* We potentially have a short name.  Call 
  -         * ap_os_systemcase_filename to examine the filesystem
  -         * and possibly extract the long name.
  -         */
  -        pConvertedName = ap_os_systemcase_filename(pPool, pNewStr);
  -
  -        /* Since we want to preserve the incoming case as much
  -         * as we can, compare for differences in the string and
  -         * only substitute in the path names that changed.
  -         */
  -        if (stricmp(pNewStr, pConvertedName)) {
  -            buf[0] = '\0';
  -
  -            q = pQstr = pConvertedName;
  -            p = pPstr = pNewStr;
  -            do {
  -                q = strchr(q,'/');
  -                p = strchr(p,'/');
  -
  -                if (p != NULL) {
  -                    *q = '\0';
  -                    *p = '\0';
  -                }
  -
  -                if (stricmp(pQstr, pPstr)) 
  -                    strcat(buf, pQstr);   /* Converted name */
  -                else 
  -                    strcat(buf, pPstr);   /* Original name  */
  -
  -
  -                if (p != NULL) {
  -                    pQstr = q;
  -                    pPstr = p;
  -                    *q++ = '/';
  -                    *p++ = '/';
  -                }
  -
  -            } while (p != NULL); 
  -
  -            pNewStr = ap_pstrdup(pPool, buf);
  -        }
  -    }
  +    /* ap_os_systemcase_filename now changes the case of only
  +     * the pathname elements that are found.
  +     */
  +        pNewStr = ap_os_systemcase_filename(pPool, pNewStr);
   
       return pNewStr;
   }
  
  
  
  1.11      +5 -5      apache-1.3/src/os/os2/util_os2.c
  
  Index: util_os2.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/os/os2/util_os2.c,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- util_os2.c	2000/11/04 07:36:21	1.10
  +++ util_os2.c	2001/05/10 04:07:57	1.11
  @@ -7,14 +7,14 @@
   
   API_EXPORT(char *)ap_os_case_canonical_filename(pool *pPool, const char *szFile)
   {
  -    char buf[HUGE_STRING_LEN];
  -    char buf2[HUGE_STRING_LEN];
  +    char *buf;
  +    char buf2[CCHMAXPATH];
       int rc, len; 
       char *pos;
       
   /* Remove trailing slash unless it's a root directory */
  -    strcpy(buf, szFile);
  -    len = strlen(buf);
  +    len = strlen(szFile);
  +    buf = ap_pstrndup(pPool, szFile, len);
       
       if (len > 3 && buf[len-1] == '/')
           buf[--len] = 0;
  @@ -26,7 +26,7 @@
           }
       }
   
  -    rc = DosQueryPathInfo(buf, FIL_QUERYFULLNAME, buf2, HUGE_STRING_LEN);
  +    rc = DosQueryPathInfo(buf, FIL_QUERYFULLNAME, buf2, sizeof(buf2));
   
       if (rc) {
           if ( rc != ERROR_INVALID_NAME ) {
  
  
  

Mime
View raw message