which included commits to RCS files with non-trunk default branches. git-svn-id: svn://10.65.10.50/trunk@5403 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			561 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			561 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/*
 | 
						|
   crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
 | 
						|
 | 
						|
   This code is not copyrighted and is put in the public domain.  The
 | 
						|
   encryption/decryption parts (as opposed to the non-echoing password
 | 
						|
   parts) were originally written in Europe; the whole file can there-
 | 
						|
   fore be freely distributed from any country except the USA.  If this
 | 
						|
   code is imported into the USA, it cannot be re-exported from from
 | 
						|
   there to another country.  (This restriction might seem curious, but
 | 
						|
   this is what US law requires.)
 | 
						|
 */
 | 
						|
 | 
						|
/* This encryption code is a direct transcription of the algorithm from
 | 
						|
   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
 | 
						|
   file (appnote.txt) is distributed with the PKZIP program (even in the
 | 
						|
   version without encryption capabilities).
 | 
						|
 */
 | 
						|
 | 
						|
#define ZCRYPT_INTERNAL
 | 
						|
#include "zip.h"
 | 
						|
#include "crypt.h"
 | 
						|
#include "ttyio.h"
 | 
						|
 | 
						|
#ifndef FALSE
 | 
						|
#  define FALSE 0
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef ZIP
 | 
						|
   /* For the encoding task used in Zip (and ZipCloak), we want to initialize
 | 
						|
      the crypt algorithm with some reasonably unpredictable bytes, see
 | 
						|
      the crypthead() function. The standard rand() library function is
 | 
						|
      used to supply these `random' bytes, which in turn is initialized by
 | 
						|
      a srand() call. The srand() function takes an "unsigned" (at least 16bit)
 | 
						|
      seed value as argument to determine the starting point of the rand()
 | 
						|
      pseudo-random number generator.
 | 
						|
      This seed number is constructed as "Seed = Seed1 .XOR. Seed2" with
 | 
						|
      Seed1 supplied by the current time (= "(unsigned)time()") and Seed2
 | 
						|
      as some (hopefully) nondeterministic bitmask. On many (most) systems,
 | 
						|
      we use some "process specific" number, as the PID or something similar,
 | 
						|
      but when nothing unpredictable is available, a fixed number may be
 | 
						|
      sufficient.
 | 
						|
      NOTE:
 | 
						|
      1.) This implementation requires the availability of the following
 | 
						|
          standard UNIX C runtime library functions: time(), rand(), srand().
 | 
						|
          On systems where some of them are missing, the environment that
 | 
						|
          incorporates the crypt routines must supply suitable replacement
 | 
						|
          functions.
 | 
						|
      2.) It is a very bad idea to use a second call to time() to set the
 | 
						|
          "Seed2" number! In this case, both "Seed1" and "Seed2" would be
 | 
						|
          (almost) identical, resulting in a (mostly) "zero" constant seed
 | 
						|
          number passed to srand().
 | 
						|
 | 
						|
      The implementation environment defined in the "zip.h" header should
 | 
						|
      supply a reasonable definition for ZCR_SEED2 (an unsigned number; for
 | 
						|
      most implementations of rand() and srand(), only the lower 16 bits are
 | 
						|
      significant!). An example that works on many systems would be
 | 
						|
           "#define ZCR_SEED2  (unsigned)getpid()".
 | 
						|
      The default definition for ZCR_SEED2 supplied below should be regarded
 | 
						|
      as a fallback to allow successful compilation in "beta state"
 | 
						|
      environments.
 | 
						|
    */
 | 
						|
#  include <time.h>     /* time() function supplies first part of crypt seed */
 | 
						|
   /* "last resort" source for second part of crypt seed pattern */
 | 
						|
#  ifndef ZCR_SEED2
 | 
						|
#    define ZCR_SEED2 (unsigned)3141592654L     /* use PI as default pattern */
 | 
						|
#  endif
 | 
						|
#  ifdef GLOBAL         /* used in Amiga system headers, maybe others too */
 | 
						|
#    undef GLOBAL
 | 
						|
#  endif
 | 
						|
#  define GLOBAL(g) g
 | 
						|
#else /* !ZIP */
 | 
						|
#  define GLOBAL(g) G.g
 | 
						|
#endif /* ?ZIP */
 | 
						|
 | 
						|
 | 
						|
#ifdef UNZIP
 | 
						|
   /* char *key = (char *)NULL; moved to globals.h */
 | 
						|
#  ifndef FUNZIP
 | 
						|
     local int testp OF((__GPRO__ uch *h));
 | 
						|
     local int testkey OF((__GPRO__ uch *h, char *key));
 | 
						|
#  endif
 | 
						|
#endif /* UNZIP */
 | 
						|
 | 
						|
#ifndef UNZIP             /* moved to globals.h for UnZip */
 | 
						|
   local ulg keys[3];     /* keys defining the pseudo-random sequence */
 | 
						|
#endif /* !UNZIP */
 | 
						|
 | 
						|
#ifndef Trace
 | 
						|
#  ifdef CRYPT_DEBUG
 | 
						|
#    define Trace(x) fprintf x
 | 
						|
#  else
 | 
						|
#    define Trace(x)
 | 
						|
#  endif
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef CRC_32_TAB
 | 
						|
#  define CRC_32_TAB     crc_32_tab
 | 
						|
#endif
 | 
						|
 | 
						|
#define CRC32(c, b) (CRC_32_TAB[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
 * Return the next byte in the pseudo-random sequence
 | 
						|
 */
 | 
						|
int decrypt_byte(__G)
 | 
						|
    __GDEF
 | 
						|
{
 | 
						|
    unsigned temp;  /* POTENTIAL BUG:  temp*(temp^1) may overflow in an
 | 
						|
                     * unpredictable manner on 16-bit systems; not a problem
 | 
						|
                     * with any known compiler so far, though */
 | 
						|
 | 
						|
    temp = ((unsigned)GLOBAL(keys[2]) & 0xffff) | 2;
 | 
						|
    return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
 * Update the encryption keys with the next byte of plain text
 | 
						|
 */
 | 
						|
int update_keys(__G__ c)
 | 
						|
    __GDEF
 | 
						|
    int c;                  /* byte of plain text */
 | 
						|
{
 | 
						|
    GLOBAL(keys[0]) = CRC32(GLOBAL(keys[0]), c);
 | 
						|
    GLOBAL(keys[1]) += GLOBAL(keys[0]) & 0xff;
 | 
						|
    GLOBAL(keys[1]) = GLOBAL(keys[1]) * 134775813L + 1;
 | 
						|
    {
 | 
						|
      register int keyshift = (int)(GLOBAL(keys[1]) >> 24);
 | 
						|
      GLOBAL(keys[2]) = CRC32(GLOBAL(keys[2]), keyshift);
 | 
						|
    }
 | 
						|
    return c;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
 * Initialize the encryption keys and the random header according to
 | 
						|
 * the given password.
 | 
						|
 */
 | 
						|
void init_keys(__G__ passwd)
 | 
						|
    __GDEF
 | 
						|
    char *passwd;             /* password string with which to modify keys */
 | 
						|
{
 | 
						|
    GLOBAL(keys[0]) = 305419896L;
 | 
						|
    GLOBAL(keys[1]) = 591751049L;
 | 
						|
    GLOBAL(keys[2]) = 878082192L;
 | 
						|
    while (*passwd != '\0') {
 | 
						|
        update_keys(__G__ (int)*passwd);
 | 
						|
        passwd++;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#ifdef ZIP
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
 * Write encryption header to file zfile using the password passwd
 | 
						|
 * and the cyclic redundancy check crc.
 | 
						|
 */
 | 
						|
void crypthead(passwd, crc, zfile)
 | 
						|
    char *passwd;                /* password string */
 | 
						|
    ulg crc;                     /* crc of file being encrypted */
 | 
						|
    FILE *zfile;                 /* where to write header */
 | 
						|
{
 | 
						|
    int n;                       /* index in random header */
 | 
						|
    int t;                       /* temporary */
 | 
						|
    int c;                       /* random byte */
 | 
						|
    int ztemp;                   /* temporary for zencoded value */
 | 
						|
    uch header[RAND_HEAD_LEN-2]; /* random header */
 | 
						|
    static unsigned calls = 0;   /* ensure different random header each time */
 | 
						|
 | 
						|
    /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
 | 
						|
     * output of rand() to get less predictability, since rand() is
 | 
						|
     * often poorly implemented.
 | 
						|
     */
 | 
						|
    if (++calls == 1) {
 | 
						|
        srand((unsigned)time(NULL) ^ ZCR_SEED2);
 | 
						|
    }
 | 
						|
    init_keys(passwd);
 | 
						|
    for (n = 0; n < RAND_HEAD_LEN-2; n++) {
 | 
						|
        c = (rand() >> 7) & 0xff;
 | 
						|
        header[n] = (uch)zencode(c, t);
 | 
						|
    }
 | 
						|
    /* Encrypt random header (last two bytes is high word of crc) */
 | 
						|
    init_keys(passwd);
 | 
						|
    for (n = 0; n < RAND_HEAD_LEN-2; n++) {
 | 
						|
        ztemp = zencode(header[n], t);
 | 
						|
        putc(ztemp, zfile);
 | 
						|
    }
 | 
						|
    ztemp = zencode((int)(crc >> 16) & 0xff, t);
 | 
						|
    putc(ztemp, zfile);
 | 
						|
    ztemp = zencode((int)(crc >> 24) & 0xff, t);
 | 
						|
    putc(ztemp, zfile);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#ifdef UTIL
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
 * Encrypt the zip entry described by z from file source to file dest
 | 
						|
 * using the password passwd.  Return an error code in the ZE_ class.
 | 
						|
 */
 | 
						|
int zipcloak(z, source, dest, passwd)
 | 
						|
    struct zlist far *z;    /* zip entry to encrypt */
 | 
						|
    FILE *source, *dest;    /* source and destination files */
 | 
						|
    char *passwd;           /* password string */
 | 
						|
{
 | 
						|
    int c;                  /* input byte */
 | 
						|
    int res;                /* result code */
 | 
						|
    ulg n;                  /* holds offset and counts size */
 | 
						|
    ush flag;               /* previous flags */
 | 
						|
    int t;                  /* temporary */
 | 
						|
    int ztemp;              /* temporary storage for zencode value */
 | 
						|
 | 
						|
    /* Set encrypted bit, clear extended local header bit and write local
 | 
						|
       header to output file */
 | 
						|
    if ((n = ftell(dest)) == -1L) return ZE_TEMP;
 | 
						|
    z->off = n;
 | 
						|
    flag = z->flg;
 | 
						|
    z->flg |= 1,  z->flg &= ~8;
 | 
						|
    z->lflg |= 1, z->lflg &= ~8;
 | 
						|
    z->siz += RAND_HEAD_LEN;
 | 
						|
    if ((res = putlocal(z, dest)) != ZE_OK) return res;
 | 
						|
 | 
						|
    /* Initialize keys with password and write random header */
 | 
						|
    crypthead(passwd, z->crc, dest);
 | 
						|
 | 
						|
    /* Skip local header in input file */
 | 
						|
    if (fseek(source, (long)(4 + LOCHEAD + (ulg)z->nam + (ulg)z->ext),
 | 
						|
              SEEK_CUR)) {
 | 
						|
        return ferror(source) ? ZE_READ : ZE_EOF;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Encrypt data */
 | 
						|
    for (n = z->siz - RAND_HEAD_LEN; n; n--) {
 | 
						|
        if ((c = getc(source)) == EOF) {
 | 
						|
            return ferror(source) ? ZE_READ : ZE_EOF;
 | 
						|
        }
 | 
						|
        ztemp = zencode(c, t);
 | 
						|
        putc(ztemp, dest);
 | 
						|
    }
 | 
						|
    /* Skip extended local header in input file if there is one */
 | 
						|
    if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) {
 | 
						|
        return ferror(source) ? ZE_READ : ZE_EOF;
 | 
						|
    }
 | 
						|
    if (fflush(dest) == EOF) return ZE_TEMP;
 | 
						|
    return ZE_OK;
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
 * Decrypt the zip entry described by z from file source to file dest
 | 
						|
 * using the password passwd.  Return an error code in the ZE_ class.
 | 
						|
 */
 | 
						|
int zipbare(__G__ z, source, dest, passwd)
 | 
						|
    __GDEF
 | 
						|
    struct zlist far *z;  /* zip entry to encrypt */
 | 
						|
    FILE *source, *dest;  /* source and destination files */
 | 
						|
    char *passwd;         /* password string */
 | 
						|
{
 | 
						|
    int c0, c1;           /* last two input bytes */
 | 
						|
    ulg offset;           /* used for file offsets */
 | 
						|
    ulg size;             /* size of input data */
 | 
						|
    int r;                /* size of encryption header */
 | 
						|
    int res;              /* return code */
 | 
						|
    ush flag;             /* previous flags */
 | 
						|
 | 
						|
    /* Save position and skip local header in input file */
 | 
						|
    if ((offset = ftell(source)) == -1L ||
 | 
						|
        fseek(source, (long)(4 + LOCHEAD + (ulg)z->nam + (ulg)z->ext),
 | 
						|
              SEEK_CUR)) {
 | 
						|
        return ferror(source) ? ZE_READ : ZE_EOF;
 | 
						|
    }
 | 
						|
    /* Initialize keys with password */
 | 
						|
    init_keys(passwd);
 | 
						|
 | 
						|
    /* Decrypt encryption header, save last two bytes */
 | 
						|
    c1 = 0;
 | 
						|
    for (r = RAND_HEAD_LEN; r; r--) {
 | 
						|
        c0 = c1;
 | 
						|
        if ((c1 = getc(source)) == EOF) {
 | 
						|
            return ferror(source) ? ZE_READ : ZE_EOF;
 | 
						|
        }
 | 
						|
        Trace((stdout, " (%02x)", c1));
 | 
						|
        zdecode(c1);
 | 
						|
        Trace((stdout, " %02x", c1));
 | 
						|
    }
 | 
						|
    Trace((stdout, "\n"));
 | 
						|
 | 
						|
    /* If last two bytes of header don't match crc (or file time in the
 | 
						|
     * case of an extended local header), back up and just copy. For
 | 
						|
     * pkzip 2.0, the check has been reduced to one byte only.
 | 
						|
     */
 | 
						|
#ifdef ZIP10
 | 
						|
    if ((ush)(c0 | (c1<<8)) !=
 | 
						|
        (z->flg & 8 ? (ush) z->tim & 0xffff : (ush)(z->crc >> 16))) {
 | 
						|
#else
 | 
						|
    c0++; /* avoid warning on unused variable */
 | 
						|
    if ((ush)c1 != (z->flg & 8 ? (ush) z->tim >> 8 : (ush)(z->crc >> 24))) {
 | 
						|
#endif
 | 
						|
        if (fseek(source, offset, SEEK_SET)) {
 | 
						|
            return ferror(source) ? ZE_READ : ZE_EOF;
 | 
						|
        }
 | 
						|
        if ((res = zipcopy(z, source, dest)) != ZE_OK) return res;
 | 
						|
        return ZE_MISS;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Clear encrypted bit and local header bit, and write local header to
 | 
						|
       output file */
 | 
						|
    if ((offset = ftell(dest)) == -1L) return ZE_TEMP;
 | 
						|
    z->off = offset;
 | 
						|
    flag = z->flg;
 | 
						|
    z->flg &= ~9;
 | 
						|
    z->lflg &= ~9;
 | 
						|
    z->siz -= RAND_HEAD_LEN;
 | 
						|
    if ((res = putlocal(z, dest)) != ZE_OK) return res;
 | 
						|
 | 
						|
    /* Decrypt data */
 | 
						|
    for (size = z->siz; size; size--) {
 | 
						|
        if ((c1 = getc(source)) == EOF) {
 | 
						|
            return ferror(source) ? ZE_READ : ZE_EOF;
 | 
						|
        }
 | 
						|
        zdecode(c1);
 | 
						|
        putc(c1, dest);
 | 
						|
    }
 | 
						|
    /* Skip extended local header in input file if there is one */
 | 
						|
    if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) {
 | 
						|
        return ferror(source) ? ZE_READ : ZE_EOF;
 | 
						|
    }
 | 
						|
    if (fflush(dest) == EOF) return ZE_TEMP;
 | 
						|
 | 
						|
    return ZE_OK;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#else /* !UTIL */
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
 * If requested, encrypt the data in buf, and in any case call fwrite()
 | 
						|
 * with the arguments to zfwrite().  Return what fwrite() returns.
 | 
						|
 */
 | 
						|
unsigned zfwrite(buf, item_size, nb, f)
 | 
						|
    zvoid *buf;                /* data buffer */
 | 
						|
    extent item_size;          /* size of each item in bytes */
 | 
						|
    extent nb;                 /* number of items */
 | 
						|
    FILE *f;                   /* file to write to */
 | 
						|
{
 | 
						|
    int t;                    /* temporary */
 | 
						|
 | 
						|
    if (key != (char *)NULL) { /* key is the global password pointer */
 | 
						|
        ulg size;              /* buffer size */
 | 
						|
        char *p = (char*)buf;  /* steps through buffer */
 | 
						|
 | 
						|
        /* Encrypt data in buffer */
 | 
						|
        for (size = item_size*(ulg)nb; size != 0; p++, size--) {
 | 
						|
            *p = (char)zencode(*p, t);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    /* Write the buffer out */
 | 
						|
    return fwrite(buf, item_size, nb, f);
 | 
						|
}
 | 
						|
 | 
						|
#endif /* ?UTIL */
 | 
						|
#endif /* ZIP */
 | 
						|
 | 
						|
 | 
						|
#if (defined(UNZIP) && !defined(FUNZIP))
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
 * Get the password and set up keys for current zipfile member.  Return
 | 
						|
 * PK_ class error.
 | 
						|
 */
 | 
						|
int decrypt(__G)
 | 
						|
    __GDEF
 | 
						|
{
 | 
						|
    ush b;
 | 
						|
    int n, r;
 | 
						|
    uch h[RAND_HEAD_LEN];
 | 
						|
 | 
						|
    Trace((stdout, "\n[incnt = %d]: ", GLOBAL(incnt)));
 | 
						|
 | 
						|
    /* get header once (turn off "encrypted" flag temporarily so we don't
 | 
						|
     * try to decrypt the same data twice) */
 | 
						|
    GLOBAL(pInfo->encrypted) = FALSE;
 | 
						|
    defer_leftover_input(__G);
 | 
						|
    for (n = 0; n < RAND_HEAD_LEN; n++) {
 | 
						|
        b = NEXTBYTE;
 | 
						|
        h[n] = (uch)b;
 | 
						|
        Trace((stdout, " (%02x)", h[n]));
 | 
						|
    }
 | 
						|
    undefer_input(__G);
 | 
						|
    GLOBAL(pInfo->encrypted) = TRUE;
 | 
						|
 | 
						|
    if (GLOBAL(newzip)) { /* this is first encrypted member in this zipfile */
 | 
						|
        GLOBAL(newzip) = FALSE;
 | 
						|
        if (GLOBAL(P_flag)) {     /* user gave password on command line */
 | 
						|
            if (!GLOBAL(key)) {
 | 
						|
                if ((GLOBAL(key) = (char *)malloc(PWLEN+1)) == (char *)NULL)
 | 
						|
                    return PK_MEM2;
 | 
						|
                strncpy(GLOBAL(key), GLOBAL(pwdarg), PWLEN);
 | 
						|
                GLOBAL(nopwd) = TRUE;  /* inhibit password prompting! */
 | 
						|
            }
 | 
						|
        } else if (GLOBAL(key)) { /* get rid of previous zipfile's key */
 | 
						|
            free(GLOBAL(key));
 | 
						|
            GLOBAL(key) = (char *)NULL;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* if have key already, test it; else allocate memory for it */
 | 
						|
    if (GLOBAL(key)) {
 | 
						|
        if (!testp(__G__ h))
 | 
						|
            return PK_COOL;   /* existing password OK (else prompt for new) */
 | 
						|
        else if (GLOBAL(nopwd))
 | 
						|
            return PK_WARN;   /* user indicated no more prompting */
 | 
						|
    } else if ((GLOBAL(key) = (char *)malloc(PWLEN+1)) == (char *)NULL)
 | 
						|
        return PK_MEM2;
 | 
						|
 | 
						|
    /* try a few keys */
 | 
						|
    n = 0;
 | 
						|
    do {
 | 
						|
        r = (*G.decr_passwd)((zvoid *)&G, &n, GLOBAL(key), PWLEN+1,
 | 
						|
                             GLOBAL(zipfn), GLOBAL(filename));
 | 
						|
        if (r == IZ_PW_ERROR) {         /* internal error in fetch of PW */
 | 
						|
            free (GLOBAL(key));
 | 
						|
            GLOBAL(key) = NULL;
 | 
						|
            return PK_MEM2;
 | 
						|
        }
 | 
						|
        if (r != IZ_PW_ENTERED) {       /* user replied "skip" or "skip all" */
 | 
						|
            *GLOBAL(key) = '\0';        /*   We try the NIL password, ... */
 | 
						|
            n = 0;                      /*   and cancel fetch for this item. */
 | 
						|
        }
 | 
						|
        if (!testp(__G__ h))
 | 
						|
            return PK_COOL;
 | 
						|
        if (r == IZ_PW_CANCELALL)       /* User replied "Skip all" */
 | 
						|
            GLOBAL(nopwd) = TRUE;       /*   inhibit any further PW prompt! */
 | 
						|
    } while (n > 0);
 | 
						|
 | 
						|
    return PK_WARN;
 | 
						|
 | 
						|
} /* end function decrypt() */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
 * Test the password.  Return -1 if bad, 0 if OK.
 | 
						|
 */
 | 
						|
local int testp(__G__ h)
 | 
						|
    __GDEF
 | 
						|
    uch *h;
 | 
						|
{
 | 
						|
    int r;
 | 
						|
    char *key_translated;
 | 
						|
 | 
						|
    /* On systems with "obscure" native character coding (e.g., EBCDIC),
 | 
						|
     * the first test translates the password to the "main standard"
 | 
						|
     * character coding. */
 | 
						|
 | 
						|
#ifdef STR_TO_CP1
 | 
						|
    /* allocate buffer for translated password */
 | 
						|
    if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL)
 | 
						|
        return -1;
 | 
						|
    /* first try, test password translated "standard" charset */
 | 
						|
    r = testkey(__G__ h, STR_TO_CP1(key_translated, GLOBAL(key)));
 | 
						|
#else /* !STR_TO_CP1 */
 | 
						|
    /* first try, test password as supplied on the extractor's host */
 | 
						|
    r = testkey(__G__ h, GLOBAL(key));
 | 
						|
#endif /* ?STR_TO_CP1 */
 | 
						|
 | 
						|
#ifdef STR_TO_CP2
 | 
						|
    if (r != 0) {
 | 
						|
#ifndef STR_TO_CP1
 | 
						|
        /* now prepare for second (and maybe third) test with translated pwd */
 | 
						|
        if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL)
 | 
						|
            return -1;
 | 
						|
#endif
 | 
						|
        /* second try, password translated to alternate ("standard") charset */
 | 
						|
        r = testkey(__G__ h, STR_TO_CP2(key_translated, GLOBAL(key)));
 | 
						|
#ifdef STR_TO_CP3
 | 
						|
        if (r != 0)
 | 
						|
            /* third try, password translated to another "standard" charset */
 | 
						|
            r = testkey(__G__ h, STR_TO_CP3(key_translated, GLOBAL(key)));
 | 
						|
#endif
 | 
						|
#ifndef STR_TO_CP1
 | 
						|
        free(key_translated);
 | 
						|
#endif
 | 
						|
    }
 | 
						|
#endif /* STR_TO_CP2 */
 | 
						|
 | 
						|
#ifdef STR_TO_CP1
 | 
						|
    free(key_translated);
 | 
						|
    if (r != 0) {
 | 
						|
        /* last resort, test password as supplied on the extractor's host */
 | 
						|
        r = testkey(__G__ h, GLOBAL(key));
 | 
						|
    }
 | 
						|
#endif /* STR_TO_CP1 */
 | 
						|
 | 
						|
    return r;
 | 
						|
 | 
						|
} /* end function testp() */
 | 
						|
 | 
						|
 | 
						|
local int testkey(__G__ h, key)
 | 
						|
    __GDEF
 | 
						|
    uch *h;             /* decrypted header */
 | 
						|
    char *key;          /* decryption password to test */
 | 
						|
{
 | 
						|
    ush b;
 | 
						|
#ifdef ZIP10
 | 
						|
    ush c;
 | 
						|
#endif
 | 
						|
    int n;
 | 
						|
    uch *p;
 | 
						|
    uch hh[RAND_HEAD_LEN]; /* decrypted header */
 | 
						|
 | 
						|
    /* set keys and save the encrypted header */
 | 
						|
    init_keys(__G__ key);
 | 
						|
    memcpy(hh, h, RAND_HEAD_LEN);
 | 
						|
 | 
						|
    /* check password */
 | 
						|
    for (n = 0; n < RAND_HEAD_LEN; n++) {
 | 
						|
        zdecode(hh[n]);
 | 
						|
        Trace((stdout, " %02x", hh[n]));
 | 
						|
    }
 | 
						|
 | 
						|
    Trace((stdout,
 | 
						|
      "\n  lrec.crc= %08lx  crec.crc= %08lx  pInfo->ExtLocHdr= %s\n",
 | 
						|
      GLOBAL(lrec.crc32), GLOBAL(pInfo->crc),
 | 
						|
      GLOBAL(pInfo->ExtLocHdr) ? "true":"false"));
 | 
						|
    Trace((stdout, "  incnt = %d  unzip offset into zipfile = %ld\n",
 | 
						|
      GLOBAL(incnt),
 | 
						|
      GLOBAL(cur_zipfile_bufstart)+(GLOBAL(inptr)-GLOBAL(inbuf))));
 | 
						|
 | 
						|
    /* same test as in zipbare(): */
 | 
						|
 | 
						|
#ifdef ZIP10 /* check two bytes */
 | 
						|
    c = hh[RAND_HEAD_LEN-2], b = hh[RAND_HEAD_LEN-1];
 | 
						|
    Trace((stdout,
 | 
						|
      "  (c | (b<<8)) = %04x  (crc >> 16) = %04x  lrec.time = %04x\n",
 | 
						|
      (ush)(c | (b<<8)), (ush)(GLOBAL(lrec.crc32) >> 16),
 | 
						|
      GLOBAL(lrec.last_mod_file_time)));
 | 
						|
    if ((ush)(c | (b<<8)) != (GLOBAL(pInfo->ExtLocHdr) ?
 | 
						|
                              GLOBAL(lrec.last_mod_file_time) :
 | 
						|
                              (ush)(GLOBAL(lrec.crc32) >> 16)))
 | 
						|
        return -1;  /* bad */
 | 
						|
#else
 | 
						|
    b = hh[RAND_HEAD_LEN-1];
 | 
						|
    Trace((stdout, "  b = %02x  (crc >> 24) = %02x  (lrec.time >> 8) = %02x\n",
 | 
						|
      b, (ush)(GLOBAL(lrec.crc32) >> 24),
 | 
						|
      (GLOBAL(lrec.last_mod_file_time) >> 8)));
 | 
						|
    if (b != (GLOBAL(pInfo->ExtLocHdr) ? GLOBAL(lrec.last_mod_file_time) >> 8 :
 | 
						|
        (ush)(GLOBAL(lrec.crc32) >> 24)))
 | 
						|
        return -1;  /* bad */
 | 
						|
#endif
 | 
						|
    /* password OK:  decrypt current buffer contents before leaving */
 | 
						|
    for (n = (long)GLOBAL(incnt) > GLOBAL(csize) ?
 | 
						|
             (int)GLOBAL(csize) : GLOBAL(incnt),
 | 
						|
         p = GLOBAL(inptr); n--; p++)
 | 
						|
        zdecode(*p);
 | 
						|
    return 0;       /* OK */
 | 
						|
 | 
						|
} /* end function testkey() */
 | 
						|
 | 
						|
#endif /* UNZIP && !FUNZIP */
 |