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:
christos 2002-10-15 16:16:29 +00:00
parent a2e26d6e11
commit ca541391bc
4 changed files with 101 additions and 33 deletions

View File

@ -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. * Copyright (c) 1992 Keith Muller.
@ -56,6 +56,7 @@ extern time_t starttime;
extern int force_one_volume; extern int force_one_volume;
extern char *chdname; extern char *chdname;
extern int forcelocal; extern int forcelocal;
extern int secure;
int ar_open(const char *); int ar_open(const char *);
void ar_close(void); void ar_close(void);

View File

@ -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. * Copyright (c) 1992 Keith Muller.
@ -42,7 +42,7 @@
#if 0 #if 0
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 4/18/94"; static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 4/18/94";
#else #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
#endif /* not lint */ #endif /* not lint */
@ -98,6 +98,25 @@ static int getline_error;
#define GZIP_CMD "gzip" /* command to run as gzip */ #define GZIP_CMD "gzip" /* command to run as gzip */
#define COMPRESS_CMD "compress" /* command to run as compress */ #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 * Format specific routine table - MUST BE IN SORTED ORDER BY NAME
* (see pax.h for description of each function) * (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() * pax_options()
* look at the user specified flags. set globals as required and check if * 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 * process option flags
*/ */
while ((c = getopt(argc, argv, while ((c = getopt_long(argc, argv,
"ab:cdf:iklno:p:rs:tuvwx:zAB:DE:G:HLMN:OPT:U:XYZ")) != -1) { "ab:cdf:iklno:p:rs:tuvwx:zAB:DE:G:HLMN:OPT:U:XYZ",
pax_longopts, NULL)) != -1) {
switch (c) { switch (c) {
case 'a': case 'a':
/* /*
@ -555,6 +580,9 @@ pax_options(int argc, char **argv)
Zflag = 1; Zflag = 1;
flg |= CZF; flg |= CZF;
break; break;
case OPT_INSECURE:
secure = 0;
break;
case '?': case '?':
default: default:
pax_usage(); 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 * 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[] = { struct option tar_longopts[] = {
{ "block-size", required_argument, 0, 'b' }, { "block-size", required_argument, 0, 'b' },
{ "create", no_argument, 0, 'c' }, /* F */ { "create", no_argument, 0, 'c' }, /* F */
@ -693,6 +706,8 @@ struct option tar_longopts[] = {
OPT_USE_COMPRESS_PROGRAM }, OPT_USE_COMPRESS_PROGRAM },
{ "force-local", no_argument, 0, { "force-local", no_argument, 0,
OPT_FORCE_LOCAL }, OPT_FORCE_LOCAL },
{ "insecure", no_argument, 0,
OPT_INSECURE },
#if 0 /* Not implemented */ #if 0 /* Not implemented */
{ "catenate", no_argument, 0, 'A' }, /* F */ { "catenate", no_argument, 0, 'A' }, /* F */
{ "concatenate", 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: case OPT_FORCE_LOCAL:
forcelocal = 1; forcelocal = 1;
break; break;
case OPT_INSECURE:
secure = 0;
break;
default: default:
tar_usage(); tar_usage();
break; break;
@ -1222,10 +1240,12 @@ struct option cpio_longopts[] = {
{ "pattern-file", required_argument, 0, 'E' }, { "pattern-file", required_argument, 0, 'E' },
{ "file", required_argument, 0, 'F' }, { "file", required_argument, 0, 'F' },
{ "force-local", no_argument, 0, { "force-local", no_argument, 0,
OPT_FORCE_LOCAL }, OPT_FORCE_LOCAL },
{ "format", required_argument, 0, 'H' }, { "format", required_argument, 0, 'H' },
{ "dereference", no_argument, 0, 'L' }, { "dereference", no_argument, 0, 'L' },
{ "swap-halfwords", no_argument, 0, 'S' }, { "swap-halfwords", no_argument, 0, 'S' },
{ "insecure", no_argument, 0,
OPT_INSECURE },
#ifdef notyet #ifdef notyet
/* Not implemented */ /* Not implemented */
@ -1237,19 +1257,19 @@ struct option cpio_longopts[] = {
{ "owner", required_argument, 0 'R' }, { "owner", required_argument, 0 'R' },
{ "dot", no_argument, 0, 'V' }, { "dot", no_argument, 0, 'V' },
{ "block-size", required_argument, 0, { "block-size", required_argument, 0,
OPT_BLOCK_SIZE }, OPT_BLOCK_SIZE },
{ "no-absolute-pathnames", no_argument, 0, { "no-absolute-pathnames", no_argument, 0,
OPT_NO_ABSOLUTE_PATHNAMES }, OPT_NO_ABSOLUTE_PATHNAMES },
{ "no-preserve-owner", no_argument, 0, { "no-preserve-owner", no_argument, 0,
OPT_NO_PRESERVE_OWNER }, OPT_NO_PRESERVE_OWNER },
{ "only-verify-crc", no_argument, 0, { "only-verify-crc", no_argument, 0,
OPT_ONLY_VERIFY_CRC }, OPT_ONLY_VERIFY_CRC },
{ "rsh-command", required_argument, 0, { "rsh-command", required_argument, 0,
OPT_RSH_COMMAND }, OPT_RSH_COMMAND },
{ "sparce", no_argument, 0, { "sparce", no_argument, 0,
OPT_SPARSE }, OPT_SPARSE },
{ "version", no_argument, 0, { "version", no_argument, 0,
OPT_VERSION }, OPT_VERSION },
#endif #endif
}; };
@ -1282,7 +1302,7 @@ cpio_options(int argc, char **argv)
* process option flags * process option flags
*/ */
while ((c = getoldopt(argc, argv, 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) { cpio_longopts, NULL)) != -1) {
switch(c) { switch(c) {
case 'a': case 'a':
@ -1513,6 +1533,9 @@ cpio_options(int argc, char **argv)
case OPT_FORCE_LOCAL: case OPT_FORCE_LOCAL:
forcelocal = 1; forcelocal = 1;
break; break;
case OPT_INSECURE:
secure = 0;
break;
default: default:
cpio_usage(); cpio_usage();
break; break;

View File

@ -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. * Copyright (c) 1992 Keith Muller.
@ -42,7 +42,7 @@
#if 0 #if 0
static char sccsid[] = "@(#)pat_rep.c 8.2 (Berkeley) 4/18/94"; static char sccsid[] = "@(#)pat_rep.c 8.2 (Berkeley) 4/18/94";
#else #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
#endif /* not lint */ #endif /* not lint */
@ -82,6 +82,7 @@ static int tty_rename(ARCHD *);
static int fix_path(char *, int *, char *, int); static int fix_path(char *, int *, char *, int);
static int fn_match(char *, char *, char **); static int fn_match(char *, char *, char **);
static char * range_match(char *, int); static char * range_match(char *, int);
static int checkdotdot(const char *);
#ifdef NET2_REGEX #ifdef NET2_REGEX
static int resub(regexp *, char *, char *, char *); static int resub(regexp *, char *, char *, char *);
#else #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? * IMPORTANT: We have a problem. what do we do with symlinks?
* Modifying a hard link name makes sense, as we know the file it * 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); 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 #ifdef NET2_REGEX
/* /*
* resub() * resub()

View File

@ -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. * Copyright (c) 1992 Keith Muller.
@ -47,7 +47,7 @@ __COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\
#if 0 #if 0
static char sccsid[] = "@(#)pax.c 8.2 (Berkeley) 4/18/94"; static char sccsid[] = "@(#)pax.c 8.2 (Berkeley) 4/18/94";
#else #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
#endif /* not lint */ #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 int forcelocal; /* force local operation even if the name
* contains a : * contains a :
*/ */
int secure = 1; /* don't extract names that contain .. */
/* /*
* PAX - Portable Archive Interchange * PAX - Portable Archive Interchange