Author: nhosoi
Update of /cvs/dirsec/ldapserver/ldap/servers/slapd In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv4197
Modified Files: proto-slap.h util.c Log Message: [174776] Multiple restores from a non-existant directory could wipe out database If the specified backup dir does not exist, does not contain necessary files (including the directory is not accessible), is not a directory, or is identical to the path to the db dir, issues an error and stops restoring before wiping out the database.
Index: proto-slap.h =================================================================== RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/proto-slap.h,v retrieving revision 1.13 retrieving revision 1.14 diff -u -r1.13 -r1.14 --- proto-slap.h 3 Dec 2005 01:45:34 -0000 1.13 +++ proto-slap.h 10 Jan 2006 23:53:02 -0000 1.14 @@ -589,6 +589,8 @@ void slapd_nasty(char* str, int c, int err); int strarray2str( char **a, char *buf, size_t buflen, int include_quotes ); int slapd_chown_if_not_owner(const char *filename, uid_t uid, gid_t gid); +int slapd_comp_path(char *p0, char *p1); +
/* * modify.c
Index: util.c =================================================================== RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/util.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- util.c 23 Nov 2005 17:58:01 -0000 1.7 +++ util.c 10 Jan 2006 23:53:02 -0000 1.8 @@ -44,6 +44,7 @@ #include <unistd.h> #include <pwd.h> #endif +#include <libgen.h> #include <pk11func.h> #include "slap.h" #include "prtime.h" @@ -53,6 +54,14 @@ #define UTIL_ESCAPE_HEX 1 #define UTIL_ESCAPE_BACKSLASH 2
+#if defined( _WIN32 ) +#define _PSEP "\" +#define _CSEP '\' +#else +#define _PSEP "/" +#define _CSEP '/' +#endif + static int special_np(unsigned char c) { if(c < 32 || c > 126) { @@ -383,6 +392,60 @@ return 0; /* not an abs path */ }
+static void +clean_path(char **norm_path) +{ + char **np; + + for (np = norm_path; np && *np; np++) + slapi_ch_free((void **)np); + slapi_ch_free((void **)&norm_path); +} + +static char ** +normalize_path(char *path) +{ + char *dname = slapi_ch_strdup(path); + char *dnamep = dname; + char *bnamep = NULL; + char **dirs = (char **)slapi_ch_calloc(strlen(path), 1); + char **rdirs = (char **)slapi_ch_calloc(strlen(path), 1); + char **dp = dirs; + char **rdp; + do { + bnamep = basename(dnamep); + if (0 != strcmp(bnamep, ".")) { + *dp++ = slapi_ch_strdup(bnamep); /* remove "/./" in the path */ + } + dnamep = dirname(dnamep); + } while (strcmp(dnamep, _PSEP) && + !(0 == strcmp(dnamep, ".") && 0 == strcmp(bnamep, "."))); + + /* remove "xxx/.." in the path */ + for (dp = dirs, rdp = rdirs; dp && *dp; dp++) { + while (*dp && 0 == strcmp(*dp, "..")) { + dp++; + if (rdp > rdirs) + rdp--; + } + if (*dp) + *rdp++ = slapi_ch_strdup(*dp); + } + for (--dp, rdp = rdirs; dp >= dirs; dp--) { + while (*dp && 0 == strcmp(*dp, "..")) { + dp--; + if (rdp > rdirs) + rdp--; + } + if (*dp) + *rdp++ = slapi_ch_strdup(*dp); + } + + clean_path(dirs); + slapi_ch_free_string(&dname); + + return rdirs; +}
/* * Take "relpath" and prepend the current working directory to it @@ -399,13 +462,10 @@ CHAR szDir[_MAX_DIR]; CHAR szFname[_MAX_FNAME]; CHAR szExt[_MAX_EXT]; -#define _PSEP "\" -#else -#define _PSEP "/" #endif
if ( relpath == NULL ) { - return NULL; + return NULL; }
#if defined( _WIN32 ) @@ -413,41 +473,51 @@ memset (&szDir, 0, sizeof (szDir)); memset (&szFname, 0, sizeof (szFname)); memset (&szExt, 0, sizeof (szExt)); - _splitpath( relpath, szDrive, szDir, szFname, szExt ); - if( szDrive[0] && szDir[0] ) - return( slapi_ch_strdup( relpath )); - if ( relpath[ 0 ] == '/' || relpath[ 0 ] == '\' ) { - return( slapi_ch_strdup( relpath )); -#else - if ( relpath[ 0 ] == '/' ) { - return( slapi_ch_strdup( relpath )); - } + _splitpath( relpath, szDrive, szDir, szFname, szExt ); + if( szDrive[0] && szDir[0] ) + return( slapi_ch_strdup( relpath )); #endif - - if ( getcwd( abspath, MAXPATHLEN ) == NULL ) { - perror( "getcwd" ); - LDAPDebug( LDAP_DEBUG_ANY, "Cannot determine current directory\n", - 0, 0, 0 ); - exit( 1 ); - } - - if ( strlen( relpath ) + strlen( abspath ) + 1 > MAXPATHLEN ) { - LDAPDebug( LDAP_DEBUG_ANY, "Pathname "%s" _PSEP "%s" too long\n", - abspath, relpath, 0 ); - exit( 1 ); + if ( relpath[ 0 ] == _CSEP ) { /* absolute path */ + PR_snprintf(abspath, sizeof(abspath), "%s", relpath); + } else { /* relative path */ + if ( getcwd( abspath, MAXPATHLEN ) == NULL ) { + perror( "getcwd" ); + LDAPDebug( LDAP_DEBUG_ANY, "Cannot determine current directory\n", + 0, 0, 0 ); + exit( 1 ); + } + + if ( strlen( relpath ) + strlen( abspath ) + 1 > MAXPATHLEN ) { + LDAPDebug( LDAP_DEBUG_ANY, "Pathname "%s" _PSEP "%s" too long\n", + abspath, relpath, 0 ); + exit( 1 ); + } + + if ( strcmp( relpath, "." )) { + if ( abspath[ 0 ] != '\0' && + abspath[ strlen( abspath ) - 1 ] != _CSEP ) + { + PL_strcatn( abspath, sizeof(abspath), "/" ); + } + PL_strcatn( abspath, sizeof(abspath), relpath ); + } } - - if ( strcmp( relpath, "." )) { -#if defined( _WIN32 ) - if ( abspath[ 0 ] != '\0' && abspath[ strlen( abspath ) - 1 ] != '/' && abspath[ strlen( abspath ) - 1 ] != '\' ) -#else - if ( abspath[ 0 ] != '\0' && abspath[ strlen( abspath ) - 1 ] != '/' ) { -#endif - PL_strcatn( abspath, sizeof(abspath), "/" ); - } - PL_strcatn( abspath, sizeof(abspath), relpath ); + { + char **norm_path = normalize_path(abspath); + char *retpath = slapi_ch_strdup(abspath); /* size is long enough */ + char **np, *rp; + int pathlen = strlen(abspath) + 1; + int usedlen = 0; + for (np = norm_path, rp = retpath; np && *np; np++) { + int thislen = strlen(*np) + 1; + if (0 != strcmp(*np, _PSEP)) + PR_snprintf(rp, pathlen - usedlen, "%c%s", _CSEP, *np); + rp += thislen; + usedlen += thislen; + } + clean_path(norm_path); + return retpath; } - return( slapi_ch_strdup( abspath )); }
@@ -658,3 +728,20 @@ return result; }
+/* + * Compare 2 pathes + * Paths could contain ".", "..", "//" in the path, thus normalize them first. + * One or two of the paths could be a relative path. + */ +int +slapd_comp_path(char *p0, char *p1) +{ + int rval = 0; + char *norm_p0 = rel2abspath(p0); + char *norm_p1 = rel2abspath(p1); + + rval = strcmp(norm_p0, norm_p1); + slapi_ch_free_string(&norm_p0); + slapi_ch_free_string(&norm_p1); + return rval; +}