1 /*
2 * Copyright (C) 2001, 2002, and 2003 Roy Keene
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 * email: dact@rkeene.org
19 */
20
21 #include "dact.h"
22 #define __DACT_C
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <ctype.h>
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 #ifdef HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif
32 #ifdef HAVE_STRING_H
33 #include <string.h>
34 #endif
35 #ifdef HAVE_SYS_STAT_H
36 #include <sys/stat.h>
37 #endif
38 #ifdef HAVE_SYS_WAIT_H
39 #include <sys/wait.h>
40 #endif
41 #ifdef HAVE_SYS_TYPES_H
42 #include <sys/types.h>
43 #endif
44 #include "parse.h"
45 #include "dendian.h"
46 #include "crc.h"
47 #include "math.h"
48 #include "dact_common.h"
49 #include "algorithms.h"
50 #include "ciphers.h"
51 #include "module.h"
52 #include "header.h"
53 #include "parse.h"
54 #include "net.h"
55 #include "sfx.h"
56 #include "ui.h"
57 #ifdef HAVE_ZLIB_H
58 #include <zlib.h>
59 #endif
60 #ifdef HAVE_BZLIB_H
61 #include <bzlib.h>
62 #endif
63
64 char dact_nonetwork=0;
65
dact_blksize_calc(int fsize)66 uint32_t dact_blksize_calc(int fsize) {
67 uint32_t ret=0;
68
69 if (fsize==0) return(DACT_BLK_SIZE_DEF);
70 if (fsize<(204800)) {
71 ret=(fsize+5);
72 }
73 if (ret==0) ret=(((int) ((((float) fsize)/102400.0)-(0.9999999)))*65535);
74 if (ret>DACT_BLK_SIZE_MAX) ret=DACT_BLK_SIZE_MAX;
75 return(ret);
76 }
77
dact_config_execute(const char * cmd,unsigned char * options,uint32_t * blksize)78 int dact_config_execute(const char *cmd, unsigned char *options, uint32_t *blksize) {
79 char *line=NULL, *line_s, *item_buf[4]={NULL, NULL, NULL, NULL};
80 int i;
81
82 line_s=line=strdup(cmd);
83 if (line[0]=='#') return(0);
84 while (line[strlen(line)-1]<32) line[strlen(line)-1]='\0';
85 for (i=0;i<4;i++) item_buf[i]=NULL;
86 for (i=0;i<4;i++) {
87 if ((item_buf[i]=strsep(&line, "\t "))==NULL) break;
88 if (item_buf[i][0]==0) i--;
89 }
90 if (item_buf[0]==NULL || item_buf[1]==NULL) return(0); /* This means all commands must have arguments. */
91
92 switch (elfcrc(0, (unsigned char *) item_buf[0], strlen(item_buf[0]))) {
93 case 164209419: /* binary_check */
94 options[DACT_OPT_BINCHK]=!!strcmp(item_buf[1],"off");
95 break;
96 case 9456603: /* version_check */
97 options[DACT_OPT_VERCHK]=!!strcmp(item_buf[1],"off");
98 break;
99 case 204349618: /* module_dir */
100 if ((sizeof(moduledirectory)-strlen(moduledirectory)-1)<=0) break;
101 strncat(moduledirectory,":",sizeof(moduledirectory)-strlen(moduledirectory)-1);
102 strncat(moduledirectory,item_buf[1],sizeof(moduledirectory)-strlen(moduledirectory)-1);
103 break;
104 case 247248556: /* module_load_all */
105 if (strcmp(item_buf[1], "on")==0) {
106 init_modules();
107 load_modules_all(options);
108 }
109 break;
110 case 48402100: /* module_load */
111 case 106360197: /* load_module */
112 init_modules();
113 load_module(item_buf[1], options);
114 break;
115 case 164097267: /* network_access */
116 #ifndef NO_NETWORK
117 dact_nonetwork=!strcmp(item_buf[1],"off");
118 #endif
119 break;
120 case 209445231: /* exclude_algo */
121 i=(atoi(item_buf[1])&0xff);
122 algorithms[i]=DACT_FAILED_ALGO;
123 break;
124 case 168825941: /* block_size */
125 if (blksize!=NULL) {
126 *blksize=atoi2(item_buf[1]);
127 }
128 break;
129 case 162975987: /* use_urls */
130 options[DACT_OPT_URL]=!!strcmp(item_buf[1],"off");
131 break;
132 case 104235033: /* color_ui */
133 dact_ui_setopt(DACT_UI_OPT_COLOR,!!strcmp(item_buf[1],"off"));
134 break;
135 case 164800901: /* module_upgrade */
136 if (strcmp(item_buf[1],"on")==0) options[DACT_OPT_UPGRADE]=1;
137 break;
138 case 63160590: /* pass_use_stdin */
139 case 191551086: /* use_stdin */
140 dact_ui_setopt(DACT_UI_OPT_PASSSTDIN, 1);
141 break;
142 #ifdef DEBUG
143 default:
144 fprintf(stderr, "Unknown command %s (%i)\n",item_buf[0],elfcrc(0,item_buf[0],strlen(item_buf[0])));
145 break;
146 #endif
147 }
148 free(line_s);
149 return(1);
150 }
151
dact_config_loadfile(const char * path,unsigned char * options,uint32_t * blksize)152 void dact_config_loadfile(const char *path, unsigned char *options, uint32_t *blksize) {
153 char *line=NULL;
154 FILE *cfd;
155
156 line=malloc(512);
157 if ((cfd=fopen(path,"r"))==NULL) return;
158 while (!feof(cfd)) {
159 fgets(line, 511, cfd);
160 dact_config_execute(line, options, blksize);
161 }
162 free(line);
163 fclose(cfd);
164 }
165
dact_blk_decompress(unsigned char * ret,const unsigned char * srcbuf,const uint32_t size,const unsigned char * options,const int algo,uint32_t bufsize)166 uint32_t dact_blk_decompress(unsigned char *ret, const unsigned char *srcbuf, const uint32_t size, const unsigned char *options, const int algo, uint32_t bufsize) {
167 uint32_t retval;
168
169 if (algo==0xff) return(0);
170
171 if (algorithms[algo]==NULL) {
172 PRINTERR("Algorithm unavailble.");
173 return(0);
174 }
175
176 retval=algorithms[algo](DACT_MODE_DECMP, NULL, srcbuf, ret, size, bufsize);
177
178 return(retval);
179 }
180
181
dact_blk_compress(unsigned char * algo,unsigned char * ret,const unsigned char * srcbuf,const uint32_t size,const unsigned char * options,uint32_t bufsize)182 uint32_t dact_blk_compress(unsigned char *algo, unsigned char *ret, const unsigned char *srcbuf, const uint32_t size, const unsigned char *options, uint32_t bufsize) {
183 char *tmpbuf, *smallbuf=NULL;
184 int i, highest_algo=0;
185 char smallest_algo;
186 uint32_t smallest_size=-1, x;
187 #ifndef DACT_UNSAFE
188 char *verif_bf=NULL;
189 uint32_t m;
190 if ((verif_bf=malloc(size))==NULL) { PERROR("malloc"); return(0); }
191 #endif
192
193 if ((tmpbuf=malloc(bufsize))==NULL) { PERROR("malloc"); return(0); }
194
195 for (i=0;i<256;i++) {
196 if (algorithms[i]!=NULL && algorithms[i]!=DACT_FAILED_ALGO) highest_algo=i;
197 }
198
199 for (i=0;i<=highest_algo;i++) {
200 if (algorithms[i]!=NULL && algorithms[i]!=DACT_FAILED_ALGO) {
201 x=algorithms[i](DACT_MODE_COMPR, NULL, srcbuf, tmpbuf, size, bufsize);
202 #ifndef DACT_UNSAFE
203 if ((x<smallest_size || smallest_size==-1) && x!=-1) {
204 m=algorithms[i](DACT_MODE_DECMP, NULL, tmpbuf, verif_bf, x, size);
205 if (memcmp(verif_bf, srcbuf,m) || m!=size) {
206 x=-1;
207 if (options[DACT_OPT_COMPLN]) {
208 dact_ui_status(DACT_UI_LVL_ALL, "Compression verification failed (ignoring)");
209 }
210 }
211 }
212 #endif
213 if ((x<smallest_size || smallest_size==-1) && x!=-1) {
214 smallest_size=x;
215 smallest_algo=i;
216 if (smallbuf!=NULL) free(smallbuf);
217 if ((smallbuf=malloc(smallest_size))==NULL) {
218 PERROR("malloc");
219 free(tmpbuf);
220 #ifndef DACT_UNSAFE
221 free(verif_bf);
222 #endif
223 return(0);
224 }
225 memcpy(smallbuf, tmpbuf, smallest_size);
226 }
227
228 if (options[DACT_OPT_VERB]>2) {
229 PRINT_LINE; fprintf(stderr, "dact: \033[%im----| %03i | %-7i | %s\033[0m\n", (smallest_algo==i)*7 , i, x, algorithm_names[i]);
230 }
231
232 }
233 }
234
235 free(tmpbuf);
236 #ifndef DACT_UNSAFE
237 free(verif_bf);
238 #endif
239 if (smallest_size==-1) {
240 return(0);
241 }
242 memcpy(algo, &smallest_algo, sizeof(char));
243 memcpy(ret, smallbuf, smallest_size);
244 /* This was MISSING ! memory leak. */
245 free(smallbuf);
246 return(smallest_size);
247 }
248
dact_process_file(const int src,const int dest,const int mode,const unsigned char * options,const char * filename,uint32_t * crcs,uint32_t dact_blksize,int cipher)249 uint64_t dact_process_file(const int src, const int dest, const int mode, const unsigned char *options, const char *filename, uint32_t *crcs, uint32_t dact_blksize, int cipher) {
250 struct stat filestats;
251 FILE *extd_urlfile;
252 char *file_extd_urls[256];
253 unsigned char algo;
254 char ch;
255 char *hdr_buf, *keybuf=NULL, *tmpbuf=NULL;
256 unsigned char *in_buf, *out_buf;
257 char version[3]={DACT_VER_MAJOR, DACT_VER_MINOR, DACT_VER_REVISION};
258 char file_opts=0;
259 uint32_t bytes_read, retsize;
260 uint64_t filesize=0, fileoutsize=0, out_bufsize=0;
261 uint32_t blk_cnt=0, file_extd_size=0, blksize=0, blksize_uncomp=0;
262 uint32_t magic=0, file_extd_read=0, file_extd_urlcnt=0;
263 int hdr_reg_size=28;
264 int blksize_size;
265 int x=0, new_fd, canlseek=0;
266 ssize_t offset=0;
267
268 if (fstat(src, &filestats)<0) {
269 PERROR("fstat");
270 return(0);
271 }
272
273 if (mode==DACT_MODE_COMPR) {
274 blksize=dact_blksize;
275 if (blksize==0) {
276 blksize=dact_blksize_calc(filestats.st_size);
277 }
278
279 if (options[DACT_OPT_SFX]) {
280 offset=sfx_init_compress(dest);
281 if (offset<0) {
282 PRINTERR("Couldn't initialize self-extracting header.");
283 return(0);
284 }
285 dact_hdr_ext_regn(DACT_HDR_SFXLEN, offset, sizeof(offset));
286 }
287
288 out_bufsize=blksize*2;
289 if (((in_buf=malloc(blksize))==NULL) || \
290 ((out_buf=malloc(out_bufsize))==NULL)) {
291 PERROR("malloc");
292 return(0);
293 }
294
295 dact_ui_setup(((float) (filestats.st_size/blksize)+0.9999));
296 if (cipher!=-1) {
297 dact_hdr_ext_regn(DACT_HDR_CIPHER, cipher, sizeof(cipher));
298 keybuf=malloc(DACT_KEY_SIZE);
299 ciphers[cipher](NULL, NULL, 0, keybuf, DACT_MODE_CINIT+DACT_MODE_CENC);
300
301 }
302
303 blksize_size=BYTESIZE(blksize);
304
305 if (!options[DACT_OPT_ORIG] && filename!=NULL)
306 dact_hdr_ext_regs(DACT_HDR_NAME, filename, strlen(filename));
307 file_extd_size=(dact_hdr_ext_size()+14); /* The +14 is for crc0 and crc1 */
308 write_de(dest, DACT_MAGIC_NUMBER, 4);
309 write(dest, &version[0], 1);
310 write(dest, &version[1], 1);
311 write(dest, &version[2], 1);
312 write_de(dest, 0, 8); /* Place holder for ORIG FILE SIZE */
313 write_de(dest, 0, 4); /* Place holder for NUM BLOCKS */
314 write_de(dest, blksize, 4);
315 write_de(dest, file_opts, 1); /* XXX: Option byte... Or not? */
316 write_de(dest, file_extd_size, 4); /* Place holder for SIZEOF EXTENDED DTA */
317 /* Fill the header with NOPs incase we can't come back and put the CRCs */
318 ch=DACT_HDR_NOP;
319 for (x=0;x<file_extd_size;x++) write(dest, &ch, 1);
320
321 if (options[DACT_OPT_VERB]>1) {
322 PRINTERR("Blk | Algo | Size | Name");
323 PRINTERR("----+------+---------+---------------------------");
324 }
325
326 memset(in_buf, 0, blksize);
327 while ( (bytes_read=read_f(src, in_buf, blksize))>0) {
328 filesize+=bytes_read;
329 blk_cnt++;
330
331 retsize=dact_blk_compress(&algo, out_buf, in_buf, blksize, options, out_bufsize);
332
333 /* CIPHER the data if an encryption algorithm is specified. */
334 if (cipher!=-1) {
335 tmpbuf=malloc(retsize*2);
336 x=ciphers[cipher](out_buf, tmpbuf, retsize, keybuf, DACT_MODE_CENC);
337 memcpy(out_buf,tmpbuf,x);
338 free(tmpbuf);
339 }
340
341 if (retsize>0) {
342 if (options[DACT_OPT_VERB]>1) {
343 if (options[DACT_OPT_VERB]>2) {
344 PRINTERR("^^^\\ /^^^^\\ /^^^^^^^\\ /^^^^^^^^^^^^^^^^^^^^^^^^^^");
345 }
346 PRINT_LINE; fprintf(stderr, "dact: %03i | %03i | %-7i | %s\n",blk_cnt,algo,retsize,algorithm_names[algo]);
347 if (options[DACT_OPT_VERB]>2) {
348 PRINTERR("___/ \\____/ \\_______/ \\__________________________");
349 }
350 }
351
352
353 dact_ui_incrblkcnt(1);
354 dact_ui_status(DACT_UI_LVL_GEN, "Algorithm ");
355 dact_ui_status_append(DACT_UI_LVL_GEN,algorithm_names[algo]);
356
357 crcs[0]=crc(crcs[0], out_buf, retsize);
358 /* Do not generate a CRC of the plaintext if encrypting */
359 if (cipher==-1) {
360 crcs[1]=crc(crcs[1], in_buf, blksize);
361 }
362
363 if (!options[DACT_OPT_HDONLY]) {
364 write(dest, &algo, 1);
365 write_de(dest, retsize, blksize_size);
366
367 if (write(dest, out_buf, retsize)!=retsize) {
368 PERROR("write");
369 free(in_buf);
370 free(out_buf);
371 return(0);
372 }
373 }
374 } else {
375 PRINTERR("Compression resulted in 0-byte block.");
376 free(in_buf);
377 free(out_buf);
378 return(0);
379 }
380 memset(in_buf, 0, blksize);
381 }
382
383 if (bytes_read<0) {
384 PERROR("read");
385 }
386
387 free(in_buf);
388 free(out_buf);
389
390 /* Put the filesize and file block count in the header, if possible. */
391 if (lseek_net(dest, offset+7, SEEK_SET)<0) {
392 /* If we can't rewind the stream, put magic+fileisze */
393 write_de(dest, DACT_MAGIC_PEOF, 4);
394 write_de(dest, filesize, 8);
395 } else {
396 write_de(dest, filesize, 8);
397 write_de(dest, blk_cnt, 4);
398 }
399
400 if (lseek_net(dest, offset+hdr_reg_size, SEEK_SET)>0) {
401 if (!options[DACT_OPT_NOCRC]) {
402 dact_hdr_ext_regn(DACT_HDR_CRC0, crcs[0], 4);
403 dact_hdr_ext_regn(DACT_HDR_CRC1, crcs[1], 4);
404 }
405 write(dest, dact_hdr_ext_data(), dact_hdr_ext_size());
406 }
407
408 dact_hdr_ext_clear();
409
410 return(filesize);
411 }
412
413 if (mode==DACT_MODE_DECMP) {
414
415 dact_ui_status(DACT_UI_LVL_GEN, "Decompressing.");
416
417 dact_hdr_ext_clear();
418
419 read_de(src, &magic, 4, sizeof(magic));
420
421 if (magic!=DACT_MAGIC_NUMBER) {
422 dact_ui_status(DACT_UI_LVL_GEN, "Bad DACT magic, checking others...");
423 return(dact_process_other(src,dest,magic,options));
424 }
425
426 read(src, &version[0], 1);
427 read(src, &version[1], 1);
428 read(src, &version[2], 1);
429 #ifndef DACT_DONT_SUPPORT_OLDDACT
430 if (DACT_VERS(version[0], version[1], version[2])<DACT_VERS(0, 8, 39)) {
431 PRINTERR("**WARNING** This file uses the old DACT file header, support will go away in future versions for this.");
432 read_de(src, &filesize, 4, sizeof(filesize));
433 hdr_reg_size=24;
434 } else {
435 read_de(src, &filesize, 8, sizeof(filesize));
436 }
437 #else
438 read_de(src, &filesize, 8, sizeof(filesize));
439 #endif
440 read_de(src, &blk_cnt, 4, sizeof(blk_cnt));
441 read_de(src, &blksize_uncomp, 4, sizeof(blksize_uncomp));
442 read(src, &file_opts, 1);
443 read_de(src, &file_extd_size, 4, sizeof(file_extd_size));
444
445
446
447 while (file_extd_read<file_extd_size) {
448 x=0;
449 read(src, &ch, 1);
450 if (ch!=DACT_HDR_NOP) read_de(src, &x, 2, sizeof(x));
451 switch (ch) {
452 case DACT_HDR_CRC0:
453 read_de(src, &crcs[2], 4, sizeof(crcs[2]));
454 if (crcs[4]!=0 && crcs[2]!=crcs[4]) {
455 dact_ui_status(DACT_UI_LVL_GEN, "CRC error.");
456 if (!options[DACT_OPT_NOCRC])
457 return(0);
458 }
459 break;
460 case DACT_HDR_CRC1:
461 read_de(src, &crcs[3], 4, sizeof(crcs[3]));
462 if (crcs[5]!=0 && crcs[3]!=crcs[5]) {
463 dact_ui_status(DACT_UI_LVL_GEN, "CRC error.");
464 if (!options[DACT_OPT_NOCRC])
465 return(0);
466 }
467 break;
468 /*
469
470 XXX: Todo, make this do something...
471 case DACT_HDR_NAME:
472 break;
473 */
474 case DACT_HDR_URL:
475 hdr_buf=malloc(x+1);
476 read_f(src, hdr_buf, x);
477 hdr_buf[x]=0;
478 file_extd_urls[file_extd_urlcnt++]=parse_url_subst(hdr_buf,filename);
479 free(hdr_buf);
480 break;
481 case DACT_HDR_URLFILE:
482 hdr_buf=malloc(x+1);
483 read_f(src, hdr_buf, x);
484 hdr_buf[x]=0;
485 extd_urlfile=fopen(hdr_buf, "r");
486 free(hdr_buf); /* We shouldn't need this anymore. */
487 if (extd_urlfile==NULL) break;
488 hdr_buf=malloc(4096);
489 while (1) {
490 fgets(hdr_buf, 4095, extd_urlfile);
491 if (feof(extd_urlfile)) break;
492 hdr_buf=strsep(&hdr_buf,"\n");
493 file_extd_urls[file_extd_urlcnt++]=parse_url_subst(hdr_buf,filename);
494 }
495 free(hdr_buf);
496 break;
497 case DACT_HDR_DESC:
498 hdr_buf=malloc(x+1);
499 read_f(src, hdr_buf, x);
500 hdr_buf[x]=0;
501 fprintf(stderr, "DESC: %s\n",hdr_buf);
502 free(hdr_buf);
503 break;
504 case DACT_HDR_CIPHER:
505 read_de(src, &cipher, x, sizeof(cipher));
506 break;
507 case DACT_HDR_NOP:
508 x=-2;
509 break;
510 case DACT_HDR_SFXLEN:
511 read_de(src, &offset, x, sizeof(offset));
512 break;
513 default:
514 hdr_buf=malloc(x);
515 read_f(src, hdr_buf, x);
516 free(hdr_buf);
517 break;
518 }
519
520
521
522 file_extd_read+=(x+3);
523 }
524
525 if (options[DACT_OPT_URL]) {
526 for (x=0;x<file_extd_urlcnt;x++) {
527 dact_ui_status(DACT_UI_LVL_GEN,"Trying to get remote url ");
528 dact_ui_status_append(DACT_UI_LVL_SPEC, file_extd_urls[x]);
529 if ((new_fd=open_net(file_extd_urls[x],O_RDONLY,0))<0) {
530 dact_ui_status(DACT_UI_LVL_GEN, "Failed.");
531 continue;
532 }
533 close(src);
534 crcs[4]=crcs[2];
535 crcs[5]=crcs[3];
536 return(dact_process_file(new_fd, dest, mode, options, filename, crcs, blksize_uncomp, cipher));
537 }
538 }
539
540
541 /*
542 XXX: Even if we don't resolve it here, we can resolve it later...
543 Should we even bother to do it here if we can?
544
545 XXX: When CAN'T we rewind a read stream?
546 When it's a pipe
547
548 */
549 if (filesize==0) {
550 /* See if we can rewind our stream, so when we get to the end, we can come back! */
551 if (lseek_net(src, offset+1, SEEK_SET)==(offset+1)) { /* MAJOR BUG HERE! was: lseek(src,1,SEEK_SET)==0 which will always be false. */
552 canlseek=1;
553 #ifndef DACT_DONT_SUPPORT_OLDDACT
554 if (DACT_VERS(version[0], version[1], version[2])<DACT_VERS(0, 8, 39)) {
555 PRINTERR("**WARNING** This file uses the old DACT file header, support will go away in future versions for this.");
556 lseek_net(src, -8, SEEK_END);
557 read_de(src, &magic, 4, sizeof(magic));
558 read_de(src, &filesize, 4, sizeof(filesize));
559 hdr_reg_size=24;
560 } else {
561 lseek_net(src, -12, SEEK_END);
562 read_de(src, &magic, 4, sizeof(magic));
563 read_de(src, &filesize, 8, sizeof(filesize));
564 }
565 #else
566 lseek_net(src, -12, SEEK_END);
567 read_de(src, &magic, 4, sizeof(magic));
568 read_de(src, &filesize, 8, sizeof(filesize));
569 #endif
570 if (magic!=DACT_MAGIC_PEOF) {
571 dact_ui_status(DACT_UI_LVL_GEN, "File is corrupt.");
572 filesize=0;
573 }
574 lseek_net(src, offset+hdr_reg_size+file_extd_size, SEEK_SET);
575 } else {
576 canlseek=0;
577 }
578 }
579
580 out_bufsize=blksize_uncomp;
581 if (((out_buf=malloc(out_bufsize))==NULL)) {
582 PERROR("malloc");
583 return(0);
584 }
585
586 blksize_size=BYTESIZE(blksize_uncomp);
587
588 dact_ui_setup((int)(((float) filesize/(float) blksize_uncomp)+0.9999));
589
590 if (cipher!=-1) {
591 keybuf=malloc(DACT_KEY_SIZE);
592 ciphers[cipher](NULL, NULL, 0, keybuf, DACT_MODE_CINIT+DACT_MODE_CDEC);
593
594 }
595
596
597
598 while (1) {
599 if (read(src, &algo, 1)==0) break;
600 if (algo==0xff) break; /* 0xff is reserved for EOF */
601
602 read_de(src, &blksize, blksize_size, sizeof(blksize));
603
604 if ((in_buf=malloc(blksize))==NULL) {
605 PERROR("malloc");
606 free(out_buf);
607 return(0);
608 }
609
610 read_f(src, in_buf, blksize);
611
612 #ifndef DACT_DONT_SUPPORT_OLDDACT
613 if (DACT_VERS(version[0], version[1], version[2])<DACT_VERS(0, 8, 39)) {
614 PRINTERR("**WARNING** This file uses the old DACT file header, support will go away in future versions for this.");
615 crcs[0]=elfcrc(crcs[0],in_buf,blksize);
616 } else {
617 crcs[0]=crc(crcs[0],in_buf,blksize);
618 }
619 #else
620 crcs[0]=crc(crcs[0],in_buf,blksize);
621 #endif
622
623 if (cipher!=-1) {
624 tmpbuf=malloc(blksize*2);
625 x=ciphers[cipher](in_buf, tmpbuf, blksize, keybuf, DACT_MODE_CDEC);
626 memcpy(in_buf,tmpbuf,x);
627 free(tmpbuf);
628 }
629
630 /*
631 * If the filesize is not specified, try to find it in the stream...
632 * this is pretty stupid, because if we can't rewind OUR read stream
633 * we're SOL... do we really need the filesize that badly? I guess
634 * we do to truncate the last of it... Adding more checks in here..
635 *
636 * This will never get used, canlseek will be 1 only if we can sucessfully
637 * seek, in which case, we have done it above.
638 */
639 #if 0
640 if (filesize==0 && canlseek) {
641 read_de(src, &magic, 4);
642 read_de(src, &filesize, 4);
643 if (read(src, &x, 1)==0) {
644 if (magic!=DACT_MAGIC_PEOF) {
645 dact_ui_status(DACT_UI_LVL_GEN, "Stream is corrupt.");
646 free(in_buf);
647 free(out_buf);
648 return(0);
649 }
650 } else {
651 lseek(src, -9, SEEK_CUR);
652 filesize=0;
653 }
654 }
655 #endif
656
657
658 if ((bytes_read=dact_blk_decompress(out_buf, in_buf, blksize, 0, algo, out_bufsize))==0) {
659 if (cipher!=-1) {
660 PRINTERR("Decompression resulted in 0-byte block. Invalid key?");
661 } else {
662 PRINTERR("Decompression resulted in 0-byte block.");
663 }
664 }
665 fileoutsize+=bytes_read;
666
667 /* If ciphering, don't try to calculate this (the plaintext) CRC. */
668 if (cipher==-1) {
669 #ifndef DACT_DONT_SUPPORT_OLDDACT
670 if (DACT_VERS(version[0], version[1], version[2])<DACT_VERS(0, 8, 39)) {
671 PRINTERR("**WARNING** This file uses the old DACT file header, support will go away in future versions for this.");
672 crcs[1]=elfcrc(crcs[1],out_buf,bytes_read);
673 } else {
674 crcs[1]=crc(crcs[1],out_buf,bytes_read);
675 }
676 #else
677 crcs[1]=crc(crcs[1],out_buf,bytes_read);
678 #endif
679 }
680
681 dact_ui_incrblkcnt(1);
682
683 if (fileoutsize>filesize && filesize!=0) {
684 write(dest, out_buf, blksize_uncomp-(fileoutsize-filesize));
685 } else {
686 write(dest, out_buf, bytes_read);
687 }
688
689 free(in_buf);
690 }
691
692 free(out_buf);
693
694 if ((crcs[0]!=crcs[2] && crcs[0]!=0 && crcs[2]!=0) \
695 || (crcs[1]!=crcs[3] && crcs[1]!=0 && crcs[3]!=0)) {
696 dact_ui_status(DACT_UI_LVL_GEN, "CRC error.");
697 if (!options[DACT_OPT_NOCRC] || options[DACT_OPT_FORCE]<1)
698 return(0);
699 }
700
701 dact_hdr_ext_clear();
702
703 return(filesize);
704
705 }
706
707
708 if (mode==DACT_MODE_STAT) {
709 read_de(src, &magic, 4, sizeof(magic));
710 read(src, &version[0], 1);
711 read(src, &version[1], 1);
712 read(src, &version[2], 1);
713 #ifndef DACT_DONT_SUPPORT_OLDDACT
714 if (DACT_VERS(version[0], version[1], version[2])<DACT_VERS(0, 8, 39)) {
715 PRINTERR("**WARNING** This file uses the old DACT file header, support will go away in future versions for this.");
716 read_de(src, &filesize, 4, sizeof(filesize));
717 hdr_reg_size=24;
718 } else {
719 read_de(src, &filesize, 8, sizeof(filesize));
720 }
721 #else
722 read_de(src, &filesize, 8, sizeof(filesize));
723 #endif
724 read_de(src, &blk_cnt, 4, sizeof(blk_cnt));
725 read_de(src, &blksize, 4, sizeof(blksize));
726 read(src, &file_opts, 1);
727 read_de(src, &file_extd_size, 4, sizeof(file_extd_size));
728
729 printf("File : %s\n", filename);
730 printf("Magic : 0x%08x",magic);
731 if (magic!=DACT_MAGIC_NUMBER) {
732 printf(" (bad magic)\n");
733 return(0);
734 } else {
735 printf("\n");
736 }
737
738 if (filesize==0) {
739 if (lseek_net(src, offset+1, SEEK_SET)==(offset+1)) {
740 #ifndef DACT_DONT_SUPPORT_OLDDACT
741 if (DACT_VERS(version[0], version[1], version[2])<DACT_VERS(0, 8, 39)) {
742 PRINTERR("**WARNING** This file uses the old DACT file header, support will go away in future versions for this.");
743 lseek_net(src, -8, SEEK_END);
744 read_de(src, &magic, 4, sizeof(magic));
745 read_de(src, &filesize, 4, sizeof(filesize));
746 hdr_reg_size=24;
747 } else {
748 lseek_net(src, -12, SEEK_END);
749 read_de(src, &magic, 4, sizeof(magic));
750 read_de(src, &filesize, 8, sizeof(filesize));
751 }
752 #else
753 lseek_net(src, -12, SEEK_END);
754 read_de(src, &magic, 4, sizeof(magic));
755 read_de(src, &filesize, 8, sizeof(filesize));
756 #endif
757 if (magic!=DACT_MAGIC_PEOF) {
758 PRINTERR("Bad end-of-file magic. Corrupt or incomplete file?");
759 filesize=0;
760 }
761 }
762 }
763 fileoutsize=lseek_net(src, 0, SEEK_END);
764 fileoutsize-=offset;
765
766 printf("Dact Version : %i.%i.%i\n",version[0],version[1],version[2]);
767 printf("Block Size : %i\n", blksize);
768 printf("Block Header Size : %i\n", BYTESIZE(blksize)+1);
769 printf("Compressed Size : %llu\n", fileoutsize);
770 printf("Uncompressed Size : %llu\n", filesize);
771 printf("Ratio : %2.3f to 1.0\n", ((float) filesize)/((float) fileoutsize) );
772 lseek_net(src, offset+hdr_reg_size, SEEK_SET);
773 while (file_extd_read<file_extd_size) {
774 x=0;
775 read(src, &ch, 1);
776 if (ch!=DACT_HDR_NOP) read_de(src, &x, 2, sizeof(x));
777 switch (ch) {
778 case DACT_HDR_CRC0:
779 read_de(src, &crcs[2], 4, sizeof(crcs[2]));
780 printf("CRC 0 : 0x%08x\n", crcs[2]);
781 break;
782 case DACT_HDR_CRC1:
783 read_de(src, &crcs[3], 4, sizeof(crcs[3]));
784 printf("CRC 1 : 0x%08x\n", crcs[3]);
785 break;
786 case DACT_HDR_NAME:
787 hdr_buf=malloc(x+1);
788 read_f(src, hdr_buf, x);
789 hdr_buf[x]=0;
790 printf("Original Name : %s\n", hdr_buf);
791 free(hdr_buf);
792 break;
793 case DACT_HDR_URL:
794 hdr_buf=malloc(x+1);
795 read_f(src, hdr_buf, x);
796 hdr_buf[x]=0;
797 file_extd_urls[file_extd_urlcnt++]=parse_url_subst(hdr_buf,filename);
798 free(hdr_buf);
799 break;
800 case DACT_HDR_URLFILE:
801 hdr_buf=malloc(x+1);
802 read_f(src, hdr_buf, x);
803 hdr_buf[x]=0;
804 printf("Download Loc File : %s\n", hdr_buf);
805 extd_urlfile=fopen(hdr_buf, "r");
806 free(hdr_buf); /* We shouldn't need this anymore. */
807 if (extd_urlfile==NULL) break;
808 hdr_buf=malloc(4096);
809 while (1) {
810 fgets(hdr_buf, 4095, extd_urlfile);
811 if (feof(extd_urlfile)) break;
812 hdr_buf=strsep(&hdr_buf,"\n");
813 file_extd_urls[file_extd_urlcnt++]=parse_url_subst(hdr_buf,filename);
814 }
815 free(hdr_buf);
816 break;
817 case DACT_HDR_DESC:
818 hdr_buf=malloc(x+1);
819 read_f(src, hdr_buf, x);
820 hdr_buf[x]=0;
821 printf("Description : %s\n", hdr_buf);
822 free(hdr_buf);
823 break;
824 case DACT_HDR_CIPHER:
825 read_de(src, &cipher, x, sizeof(cipher));
826 printf("Ciphered using : %s\n", ciphers_name[cipher]);
827 break;
828 case DACT_HDR_NOP:
829 x=-2;
830 break;
831 case DACT_HDR_SFXLEN:
832 read_de(src, &offset, x, sizeof(offset));
833 printf("Program length : %lu\n", (unsigned long) offset);
834 break;
835 default:
836 hdr_buf=malloc(x);
837 read_f(src, hdr_buf, x);
838 free(hdr_buf);
839 break;
840 }
841
842
843 file_extd_read+=(x+3);
844 }
845
846 for (x=0;x<file_extd_urlcnt;x++) {
847 printf("Download Location : %s",file_extd_urls[x]);
848 if (options[DACT_OPT_VERB]) {
849 if ((new_fd=open_net(file_extd_urls[x],O_RDONLY, 0))<0) {
850 printf(" [broken]\n");
851 continue;
852 }
853 close(new_fd);
854 }
855 printf("\n");
856 }
857
858 blk_cnt=0;
859 blksize_size=BYTESIZE(blksize);
860 if (options[DACT_OPT_VERB]) {
861 lseek_net(src, offset+hdr_reg_size+file_extd_size, SEEK_SET);
862 printf("\n");
863 printf("Break down: \n");
864 printf(" Blk | Algo | Size | Name\n");
865 printf(" ----+------+---------+---------------------------\n");
866 while (1) {
867 if (read(src, &algo, 1)==0) break;
868 if (algo==0xff) break; /* 0xff is reserved for EOF */
869
870 read_de(src, &blksize, blksize_size, sizeof(blksize));
871 lseek_net(src, blksize, SEEK_CUR);
872 printf(" %03i | %03i | %-7i | %s\n",blk_cnt,algo,blksize,algorithm_names[algo]);
873 blk_cnt++;
874 }
875 }
876
877 printf("\n");
878
879
880 return(1);
881 }
882
883 return(0);
884 }
885
dact_process_other(int src,const int dest,const uint32_t magic,const unsigned char * options)886 uint32_t dact_process_other(int src, const int dest, const uint32_t magic, const unsigned char *options) {
887 char *buf, tmpbuf[128]="/tmp/dactXXXXXX";
888 uint32_t filesize=0, x;
889 int tmpfd=0;
890 #if defined(HAVE_LIBBZ2) && (defined(HAVE_BZDOPEN) || defined(HAVE_NEW_BZDOPEN))
891 BZFILE *bzfd;
892 #endif
893 #if defined(HAVE_LIBZ) && defined(HAVE_GZDOPEN)
894 gzFile gzfd;
895 #endif
896
897 filesize=0; /* Fix a warning, that is all. */
898
899 /*
900 * bad and broke stuff XXX FIXME XXX FIXME XXX FIXME
901 * There has to be a better way to do this... I just want
902 * to rewind my socket/pipe 4 bytes... 4 bytes is all I ask
903 * Is that so much to ask for? Well?! Is it?! I don't
904 * think it is.
905 * I give up on this.
906 *
907 * Someone please fix it.
908 * -- Roy Keene <dact@rkeene.org>
909 */
910 if (lseek_net(src, 0, SEEK_SET)<0) {
911 /*
912 * lseek_net() should make this obsolete.
913 * ... EXCEPT! when reading from stdin.
914 */
915 tmpfd=mkstemp(tmpbuf);
916 write_de(tmpfd, magic, 4);
917 buf=malloc(1024);
918 while (1) {
919 x=read_f(src, buf, 1024);
920 write(tmpfd, buf, x);
921 if (x<1024) break;
922 }
923 close(src);
924 src=tmpfd;
925 lseek_net(src, 0, SEEK_SET); /* Now bitch. */
926 free(buf);
927 }
928 #if defined(HAVE_LIBZ) && defined(HAVE_GZDOPEN)
929
930 if ((magic&0xffff0000)==0x1f8b0000) { /* gzip */
931 dact_ui_status(DACT_UI_LVL_GEN, "Gunzipping...");
932 buf=malloc(1024);
933
934 gzfd=gzdopen(src, "r");
935 /*XXX: need to dact_ui_setup() */
936 while (1) {
937 dact_ui_incrblkcnt(1);
938 x=gzread(gzfd,buf,1024);
939 filesize+=write(dest, buf, x);
940 if (x<1024) break;
941 }
942 free(buf);
943 if (tmpfd!=0) unlink(tmpbuf);
944 return(filesize);
945 }
946 #endif
947
948 #if defined(HAVE_LIBBZ2) && (defined(HAVE_BZDOPEN) || defined(HAVE_NEW_BZDOPEN))
949 if ((magic&0xffffff00)==0x425a6800) { /* bzip2 */
950 dact_ui_status(DACT_UI_LVL_GEN, "Bunzipping...");
951 buf=malloc(1024);
952
953 #ifdef HAVE_NEW_BZDOPEN
954 bzfd=BZ2_bzdopen(src, "r");
955 #else
956 bzfd=bzdopen(src, "r");
957 #endif
958 /*XXX: need to dact_ui_setup() */
959 while(1) {
960 dact_ui_incrblkcnt(1);
961 #ifdef HAVE_NEW_BZDOPEN
962 x=BZ2_bzread(bzfd, buf, 1024);
963 #else
964 x=bzread(bzfd, buf, 1024);
965 #endif
966 filesize+=write(dest, buf, x);
967 if (x<1024) break;
968 }
969 free(buf);
970 if (tmpfd!=0) unlink(tmpbuf);
971 return(filesize);
972 }
973 #endif
974 return(0);
975 }
976