Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6725 | siemargl | 1 | /* |
2 | Copyright (c) 1990-2007 Info-ZIP. All rights reserved. |
||
3 | |||
4 | See the accompanying file LICENSE, version 2005-Feb-10 or later |
||
5 | (the contents of which are also included in (un)zip.h) for terms of use. |
||
6 | If, for some reason, all these files are missing, the Info-ZIP license |
||
7 | also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html |
||
8 | */ |
||
9 | /* |
||
10 | crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] |
||
11 | |||
12 | The main encryption/decryption source code for Info-Zip software was |
||
13 | originally written in Europe. To the best of our knowledge, it can |
||
14 | be freely distributed in both source and object forms from any country, |
||
15 | including the USA under License Exception TSU of the U.S. Export |
||
16 | Administration Regulations (section 740.13(e)) of 6 June 2002. |
||
17 | |||
18 | NOTE on copyright history: |
||
19 | Previous versions of this source package (up to version 2.8) were |
||
20 | not copyrighted and put in the public domain. If you cannot comply |
||
21 | with the Info-Zip LICENSE, you may want to look for one of those |
||
22 | public domain versions. |
||
23 | */ |
||
24 | |||
25 | /* |
||
26 | This encryption code is a direct transcription of the algorithm from |
||
27 | Roger Schlafly, described by Phil Katz in the file appnote.txt. This |
||
28 | file (appnote.txt) is distributed with the PKZIP program (even in the |
||
29 | version without encryption capabilities). |
||
30 | */ |
||
31 | |||
32 | #define ZCRYPT_INTERNAL |
||
33 | #include "zip.h" |
||
34 | #include "crypt.h" |
||
35 | #include "ttyio.h" |
||
36 | |||
37 | #if CRYPT |
||
38 | |||
39 | #ifndef FALSE |
||
40 | # define FALSE 0 |
||
41 | #endif |
||
42 | |||
43 | #ifdef ZIP |
||
44 | /* For the encoding task used in Zip (and ZipCloak), we want to initialize |
||
45 | the crypt algorithm with some reasonably unpredictable bytes, see |
||
46 | the crypthead() function. The standard rand() library function is |
||
47 | used to supply these `random' bytes, which in turn is initialized by |
||
48 | a srand() call. The srand() function takes an "unsigned" (at least 16bit) |
||
49 | seed value as argument to determine the starting point of the rand() |
||
50 | pseudo-random number generator. |
||
51 | This seed number is constructed as "Seed = Seed1 .XOR. Seed2" with |
||
52 | Seed1 supplied by the current time (= "(unsigned)time()") and Seed2 |
||
53 | as some (hopefully) nondeterministic bitmask. On many (most) systems, |
||
54 | we use some "process specific" number, as the PID or something similar, |
||
55 | but when nothing unpredictable is available, a fixed number may be |
||
56 | sufficient. |
||
57 | NOTE: |
||
58 | 1.) This implementation requires the availability of the following |
||
59 | standard UNIX C runtime library functions: time(), rand(), srand(). |
||
60 | On systems where some of them are missing, the environment that |
||
61 | incorporates the crypt routines must supply suitable replacement |
||
62 | functions. |
||
63 | 2.) It is a very bad idea to use a second call to time() to set the |
||
64 | "Seed2" number! In this case, both "Seed1" and "Seed2" would be |
||
65 | (almost) identical, resulting in a (mostly) "zero" constant seed |
||
66 | number passed to srand(). |
||
67 | |||
68 | The implementation environment defined in the "zip.h" header should |
||
69 | supply a reasonable definition for ZCR_SEED2 (an unsigned number; for |
||
70 | most implementations of rand() and srand(), only the lower 16 bits are |
||
71 | significant!). An example that works on many systems would be |
||
72 | "#define ZCR_SEED2 (unsigned)getpid()". |
||
73 | The default definition for ZCR_SEED2 supplied below should be regarded |
||
74 | as a fallback to allow successful compilation in "beta state" |
||
75 | environments. |
||
76 | */ |
||
77 | # include |
||
78 | /* "last resort" source for second part of crypt seed pattern */ |
||
79 | # ifndef ZCR_SEED2 |
||
80 | # define ZCR_SEED2 (unsigned)3141592654L /* use PI as default pattern */ |
||
81 | # endif |
||
82 | # ifdef GLOBAL /* used in Amiga system headers, maybe others too */ |
||
83 | # undef GLOBAL |
||
84 | # endif |
||
85 | # define GLOBAL(g) g |
||
86 | #else /* !ZIP */ |
||
87 | # define GLOBAL(g) G.g |
||
88 | #endif /* ?ZIP */ |
||
89 | |||
90 | |||
91 | #ifdef UNZIP |
||
92 | /* char *key = (char *)NULL; moved to globals.h */ |
||
93 | # ifndef FUNZIP |
||
94 | local int testp OF((__GPRO__ ZCONST uch *h)); |
||
95 | local int testkey OF((__GPRO__ ZCONST uch *h, ZCONST char *key)); |
||
96 | # endif |
||
97 | #endif /* UNZIP */ |
||
98 | |||
99 | #ifndef UNZIP /* moved to globals.h for UnZip */ |
||
100 | # ifndef Z_UINT4_DEFINED |
||
101 | # if !defined(NO_LIMITS_H) |
||
102 | # if (defined(UINT_MAX) && (UINT_MAX == 0xffffffffUL)) |
||
103 | typedef unsigned int z_uint4; |
||
104 | # define Z_UINT4_DEFINED |
||
105 | # else |
||
106 | # if (defined(ULONG_MAX) && (ULONG_MAX == 0xffffffffUL)) |
||
107 | typedef unsigned long z_uint4; |
||
108 | # define Z_UINT4_DEFINED |
||
109 | # else |
||
110 | # if (defined(USHRT_MAX) && (USHRT_MAX == 0xffffffffUL)) |
||
111 | typedef unsigned short z_uint4; |
||
112 | # define Z_UINT4_DEFINED |
||
113 | # endif |
||
114 | # endif |
||
115 | # endif |
||
116 | # endif /* !NO_LIMITS_H */ |
||
117 | # endif /* !Z_UINT4_DEFINED */ |
||
118 | # ifndef Z_UINT4_DEFINED |
||
119 | typedef ulg z_uint4; |
||
120 | # define Z_UINT4_DEFINED |
||
121 | # endif |
||
122 | local z_uint4 keys[3]; /* keys defining the pseudo-random sequence */ |
||
123 | #endif /* !UNZIP */ |
||
124 | |||
125 | #ifndef Trace |
||
126 | # ifdef CRYPT_DEBUG |
||
127 | # define Trace(x) fprintf x |
||
128 | # else |
||
129 | # define Trace(x) |
||
130 | # endif |
||
131 | #endif |
||
132 | |||
133 | #include "crc32.h" |
||
134 | |||
135 | #ifdef IZ_CRC_BE_OPTIMIZ |
||
136 | local z_uint4 near crycrctab[256]; |
||
137 | local z_uint4 near *cry_crctb_p = NULL; |
||
138 | local z_uint4 near *crytab_init OF((__GPRO)); |
||
139 | # define CRY_CRC_TAB cry_crctb_p |
||
140 | # undef CRC32 |
||
141 | # define CRC32(c, b, crctab) (crctab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) |
||
142 | #else |
||
143 | # define CRY_CRC_TAB CRC_32_TAB |
||
144 | #endif /* ?IZ_CRC_BE_OPTIMIZ */ |
||
145 | |||
146 | /*********************************************************************** |
||
147 | * Return the next byte in the pseudo-random sequence |
||
148 | */ |
||
149 | int decrypt_byte(__G) |
||
150 | __GDEF |
||
151 | { |
||
152 | unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an |
||
153 | * unpredictable manner on 16-bit systems; not a problem |
||
154 | * with any known compiler so far, though */ |
||
155 | |||
156 | temp = ((unsigned)GLOBAL(keys[2]) & 0xffff) | 2; |
||
157 | return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); |
||
158 | } |
||
159 | |||
160 | /*********************************************************************** |
||
161 | * Update the encryption keys with the next byte of plain text |
||
162 | */ |
||
163 | int update_keys(__G__ c) |
||
164 | __GDEF |
||
165 | int c; /* byte of plain text */ |
||
166 | { |
||
167 | GLOBAL(keys[0]) = CRC32(GLOBAL(keys[0]), c, CRY_CRC_TAB); |
||
168 | GLOBAL(keys[1]) = (GLOBAL(keys[1]) |
||
169 | + (GLOBAL(keys[0]) & 0xff)) |
||
170 | * 134775813L + 1; |
||
171 | { |
||
172 | register int keyshift = (int)(GLOBAL(keys[1]) >> 24); |
||
173 | GLOBAL(keys[2]) = CRC32(GLOBAL(keys[2]), keyshift, CRY_CRC_TAB); |
||
174 | } |
||
175 | return c; |
||
176 | } |
||
177 | |||
178 | |||
179 | /*********************************************************************** |
||
180 | * Initialize the encryption keys and the random header according to |
||
181 | * the given password. |
||
182 | */ |
||
183 | void init_keys(__G__ passwd) |
||
184 | __GDEF |
||
185 | ZCONST char *passwd; /* password string with which to modify keys */ |
||
186 | { |
||
187 | #ifdef IZ_CRC_BE_OPTIMIZ |
||
188 | if (cry_crctb_p == NULL) { |
||
189 | cry_crctb_p = crytab_init(__G); |
||
190 | } |
||
191 | #endif |
||
192 | GLOBAL(keys[0]) = 305419896L; |
||
193 | GLOBAL(keys[1]) = 591751049L; |
||
194 | GLOBAL(keys[2]) = 878082192L; |
||
195 | while (*passwd != '\0') { |
||
196 | update_keys(__G__ (int)*passwd); |
||
197 | passwd++; |
||
198 | } |
||
199 | } |
||
200 | |||
201 | |||
202 | /*********************************************************************** |
||
203 | * Initialize the local copy of the table of precomputed crc32 values. |
||
204 | * Whereas the public crc32-table is optimized for crc32 calculations |
||
205 | * on arrays of bytes, the crypt code needs the crc32 values in an |
||
206 | * byte-order-independent form as 32-bit unsigned numbers. On systems |
||
207 | * with Big-Endian byte order using the optimized crc32 code, this |
||
208 | * requires inverting the byte-order of the values in the |
||
209 | * crypt-crc32-table. |
||
210 | */ |
||
211 | #ifdef IZ_CRC_BE_OPTIMIZ |
||
212 | local z_uint4 near *crytab_init(__G) |
||
213 | __GDEF |
||
214 | { |
||
215 | int i; |
||
216 | |||
217 | for (i = 0; i < 256; i++) { |
||
218 | crycrctab[i] = REV_BE(CRC_32_TAB[i]); |
||
219 | } |
||
220 | return crycrctab; |
||
221 | } |
||
222 | #endif |
||
223 | |||
224 | |||
225 | #ifdef ZIP |
||
226 | |||
227 | /*********************************************************************** |
||
228 | * Write encryption header to file zfile using the password passwd |
||
229 | * and the cyclic redundancy check crc. |
||
230 | */ |
||
231 | void crypthead(passwd, crc, zfile) |
||
232 | ZCONST char *passwd; /* password string */ |
||
233 | ulg crc; /* crc of file being encrypted */ |
||
234 | FILE *zfile; /* where to write header */ |
||
235 | { |
||
236 | int n; /* index in random header */ |
||
237 | int t; /* temporary */ |
||
238 | int c; /* random byte */ |
||
239 | uch header[RAND_HEAD_LEN]; /* random header */ |
||
240 | static unsigned calls = 0; /* ensure different random header each time */ |
||
241 | |||
242 | /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the |
||
243 | * output of rand() to get less predictability, since rand() is |
||
244 | * often poorly implemented. |
||
245 | */ |
||
246 | if (++calls == 1) { |
||
247 | srand((unsigned)time(NULL) ^ ZCR_SEED2); |
||
248 | } |
||
249 | init_keys(passwd); |
||
250 | for (n = 0; n < RAND_HEAD_LEN-2; n++) { |
||
251 | c = (rand() >> 7) & 0xff; |
||
252 | header[n] = (uch)zencode(c, t); |
||
253 | } |
||
254 | /* Encrypt random header (last two bytes is high word of crc) */ |
||
255 | init_keys(passwd); |
||
256 | for (n = 0; n < RAND_HEAD_LEN-2; n++) { |
||
257 | header[n] = (uch)zencode(header[n], t); |
||
258 | } |
||
259 | header[RAND_HEAD_LEN-2] = (uch)zencode((int)(crc >> 16) & 0xff, t); |
||
260 | header[RAND_HEAD_LEN-1] = (uch)zencode((int)(crc >> 24) & 0xff, t); |
||
261 | fwrite(header, 1, RAND_HEAD_LEN, f); |
||
262 | } |
||
263 | |||
264 | |||
265 | #ifdef UTIL |
||
266 | |||
267 | /*********************************************************************** |
||
268 | * Encrypt the zip entry described by z from file source to file dest |
||
269 | * using the password passwd. Return an error code in the ZE_ class. |
||
270 | */ |
||
271 | int zipcloak(z, source, dest, passwd) |
||
272 | struct zlist far *z; /* zip entry to encrypt */ |
||
273 | FILE *source, *dest; /* source and destination files */ |
||
274 | ZCONST char *passwd; /* password string */ |
||
275 | { |
||
276 | int c; /* input byte */ |
||
277 | int res; /* result code */ |
||
278 | ulg n; /* holds offset and counts size */ |
||
279 | ush flag; /* previous flags */ |
||
280 | int t; /* temporary */ |
||
281 | int ztemp; /* temporary storage for zencode value */ |
||
282 | |||
283 | /* Set encrypted bit, clear extended local header bit and write local |
||
284 | header to output file */ |
||
285 | if ((n = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP; |
||
286 | z->off = n; |
||
287 | flag = z->flg; |
||
288 | z->flg |= 1, z->flg &= ~8; |
||
289 | z->lflg |= 1, z->lflg &= ~8; |
||
290 | z->siz += RAND_HEAD_LEN; |
||
291 | if ((res = putlocal(z, dest)) != ZE_OK) return res; |
||
292 | |||
293 | /* Initialize keys with password and write random header */ |
||
294 | crypthead(passwd, z->crc, dest); |
||
295 | |||
296 | /* Skip local header in input file */ |
||
297 | if (fseek(source, (long)((4 + LOCHEAD) + (ulg)z->nam + (ulg)z->ext), |
||
298 | SEEK_CUR)) { |
||
299 | return ferror(source) ? ZE_READ : ZE_EOF; |
||
300 | } |
||
301 | |||
302 | /* Encrypt data */ |
||
303 | for (n = z->siz - RAND_HEAD_LEN; n; n--) { |
||
304 | if ((c = getc(source)) == EOF) { |
||
305 | return ferror(source) ? ZE_READ : ZE_EOF; |
||
306 | } |
||
307 | ztemp = zencode(c, t); |
||
308 | putc(ztemp, dest); |
||
309 | } |
||
310 | /* Skip extended local header in input file if there is one */ |
||
311 | if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) { |
||
312 | return ferror(source) ? ZE_READ : ZE_EOF; |
||
313 | } |
||
314 | if (fflush(dest) == EOF) return ZE_TEMP; |
||
315 | |||
316 | /* Update number of bytes written to output file */ |
||
317 | tempzn += (4 + LOCHEAD) + z->nam + z->ext + z->siz; |
||
318 | |||
319 | return ZE_OK; |
||
320 | } |
||
321 | |||
322 | /*********************************************************************** |
||
323 | * Decrypt the zip entry described by z from file source to file dest |
||
324 | * using the password passwd. Return an error code in the ZE_ class. |
||
325 | */ |
||
326 | int zipbare(z, source, dest, passwd) |
||
327 | struct zlist far *z; /* zip entry to encrypt */ |
||
328 | FILE *source, *dest; /* source and destination files */ |
||
329 | ZCONST char *passwd; /* password string */ |
||
330 | { |
||
331 | #ifdef ZIP10 |
||
332 | int c0 /* byte preceding the last input byte */ |
||
333 | #endif |
||
334 | int c1; /* last input byte */ |
||
335 | ulg offset; /* used for file offsets */ |
||
336 | ulg size; /* size of input data */ |
||
337 | int r; /* size of encryption header */ |
||
338 | int res; /* return code */ |
||
339 | ush flag; /* previous flags */ |
||
340 | |||
341 | /* Save position and skip local header in input file */ |
||
342 | if ((offset = (ulg)ftell(source)) == (ulg)-1L || |
||
343 | fseek(source, (long)((4 + LOCHEAD) + (ulg)z->nam + (ulg)z->ext), |
||
344 | SEEK_CUR)) { |
||
345 | return ferror(source) ? ZE_READ : ZE_EOF; |
||
346 | } |
||
347 | /* Initialize keys with password */ |
||
348 | init_keys(passwd); |
||
349 | |||
350 | /* Decrypt encryption header, save last two bytes */ |
||
351 | c1 = 0; |
||
352 | for (r = RAND_HEAD_LEN; r; r--) { |
||
353 | #ifdef ZIP10 |
||
354 | c0 = c1; |
||
355 | #endif |
||
356 | if ((c1 = getc(source)) == EOF) { |
||
357 | return ferror(source) ? ZE_READ : ZE_EOF; |
||
358 | } |
||
359 | Trace((stdout, " (%02x)", c1)); |
||
360 | zdecode(c1); |
||
361 | Trace((stdout, " %02x", c1)); |
||
362 | } |
||
363 | Trace((stdout, "\n")); |
||
364 | |||
365 | /* If last two bytes of header don't match crc (or file time in the |
||
366 | * case of an extended local header), back up and just copy. For |
||
367 | * pkzip 2.0, the check has been reduced to one byte only. |
||
368 | */ |
||
369 | #ifdef ZIP10 |
||
370 | if ((ush)(c0 | (c1<<8)) != |
||
371 | (z->flg & 8 ? (ush) z->tim & 0xffff : (ush)(z->crc >> 16))) { |
||
372 | #else |
||
373 | if ((ush)c1 != (z->flg & 8 ? (ush) z->tim >> 8 : (ush)(z->crc >> 24))) { |
||
374 | #endif |
||
375 | if (fseek(source, offset, SEEK_SET)) { |
||
376 | return ferror(source) ? ZE_READ : ZE_EOF; |
||
377 | } |
||
378 | if ((res = zipcopy(z, source, dest)) != ZE_OK) return res; |
||
379 | return ZE_MISS; |
||
380 | } |
||
381 | |||
382 | /* Clear encrypted bit and local header bit, and write local header to |
||
383 | output file */ |
||
384 | if ((offset = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP; |
||
385 | z->off = offset; |
||
386 | flag = z->flg; |
||
387 | z->flg &= ~9; |
||
388 | z->lflg &= ~9; |
||
389 | z->siz -= RAND_HEAD_LEN; |
||
390 | if ((res = putlocal(z, dest)) != ZE_OK) return res; |
||
391 | |||
392 | /* Decrypt data */ |
||
393 | for (size = z->siz; size; size--) { |
||
394 | if ((c1 = getc(source)) == EOF) { |
||
395 | return ferror(source) ? ZE_READ : ZE_EOF; |
||
396 | } |
||
397 | zdecode(c1); |
||
398 | putc(c1, dest); |
||
399 | } |
||
400 | /* Skip extended local header in input file if there is one */ |
||
401 | if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) { |
||
402 | return ferror(source) ? ZE_READ : ZE_EOF; |
||
403 | } |
||
404 | if (fflush(dest) == EOF) return ZE_TEMP; |
||
405 | |||
406 | /* Update number of bytes written to output file */ |
||
407 | tempzn += (4 + LOCHEAD) + z->nam + z->ext + z->siz; |
||
408 | |||
409 | return ZE_OK; |
||
410 | } |
||
411 | |||
412 | |||
413 | #else /* !UTIL */ |
||
414 | |||
415 | /*********************************************************************** |
||
416 | * If requested, encrypt the data in buf, and in any case call fwrite() |
||
417 | * with the arguments to zfwrite(). Return what fwrite() returns. |
||
418 | * |
||
419 | * A bug has been found when encrypting large files. See trees.c |
||
420 | * for details and the fix. |
||
421 | */ |
||
422 | unsigned zfwrite(buf, item_size, nb, f) |
||
423 | zvoid *buf; /* data buffer */ |
||
424 | extent item_size; /* size of each item in bytes */ |
||
425 | extent nb; /* number of items */ |
||
426 | FILE *f; /* file to write to */ |
||
427 | { |
||
428 | int t; /* temporary */ |
||
429 | |||
430 | if (key != (char *)NULL) { /* key is the global password pointer */ |
||
431 | ulg size; /* buffer size */ |
||
432 | char *p = (char*)buf; /* steps through buffer */ |
||
433 | |||
434 | /* Encrypt data in buffer */ |
||
435 | for (size = item_size*(ulg)nb; size != 0; p++, size--) { |
||
436 | *p = (char)zencode(*p, t); |
||
437 | } |
||
438 | } |
||
439 | /* Write the buffer out */ |
||
440 | return fwrite(buf, item_size, nb, f); |
||
441 | } |
||
442 | |||
443 | #endif /* ?UTIL */ |
||
444 | #endif /* ZIP */ |
||
445 | |||
446 | |||
447 | #if (defined(UNZIP) && !defined(FUNZIP)) |
||
448 | |||
449 | /*********************************************************************** |
||
450 | * Get the password and set up keys for current zipfile member. |
||
451 | * Return PK_ class error. |
||
452 | */ |
||
453 | int decrypt(__G__ passwrd) |
||
454 | __GDEF |
||
455 | ZCONST char *passwrd; |
||
456 | { |
||
457 | ush b; |
||
458 | int n, r; |
||
459 | uch h[RAND_HEAD_LEN]; |
||
460 | |||
461 | Trace((stdout, "\n[incnt = %d]: ", GLOBAL(incnt))); |
||
462 | |||
463 | /* get header once (turn off "encrypted" flag temporarily so we don't |
||
464 | * try to decrypt the same data twice) */ |
||
465 | GLOBAL(pInfo->encrypted) = FALSE; |
||
466 | defer_leftover_input(__G); |
||
467 | for (n = 0; n < RAND_HEAD_LEN; n++) { |
||
468 | b = NEXTBYTE; |
||
469 | h[n] = (uch)b; |
||
470 | Trace((stdout, " (%02x)", h[n])); |
||
471 | } |
||
472 | undefer_input(__G); |
||
473 | GLOBAL(pInfo->encrypted) = TRUE; |
||
474 | |||
475 | if (GLOBAL(newzip)) { /* this is first encrypted member in this zipfile */ |
||
476 | GLOBAL(newzip) = FALSE; |
||
477 | if (passwrd != (char *)NULL) { /* user gave password on command line */ |
||
478 | if (!GLOBAL(key)) { |
||
479 | if ((GLOBAL(key) = (char *)malloc(strlen(passwrd)+1)) == |
||
480 | (char *)NULL) |
||
481 | return PK_MEM2; |
||
482 | strcpy(GLOBAL(key), passwrd); |
||
483 | GLOBAL(nopwd) = TRUE; /* inhibit password prompting! */ |
||
484 | } |
||
485 | } else if (GLOBAL(key)) { /* get rid of previous zipfile's key */ |
||
486 | free(GLOBAL(key)); |
||
487 | GLOBAL(key) = (char *)NULL; |
||
488 | } |
||
489 | } |
||
490 | |||
491 | /* if have key already, test it; else allocate memory for it */ |
||
492 | if (GLOBAL(key)) { |
||
493 | if (!testp(__G__ h)) |
||
494 | return PK_COOL; /* existing password OK (else prompt for new) */ |
||
495 | else if (GLOBAL(nopwd)) |
||
496 | return PK_WARN; /* user indicated no more prompting */ |
||
497 | } else if ((GLOBAL(key) = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL) |
||
498 | return PK_MEM2; |
||
499 | |||
500 | /* try a few keys */ |
||
501 | n = 0; |
||
502 | do { |
||
503 | r = (*G.decr_passwd)((zvoid *)&G, &n, GLOBAL(key), IZ_PWLEN+1, |
||
504 | GLOBAL(zipfn), GLOBAL(filename)); |
||
505 | if (r == IZ_PW_ERROR) { /* internal error in fetch of PW */ |
||
506 | free (GLOBAL(key)); |
||
507 | GLOBAL(key) = NULL; |
||
508 | return PK_MEM2; |
||
509 | } |
||
510 | if (r != IZ_PW_ENTERED) { /* user replied "skip" or "skip all" */ |
||
511 | *GLOBAL(key) = '\0'; /* We try the NIL password, ... */ |
||
512 | n = 0; /* and cancel fetch for this item. */ |
||
513 | } |
||
514 | if (!testp(__G__ h)) |
||
515 | return PK_COOL; |
||
516 | if (r == IZ_PW_CANCELALL) /* User replied "Skip all" */ |
||
517 | GLOBAL(nopwd) = TRUE; /* inhibit any further PW prompt! */ |
||
518 | } while (n > 0); |
||
519 | |||
520 | return PK_WARN; |
||
521 | |||
522 | } /* end function decrypt() */ |
||
523 | |||
524 | |||
525 | |||
526 | /*********************************************************************** |
||
527 | * Test the password. Return -1 if bad, 0 if OK. |
||
528 | */ |
||
529 | local int testp(__G__ h) |
||
530 | __GDEF |
||
531 | ZCONST uch *h; |
||
532 | { |
||
533 | int r; |
||
534 | char *key_translated; |
||
535 | |||
536 | /* On systems with "obscure" native character coding (e.g., EBCDIC), |
||
537 | * the first test translates the password to the "main standard" |
||
538 | * character coding. */ |
||
539 | |||
540 | #ifdef STR_TO_CP1 |
||
541 | /* allocate buffer for translated password */ |
||
542 | if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL) |
||
543 | return -1; |
||
544 | /* first try, test password translated "standard" charset */ |
||
545 | r = testkey(__G__ h, STR_TO_CP1(key_translated, GLOBAL(key))); |
||
546 | #else /* !STR_TO_CP1 */ |
||
547 | /* first try, test password as supplied on the extractor's host */ |
||
548 | r = testkey(__G__ h, GLOBAL(key)); |
||
549 | #endif /* ?STR_TO_CP1 */ |
||
550 | |||
551 | #ifdef STR_TO_CP2 |
||
552 | if (r != 0) { |
||
553 | #ifndef STR_TO_CP1 |
||
554 | /* now prepare for second (and maybe third) test with translated pwd */ |
||
555 | if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL) |
||
556 | return -1; |
||
557 | #endif |
||
558 | /* second try, password translated to alternate ("standard") charset */ |
||
559 | r = testkey(__G__ h, STR_TO_CP2(key_translated, GLOBAL(key))); |
||
560 | #ifdef STR_TO_CP3 |
||
561 | if (r != 0) |
||
562 | /* third try, password translated to another "standard" charset */ |
||
563 | r = testkey(__G__ h, STR_TO_CP3(key_translated, GLOBAL(key))); |
||
564 | #endif |
||
565 | #ifndef STR_TO_CP1 |
||
566 | free(key_translated); |
||
567 | #endif |
||
568 | } |
||
569 | #endif /* STR_TO_CP2 */ |
||
570 | |||
571 | #ifdef STR_TO_CP1 |
||
572 | free(key_translated); |
||
573 | if (r != 0) { |
||
574 | /* last resort, test password as supplied on the extractor's host */ |
||
575 | r = testkey(__G__ h, GLOBAL(key)); |
||
576 | } |
||
577 | #endif /* STR_TO_CP1 */ |
||
578 | |||
579 | return r; |
||
580 | |||
581 | } /* end function testp() */ |
||
582 | |||
583 | |||
584 | local int testkey(__G__ h, key) |
||
585 | __GDEF |
||
586 | ZCONST uch *h; /* decrypted header */ |
||
587 | ZCONST char *key; /* decryption password to test */ |
||
588 | { |
||
589 | ush b; |
||
590 | #ifdef ZIP10 |
||
591 | ush c; |
||
592 | #endif |
||
593 | int n; |
||
594 | uch *p; |
||
595 | uch hh[RAND_HEAD_LEN]; /* decrypted header */ |
||
596 | |||
597 | /* set keys and save the encrypted header */ |
||
598 | init_keys(__G__ key); |
||
599 | memcpy(hh, h, RAND_HEAD_LEN); |
||
600 | |||
601 | /* check password */ |
||
602 | for (n = 0; n < RAND_HEAD_LEN; n++) { |
||
603 | zdecode(hh[n]); |
||
604 | Trace((stdout, " %02x", hh[n])); |
||
605 | } |
||
606 | |||
607 | Trace((stdout, |
||
608 | "\n lrec.crc= %08lx crec.crc= %08lx pInfo->ExtLocHdr= %s\n", |
||
609 | GLOBAL(lrec.crc32), GLOBAL(pInfo->crc), |
||
610 | GLOBAL(pInfo->ExtLocHdr) ? "true":"false")); |
||
611 | Trace((stdout, " incnt = %d unzip offset into zipfile = %ld\n", |
||
612 | GLOBAL(incnt), |
||
613 | GLOBAL(cur_zipfile_bufstart)+(GLOBAL(inptr)-GLOBAL(inbuf)))); |
||
614 | |||
615 | /* same test as in zipbare(): */ |
||
616 | |||
617 | #ifdef ZIP10 /* check two bytes */ |
||
618 | c = hh[RAND_HEAD_LEN-2], b = hh[RAND_HEAD_LEN-1]; |
||
619 | Trace((stdout, |
||
620 | " (c | (b<<8)) = %04x (crc >> 16) = %04x lrec.time = %04x\n", |
||
621 | (ush)(c | (b<<8)), (ush)(GLOBAL(lrec.crc32) >> 16), |
||
622 | ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff)))); |
||
623 | if ((ush)(c | (b<<8)) != (GLOBAL(pInfo->ExtLocHdr) ? |
||
624 | ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff) : |
||
625 | (ush)(GLOBAL(lrec.crc32) >> 16))) |
||
626 | return -1; /* bad */ |
||
627 | #else |
||
628 | b = hh[RAND_HEAD_LEN-1]; |
||
629 | Trace((stdout, " b = %02x (crc >> 24) = %02x (lrec.time >> 8) = %02x\n", |
||
630 | b, (ush)(GLOBAL(lrec.crc32) >> 24), |
||
631 | ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff)); |
||
632 | if (b != (GLOBAL(pInfo->ExtLocHdr) ? |
||
633 | ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff : |
||
634 | (ush)(GLOBAL(lrec.crc32) >> 24))) |
||
635 | return -1; /* bad */ |
||
636 | #endif |
||
637 | /* password OK: decrypt current buffer contents before leaving */ |
||
638 | for (n = (long)GLOBAL(incnt) > GLOBAL(csize) ? |
||
639 | (int)GLOBAL(csize) : GLOBAL(incnt), |
||
640 | p = GLOBAL(inptr); n--; p++) |
||
641 | zdecode(*p); |
||
642 | return 0; /* OK */ |
||
643 | |||
644 | } /* end function testkey() */ |
||
645 | |||
646 | #endif /* UNZIP && !FUNZIP */ |
||
647 | |||
648 | #else /* !CRYPT */ |
||
649 | |||
650 | /* something "externally visible" to shut up compiler/linker warnings */ |
||
651 | int zcr_dummy; |
||
652 | |||
653 | #endif /* ?CRYPT */8))><8))>8)),><8)),>8))><8))>>>8))><8))>>>> |