Re: unzip-5.51d

Darren Salt <ds-Ym6Ivm/Ks7B65+NM0QMiFAbYiX8G1TQY9dF7HbQ/[email protected]> Mon, 01 Mar 2004 21:42:52 +0000
Newsgroups gmane.comp.archivers.info-zip
Message-ID <4C89098620%[email protected]>
This message is in MIME format which your mailer apparently does not support.
You either require a newer version of your software which supports MIME, or
a separate MIME decoding utility.  Alternatively, ask the sender of this
message to resend it in a different format.

--1014587648--1902074837--1393447705
Content-Type: text/plain; charset=us-ascii

I demand that Cosmin T may or may not have written...

[snip]
> - Acorn, AosVS, Atari, BeOS, MacOS, Novell, OS/2, QDOS, Tandem, Unix, VMS:
>     fixed hole in directory traversal security code which did not map
>     a quoted '/' character to '_', allowing the creation of harmful
>     ("../" or leading-"/") paths [ITO Tsuyosi, Cosmin Truta]

RISC OS ("Acorn" in the above list) uses "." as its directory separator, and
"/" has no special meaning. "^" means the parent directory.

With an older unzip:

  *unzip ^.unz551test
  Archive:  ^.unz551test
  replace /unz-test1? [y]es, [n]o, [A]ll, [N]one, [r]ename: n
  checkdir error:  cannot create ./
                   unable to process ^V../unz-test2.
  checkdir error:  cannot create /.
                   unable to process .^V./unz-test3.
  replace ///unz-test4? [y]es, [n]o, [A]ll, [N]one, [r]ename: n
  *

=> files "/unz-test1" and "///unz-test4" exist in the current directory.

With unzip 5.51d, "/unz-test1" becomes "_unz-test1" and "///unz-test4"
becomes "//_unz-test4".

There were compilation problems; the attached patch "acorn-makefile.patch"
fixes this. It brings acorn.makefile into line with acorn.GMakefile, and also
drops the -apcs flags - it now uses the compiler's default setting.
(Compilation with gcc should be fine. However, due to some disagreement
between gcc and my Risc PC, I'm unable to check this.)

However, now that I'm aware of the 'quote' control code, a couple of other
possibilities come to mind involving RISC OS's special characters "@$%^&:\".
In practice, however, only some of these can be used in specific ways to
trigger the directory traversal bug. Except for ^, this bug does not apply
when the -d option is used.

When quoted:
 - ":", "/" and "." always need to be translated.
 - "^" requires translation when it is surrounded by "/"s or the start or end
   of the name.
 - the others only require translation when at the start of the name and
   followed by "/" or the end of the name.

It is easiest to translate them all regardless, BUT since some third-party
filing systems for RISC OS allow use of those special characters as ordinary
characters in filenames, this may not always be wanted. Maybe there should be
an option to suppress at least some translation, independent of the quote
character?

Consequently, the attached patch "acorn-filenames.patch" enables this
translation for quoted characters; however, it also causes any side effects
not to be performed. It also fixes the "European characters" test to also
allow character code 255.

Also attached is a replacement acorn/ReadMe.


RISC OS is, these days, owned by Castle Technology. However, for historical
reasons, it is best to stick with the "Acorn" label wrt zip and unzip.
  <URL:http://www.castle-technology.co.uk/>

-- 
| Darren Salt    | nr. Ashington, | d youmustbejoking.demon.co.uk
| Running Debian | Northumberland | s zap.tartarus.org
| and RISC OS    | Toon Army      | @
|   This was put here by ZapEmail. Don't... *er*, do blame me.

90% of being smart is knowing what you're dumb at.

--1014587648--1902074837--1393447705
Content-Type: text/plain; charset=iso-8859-1; name="acorn-filenames.patch"
Content-Disposition: attachment; filename="acorn-filenames.patch"
Content-Transfer-Encoding: quoted-printable

--- unz551d.zip/acorn/acorn~.c	2004-03-01 21:06:40.0 +0000
+++ unz551d/acorn/acorn.c	2004-03-01 21:06:40.0 +0000
@@ -391,14 +391,13 @@

     while ((workch =3D (uch)*cp++) !=3D 0) {

-        if (quote) {
-            /* if character quoted, include it literally, */
-            /*  unless it is a slash */
-            *pp++ =3D (workch =3D=3D '/' ? '_' : (char)workch);
-            quote =3D FALSE;
-        } else
             switch (workch) {
             case '/':             /* can assume -j flag not given */
+                if (quote) {
+                    *pp++ =3D '.';
+                    break;
+                }
+
                 *pp =3D '\0';
                 if (((error =3D checkdir(__G__ pathcomp, APPEND_DIR)) & =
MPN_MASK)
                      > MPN_INF_TRUNC)
@@ -410,16 +409,18 @@

             case '.':
                 *pp++ =3D '/';
-                checkswap=3Dpp;
+                if (!quote)
+                    checkswap=3Dpp;
                 break;

             case ';':             /* VMS version (or DEC-20 attrib?) */
-                lastsemi =3D pp;
+                if (!quote)
+                    lastsemi =3D pp;
                 *pp++ =3D ';';      /* keep for now; remove VMS ";##" */=

                 break;            /*  later, if requested */

             case '\026':          /* control-V quote for special chars *=
/
-                quote =3D TRUE;     /* set flag for next character */
+                quote =3D 2;        /* set flag for next character */
                 break;

             case ' ':             /* change spaces to hard-spaces */
@@ -446,10 +447,15 @@

             default:
                 /* allow European characters in filenames: */
-                if (isprint(workch) || (128 <=3D workch && workch <=3D 2=
54))
+                if (workch > 32 && workch !=3D 127)
                     *pp++ =3D (char)workch;
             } /* end switch */

+            /* This is the "affect only the next item by setting the fla=
g to
+             * 2 then decrementing it" trick... */
+            if (quote)
+                --quote;
+
     } /* end while loop */

 /*----------------------------------------------------------------------=
-----

--1014587648--1902074837--1393447705
Content-Type: text/plain; charset=iso-8859-1; name="acorn-makefile.patch"
Content-Disposition: attachment; filename="acorn-makefile.patch"
Content-Transfer-Encoding: quoted-printable

diff -u/ unz551d/zip.acorn.makefile unz551d.acorn.makefile
--- unz551d.zip/acorn/makefile	2004-03-01 20:33:48.0 +0000
+++ unz551d/acorn/makefile	2004-03-01 20:33:48.0 +0000
@@ -16,9 +16,9 @@
 #   LFLAGS2   flags after obj file list (libraries, etc)
 #
 LIB      =3D
-CBASE    =3D -throwback -apcs 3/26 -wn -DNO_STRNICMP
+CBASE    =3D -throwback -wn -DNO_STRNICMP
 CFLAGS   =3D $(CBASE) -IC:,@.
-ASMFLAGS =3D -Throwback -Stamp -NoCache -CloseExec -quit -apcs 3/26
+ASMFLAGS =3D -Throwback -Stamp -NoCache -CloseExec -quit
 LFLAGS1  =3D
 LFLAGS2  =3D $(LIB) C:o.Stubs

@@ -27,9 +27,9 @@
 OBJS2 =3D extract.o fileio.o globals.o inflate.o list.o match.o
 OBJS3 =3D process.o ttyio.o unreduce.o unshrink.o zipinfo.o
 OBJS  =3D $(OBJS1) $(OBJS2) $(OBJS3) riscos.o swiven.o acorn.o
-OBJF  =3D funzip.o crc32.o crypt_.o globals_.o inflate_.o ttyio_.o \
+OBJF  =3D funzip.o crc32.o cryptf.o globalsf.o inflatef.o ttyiof.o \
         riscos.o swiven.o
-OBJX  =3D unzipsfx.o crc32.o crctab.o crypt.o extract_.o fileio.o global=
s.o \
+OBJX  =3D unzipsfx.o crc32.o crctab.o crypt_.o extract_.o fileio_.o glob=
als.o \
         inflate.o match.o process_.o ttyio.o acorn_.o swiven.o riscos_.o=


 UNZIP_H =3D unzip.h unzpriv.h globals.h acorn/riscos.h acorn/swiven.h
@@ -71,9 +71,11 @@
 zipinfo.o:      zipinfo.c $(UNZIP_H)

 crypt_.o:       crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h
-        $(CC) $(CFLAGS) -DFUNZIP -c c.crypt -o o.crypt_
+        $(CC) $(CFLAGS) -DSFX -c c.crypt -o o.crypt_
 extract_.o:     extract.c $(UNZIP_H) crypt.h
         $(CC) $(CFLAGS) -DSFX -c c.extract -o o.extract_
+fileio_.o:      fileio.c $(UNZIP_H) crypt.h
+        $(CC) $(CFLAGS) -DSFX -c c.fileio -o o.fileio_
 globals_.o:     globals.c $(UNZIP_H)
         $(CC) $(CFLAGS) -DFUNZIP -c c.globals -o o.globals_
 inflate_.o:     inflate.c inflate.h $(UNZIP_H) crypt.h
@@ -86,6 +88,15 @@
 unzipsfx.o:     unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h
         $(CC) $(CFLAGS) -DSFX -c c.unzip -o o.unzipsfx

+o.cryptf:       c.crypt $(UNZIP_H) h.zip h.crypt h.ttyio
+        $(CC) $(CFLAGS) -DFUNZIP -c c.crypt -o o.cryptf
+o.globalsf:     c.globals $(UNZIP_H)
+        $(CC) $(CFLAGS) -DFUNZIP -c c.globals -o o.globalsf
+o.inflatef:     c.inflate h.inflate $(UNZIP_H) h.crypt
+        $(CC) $(CFLAGS) -DFUNZIP -c c.inflate -o o.inflatef
+o.ttyiof:       c.ttyio $(UNZIP_H) h.zip h.crypt h.ttyio
+        $(CC) $(CFLAGS) -DFUNZIP -c c.ttyio -o o.ttyiof
+
 acorn.o:       acorn/acorn.c $(UNZIP_H)
         $(CC) $(CFLAGS) -c acorn/acorn.c
 acorn_.o:       acorn/acorn.c $(UNZIP_H)

--1014587648--1902074837--1393447705
Content-Type: text/plain; charset=iso-8859-1; name="acorn-ReadMe"
Content-Disposition: attachment; filename="acorn-ReadMe"
Content-Transfer-Encoding: quoted-printable

Acorn-specific usage instructions
---------------------------------

As zipfiles can come from a variety of sources apart from Acorn machines,=

consideration had to be given to the handling of dot-extensions, e.g.
"DOSFILE.TXT", "unix-filename.tar.gz". These are extracted as "DOSFILE/TX=
T"
and "unix-filename/tar/gz"; their names may or may not be truncated,
depending on where the files are being created: what filing system and, f=
or
Filecore-based filing systems such as ADFS or an IDEFS or SCSIFS, which
disk/partition format (names will not be truncated if you're using E+ or =
F+).

Where truncation occurs, you must be REALLY careful about extracting file=
s
from archives. The files

    dummy_source.c and dummy_source.h

will both be extracted as

    dummy_sour

UnZip will prompt you for confirmation of the over-writing of these files=
,
but you must be really careful unless you wish to lose files! Also, becau=
se
UnZip is a unix-ported program, the filenames are CASE SENSITIVE.

    *unzip new/zip newfile

will extract 'newfile', but not 'NewFile', 'NEWFILE' or any other
combinations. However, you can use the -C option to force operations to
disregard the case of filenames.

The Acorn UnZip port has an additional feature to cope with the extractio=
n of
files containing 'c' code. As you may be aware, Acorn Desktop C requires =
all
files called "foo.c" to be renamed to "c.foo", ie "foo" in a directory ca=
lled
"c".

There are two ways of using this feature.

- The old way: use a colon-separated environment variable named "Unzip$Ex=
ts".

  Any extensions found in this variable will be extracted to directories
  named after the extension, with the extension stripped. For example:

    *Set Unzip$Exts "c:h:o:s"
    *unzip foo/zip

- The new way: use the -/ option. For example:

  Any extensions found in the parameter for this option will be extracted=
 to
  directories named after the extension, with the extension stripped. For=

  example:

    *unzip -/c:h:o:s foo/zip

If foo/zip contains a file named "foo.c", this file will be written as "f=
oo"
in directory "c". This can be used to include "c:h:o:s:txt" to pull all t=
he
text files out to a separate directory.

UnZip fully supports SparkFS Extra Field. This means that zipfiles create=
d
with SparkFS or Zip (on RISC OS) will be correctly unzipped, including
filetypes.

UnZipSFX can be used to create self-extracting archives. To use it, just
create a common zipfile using Zip (or SparkFS), then load the UnZipSFX
executable into an editor (eg. Edit, Zap), go with the caret the end of t=
he
file (using CTRL-CursorDown) and drag the zipfile to the editor window (i=
n
other words, append the zipfile to the UnZipSFX executable). Now, saving =
the
resulting file (with filetype Absolute (&FF8)), you have a self-extractin=
g
archive (ie. double-clicking on it will unzip the contents of the origina=
l
zipfile to the currently selected directory).

--1014587648--1902074837--1393447705--