version 1.24, 2001/06/23 00:20:57 |
version 1.25, 2001/06/25 17:54:48 |
|
|
* Returns 0 on success and -1 on failure |
* Returns 0 on success and -1 on failure |
*/ |
*/ |
int |
int |
secure_filename(FILE *f, const char *file, uid_t uid, char *err, size_t errlen) |
secure_filename(FILE *f, const char *file, struct passwd *pw, |
|
char *err, size_t errlen) |
{ |
{ |
|
uid_t uid = pw->pw_uid; |
|
char homedir[MAXPATHLEN]; |
char buf[MAXPATHLEN]; |
char buf[MAXPATHLEN]; |
char *cp; |
char *cp; |
struct stat st; |
struct stat st; |
|
|
|
strlcpy(homedir, dirname(pw->pw_dir), sizeof(homedir)); |
|
|
if (realpath(file, buf) == NULL) { |
if (realpath(file, buf) == NULL) { |
snprintf(err, errlen, "realpath %s failed: %s", file, |
snprintf(err, errlen, "realpath %s failed: %s", file, |
strerror(errno)); |
strerror(errno)); |
|
|
return -1; |
return -1; |
} |
} |
|
|
|
debug3("secure_filename: terminating check at '%s'", homedir); |
|
|
/* for each component of the canonical path, walking upwards */ |
/* for each component of the canonical path, walking upwards */ |
for (;;) { |
for (;;) { |
if ((cp = dirname(buf)) == NULL) { |
if ((cp = dirname(buf)) == NULL) { |
|
|
return -1; |
return -1; |
} |
} |
strlcpy(buf, cp, sizeof(buf)); |
strlcpy(buf, cp, sizeof(buf)); |
|
|
|
/* If are passed the homedir then we can stop */ |
|
if (strcmp(buf, homedir) == 0) |
|
break; |
|
|
debug3("secure_filename: checking '%s'", buf); |
debug3("secure_filename: checking '%s'", buf); |
if (stat(buf, &st) < 0 || |
if (stat(buf, &st) < 0 || |