PR/18663: Jeremy Reed: pax/tar/cpio allows ".." in names.
We now disallow it by default on both archive creation and extraction. Add --insecure option to override.
This commit is contained in:
parent
a2e26d6e11
commit
ca541391bc
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: extern.h,v 1.32 2002/10/13 00:34:16 mrg Exp $ */
|
||||
/* $NetBSD: extern.h,v 1.33 2002/10/15 16:16:29 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
@ -56,6 +56,7 @@ extern time_t starttime;
|
||||
extern int force_one_volume;
|
||||
extern char *chdname;
|
||||
extern int forcelocal;
|
||||
extern int secure;
|
||||
|
||||
int ar_open(const char *);
|
||||
void ar_close(void);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: options.c,v 1.46 2002/10/15 14:58:53 christos Exp $ */
|
||||
/* $NetBSD: options.c,v 1.47 2002/10/15 16:16:29 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
@ -42,7 +42,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 4/18/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: options.c,v 1.46 2002/10/15 14:58:53 christos Exp $");
|
||||
__RCSID("$NetBSD: options.c,v 1.47 2002/10/15 16:16:29 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -98,6 +98,25 @@ static int getline_error;
|
||||
#define GZIP_CMD "gzip" /* command to run as gzip */
|
||||
#define COMPRESS_CMD "compress" /* command to run as compress */
|
||||
|
||||
/*
|
||||
* Long options.
|
||||
*/
|
||||
#define OPT_USE_COMPRESS_PROGRAM 0
|
||||
#define OPT_CHECKPOINT 1
|
||||
#define OPT_UNLINK 2
|
||||
#define OPT_HELP 3
|
||||
#define OPT_ATIME_PRESERVE 4
|
||||
#define OPT_IGNORE_FAILED_READ 5
|
||||
#define OPT_REMOVE_FILES 6
|
||||
#define OPT_NULL 7
|
||||
#define OPT_TOTALS 8
|
||||
#define OPT_VERSION 9
|
||||
#define OPT_EXCLUDE 10
|
||||
#define OPT_BLOCK_COMPRESS 11
|
||||
#define OPT_NORECURSE 12
|
||||
#define OPT_FORCE_LOCAL 13
|
||||
#define OPT_INSECURE 14
|
||||
|
||||
/*
|
||||
* Format specific routine table - MUST BE IN SORTED ORDER BY NAME
|
||||
* (see pax.h for description of each function)
|
||||
@ -181,6 +200,11 @@ options(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
struct option pax_longopts[] = {
|
||||
{ "insecure", no_argument, 0,
|
||||
OPT_INSECURE },
|
||||
};
|
||||
|
||||
/*
|
||||
* pax_options()
|
||||
* look at the user specified flags. set globals as required and check if
|
||||
@ -200,8 +224,9 @@ pax_options(int argc, char **argv)
|
||||
/*
|
||||
* process option flags
|
||||
*/
|
||||
while ((c = getopt(argc, argv,
|
||||
"ab:cdf:iklno:p:rs:tuvwx:zAB:DE:G:HLMN:OPT:U:XYZ")) != -1) {
|
||||
while ((c = getopt_long(argc, argv,
|
||||
"ab:cdf:iklno:p:rs:tuvwx:zAB:DE:G:HLMN:OPT:U:XYZ",
|
||||
pax_longopts, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
/*
|
||||
@ -555,6 +580,9 @@ pax_options(int argc, char **argv)
|
||||
Zflag = 1;
|
||||
flg |= CZF;
|
||||
break;
|
||||
case OPT_INSECURE:
|
||||
secure = 0;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
pax_usage();
|
||||
@ -638,21 +666,6 @@ pax_options(int argc, char **argv)
|
||||
* the user specified a legal set of flags. If not, complain and exit
|
||||
*/
|
||||
|
||||
#define OPT_USE_COMPRESS_PROGRAM 0
|
||||
#define OPT_CHECKPOINT 1
|
||||
#define OPT_UNLINK 2
|
||||
#define OPT_HELP 3
|
||||
#define OPT_ATIME_PRESERVE 4
|
||||
#define OPT_IGNORE_FAILED_READ 5
|
||||
#define OPT_REMOVE_FILES 6
|
||||
#define OPT_NULL 7
|
||||
#define OPT_TOTALS 8
|
||||
#define OPT_VERSION 9
|
||||
#define OPT_EXCLUDE 10
|
||||
#define OPT_BLOCK_COMPRESS 11
|
||||
#define OPT_NORECURSE 12
|
||||
#define OPT_FORCE_LOCAL 13
|
||||
|
||||
struct option tar_longopts[] = {
|
||||
{ "block-size", required_argument, 0, 'b' },
|
||||
{ "create", no_argument, 0, 'c' }, /* F */
|
||||
@ -693,6 +706,8 @@ struct option tar_longopts[] = {
|
||||
OPT_USE_COMPRESS_PROGRAM },
|
||||
{ "force-local", no_argument, 0,
|
||||
OPT_FORCE_LOCAL },
|
||||
{ "insecure", no_argument, 0,
|
||||
OPT_INSECURE },
|
||||
#if 0 /* Not implemented */
|
||||
{ "catenate", no_argument, 0, 'A' }, /* F */
|
||||
{ "concatenate", no_argument, 0, 'A' }, /* F */
|
||||
@ -996,6 +1011,9 @@ tar_options(int argc, char **argv)
|
||||
case OPT_FORCE_LOCAL:
|
||||
forcelocal = 1;
|
||||
break;
|
||||
case OPT_INSECURE:
|
||||
secure = 0;
|
||||
break;
|
||||
default:
|
||||
tar_usage();
|
||||
break;
|
||||
@ -1222,10 +1240,12 @@ struct option cpio_longopts[] = {
|
||||
{ "pattern-file", required_argument, 0, 'E' },
|
||||
{ "file", required_argument, 0, 'F' },
|
||||
{ "force-local", no_argument, 0,
|
||||
OPT_FORCE_LOCAL },
|
||||
OPT_FORCE_LOCAL },
|
||||
{ "format", required_argument, 0, 'H' },
|
||||
{ "dereference", no_argument, 0, 'L' },
|
||||
{ "swap-halfwords", no_argument, 0, 'S' },
|
||||
{ "insecure", no_argument, 0,
|
||||
OPT_INSECURE },
|
||||
|
||||
#ifdef notyet
|
||||
/* Not implemented */
|
||||
@ -1237,19 +1257,19 @@ struct option cpio_longopts[] = {
|
||||
{ "owner", required_argument, 0 'R' },
|
||||
{ "dot", no_argument, 0, 'V' },
|
||||
{ "block-size", required_argument, 0,
|
||||
OPT_BLOCK_SIZE },
|
||||
OPT_BLOCK_SIZE },
|
||||
{ "no-absolute-pathnames", no_argument, 0,
|
||||
OPT_NO_ABSOLUTE_PATHNAMES },
|
||||
OPT_NO_ABSOLUTE_PATHNAMES },
|
||||
{ "no-preserve-owner", no_argument, 0,
|
||||
OPT_NO_PRESERVE_OWNER },
|
||||
OPT_NO_PRESERVE_OWNER },
|
||||
{ "only-verify-crc", no_argument, 0,
|
||||
OPT_ONLY_VERIFY_CRC },
|
||||
OPT_ONLY_VERIFY_CRC },
|
||||
{ "rsh-command", required_argument, 0,
|
||||
OPT_RSH_COMMAND },
|
||||
OPT_RSH_COMMAND },
|
||||
{ "sparce", no_argument, 0,
|
||||
OPT_SPARSE },
|
||||
OPT_SPARSE },
|
||||
{ "version", no_argument, 0,
|
||||
OPT_VERSION },
|
||||
OPT_VERSION },
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -1282,7 +1302,7 @@ cpio_options(int argc, char **argv)
|
||||
* process option flags
|
||||
*/
|
||||
while ((c = getoldopt(argc, argv,
|
||||
"abcdfiklmoprstuvzABC:E:F:H:I:LM:O:R:SVZ6",
|
||||
"+abcdfiklmoprstuvzABC:E:F:H:I:LM:O:R:SVZ6",
|
||||
cpio_longopts, NULL)) != -1) {
|
||||
switch(c) {
|
||||
case 'a':
|
||||
@ -1513,6 +1533,9 @@ cpio_options(int argc, char **argv)
|
||||
case OPT_FORCE_LOCAL:
|
||||
forcelocal = 1;
|
||||
break;
|
||||
case OPT_INSECURE:
|
||||
secure = 0;
|
||||
break;
|
||||
default:
|
||||
cpio_usage();
|
||||
break;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pat_rep.c,v 1.14 2002/10/12 15:39:30 christos Exp $ */
|
||||
/* $NetBSD: pat_rep.c,v 1.15 2002/10/15 16:16:30 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
@ -42,7 +42,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)pat_rep.c 8.2 (Berkeley) 4/18/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: pat_rep.c,v 1.14 2002/10/12 15:39:30 christos Exp $");
|
||||
__RCSID("$NetBSD: pat_rep.c,v 1.15 2002/10/15 16:16:30 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -82,6 +82,7 @@ static int tty_rename(ARCHD *);
|
||||
static int fix_path(char *, int *, char *, int);
|
||||
static int fn_match(char *, char *, char **);
|
||||
static char * range_match(char *, int);
|
||||
static int checkdotdot(const char *);
|
||||
#ifdef NET2_REGEX
|
||||
static int resub(regexp *, char *, char *, char *);
|
||||
#else
|
||||
@ -670,6 +671,19 @@ mod_name(ARCHD *arcn)
|
||||
}
|
||||
}
|
||||
|
||||
if (secure) {
|
||||
if (checkdotdot(arcn->name)) {
|
||||
tty_warn(0, "Ignoring file containing `..' (%s)",
|
||||
arcn->name);
|
||||
return 1;
|
||||
}
|
||||
if (checkdotdot(arcn->ln_name)) {
|
||||
tty_warn(0, "Ignoring link containing `..' (%s)",
|
||||
arcn->ln_name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* IMPORTANT: We have a problem. what do we do with symlinks?
|
||||
* Modifying a hard link name makes sense, as we know the file it
|
||||
@ -1041,6 +1055,35 @@ rep_name(char *name, size_t namelen, int *nlen, int prnt)
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* checkdotdot()
|
||||
* Return true if a component of the name contains a reference to ".."
|
||||
*/
|
||||
static int
|
||||
checkdotdot(const char *name)
|
||||
{
|
||||
const char *p;
|
||||
/* 1. "..{[/],}" */
|
||||
if (name[0] == '.' && name[1] == '.' &&
|
||||
(name[2] == '/' || name[2] == '\0'))
|
||||
return 1;
|
||||
|
||||
/* 2. "*[/]..[/]*" */
|
||||
if (strstr(name, "/../") != NULL)
|
||||
return 1;
|
||||
|
||||
/* 3. "*[/].." */
|
||||
for (p = name; *p; p++)
|
||||
continue;
|
||||
if (p - name < 3)
|
||||
return 0;
|
||||
if (p[-1] == '.' && p[-2] == '.' && p[-3] == '/')
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef NET2_REGEX
|
||||
/*
|
||||
* resub()
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pax.c,v 1.19 2002/10/13 00:31:28 mrg Exp $ */
|
||||
/* $NetBSD: pax.c,v 1.20 2002/10/15 16:16:30 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
@ -47,7 +47,7 @@ __COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)pax.c 8.2 (Berkeley) 4/18/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: pax.c,v 1.19 2002/10/13 00:31:28 mrg Exp $");
|
||||
__RCSID("$NetBSD: pax.c,v 1.20 2002/10/15 16:16:30 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -116,6 +116,7 @@ char *tempbase; /* basename of tempfile to use for mkstemp(3) */
|
||||
int forcelocal; /* force local operation even if the name
|
||||
* contains a :
|
||||
*/
|
||||
int secure = 1; /* don't extract names that contain .. */
|
||||
|
||||
/*
|
||||
* PAX - Portable Archive Interchange
|
||||
|
Loading…
Reference in New Issue
Block a user