summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/util.c
diff options
context:
space:
mode:
authorNoriko Hosoi <nhosoi@redhat.com>2006-01-10 23:53:08 +0000
committerNoriko Hosoi <nhosoi@redhat.com>2006-01-10 23:53:08 +0000
commit67385d898398f60886047b9239d027cf997f9433 (patch)
treec7f9daeed093bdef2afa6f809c13cdfb457a94c7 /ldap/servers/slapd/util.c
parent4120eda907e600d7d4b7c3b54e747db8284b4037 (diff)
downloadds-67385d898398f60886047b9239d027cf997f9433.tar.gz
ds-67385d898398f60886047b9239d027cf997f9433.tar.xz
ds-67385d898398f60886047b9239d027cf997f9433.zip
[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.
Diffstat (limited to 'ldap/servers/slapd/util.c')
-rw-r--r--ldap/servers/slapd/util.c159
1 files changed, 123 insertions, 36 deletions
diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c
index a129c6cc..a531e94c 100644
--- a/ldap/servers/slapd/util.c
+++ b/ldap/servers/slapd/util.c
@@ -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 @@ is_abspath(const char *path)
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 @@ rel2abspath( char *relpath )
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 @@ rel2abspath( char *relpath )
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 @@ slapd_chown_if_not_owner(const char *filename, uid_t uid, gid_t gid)
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;
+}