1
2 /* MD5DEEP - helpers.c
3 *
4 * By Jesse Kornblum
5 *
6 * This is a work of the US Government. In accordance with 17 USC 105,
7 * copyright protection is not available for any work of the US Government.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 */
14
15 #include "main.h"
16
17 /* Removes any newlines at the end of the string buf.
18 Works for both *nix and Windows styles of newlines.
19 Returns the new length of the string. */
chop(char * buf)20 unsigned int chop (char *buf)
21 {
22
23 /* Windows newlines are 0x0d 0x0a, *nix are 0x0a */
24 unsigned int len = strlen(buf);
25 if (buf[len - 1] == 0x0a)
26 {
27 if (buf[len - 2] == 0x0d)
28 {
29 buf[len - 2] = buf[len - 1];
30 }
31 buf[len - 1] = buf[len];
32 }
33 return strlen(buf);
34 }
35
units(unsigned int c)36 char *units(unsigned int c)
37 {
38 switch (c)
39 {
40 case 0: return "B";
41 case 1: return "KB";
42 case 2: return "MB";
43 case 3: return "GB";
44 case 4: return "TB";
45 case 5: return "PB";
46 case 6: return "EB";
47 /* Steinbach's Guideline for Systems Programming:
48 Never test for an error condition you don't know how to handle.
49
50 Granted, given that no existing system can handle anything
51 more than 18 exabytes, this shouldn't be an issue. But how do we
52 communicate that 'this shouldn't happen' to the user? */
53 default: return "??";
54 }
55 }
56
human_readable(off_t size,char * buffer)57 char *human_readable(off_t size, char *buffer)
58 {
59 unsigned int count = 0;
60 while (size > 1024)
61 {
62 size /= 1024;
63 ++count;
64 }
65
66 /* The size will be, at most, 1023, and the units will be
67 two characters no matter what. Thus, the maximum length of
68 this string is six characters. e.g. strlen("1023 EB") = 6 */
69 if (sizeof(off_t) == 4)
70 {
71 snprintf(buffer, 8, "%u %s", (unsigned int)size, units(count));
72 }
73 else if (sizeof(off_t) == 8)
74 {
75 snprintf(buffer, 8, "%llu %s", (u_int64_t) size, units(count));
76 }
77
78 return buffer;
79 }
80
current_time(void)81 char *current_time(void)
82 {
83 time_t now = time(NULL);
84 char *ascii_time = ctime(&now);
85 chop(ascii_time);
86 return ascii_time;
87 }
88
89 /* Shift the contents of a string so that the values after 'new_start'
90 will now begin at location 'start' */
shift_string(char * fn,int start,int new_start)91 void shift_string(char *fn, int start, int new_start)
92 {
93 if (start < 0 || start > strlen(fn) || new_start < 0 || new_start < start)
94 return;
95
96 while (new_start < strlen(fn))
97 {
98 fn[start] = fn[new_start];
99 new_start++;
100 start++;
101 }
102
103 fn[start] = 0;
104 }
105
make_magic(void)106 void make_magic(void)
107 {
108 printf("%s%s",
109 "\x53\x41\x4E\x20\x44\x49\x4D\x41\x53\x20\x48\x49\x47\x48\x20\x53\x43\x48\x4F\x4F\x4C\x20\x46\x4F\x4F\x54\x42\x41\x4C\x4C\x20\x52\x55\x4C\x45\x53\x21",
110 NEWLINE);
111 }
112
113 #if defined(__UNIX)
114
115 /* Return the size, in bytes of an open file stream. On error, return 0 */
116 #if defined(__LINUX)
117
find_file_size(FILE * f)118 off_t find_file_size(FILE *f)
119 {
120 off_t num_sectors = 0;
121 int fd = fileno(f);
122 struct stat sb;
123
124 if (fstat(fd, &sb))
125 {
126 return 0;
127 }
128
129 if (S_ISREG(sb.st_mode) || S_ISDIR(sb.st_mode))
130 return sb.st_size;
131 else if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode))
132 {
133 if (ioctl(fd, BLKGETSIZE, &num_sectors))
134 {
135 #if defined(__DEBUG)
136 fprintf(stderr, "%s: ioctl call to BLKGETSIZE failed.%s", __progname, NEWLINE);
137 #endif
138 }
139 else
140 return (num_sectors * 512);
141 }
142
143 return 0;
144 }
145
146 #elif defined(__MACOSX)
147
148 #include <stdint.h>
149 #include <sys/ioctl.h>
150 #include <sys/disk.h>
151
find_file_size(FILE * f)152 off_t find_file_size(FILE *f)
153 {
154 #ifdef DEBUG
155 printf(" FIND MAC file size\n");
156 #endif
157 return 0; /*FIX ME this function causes strange problems on MACOSX, so for now return 0*/
158 struct stat info;
159 off_t total = 0;
160 off_t original = ftello(f);
161 int ok = TRUE, fd = fileno(f);
162
163 /* I'd prefer not to use fstat as it will follow symbolic links. We don't
164 follow symbolic links. That being said, all symbolic links *should*
165 have been caught before we got here. */
166 fstat(fd, &info);
167
168 /* Block devices, like /dev/hda, don't return a normal filesize.
169 If we are working with a block device, we have to ask the operating
170 system to tell us the true size of the device.
171
172 The following only works on Linux as far as I know. If you know
173 how to port this code to another operating system, please contact
174 the current maintainer of this program! */
175 if (S_ISBLK(info.st_mode))
176 {
177 daddr_t blocksize = 0;
178 daddr_t blockcount = 0;
179
180 /* Get the block size */
181 if (ioctl(fd, DKIOCGETBLOCKSIZE, blocksize) < 0)
182 {
183 ok = FALSE;
184 #if defined(__DEBUG)
185 perror("DKIOCGETBLOCKSIZE failed");
186 #endif
187 }
188
189 /* Get the number of blocks */
190 if (ok)
191 {
192 if (ioctl(fd, DKIOCGETBLOCKCOUNT, blockcount) < 0)
193 {
194 #if defined(__DEBUG)
195 perror("DKIOCGETBLOCKCOUNT failed");
196 #endif
197 }
198 }
199
200 total = blocksize * blockcount;
201
202 }
203
204 else
205 {
206
207 /* I don't know why, but if you don't initialize this value you'll
208 get wildly innacurate results when you try to run this function */
209 if ((fseeko(f, 0, SEEK_END)))
210 return 0;
211 total = ftello(f);
212 if ((fseeko(f, original, SEEK_SET)))
213 return 0;
214 }
215
216 return (total - original);
217 }
218
219 #else
220
221 /* This is code for general UNIX systems
222 (e.g. NetBSD, FreeBSD, OpenBSD, etc) */
midpoint(off_t a,off_t b,long blksize)223 static off_t midpoint(off_t a, off_t b, long blksize)
224 {
225 off_t aprime = a / blksize;
226 off_t bprime = b / blksize;
227 off_t c, cprime;
228
229 cprime = (bprime - aprime) / 2 + aprime;
230 c = cprime * blksize;
231
232 return c;
233 }
234
find_dev_size(int fd,int blk_size)235 off_t find_dev_size(int fd, int blk_size)
236 {
237
238 off_t curr = 0, amount = 0;
239 void *buf;
240
241 if (blk_size == 0)
242 return 0;
243
244 buf = malloc(blk_size);
245
246 for (;;)
247 {
248 ssize_t nread;
249
250 lseek(fd, curr, SEEK_SET);
251 nread = read(fd, buf, blk_size);
252 if (nread < blk_size)
253 {
254 if (nread <= 0)
255 {
256 if (curr == amount)
257 {
258 free(buf);
259 lseek(fd, 0, SEEK_SET);
260 return amount;
261 }
262
263 curr = midpoint(amount, curr, blk_size);
264 }
265 else
266 { /* 0 < nread < blk_size */
267 free(buf);
268 lseek(fd, 0, SEEK_SET);
269 return amount + nread;
270 }
271 }
272 else
273 {
274 amount = curr + blk_size;
275 curr = amount * 2;
276 }
277 }
278
279 free(buf);
280 lseek(fd, 0, SEEK_SET);
281 return amount;
282 }
283
find_file_size(FILE * f)284 off_t find_file_size(FILE *f)
285 {
286 int fd = fileno(f);
287 struct stat sb;
288 return 0; /*FIX ME SOLARIS FILE SIZE CAUSES SEG FAULT, for now just return 0*/
289
290 if (fstat(fd, &sb))
291 return 0;
292
293 if (S_ISREG(sb.st_mode) || S_ISDIR(sb.st_mode))
294 return sb.st_size;
295 else if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode))
296 return find_dev_size(fd, sb.st_blksize);
297
298 return 0;
299 }
300
301 #endif /* UNIX Flavors */
302 #endif /* ifdef __UNIX */
303
304 #if defined(__WIN32)
find_file_size(FILE * f)305 off_t find_file_size(FILE *f)
306 {
307 off_t total = 0, original = ftello(f);
308
309 if ((fseeko(f, 0, SEEK_END)))
310 return 0;
311
312 total = ftello(f);
313 if ((fseeko(f, original, SEEK_SET)))
314 return 0;
315
316 return total;
317 }
318
319 #endif /* ifdef __WIN32 */
320
print_search_specs(f_state * s)321 void print_search_specs(f_state *s)
322 {
323 int i = 0;
324 int j = 0;
325 printf("\nDUMPING BUILTIN SEARCH INFO\n\t");
326 for (i = 0; i < s->num_builtin; i++)
327 {
328
329 printf("%s:\n\t footer_len:=%d, header_len:=%d, max_len:=%llu ",
330 search_spec[i].suffix,
331 search_spec[i].footer_len,
332 search_spec[i].header_len,
333 search_spec[i].max_len);
334 printf("\n\t header:\t");
335 printx(search_spec[i].header, 0, search_spec[i].header_len);
336 printf("\t footer:\t");
337 printx(search_spec[i].footer, 0, search_spec[i].footer_len);
338 for (j = 0; j < search_spec[i].num_markers; j++)
339 {
340 printf("\tmarker: \t");
341 printx(search_spec[i].markerlist[j].value, 0, search_spec[i].markerlist[j].len);
342 }
343
344 }
345
346 }
347
print_stats(f_state * s)348 void print_stats(f_state *s)
349 {
350 int i = 0;
351 audit_msg(s, "\n%d FILES EXTRACTED\n\t", s->fileswritten);
352 for (i = 0; i < s->num_builtin; i++)
353 {
354
355 if (search_spec[i].found != 0)
356 {
357 if (search_spec[i].type == OLE)
358 search_spec[i].suffix = "ole";
359 else if (search_spec[i].type == RIFF)
360 search_spec[i].suffix = "rif";
361 else if (search_spec[i].type == ZIP)
362 search_spec[i].suffix = "zip";
363 audit_msg(s, "%s:= %d", search_spec[i].suffix, search_spec[i].found);
364 }
365 }
366 }
367
charactersMatch(char a,char b,int caseSensitive)368 int charactersMatch(char a, char b, int caseSensitive)
369 {
370
371 //if(a==b) return 1;
372 if (a == wildcard || a == b)
373 return 1;
374 if (caseSensitive || (a < 'A' || a > 'z' || b < 'A' || b > 'z'))
375 return 0;
376
377 /* This line is equivalent to (abs(a-b)) == 'a' - 'A' */
378 return (abs(a - b) == 32);
379 }
380
memwildcardcmp(const void * s1,const void * s2,size_t n,int caseSensitive)381 int memwildcardcmp(const void *s1, const void *s2, size_t n, int caseSensitive)
382 {
383 if (n != 0)
384 {
385 register const unsigned char *p1 = s1, *p2 = s2;
386 do
387 {
388 if (!charactersMatch(*p1++, *p2++, caseSensitive))
389 return (*--p1 -*--p2);
390 }
391 while (--n != 0);
392 }
393
394 return (0);
395 }
396
printx(unsigned char * buf,int start,int end)397 void printx(unsigned char *buf, int start, int end)
398 {
399 int i = 0;
400 for (i = start; i < end; i++)
401 {
402 printf("%x ", buf[i]);
403 }
404
405 printf("\n");
406 }
407
reverse_string(char * to,char * from,int startLocation,int endLocation)408 char *reverse_string(char *to, char *from, int startLocation, int endLocation)
409 {
410 int i = endLocation;
411 int j = 0;
412 for (j = startLocation; j < endLocation; j++)
413 {
414 i--;
415 to[j] = from[i];
416 }
417
418 return to;
419 }
420
htos(unsigned char s[],int endian)421 unsigned short htos(unsigned char s[], int endian)
422 {
423
424 unsigned char *bytes = (unsigned char *)malloc(sizeof(unsigned short) * sizeof(char));
425 unsigned short size = 0;
426 char temp = 'x';
427 bytes = memcpy(bytes, s, sizeof(short));
428
429 if (endian == FOREMOST_BIG_ENDIAN && BYTE_ORDER == LITTLE_ENDIAN)
430 {
431
432 //printf("switching the byte order\n");
433 temp = bytes[0];
434 bytes[0] = bytes[1];
435 bytes[1] = temp;
436
437 }
438 else if (endian == FOREMOST_LITTLE_ENDIAN && BYTE_ORDER == BIG_ENDIAN)
439 {
440 temp = bytes[0];
441 bytes[0] = bytes[1];
442 bytes[1] = temp;
443 }
444
445 size = *((unsigned short *)bytes);
446 free(bytes);
447 return size;
448 }
449
htoi(unsigned char s[],int endian)450 unsigned int htoi(unsigned char s[], int endian)
451 {
452
453 int length = sizeof(int);
454 unsigned char *bytes = (unsigned char *)malloc(length * sizeof(char));
455 unsigned int size = 0;
456
457 bytes = memcpy(bytes, s, length);
458
459 if (endian == FOREMOST_BIG_ENDIAN && BYTE_ORDER == LITTLE_ENDIAN)
460 {
461
462 bytes = (unsigned char *)reverse_string((char *)bytes, (char *)s, 0, length);
463 }
464 else if (endian == FOREMOST_LITTLE_ENDIAN && BYTE_ORDER == BIG_ENDIAN)
465 {
466
467 bytes = (unsigned char *)reverse_string((char *)bytes, (char *)s, 0, length);
468 }
469
470 size = *((unsigned int *)bytes);
471
472 free(bytes);
473 return size;
474 }
475
htoll(unsigned char s[],int endian)476 u_int64_t htoll(unsigned char s[], int endian)
477 {
478 int length = sizeof(u_int64_t);
479 unsigned char *bytes = (unsigned char *)malloc(length * sizeof(char));
480 u_int64_t size = 0;
481 bytes = memcpy(bytes, s, length);
482 #ifdef DEBUG
483 printf("htoll len=%d endian=%d\n",length,endian);
484 #endif
485 if (endian == FOREMOST_BIG_ENDIAN && BYTE_ORDER == LITTLE_ENDIAN)
486 {
487 #ifdef DEBUG
488 printf("reverse0\n");
489 #endif
490 bytes = (unsigned char *)reverse_string((char *)bytes, (char *)s, 0, length);
491 }
492 else if (endian == FOREMOST_LITTLE_ENDIAN && BYTE_ORDER == BIG_ENDIAN)
493 {
494 #ifdef DEBUG
495 printf("reverse1\n");
496 #endif
497 bytes = (unsigned char *)reverse_string((char *)bytes, (char *)s, 0, length);
498 }
499
500 size = *((u_int64_t *)bytes);
501 #ifdef DEBUG
502 printf("htoll size=%llu\n",size);
503 printx(bytes,0,length);
504 #endif
505
506
507 free(bytes);
508 return size;
509 }
510
511 /* display Position: Tell the user how far through the infile we are */
displayPosition(f_state * s,f_info * i,u_int64_t pos)512 int displayPosition(f_state *s, f_info *i, u_int64_t pos)
513 {
514
515 int percentDone = 0;
516 static int last_val = 0;
517 int count;
518 int flag = FALSE;
519 int factor = 4;
520 int multiplier = 25;
521 int number_of_stars = 0;
522 char buffer[256];
523 long double skip = s->skip * s->block_size;
524
525 long double tot_bytes = (long double)((i->total_bytes));
526 tot_bytes -= skip;
527 if (i->total_bytes > 0)
528 {
529 percentDone = (((long double)pos) / ((long double)tot_bytes)) * 100;
530 if (percentDone != last_val)
531 flag = TRUE;
532 last_val = percentDone;
533 }
534 else
535 {
536 flag = TRUE;
537 factor = 4;
538 multiplier = 25;
539 }
540
541 if (flag)
542 {
543 number_of_stars = percentDone / factor;
544
545 printf("%s: |", s->input_file);
546 for (count = 0; count < number_of_stars; count++)
547 {
548 printf("*");
549 }
550
551 for (count = 0; count < (multiplier - number_of_stars); count++)
552 {
553 printf(" ");
554 }
555
556 if (i->total_bytes > 0)
557 {
558 printf("|\t %d%% done\n", percentDone);
559 }
560 else
561 {
562 printf("|\t %s done\n", human_readable(pos, buffer));
563
564 }
565 }
566
567 if (percentDone == 100)
568 {
569 last_val = 0;
570 }
571
572 return TRUE;
573 }
574