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