Make symlink protection a bit more useful:

* Remove terminal symlinks so they can be replaced.
  * If -U, remove intermediate symlinks as well
  * Otherwise, refuse the extraction
This commit is contained in:
Tim Kientzle 2004-05-17 03:33:06 +00:00
parent dcec34670d
commit 4a07f42b98
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=129314
3 changed files with 17 additions and 4 deletions

View File

@ -285,6 +285,7 @@ main(int argc, char **argv)
break;
case 'U': /* GNU tar */
bsdtar->extract_flags |= ARCHIVE_EXTRACT_UNLINK;
bsdtar->option_unlink_first = 1;
break;
case 'u': /* SUSv2 */
if (mode != '\0')

View File

@ -58,6 +58,7 @@ struct bsdtar {
char option_interactive; /* -w */
char option_no_subdirs; /* -d */
char option_stdout; /* -p */
char option_unlink_first; /* -U */
char option_warn_links; /* -l */
/* If >= 0, then close this when done. */

View File

@ -335,7 +335,9 @@ security_problem(struct bsdtar *bsdtar, struct archive_entry *entry)
* Gaurd against symlink tricks. Reject any archive entry whose
* destination would be altered by a symlink.
*/
/* XXX TODO: Make this faster!!! XXX */
/* XXX TODO: Make this faster by comparing current path to
* prefix of last successful check to avoid duplicate lstat()
* calls. XXX */
pn = name;
if (bsdtar->security == NULL) {
bsdtar->security = malloc(sizeof(*bsdtar->security));
@ -359,9 +361,18 @@ security_problem(struct bsdtar *bsdtar, struct archive_entry *entry)
if (errno == ENOENT)
break;
} else if (S_ISLNK(st.st_mode)) {
bsdtar_warnc(0,"Cannot extract %s through symlink %s",
name, bsdtar->security->path);
return (1);
if (*pn == '\0') {
/* Last element is symlink; just remove it. */
unlink(bsdtar->security->path);
} else if (bsdtar->option_unlink_first) {
/* User asked us to remove problems. */
unlink(bsdtar->security->path);
} else {
bsdtar_warnc(0,
"Cannot extract %s through symlink %s",
name, bsdtar->security->path);
return (1);
}
}
}