httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "William A. Rowe, Jr." <wr...@rowe-clan.net>
Subject RE: cvs commit: apache-1.3/src/os/netware os.c os.h
Date Thu, 19 Oct 2000 04:22:48 GMT
I've committed since it touches no common code, but please read 
inline comments.

> wrowe       00/10/18 21:02:57
> 
>   Modified:    src/include httpd.h
>                src/os/netware os.c os.h
>   Log:
>     Fix Netware hole of case sensitivity.  All canonical names are now in
>     lowercase.  This patch requires further work to return systemcase names,
>     if the NW user expects certain Java and related applications to function
>     properly (at least I recall FirstBill fixed a similar issue in Win32).
>   
>   PR:             Several, no doubt, I'll chase them down tonight
>   Obtained from:  <s9ed730e.016@prv-mail20.provo.novell.com>
>   Submitted by:	Brad Nicholes <BNICHOLES@novell.com>
>   Reviewed by:	William Rowe
>   
>   Revision  Changes    Path
>   1.324     +0 -2      apache-1.3/src/include/httpd.h
>   
>   Index: httpd.h
>   ===================================================================
>   RCS file: /home/cvs/apache-1.3/src/include/httpd.h,v
>   retrieving revision 1.323
>   retrieving revision 1.324
>   diff -u -r1.323 -r1.324
>   --- httpd.h	2000/10/10 20:17:40	1.323
>   +++ httpd.h	2000/10/19 04:02:56	1.324
>   @@ -1111,8 +1111,6 @@
>    API_EXPORT(char *) ap_os_case_canonical_filename(pool 
> *pPool, const char *szFile);
>    API_EXPORT(char *) ap_os_systemcase_filename(pool *pPool, 
> const char *szFile);
>    #else
>   -/* XXX: This makes little sense for NETWARE ... NETWARE is 
> case insensitive?
>   - */
>    #define ap_os_case_canonical_filename(p,f) 
> ap_os_canonical_filename(p,f)
>    #define ap_os_systemcase_filename(p,f) 
> ap_os_canonical_filename(p,f)

These last two are a little dicey, and 2.0 will make more sense.
Let me explain from the Win32 perspective:

ap_os_canonical_filename should fix up the vol:/filespec elements,
if there are \'s convert to /'s (Netware doesn't care, correct?)
and right-format the path, but it doesn't change the request case.
Don't ask why, not even we know :-/  In OS2 it's fullpathed, but 
that's dicey for its own reasons.  Some possible local problems,
perhaps there is an issue with ... being a legit .. specification
(an easy hole to walk through), perhaps some spaces can be mixed
for underscores (I'm reaching here), or whatever could allow the
admin to misconfigure, or the user to walk around multiple 
equivilant file paths.

ap_os_case_canonical_filename is the final step of what you have
already submitted, bravo!  Move the force lowercase to this call
alone and you are near done.  Looking at your patch, ap_os_canonical
wasn't needed at all, but I suspect you will discover some case you
want to protect.

ap_os_systemcase_filename takes things one step further.  Find the
most sophisticated stat (or do a dir) for the each segment of the
path, and fix each segment to its true path.  Some applications
will expect the real path, so this is where it's retrieved.

This all is entirely inefficient, and as you start on APR for 2.0,
you will discover next week there is a 'new way' of dealing with
the chaos.  You probably choose even better than Win32/OS2, but
I know we had specific reasons one day for doing it as implemented.

>    #endif
>   
>   
>   
>   1.4       +157 -0    apache-1.3/src/os/netware/os.c
>   
>   Index: os.c
>   ===================================================================
>   RCS file: /home/cvs/apache-1.3/src/os/netware/os.c,v
>   retrieving revision 1.3
>   retrieving revision 1.4
>   diff -u -r1.3 -r1.4
>   --- os.c	2000/06/01 23:42:31	1.3
>   +++ os.c	2000/10/19 04:02:57	1.4
>   @@ -55,6 +55,7 @@
>     *
>     */
>    
>   +#include "httpd.h"
>    #include "ap_config.h"
>    #include <dirent.h>
>    
>   @@ -129,4 +130,160 @@
>        UnAugmentAsterisk(TRUE);
>        SetCurrentNameSpace(NW_NS_LONG);
>        SetTargetNameSpace(NW_NS_LONG);
>   +}
>   +
>   +/*  Perform complete canonicalization.  On NetWare we are just
>   +	lower casing the file name so that the comparisons will match.
>   +	NetWare assumes that all physical paths are fully qualified.  
>   +	Each file path must include a volume name.
>   + */
>   +char *ap_os_canonical_filename(pool *pPool, const char *szFile)
>   +{
>   +    char *pNewName;
>   +    
>   +    pNewName = ap_pstrdup(pPool, szFile);
>   +    strlwr(pNewName);
>   +    return pNewName;
>   +}
>   +
>   +/*
>   + * ap_os_is_filename_valid is given a filename, and 
> returns 0 if the filename
>   + * is not valid for use on this system. On NetWare, this 
> means it fails any
>   + * of the tests below. Otherwise returns 1.
>   + *
>   + * The tests are:
>   + *
>   + * 1) total path length greater than MAX_PATH
>   + * 
>   + * 2) the file path must contain a volume specifier and no / or \
>   + *     can appear before the volume specifier.
>   + *
>   + * 3) anything using the octets 0-31 or characters " < > | :
>   + *    (these are reserved for Windows use in filenames. In addition
>   + *     each file system has its own additional characters that are
>   + *     invalid. See KB article Q100108 for more details).
>   + *
>   + * 4) anything ending in "." (no matter how many)
>   + *    (filename doc, doc. and doc... all refer to the same file)
>   + *
>   + * 5) any segment in which the basename (before first 
> period) matches
>   + *    one of the DOS device names
>   + *    (the list comes from KB article Q100108 although some people
>   + *     reports that additional names such as "COM5" are 
> also special
>   + *     devices).
>   + *
>   + * If the path fails ANY of these tests, the result must 
> be to deny access.
>   + */
>   +
>   +int ap_os_is_filename_valid(const char *file)
>   +{
>   +    const char *segstart;
>   +    unsigned int seglength;
>   +    const char *pos;
>   +	char *colonpos, *fslashpos, *bslashpos;
>   +    static const char * const invalid_characters = "?\"<>*|:";
>   +    static const char * const invalid_filenames[] = { 
>   +		"CON", "AUX", "COM1", "COM2", "COM3", 
>   +		"COM4", "LPT1", "LPT2", "LPT3", "PRN", "NUL", NULL 

is this the real netware list (out of curiousity)?

>   +    };
>   +
>   +	// First check to make sure that we have a file so that 
> we don't abend
>   +	if (file == NULL)
>   +		return 0;
>   +
>   +    /* Test 1 */
>   +    if (strlen(file) >= _MAX_PATH) {

Is there a _MAX_PATH?  Careful here, we fell in dodo before, if
stat can succeed and is_filename_valid fails or visa-versa.

>   +		/* Path too long for Windows. Note that this 
> test is not valid
>   +		 * if the path starts with //?/ or \\?\. */
>   +		return 0;
>   +    }
>   +
>   +    pos = file;
>   +
>   +    /* Skip any leading non-path components. This can be either a
>   +     * drive letter such as C:, or a UNC path such as 
> \\SERVER\SHARE\.
>   +     * We continue and check the rest of the path based on 
> the rules above.
>   +     * This means we could eliminate valid filenames from 
> servers which
>   +     * are not running NT (such as Samba).
>   +     */

If you actually have UNC paths, great, otherwise a 'comments cleanup'
patch is probably appropriate by now (against the new nightly tarball
or your now-current own copy).

>   +
>   +	colonpos = strchr (file, ':');
>   +	fslashpos = strchr (file, '/');
>   +	bslashpos = strchr (file, '\\');
>   +
>   +	// The path must contain a volume specifier and the volume
>   +	//  specifier must appear before in slashes.
>   +	if (colonpos) {
>   +		// If a slash appears before the colon then the path
>   +		//  is invalid until we support remotes server file
>   +		//  access
>   +		if (fslashpos && (fslashpos < colonpos))
>   +			return 0;
>   +		if (bslashpos && (bslashpos < colonpos))
>   +			return 0;
>   +	}
>   +	else {
>   +		return 0;
>   +	}

Do you also want to test that a slash follows that colon?  I was
under the impression that VOL1:bleck could be the subdir bleck of
the current path of VOL1.


>   +	pos = ++colonpos;
>   +   	if (!*pos) {
>   +		/* No path information */
>   +		return 0;
>   +    }
>   +
>   +    while (*pos) {
>   +		unsigned int idx;
>   +		unsigned int baselength;
>   +
>   +		while (*pos == '/' || *pos == '\\') {
>   +    	    pos++;
>   +		}
>   +		if (*pos == '\0') {
>   +		    break;
>   +		}
>   +		segstart = pos;	/* start of segment */
>   +		while (*pos && *pos != '/' && *pos != '\\') {
>   +		    pos++;
>   +		}
>   +		seglength = pos - segstart;
>   +		/* 
>   +		 * Now we have a segment of the path, starting 
> at position "segstart"
>   +		 * and length "seglength"
>   +		 */
>   +
>   +		/* Test 2 */
>   +		for (idx = 0; idx < seglength; idx++) {
>   +	    	if ((segstart[idx] > 0 && segstart[idx] < 32) ||
>   +				strchr(invalid_characters, 
> segstart[idx])) {
>   +				return 0;
>   +	    	}
>   +		}
>   +
>   +		/* Test 3 */
>   +		if (segstart[seglength-1] == '.') {
>   +		    return 0;
>   +		}
>   +
>   +		/* Test 4 */
>   +		for (baselength = 0; baselength < seglength; 
> baselength++) {
>   +		    if (segstart[baselength] == '.') {
>   +				break;
>   +		    }
>   +		}
>   +
>   +		/* baselength is the number of characters in 
> the base path of
>   +		 * the segment (which could be the same as the 
> whole segment length,
>   +		 * if it does not include any dot characters). */
>   +		if (baselength == 3 || baselength == 4) {
>   +	    	for (idx = 0; invalid_filenames[idx]; idx++) {
>   +				if 
> (strlen(invalid_filenames[idx]) == baselength &&
>   +				    
> !strnicmp(invalid_filenames[idx], segstart, baselength)) {
>   +				    return 0;
>   +				}
>   +	    	}
>   +		}
>   +    }
>   +
>   +    return 1;
>    }
>   
>   
>   
>   1.6       +2 -1      apache-1.3/src/os/netware/os.h
>   
>   Index: os.h
>   ===================================================================
>   RCS file: /home/cvs/apache-1.3/src/os/netware/os.h,v
>   retrieving revision 1.5
>   retrieving revision 1.6
>   diff -u -r1.5 -r1.6
>   --- os.h	2000/10/10 12:24:11	1.5
>   +++ os.h	2000/10/19 04:02:57	1.6
>   @@ -59,6 +59,7 @@
>    #define APACHE_OS_H
>    
>    #define PLATFORM "NETWARE"
>   +#define HAVE_CANONICAL_FILENAME
>    
>    /*
>     * This file in included in all Apache source code. It 
> contains definitions
>   @@ -113,7 +114,6 @@
>    /* Netware doesn't have symlinks so S_ISLNK is always false */
>    #define S_ISLNK(m) 0
>    #define lstat(x, y) stat(x, y)
>   -#define ap_os_is_filename_valid(f)          (1)
>    #define strcasecmp(s1, s2) stricmp(s1, s2)
>    #define strncasecmp(s1, s2, n) strnicmp(s1, s2, n)
>    #define mktemp(s) tmpnam(s)
>   @@ -142,5 +142,6 @@
>    char *remove_filename(char*);
>    char *bslash2slash(char*);
>    void init_name_space(void);
>   +int ap_os_is_filename_valid(const char *file);
>    #endif /*! APACHE_OS_H*/

Great work here... and thanks from any NetWare users out there.

Mime
View raw message