Codebase list afflib / 739b2fa
Imported Upstream version 3.6.2 Christophe Monniez 13 years ago
71 changed file(s) with 7314 addition(s) and 8776 deletion(s). Raw diff Collapse all Expand all
1010 Nicolas (kwizart)
1111 Joachim Metz
1212 David Collett (PyFlag), for the PyAFF integration
13 Phillip Hellewell (AccessData) for port to VC2008 and catching a few bugs.
1314
1415 The AFF Project has received substantial financial support from
1516 Basis Technology Corporation.
2122 I.D.E.A.L. Technology Corporation
2223 Naval Postgraduate School
2324 US Department of Defense
25 AccessData
2426
27
11
22
33 PERFORMANCE IMPROVEMENTS:
4 * Cache the results of vstat
4 * afconvert should calculate MD5, SHA256 and SHA1
55 * Store TOC sorted and find entries with binary search.
66 (A 1TB TOC has 62,500 pages or 100K segments; with fixed size records that would be 8,000,000, which is not much.)
77 * aff_write_seg() shouldn't be calling af_rewind_seg after every call
0 2010-08-01 Simson Garfinkel <simsong@Silver-Surfer.local>
1
2 * configure.ac: increased version to 3.6.2
3
4 * lib/vnode_afd.cpp (afd_identify_file): added file:// logic to
5 afd_identify_file from aff_identify_file
6
7 * lib/vnode_split_raw.cpp (split_raw_write_internal2): when
8 storing data in AFM-files the mode set by af_open is only used for
9 the AFM-file, but not for the .000 which contains the raw data. In
10 case of mode 0600 for af_open, the mode for the .000 raw-data
11 file is set to 0644, which enables read-access for everyone. This
12 is a possible security risk on multi-user systems. To correct
13 this, mode in open() is now taken from af->openmode, and not
14 hard-coded to be 0644.
15
16
17 2010-07-29 Simson Garfinkel <simsong@imac2.home>
18
19 * win32/afflib.mak (LINK_OPTS): updated for AFFLIB3.6 naming scheme
20
21 * lib/afflib.h: added #ifdef for stdint.h
22
23 * BUGLIST.txt: removed note about afd encryption not working.
24
25 2010-07-20 Simson Garfinkel <simsong@45.sub-75-206-247.myvzw.com>
26
27 2010-07-15 Simson Garfinkel <simsong@shorty.local>
28
29 * lib/vnode_afd.cpp (vnode_afd): removed AF_VNODE_NO_SEALING from vnode_afd->flags.
30 (afd_add_file): ap->num_afs>0 changed to ap->num_afs>1 for copying
31 over the metadata for the second file.
32
33 2010-07-10 Simson L. Garfinkel <simsong@imac2.home>
34
35 * lib/afflib.h (struct af_vnode_info): changed imagesize in
36 af_vnode_info structure from int64_t to uint64_t.
37
38 2010-07-10 Simson L. Garfinkel <simsong@imac2.local>
39
40 * tools/Makefile.am: all commands now begin aff rather than af.
41
42 * lib/vnode_ewf.cpp (ewf_vstat): removed EWF support from AFF
43
44 2010-07-06 Simson L. Garfinkel <simsong@imac2.home>
45
46 * lib/vnode_aff.cpp (aff_get_seg): fixed assertion in ret.
47
48 2010-06-28 Simson Garfinkel <simsong@silver-surfer.home>
49
50 * configure.ac: increased version number to 3.5.13.
51
52 * tools/Makefile.am (bin_PROGRAMS): renamed afconvert to
53 affconvert because of name collission with MacOS
54
55 2010-06-27 Simson Garfinkel <simsong@silver-surfer.home>
56
57 * lib/Makefile.am (EXTRA_PROGRAMS): I read on a debian complaint
58 list that "aftest" and "s3" shouldn't be installed, but nobody
59 thought to drop me a note explaining this or telling me how to do
60 it. So after about 15 minutes with the automake manual I moved
61 aftest and s3 from bin_PROGRAMS to EXTRA_PROGRAMS and now they
62 shouldn't get installed. It would be really nice if those Debian
63 folks to send their comments back to package authors.
64
065 2010-04-25 Simson L. Garfinkel <simsong@imac2.local>
166
267 * configure.ac: version increased to 3.5.12
3030 make distribute_release
3131
3232 prerelease:
33 @echo Making sure SVN is up to date
34 svn update
35 @echo update PACKAGE_VERSION in win32 directory
36 sed s/PACKAGE_VERSION.\*/PACKAGE_VERSION\ \"$(PACKAGE_VERSION)\"/ win32/affconfig.h > win32/affconfig.h.$$
37 mv -f win32/affconfig.h.$$ win32/affconfig.h
38 @echo Commit back changes
39 svn commit -m 'make prerelease'
3340 @echo Building and uploading the release...
3441 @echo Making release $(RELEASE)
3542 @echo
7279 tests/encrypted.iso \
7380 tests/encrypted.aff \
7481 win32/Changes.txt \
75 win32/Makefile.am.old \
7682 win32/README_MSVC++.txt \
7783 win32/affconfig.h \
7884 win32/afflib.mak \
262262 tests/encrypted.iso \
263263 tests/encrypted.aff \
264264 win32/Changes.txt \
265 win32/Makefile.am.old \
266265 win32/README_MSVC++.txt \
267266 win32/affconfig.h \
268267 win32/afflib.mak \
782781 make distribute_release
783782
784783 prerelease:
784 @echo Making sure SVN is up to date
785 svn update
786 @echo update PACKAGE_VERSION in win32 directory
787 sed s/PACKAGE_VERSION.\*/PACKAGE_VERSION\ \"$(PACKAGE_VERSION)\"/ win32/affconfig.h > win32/affconfig.h.$$
788 mv -f win32/affconfig.h.$$ win32/affconfig.h
789 @echo Commit back changes
790 svn commit -m 'make prerelease'
785791 @echo Building and uploading the release...
786792 @echo Making release $(RELEASE)
787793 @echo
3838
3939 % afinfo.exe filename.aff
4040
41
4241 To convert an AFF file into a RAW file, use:
4342
44 % afconvert.exe -e raw filename.aff
43 % affconvert.exe -e raw filename.aff
4544
4645
4746 To reliably copy an AFF file from one location to another:
6564
6665
6766
68
6967 Diskprint
7068 =================
7169 An exciting feature in AFF 3.5 is the ability to rapidly calculate and
8179
8280 % afdiskprint -x myfile.xml myfile.iso
8381
84
85
86 Bulk Extractor
87 ==============
88 In the ZIP file you will also find bulk_extractor.jar, a port of the
89 bulk_extractor to Java which actually runs 2x faster than the original
90 C version. (Unlike the C version, bulk_extractor.jar can only process
91 raw disk images, not EnCase or AFF files.)
92
93 To run bulk_extractor, you must have java on your system. Then type:
94
95 % java -jar bulk_extractor.jar diskimage.raw
96
97 You will probably want to extract the output to a file:
98
99 % java -jar bulk_extractor.jar ubnist1.casper-rw.gen3.raw > output.txt
100
101 The bulk extractor will report all of the email addresses, URLs,
102 domain names, and timestamps on the disk images. The current version
103 can handle a variety of Unicode encodings but it cannot handle
104 compressed regions.
10582
10683
10784 Verifying the AFFLIB Digital Signature
123123 /* Define to 1 if you have the `curl' library (-lcurl). */
124124 #undef HAVE_LIBCURL
125125
126 /* Define to 1 if you have the `ewf' library (-lewf). */
127 #undef HAVE_LIBEWF
128
129 /* Define to 1 if you have the libewf_get_bytes_per_sector function. */
130 #undef HAVE_LIBEWF_GET_BYTES_PER_SECTOR
131
132 /* Define to 1 if libewf_get_bytes_per_sector takes value as an argument. */
133 #undef HAVE_LIBEWF_GET_BYTES_PER_SECTOR_ARGUMENT_VALUE
134
135 /* Define to 1 if you have the libewf_get_chunk_size function. */
136 #undef HAVE_LIBEWF_GET_CHUNK_SIZE
137
138 /* Define to 1 if libewf_get_chunk_size takes value as an argument. */
139 #undef HAVE_LIBEWF_GET_CHUNK_SIZE_ARGUMENT_VALUE
140
141 /* Define to 1 if you have the libewf_get_media_size function. */
142 #undef HAVE_LIBEWF_GET_MEDIA_SIZE
143
144 /* Define to 1 if libewf_get_media_size takes value as an argument. */
145 #undef HAVE_LIBEWF_GET_MEDIA_SIZE_ARGUMENT_VALUE
146
147 /* Define to 1 if you have the <libewf.h> header file. */
148 #undef HAVE_LIBEWF_H
149
150126 /* Define to 1 if you have the `expat' library (-lexpat). */
151127 #undef HAVE_LIBEXPAT
152128
159135 /* Define to 1 if you have the `readline' library (-lreadline). */
160136 #undef HAVE_LIBREADLINE
161137
138 /* Define to 1 if you have the `regex' library (-lregex). */
139 #undef HAVE_LIBREGEX
140
162141 /* Define to 1 if you have the `rt' library (-lrt). */
163142 #undef HAVE_LIBRT
164143
165144 /* Define to 1 if you have the `ssl' library (-lssl). */
166145 #undef HAVE_LIBSSL
167
168 /* Define to 1 if you have the `uuid' library (-luuid). */
169 #undef HAVE_LIBUUID
170146
171147 /* Define to 1 if you have the `z' library (-lz). */
172148 #undef HAVE_LIBZ
467443 /* Use FUSE to mount AFF images */
468444 #undef USE_FUSE
469445
470 /* Use libewf to read EnCase files */
471 #undef USE_LIBEWF
472
473446 /* Use QEMU image drivers */
474447 #undef USE_QEMU
475448
00 Name: afflib
1 Version: 3.5.12
1 Version: 3.6.2
22 Release: 1
33 Summary: Library to support the Advanced Forensic Format
44 Group: System Environment/Libraries
55 export PATH=/usr/bin:/usr/sbin:/bin:$PATH
66 touch NEWS README AUTHORS ChangeLog stamp-h
77 aclocal
8 libtoolize -f || glibtoolize -f
8 LIBTOOLIZE=glibtoolize
9 if test `which libtoolize`x != "x" ;
10 then LIBTOOLIZE=libtoolize
11 fi
12 $LIBTOOLIZE -f
913 autoheader -f
1014 autoconf -f
1115 automake --add-missing -c
00 #!/bin/sh
1 # From http://wagner.pp.ru/~vitus/articles/openssl-mingw.html
2 # With modifications
3 # Download openssl and unpack.
4 # Open Configure script with a text editor, find this line:
5 # $IsMK1MF=1 if ($target eq "mingw" && $^O ne "cygwin" && !is_msys());
6 # and comment it out.
7 #
8 # $ perl Configure mingw
9 # $ make CC=i386-mingw32-gcc RANLIB=i386-mingw32-ranlib
101
11 export CC=/opt/local/bin/i386-mingw32-gcc
12 export CXX=/opt/local/bin/i386-mingw32-g++
13 export RANLIB=/opt/local/bin/i386-mingw32-ranlib
14 export MINGWFLAGS="-mwin32 -mconsole -march=pentium4 "
15 export CFLAGS="$MINGWFLAGS"
16 export CXXFLAGS="$MINGWFLAGS"
17 autoreconf -f
18 ./configure CC=$CC CXX=$CXX RANLIB=$RANLIB --target=i586-mingw32msvc --host=i586
19 make CC=$CC CXX=$CXX RANLIB=$RANLIB CFLAGS="$CFLAGS" CXXFLAGS="$CXXFLAGS"
2 # The easiest way to build AFFLIB for Win32 is to ues MinGW as either a cross-compiler
3 # or as a native compiler. In either case you will need to install OpenSSL and optionally
4 # libregex.
5
6 # This script will compile AFFLIB for Win32 on either Mac or Linux.
7
8 # To install OpenSSL on On Linux, first download OpenSSL 1.0.0 and then:
9 # ./Configure mingw --prefix=/usr/i586-mingw32msvc/
10 # sudo make install
11
12
13 if test -r /opt/local/bin/i386-mingw32-gcc ; then
14 echo Compiling for mingw on a Mac installed with MacPorts
15 export CC=/opt/local/bin/i386-mingw32-gcc
16 export CXX=/opt/local/bin/i386-mingw32-g++
17 export RANLIB=/opt/local/bin/i386-mingw32-ranlib
18 export AR=/opt/local/bin/i386-mingw32-ar
19 export PREFIX=/opt/local/i386-mingw32/
20 export MINGWFLAGS="-mwin32 -mconsole -march=pentium4 "
21 export CFLAGS="$MINGWFLAGS"
22 export CXXFLAGS="$MINGWFLAGS"
23 autoreconf -f
24 ./configure CC=$CC CXX=$CXX RANLIB=$RANLIB --target=i586-mingw32msvc --host=i586 \
25 --prefix=$PREFIX
26 make CC=$CC CXX=$CXX RANLIB=$RANLIB CFLAGS="$CFLAGS" CXXFLAGS="$CXXFLAGS"
27 fi
28 if test -r /usr/i586-mingw32msvc ; then
29 echo Compiling for mingw on Linux
30 export PREFIX=/usr/i586-mingw32msvc
31 export MINGW32PATH=/usr/i586-mingw32msvc
32 export CC=/usr/bin/i586-mingw32msvc-gcc
33 export CXX=/usr/bin/i586-mingw32msvc-g++
34 export AR=${MINGW32PATH}/bin/ar
35 export RANLIB=${MINGW32PATH}/bin/ranlib
36 export STRIP=${MINGW32PATH}/bin/strip
37 export MINGWFLAGS="-mwin32 -mconsole -march=i586 "
38 export CFLAGS="$MINGWFLAGS"
39 export CXXFLAGS="$MINGWFLAGS"
40 autoreconf -f
41 ./configure CC=$CC CXX=$CXX RANLIB=$RANLIB --target=i586-mingw32msvc --host=i586 \
42 --enable-winapi=yes --prefix=$PREFIX
43 make CC=$CC CXX=$CXX RANLIB=$RANLIB CFLAGS="$CFLAGS" CXXFLAGS="$CXXFLAGS"
44 fi
45
46 # Make a release of the executables
47
2048 zip afflib_windows.zip tools/*.exe
2149
00 #! /bin/sh
11 # Guess values for system-dependent variables and create Makefiles.
2 # Generated by GNU Autoconf 2.61 for AFFLIB 3.5.12.
2 # Generated by GNU Autoconf 2.61 for AFFLIB 3.6.2.
33 #
44 # Report bugs to <bugs@afflib.org>.
55 #
722722 # Identity of this package.
723723 PACKAGE_NAME='AFFLIB'
724724 PACKAGE_TARNAME='afflib'
725 PACKAGE_VERSION='3.5.12'
726 PACKAGE_STRING='AFFLIB 3.5.12'
725 PACKAGE_VERSION='3.6.2'
726 PACKAGE_STRING='AFFLIB 3.6.2'
727727 PACKAGE_BUGREPORT='bugs@afflib.org'
728728
729729 # Factoring default headers for most tests.
14261426 # Omit some internal or obsolete options to make the list less imposing.
14271427 # This message is too long to be a string in the A/UX 3.1 sh.
14281428 cat <<_ACEOF
1429 \`configure' configures AFFLIB 3.5.12 to adapt to many kinds of systems.
1429 \`configure' configures AFFLIB 3.6.2 to adapt to many kinds of systems.
14301430
14311431 Usage: $0 [OPTION]... [VAR=VALUE]...
14321432
14961496
14971497 if test -n "$ac_init_help"; then
14981498 case $ac_init_help in
1499 short | recursive ) echo "Configuration of AFFLIB 3.5.12:";;
1499 short | recursive ) echo "Configuration of AFFLIB 3.6.2:";;
15001500 esac
15011501 cat <<\_ACEOF
15021502
15131513 optimize for fast installation [default=yes]
15141514 --disable-libtool-lock avoid locking (might break parallel builds)
15151515 --disable-largefile omit support for large files
1516 --enable-libewf=yes Use libewf for reading EnCase files(default yes)
15171516 --enable-s3=yes Support for Amazon's S3 service. Requires CURL and
15181517 Expat.
15191518
16151614 test -n "$ac_init_help" && exit $ac_status
16161615 if $ac_init_version; then
16171616 cat <<\_ACEOF
1618 AFFLIB configure 3.5.12
1617 AFFLIB configure 3.6.2
16191618 generated by GNU Autoconf 2.61
16201619
16211620 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
16291628 This file contains any messages produced by compilers while
16301629 running configure, to aid debugging if configure makes a mistake.
16311630
1632 It was created by AFFLIB $as_me 3.5.12, which was
1631 It was created by AFFLIB $as_me 3.6.2, which was
16331632 generated by GNU Autoconf 2.61. Invocation command line was
16341633
16351634 $ $0 $@
23192318
23202319 # Define the identity of the package.
23212320 PACKAGE='afflib'
2322 VERSION='3.5.12'
2321 VERSION='3.6.2'
23232322
23242323
23252324 cat >>confdefs.h <<_ACEOF
45174516 else
45184517 lt_cv_nm_interface="BSD nm"
45194518 echo "int some_variable = 0;" > conftest.$ac_ext
4520 (eval echo "\"\$as_me:4521: $ac_compile\"" >&5)
4519 (eval echo "\"\$as_me:4520: $ac_compile\"" >&5)
45214520 (eval "$ac_compile" 2>conftest.err)
45224521 cat conftest.err >&5
4523 (eval echo "\"\$as_me:4524: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
4522 (eval echo "\"\$as_me:4523: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
45244523 (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
45254524 cat conftest.err >&5
4526 (eval echo "\"\$as_me:4527: output\"" >&5)
4525 (eval echo "\"\$as_me:4526: output\"" >&5)
45274526 cat conftest.out >&5
45284527 if $GREP 'External.*some_variable' conftest.out > /dev/null; then
45294528 lt_cv_nm_interface="MS dumpbin"
56345633 ;;
56355634 *-*-irix6*)
56365635 # Find out which ABI we are using.
5637 echo '#line 5638 "configure"' > conftest.$ac_ext
5636 echo '#line 5637 "configure"' > conftest.$ac_ext
56385637 if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
56395638 (eval $ac_compile) 2>&5
56405639 ac_status=$?
74817480 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
74827481 -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
74837482 -e 's:$: $lt_compiler_flag:'`
7484 (eval echo "\"\$as_me:7485: $lt_compile\"" >&5)
7483 (eval echo "\"\$as_me:7484: $lt_compile\"" >&5)
74857484 (eval "$lt_compile" 2>conftest.err)
74867485 ac_status=$?
74877486 cat conftest.err >&5
7488 echo "$as_me:7489: \$? = $ac_status" >&5
7487 echo "$as_me:7488: \$? = $ac_status" >&5
74897488 if (exit $ac_status) && test -s "$ac_outfile"; then
74907489 # The compiler can only warn and ignore the option if not recognized
74917490 # So say no if there are warnings other than the usual output.
78057804 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
78067805 -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
78077806 -e 's:$: $lt_compiler_flag:'`
7808 (eval echo "\"\$as_me:7809: $lt_compile\"" >&5)
7807 (eval echo "\"\$as_me:7808: $lt_compile\"" >&5)
78097808 (eval "$lt_compile" 2>conftest.err)
78107809 ac_status=$?
78117810 cat conftest.err >&5
7812 echo "$as_me:7813: \$? = $ac_status" >&5
7811 echo "$as_me:7812: \$? = $ac_status" >&5
78137812 if (exit $ac_status) && test -s "$ac_outfile"; then
78147813 # The compiler can only warn and ignore the option if not recognized
78157814 # So say no if there are warnings other than the usual output.
79107909 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
79117910 -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
79127911 -e 's:$: $lt_compiler_flag:'`
7913 (eval echo "\"\$as_me:7914: $lt_compile\"" >&5)
7912 (eval echo "\"\$as_me:7913: $lt_compile\"" >&5)
79147913 (eval "$lt_compile" 2>out/conftest.err)
79157914 ac_status=$?
79167915 cat out/conftest.err >&5
7917 echo "$as_me:7918: \$? = $ac_status" >&5
7916 echo "$as_me:7917: \$? = $ac_status" >&5
79187917 if (exit $ac_status) && test -s out/conftest2.$ac_objext
79197918 then
79207919 # The compiler can only warn and ignore the option if not recognized
79657964 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
79667965 -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
79677966 -e 's:$: $lt_compiler_flag:'`
7968 (eval echo "\"\$as_me:7969: $lt_compile\"" >&5)
7967 (eval echo "\"\$as_me:7968: $lt_compile\"" >&5)
79697968 (eval "$lt_compile" 2>out/conftest.err)
79707969 ac_status=$?
79717970 cat out/conftest.err >&5
7972 echo "$as_me:7973: \$? = $ac_status" >&5
7971 echo "$as_me:7972: \$? = $ac_status" >&5
79737972 if (exit $ac_status) && test -s out/conftest2.$ac_objext
79747973 then
79757974 # The compiler can only warn and ignore the option if not recognized
1071310712 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
1071410713 lt_status=$lt_dlunknown
1071510714 cat > conftest.$ac_ext <<_LT_EOF
10716 #line 10717 "configure"
10715 #line 10716 "configure"
1071710716 #include "confdefs.h"
1071810717
1071910718 #if HAVE_DLFCN_H
1081310812 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
1081410813 lt_status=$lt_dlunknown
1081510814 cat > conftest.$ac_ext <<_LT_EOF
10816 #line 10817 "configure"
10815 #line 10816 "configure"
1081710816 #include "confdefs.h"
1081810817
1081910818 #if HAVE_DLFCN_H
1397813977
1397913978
1398013979
13981 for ac_header in arpa/inet.h assert.h ctype.h dmalloc.h err.h errno.h fcntl.h getopt.h inttypes.h linux/fs.h malloc.h ncurses/term.h netinet/in.h regex.h signal.h stdio.h stdlib.h string.h sys/cdefs.h sys/disk.h sys/file.h sys/ioctl.h sys/ioctl.h sys/param.h sys/param.h sys/socket.h sys/signal.h sys/stat.h sys/time.h sys/types.h sys/vfs.h sysexits.h term.h time.h unistd.h zlib.h
13980
13981 for ac_header in arpa/inet.h assert.h ctype.h dmalloc.h err.h errno.h fcntl.h getopt.h inttypes.h linux/fs.h malloc.h ncurses/term.h netinet/in.h regex.h signal.h stdint.h stdio.h stdlib.h string.h sys/cdefs.h sys/disk.h sys/file.h sys/ioctl.h sys/ioctl.h sys/param.h sys/param.h sys/socket.h sys/signal.h sys/stat.h sys/time.h sys/types.h sys/vfs.h sysexits.h term.h time.h unistd.h zlib.h
1398213982 do
1398313983 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
1398413984 if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
1412214122
1412314123 done
1412414124
14125
14126
14127 { echo "$as_me:$LINENO: checking for regcomp in -lregex" >&5
14128 echo $ECHO_N "checking for regcomp in -lregex... $ECHO_C" >&6; }
14129 if test "${ac_cv_lib_regex_regcomp+set}" = set; then
14130 echo $ECHO_N "(cached) $ECHO_C" >&6
14131 else
14132 ac_check_lib_save_LIBS=$LIBS
14133 LIBS="-lregex $LIBS"
14134 cat >conftest.$ac_ext <<_ACEOF
14135 /* confdefs.h. */
14136 _ACEOF
14137 cat confdefs.h >>conftest.$ac_ext
14138 cat >>conftest.$ac_ext <<_ACEOF
14139 /* end confdefs.h. */
14140
14141 /* Override any GCC internal prototype to avoid an error.
14142 Use char because int might match the return type of a GCC
14143 builtin and then its argument prototype would still apply. */
14144 #ifdef __cplusplus
14145 extern "C"
14146 #endif
14147 char regcomp ();
14148 int
14149 main ()
14150 {
14151 return regcomp ();
14152 ;
14153 return 0;
14154 }
14155 _ACEOF
14156 rm -f conftest.$ac_objext conftest$ac_exeext
14157 if { (ac_try="$ac_link"
14158 case "(($ac_try" in
14159 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
14160 *) ac_try_echo=$ac_try;;
14161 esac
14162 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
14163 (eval "$ac_link") 2>conftest.er1
14164 ac_status=$?
14165 grep -v '^ *+' conftest.er1 >conftest.err
14166 rm -f conftest.er1
14167 cat conftest.err >&5
14168 echo "$as_me:$LINENO: \$? = $ac_status" >&5
14169 (exit $ac_status); } && {
14170 test -z "$ac_c_werror_flag" ||
14171 test ! -s conftest.err
14172 } && test -s conftest$ac_exeext &&
14173 $as_test_x conftest$ac_exeext; then
14174 ac_cv_lib_regex_regcomp=yes
14175 else
14176 echo "$as_me: failed program was:" >&5
14177 sed 's/^/| /' conftest.$ac_ext >&5
14178
14179 ac_cv_lib_regex_regcomp=no
14180 fi
14181
14182 rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
14183 conftest$ac_exeext conftest.$ac_ext
14184 LIBS=$ac_check_lib_save_LIBS
14185 fi
14186 { echo "$as_me:$LINENO: result: $ac_cv_lib_regex_regcomp" >&5
14187 echo "${ECHO_T}$ac_cv_lib_regex_regcomp" >&6; }
14188 if test $ac_cv_lib_regex_regcomp = yes; then
14189 cat >>confdefs.h <<_ACEOF
14190 #define HAVE_LIBREGEX 1
14191 _ACEOF
14192
14193 LIBS="-lregex $LIBS"
14194
14195 fi
14196 # see if we need -lregex
1412514197
1412614198 { echo "$as_me:$LINENO: checking for struct sockaddr_in.sin_len" >&5
1412714199 echo $ECHO_N "checking for struct sockaddr_in.sin_len... $ECHO_C" >&6; }
1733917411 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
1734017412 -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
1734117413 -e 's:$: $lt_compiler_flag:'`
17342 (eval echo "\"\$as_me:17343: $lt_compile\"" >&5)
17414 (eval echo "\"\$as_me:17415: $lt_compile\"" >&5)
1734317415 (eval "$lt_compile" 2>conftest.err)
1734417416 ac_status=$?
1734517417 cat conftest.err >&5
17346 echo "$as_me:17347: \$? = $ac_status" >&5
17418 echo "$as_me:17419: \$? = $ac_status" >&5
1734717419 if (exit $ac_status) && test -s "$ac_outfile"; then
1734817420 # The compiler can only warn and ignore the option if not recognized
1734917421 # So say no if there are warnings other than the usual output.
1743817510 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
1743917511 -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
1744017512 -e 's:$: $lt_compiler_flag:'`
17441 (eval echo "\"\$as_me:17442: $lt_compile\"" >&5)
17513 (eval echo "\"\$as_me:17514: $lt_compile\"" >&5)
1744217514 (eval "$lt_compile" 2>out/conftest.err)
1744317515 ac_status=$?
1744417516 cat out/conftest.err >&5
17445 echo "$as_me:17446: \$? = $ac_status" >&5
17517 echo "$as_me:17518: \$? = $ac_status" >&5
1744617518 if (exit $ac_status) && test -s out/conftest2.$ac_objext
1744717519 then
1744817520 # The compiler can only warn and ignore the option if not recognized
1749017562 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
1749117563 -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
1749217564 -e 's:$: $lt_compiler_flag:'`
17493 (eval echo "\"\$as_me:17494: $lt_compile\"" >&5)
17565 (eval echo "\"\$as_me:17566: $lt_compile\"" >&5)
1749417566 (eval "$lt_compile" 2>out/conftest.err)
1749517567 ac_status=$?
1749617568 cat out/conftest.err >&5
17497 echo "$as_me:17498: \$? = $ac_status" >&5
17569 echo "$as_me:17570: \$? = $ac_status" >&5
1749817570 if (exit $ac_status) && test -s out/conftest2.$ac_objext
1749917571 then
1750017572 # The compiler can only warn and ignore the option if not recognized
1860818680 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
1860918681 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
1861018682 ac_compiler_gnu=$ac_cv_c_compiler_gnu
18611
18612
18613
18614
18615 ################################################################
18616 ## LIBEWF support
18617
18618
18619
18620
18621
18622
18623
18624 # Check whether --enable-libewf was given.
18625 if test "${enable_libewf+set}" = set; then
18626 enableval=$enable_libewf; enable_libewf=$enableval
18627 else
18628 enable_libewf=yes
18629 fi
18630
18631
18632 if test "${enable_libewf}" = "yes" ; then
18633
18634 for ac_header in libewf.h
18635 do
18636 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
18637 if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
18638 { echo "$as_me:$LINENO: checking for $ac_header" >&5
18639 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
18640 if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
18641 echo $ECHO_N "(cached) $ECHO_C" >&6
18642 fi
18643 ac_res=`eval echo '${'$as_ac_Header'}'`
18644 { echo "$as_me:$LINENO: result: $ac_res" >&5
18645 echo "${ECHO_T}$ac_res" >&6; }
18646 else
18647 # Is the header compilable?
18648 { echo "$as_me:$LINENO: checking $ac_header usability" >&5
18649 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
18650 cat >conftest.$ac_ext <<_ACEOF
18651 /* confdefs.h. */
18652 _ACEOF
18653 cat confdefs.h >>conftest.$ac_ext
18654 cat >>conftest.$ac_ext <<_ACEOF
18655 /* end confdefs.h. */
18656 $ac_includes_default
18657 #include <$ac_header>
18658 _ACEOF
18659 rm -f conftest.$ac_objext
18660 if { (ac_try="$ac_compile"
18661 case "(($ac_try" in
18662 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
18663 *) ac_try_echo=$ac_try;;
18664 esac
18665 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
18666 (eval "$ac_compile") 2>conftest.er1
18667 ac_status=$?
18668 grep -v '^ *+' conftest.er1 >conftest.err
18669 rm -f conftest.er1
18670 cat conftest.err >&5
18671 echo "$as_me:$LINENO: \$? = $ac_status" >&5
18672 (exit $ac_status); } && {
18673 test -z "$ac_c_werror_flag" ||
18674 test ! -s conftest.err
18675 } && test -s conftest.$ac_objext; then
18676 ac_header_compiler=yes
18677 else
18678 echo "$as_me: failed program was:" >&5
18679 sed 's/^/| /' conftest.$ac_ext >&5
18680
18681 ac_header_compiler=no
18682 fi
18683
18684 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
18685 { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
18686 echo "${ECHO_T}$ac_header_compiler" >&6; }
18687
18688 # Is the header present?
18689 { echo "$as_me:$LINENO: checking $ac_header presence" >&5
18690 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
18691 cat >conftest.$ac_ext <<_ACEOF
18692 /* confdefs.h. */
18693 _ACEOF
18694 cat confdefs.h >>conftest.$ac_ext
18695 cat >>conftest.$ac_ext <<_ACEOF
18696 /* end confdefs.h. */
18697 #include <$ac_header>
18698 _ACEOF
18699 if { (ac_try="$ac_cpp conftest.$ac_ext"
18700 case "(($ac_try" in
18701 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
18702 *) ac_try_echo=$ac_try;;
18703 esac
18704 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
18705 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
18706 ac_status=$?
18707 grep -v '^ *+' conftest.er1 >conftest.err
18708 rm -f conftest.er1
18709 cat conftest.err >&5
18710 echo "$as_me:$LINENO: \$? = $ac_status" >&5
18711 (exit $ac_status); } >/dev/null && {
18712 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
18713 test ! -s conftest.err
18714 }; then
18715 ac_header_preproc=yes
18716 else
18717 echo "$as_me: failed program was:" >&5
18718 sed 's/^/| /' conftest.$ac_ext >&5
18719
18720 ac_header_preproc=no
18721 fi
18722
18723 rm -f conftest.err conftest.$ac_ext
18724 { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
18725 echo "${ECHO_T}$ac_header_preproc" >&6; }
18726
18727 # So? What about this header?
18728 case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
18729 yes:no: )
18730 { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
18731 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
18732 { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
18733 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
18734 ac_header_preproc=yes
18735 ;;
18736 no:yes:* )
18737 { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
18738 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
18739 { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
18740 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
18741 { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
18742 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
18743 { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
18744 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
18745 { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
18746 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
18747 { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
18748 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
18749 ( cat <<\_ASBOX
18750 ## ------------------------------ ##
18751 ## Report this to bugs@afflib.org ##
18752 ## ------------------------------ ##
18753 _ASBOX
18754 ) | sed "s/^/$as_me: WARNING: /" >&2
18755 ;;
18756 esac
18757 { echo "$as_me:$LINENO: checking for $ac_header" >&5
18758 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
18759 if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
18760 echo $ECHO_N "(cached) $ECHO_C" >&6
18761 else
18762 eval "$as_ac_Header=\$ac_header_preproc"
18763 fi
18764 ac_res=`eval echo '${'$as_ac_Header'}'`
18765 { echo "$as_me:$LINENO: result: $ac_res" >&5
18766 echo "${ECHO_T}$ac_res" >&6; }
18767
18768 fi
18769 if test `eval echo '${'$as_ac_Header'}'` = yes; then
18770 cat >>confdefs.h <<_ACEOF
18771 #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
18772 _ACEOF
18773
18774 else
18775 enable_libewf=no
18776 fi
18777
18778 done
18779
18780 fi
18781
18782 if test "${enable_libewf}" = "yes" ; then
18783 { echo "$as_me:$LINENO: On linux, libewf has a dependency which forces linking with -luuid" >&5
18784 echo "$as_me: On linux, libewf has a dependency which forces linking with -luuid" >&6;}
18785 { echo "$as_me:$LINENO: so if we are running on linux and that version of libewf is installed," >&5
18786 echo "$as_me: so if we are running on linux and that version of libewf is installed," >&6;}
18787 { echo "$as_me:$LINENO: make sure the libuuid is installed" >&5
18788 echo "$as_me: make sure the libuuid is installed" >&6;}
18789
18790 if test -r /usr/lib/libewf.la ; then
18791 if grep luuid /usr/lib/libewf.la ; then
18792 { echo "$as_me:$LINENO: Installed libewf requires libuuid." >&5
18793 echo "$as_me: Installed libewf requires libuuid." >&6;}
18794
18795 { echo "$as_me:$LINENO: checking for uuid_generate_random in -luuid" >&5
18796 echo $ECHO_N "checking for uuid_generate_random in -luuid... $ECHO_C" >&6; }
18797 if test "${ac_cv_lib_uuid_uuid_generate_random+set}" = set; then
18798 echo $ECHO_N "(cached) $ECHO_C" >&6
18799 else
18800 ac_check_lib_save_LIBS=$LIBS
18801 LIBS="-luuid $LIBS"
18802 cat >conftest.$ac_ext <<_ACEOF
18803 /* confdefs.h. */
18804 _ACEOF
18805 cat confdefs.h >>conftest.$ac_ext
18806 cat >>conftest.$ac_ext <<_ACEOF
18807 /* end confdefs.h. */
18808
18809 /* Override any GCC internal prototype to avoid an error.
18810 Use char because int might match the return type of a GCC
18811 builtin and then its argument prototype would still apply. */
18812 #ifdef __cplusplus
18813 extern "C"
18814 #endif
18815 char uuid_generate_random ();
18816 int
18817 main ()
18818 {
18819 return uuid_generate_random ();
18820 ;
18821 return 0;
18822 }
18823 _ACEOF
18824 rm -f conftest.$ac_objext conftest$ac_exeext
18825 if { (ac_try="$ac_link"
18826 case "(($ac_try" in
18827 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
18828 *) ac_try_echo=$ac_try;;
18829 esac
18830 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
18831 (eval "$ac_link") 2>conftest.er1
18832 ac_status=$?
18833 grep -v '^ *+' conftest.er1 >conftest.err
18834 rm -f conftest.er1
18835 cat conftest.err >&5
18836 echo "$as_me:$LINENO: \$? = $ac_status" >&5
18837 (exit $ac_status); } && {
18838 test -z "$ac_c_werror_flag" ||
18839 test ! -s conftest.err
18840 } && test -s conftest$ac_exeext &&
18841 $as_test_x conftest$ac_exeext; then
18842 ac_cv_lib_uuid_uuid_generate_random=yes
18843 else
18844 echo "$as_me: failed program was:" >&5
18845 sed 's/^/| /' conftest.$ac_ext >&5
18846
18847 ac_cv_lib_uuid_uuid_generate_random=no
18848 fi
18849
18850 rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
18851 conftest$ac_exeext conftest.$ac_ext
18852 LIBS=$ac_check_lib_save_LIBS
18853 fi
18854 { echo "$as_me:$LINENO: result: $ac_cv_lib_uuid_uuid_generate_random" >&5
18855 echo "${ECHO_T}$ac_cv_lib_uuid_uuid_generate_random" >&6; }
18856 if test $ac_cv_lib_uuid_uuid_generate_random = yes; then
18857 cat >>confdefs.h <<_ACEOF
18858 #define HAVE_LIBUUID 1
18859 _ACEOF
18860
18861 LIBS="-luuid $LIBS"
18862
18863 else
18864 enable_libewf=no
18865 fi
18866
18867 fi
18868 fi
18869 fi
18870
18871 if test "${enable_libewf}" = "yes" ; then
18872
18873 { echo "$as_me:$LINENO: checking for libewf_get_version in -lewf" >&5
18874 echo $ECHO_N "checking for libewf_get_version in -lewf... $ECHO_C" >&6; }
18875 if test "${ac_cv_lib_ewf_libewf_get_version+set}" = set; then
18876 echo $ECHO_N "(cached) $ECHO_C" >&6
18877 else
18878 ac_check_lib_save_LIBS=$LIBS
18879 LIBS="-lewf $LIBS"
18880 cat >conftest.$ac_ext <<_ACEOF
18881 /* confdefs.h. */
18882 _ACEOF
18883 cat confdefs.h >>conftest.$ac_ext
18884 cat >>conftest.$ac_ext <<_ACEOF
18885 /* end confdefs.h. */
18886
18887 /* Override any GCC internal prototype to avoid an error.
18888 Use char because int might match the return type of a GCC
18889 builtin and then its argument prototype would still apply. */
18890 #ifdef __cplusplus
18891 extern "C"
18892 #endif
18893 char libewf_get_version ();
18894 int
18895 main ()
18896 {
18897 return libewf_get_version ();
18898 ;
18899 return 0;
18900 }
18901 _ACEOF
18902 rm -f conftest.$ac_objext conftest$ac_exeext
18903 if { (ac_try="$ac_link"
18904 case "(($ac_try" in
18905 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
18906 *) ac_try_echo=$ac_try;;
18907 esac
18908 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
18909 (eval "$ac_link") 2>conftest.er1
18910 ac_status=$?
18911 grep -v '^ *+' conftest.er1 >conftest.err
18912 rm -f conftest.er1
18913 cat conftest.err >&5
18914 echo "$as_me:$LINENO: \$? = $ac_status" >&5
18915 (exit $ac_status); } && {
18916 test -z "$ac_c_werror_flag" ||
18917 test ! -s conftest.err
18918 } && test -s conftest$ac_exeext &&
18919 $as_test_x conftest$ac_exeext; then
18920 ac_cv_lib_ewf_libewf_get_version=yes
18921 else
18922 echo "$as_me: failed program was:" >&5
18923 sed 's/^/| /' conftest.$ac_ext >&5
18924
18925 ac_cv_lib_ewf_libewf_get_version=no
18926 fi
18927
18928 rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
18929 conftest$ac_exeext conftest.$ac_ext
18930 LIBS=$ac_check_lib_save_LIBS
18931 fi
18932 { echo "$as_me:$LINENO: result: $ac_cv_lib_ewf_libewf_get_version" >&5
18933 echo "${ECHO_T}$ac_cv_lib_ewf_libewf_get_version" >&6; }
18934 if test $ac_cv_lib_ewf_libewf_get_version = yes; then
18935 cat >>confdefs.h <<_ACEOF
18936 #define HAVE_LIBEWF 1
18937 _ACEOF
18938
18939 LIBS="-lewf $LIBS"
18940
18941 else
18942 enable_libewf=no
18943 fi
18944
18945 fi
18946
18947 if test "${enable_libewf}" = "yes" ; then
18948 { echo "$as_me:$LINENO: checking for libewf_get_media_size" >&5
18949 echo $ECHO_N "checking for libewf_get_media_size... $ECHO_C" >&6; }
18950 if test "${ac_cv_func_libewf_get_media_size+set}" = set; then
18951 echo $ECHO_N "(cached) $ECHO_C" >&6
18952 else
18953 cat >conftest.$ac_ext <<_ACEOF
18954 /* confdefs.h. */
18955 _ACEOF
18956 cat confdefs.h >>conftest.$ac_ext
18957 cat >>conftest.$ac_ext <<_ACEOF
18958 /* end confdefs.h. */
18959 /* Define libewf_get_media_size to an innocuous variant, in case <limits.h> declares libewf_get_media_size.
18960 For example, HP-UX 11i <limits.h> declares gettimeofday. */
18961 #define libewf_get_media_size innocuous_libewf_get_media_size
18962
18963 /* System header to define __stub macros and hopefully few prototypes,
18964 which can conflict with char libewf_get_media_size (); below.
18965 Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
18966 <limits.h> exists even on freestanding compilers. */
18967
18968 #ifdef __STDC__
18969 # include <limits.h>
18970 #else
18971 # include <assert.h>
18972 #endif
18973
18974 #undef libewf_get_media_size
18975
18976 /* Override any GCC internal prototype to avoid an error.
18977 Use char because int might match the return type of a GCC
18978 builtin and then its argument prototype would still apply. */
18979 #ifdef __cplusplus
18980 extern "C"
18981 #endif
18982 char libewf_get_media_size ();
18983 /* The GNU C library defines this for functions which it implements
18984 to always fail with ENOSYS. Some functions are actually named
18985 something starting with __ and the normal name is an alias. */
18986 #if defined __stub_libewf_get_media_size || defined __stub___libewf_get_media_size
18987 choke me
18988 #endif
18989
18990 int
18991 main ()
18992 {
18993 return libewf_get_media_size ();
18994 ;
18995 return 0;
18996 }
18997 _ACEOF
18998 rm -f conftest.$ac_objext conftest$ac_exeext
18999 if { (ac_try="$ac_link"
19000 case "(($ac_try" in
19001 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
19002 *) ac_try_echo=$ac_try;;
19003 esac
19004 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
19005 (eval "$ac_link") 2>conftest.er1
19006 ac_status=$?
19007 grep -v '^ *+' conftest.er1 >conftest.err
19008 rm -f conftest.er1
19009 cat conftest.err >&5
19010 echo "$as_me:$LINENO: \$? = $ac_status" >&5
19011 (exit $ac_status); } && {
19012 test -z "$ac_c_werror_flag" ||
19013 test ! -s conftest.err
19014 } && test -s conftest$ac_exeext &&
19015 $as_test_x conftest$ac_exeext; then
19016 ac_cv_func_libewf_get_media_size=yes
19017 else
19018 echo "$as_me: failed program was:" >&5
19019 sed 's/^/| /' conftest.$ac_ext >&5
19020
19021 ac_cv_func_libewf_get_media_size=no
19022 fi
19023
19024 rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
19025 conftest$ac_exeext conftest.$ac_ext
19026 fi
19027 { echo "$as_me:$LINENO: result: $ac_cv_func_libewf_get_media_size" >&5
19028 echo "${ECHO_T}$ac_cv_func_libewf_get_media_size" >&6; }
19029 if test $ac_cv_func_libewf_get_media_size = yes; then
19030
19031 cat >>confdefs.h <<\_ACEOF
19032 #define HAVE_LIBEWF_GET_MEDIA_SIZE 1
19033 _ACEOF
19034
19035 ac_ext=c
19036 ac_cpp='$CPP $CPPFLAGS'
19037 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
19038 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
19039 ac_compiler_gnu=$ac_cv_c_compiler_gnu
19040
19041 { echo "$as_me:$LINENO: checking if libewf_get_media_size takes size as an argument." >&5
19042 echo $ECHO_N "checking if libewf_get_media_size takes size as an argument.... $ECHO_C" >&6; }
19043 cat >conftest.$ac_ext <<_ACEOF
19044 /* confdefs.h. */
19045 _ACEOF
19046 cat confdefs.h >>conftest.$ac_ext
19047 cat >>conftest.$ac_ext <<_ACEOF
19048 /* end confdefs.h. */
19049 #include <libewf.h>
19050 int
19051 main ()
19052 {
19053 libewf_get_media_size(NULL,NULL);
19054 ;
19055 return 0;
19056 }
19057 _ACEOF
19058 rm -f conftest.$ac_objext conftest$ac_exeext
19059 if { (ac_try="$ac_link"
19060 case "(($ac_try" in
19061 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
19062 *) ac_try_echo=$ac_try;;
19063 esac
19064 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
19065 (eval "$ac_link") 2>conftest.er1
19066 ac_status=$?
19067 grep -v '^ *+' conftest.er1 >conftest.err
19068 rm -f conftest.er1
19069 cat conftest.err >&5
19070 echo "$as_me:$LINENO: \$? = $ac_status" >&5
19071 (exit $ac_status); } && {
19072 test -z "$ac_c_werror_flag" ||
19073 test ! -s conftest.err
19074 } && test -s conftest$ac_exeext &&
19075 $as_test_x conftest$ac_exeext; then
19076 { echo "$as_me:$LINENO: result: yes" >&5
19077 echo "${ECHO_T}yes" >&6; }
19078
19079 cat >>confdefs.h <<\_ACEOF
19080 #define HAVE_LIBEWF_GET_MEDIA_SIZE_ARGUMENT_VALUE 1
19081 _ACEOF
19082
19083 else
19084 echo "$as_me: failed program was:" >&5
19085 sed 's/^/| /' conftest.$ac_ext >&5
19086
19087 { echo "$as_me:$LINENO: result: no" >&5
19088 echo "${ECHO_T}no" >&6; }
19089 fi
19090
19091 rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
19092 conftest$ac_exeext conftest.$ac_ext
19093 ac_ext=c
19094 ac_cpp='$CPP $CPPFLAGS'
19095 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
19096 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
19097 ac_compiler_gnu=$ac_cv_c_compiler_gnu
19098
19099 fi
19100
19101
19102 { echo "$as_me:$LINENO: checking for libewf_get_chunk_size" >&5
19103 echo $ECHO_N "checking for libewf_get_chunk_size... $ECHO_C" >&6; }
19104 if test "${ac_cv_func_libewf_get_chunk_size+set}" = set; then
19105 echo $ECHO_N "(cached) $ECHO_C" >&6
19106 else
19107 cat >conftest.$ac_ext <<_ACEOF
19108 /* confdefs.h. */
19109 _ACEOF
19110 cat confdefs.h >>conftest.$ac_ext
19111 cat >>conftest.$ac_ext <<_ACEOF
19112 /* end confdefs.h. */
19113 /* Define libewf_get_chunk_size to an innocuous variant, in case <limits.h> declares libewf_get_chunk_size.
19114 For example, HP-UX 11i <limits.h> declares gettimeofday. */
19115 #define libewf_get_chunk_size innocuous_libewf_get_chunk_size
19116
19117 /* System header to define __stub macros and hopefully few prototypes,
19118 which can conflict with char libewf_get_chunk_size (); below.
19119 Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
19120 <limits.h> exists even on freestanding compilers. */
19121
19122 #ifdef __STDC__
19123 # include <limits.h>
19124 #else
19125 # include <assert.h>
19126 #endif
19127
19128 #undef libewf_get_chunk_size
19129
19130 /* Override any GCC internal prototype to avoid an error.
19131 Use char because int might match the return type of a GCC
19132 builtin and then its argument prototype would still apply. */
19133 #ifdef __cplusplus
19134 extern "C"
19135 #endif
19136 char libewf_get_chunk_size ();
19137 /* The GNU C library defines this for functions which it implements
19138 to always fail with ENOSYS. Some functions are actually named
19139 something starting with __ and the normal name is an alias. */
19140 #if defined __stub_libewf_get_chunk_size || defined __stub___libewf_get_chunk_size
19141 choke me
19142 #endif
19143
19144 int
19145 main ()
19146 {
19147 return libewf_get_chunk_size ();
19148 ;
19149 return 0;
19150 }
19151 _ACEOF
19152 rm -f conftest.$ac_objext conftest$ac_exeext
19153 if { (ac_try="$ac_link"
19154 case "(($ac_try" in
19155 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
19156 *) ac_try_echo=$ac_try;;
19157 esac
19158 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
19159 (eval "$ac_link") 2>conftest.er1
19160 ac_status=$?
19161 grep -v '^ *+' conftest.er1 >conftest.err
19162 rm -f conftest.er1
19163 cat conftest.err >&5
19164 echo "$as_me:$LINENO: \$? = $ac_status" >&5
19165 (exit $ac_status); } && {
19166 test -z "$ac_c_werror_flag" ||
19167 test ! -s conftest.err
19168 } && test -s conftest$ac_exeext &&
19169 $as_test_x conftest$ac_exeext; then
19170 ac_cv_func_libewf_get_chunk_size=yes
19171 else
19172 echo "$as_me: failed program was:" >&5
19173 sed 's/^/| /' conftest.$ac_ext >&5
19174
19175 ac_cv_func_libewf_get_chunk_size=no
19176 fi
19177
19178 rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
19179 conftest$ac_exeext conftest.$ac_ext
19180 fi
19181 { echo "$as_me:$LINENO: result: $ac_cv_func_libewf_get_chunk_size" >&5
19182 echo "${ECHO_T}$ac_cv_func_libewf_get_chunk_size" >&6; }
19183 if test $ac_cv_func_libewf_get_chunk_size = yes; then
19184
19185 cat >>confdefs.h <<\_ACEOF
19186 #define HAVE_LIBEWF_GET_CHUNK_SIZE 1
19187 _ACEOF
19188
19189 ac_ext=c
19190 ac_cpp='$CPP $CPPFLAGS'
19191 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
19192 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
19193 ac_compiler_gnu=$ac_cv_c_compiler_gnu
19194
19195 { echo "$as_me:$LINENO: checking if libewf_get_chunk_size takes size as an argument." >&5
19196 echo $ECHO_N "checking if libewf_get_chunk_size takes size as an argument.... $ECHO_C" >&6; }
19197 cat >conftest.$ac_ext <<_ACEOF
19198 /* confdefs.h. */
19199 _ACEOF
19200 cat confdefs.h >>conftest.$ac_ext
19201 cat >>conftest.$ac_ext <<_ACEOF
19202 /* end confdefs.h. */
19203 #include <libewf.h>
19204 int
19205 main ()
19206 {
19207 libewf_get_chunk_size(NULL,NULL);
19208 ;
19209 return 0;
19210 }
19211 _ACEOF
19212 rm -f conftest.$ac_objext conftest$ac_exeext
19213 if { (ac_try="$ac_link"
19214 case "(($ac_try" in
19215 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
19216 *) ac_try_echo=$ac_try;;
19217 esac
19218 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
19219 (eval "$ac_link") 2>conftest.er1
19220 ac_status=$?
19221 grep -v '^ *+' conftest.er1 >conftest.err
19222 rm -f conftest.er1
19223 cat conftest.err >&5
19224 echo "$as_me:$LINENO: \$? = $ac_status" >&5
19225 (exit $ac_status); } && {
19226 test -z "$ac_c_werror_flag" ||
19227 test ! -s conftest.err
19228 } && test -s conftest$ac_exeext &&
19229 $as_test_x conftest$ac_exeext; then
19230 { echo "$as_me:$LINENO: result: yes" >&5
19231 echo "${ECHO_T}yes" >&6; }
19232
19233 cat >>confdefs.h <<\_ACEOF
19234 #define HAVE_LIBEWF_GET_CHUNK_SIZE_ARGUMENT_VALUE 1
19235 _ACEOF
19236
19237 else
19238 echo "$as_me: failed program was:" >&5
19239 sed 's/^/| /' conftest.$ac_ext >&5
19240
19241 { echo "$as_me:$LINENO: result: no" >&5
19242 echo "${ECHO_T}no" >&6; }
19243 fi
19244
19245 rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
19246 conftest$ac_exeext conftest.$ac_ext
19247 ac_ext=c
19248 ac_cpp='$CPP $CPPFLAGS'
19249 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
19250 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
19251 ac_compiler_gnu=$ac_cv_c_compiler_gnu
19252
19253 fi
19254
19255
19256 { echo "$as_me:$LINENO: checking for libewf_get_bytes_per_sector" >&5
19257 echo $ECHO_N "checking for libewf_get_bytes_per_sector... $ECHO_C" >&6; }
19258 if test "${ac_cv_func_libewf_get_bytes_per_sector+set}" = set; then
19259 echo $ECHO_N "(cached) $ECHO_C" >&6
19260 else
19261 cat >conftest.$ac_ext <<_ACEOF
19262 /* confdefs.h. */
19263 _ACEOF
19264 cat confdefs.h >>conftest.$ac_ext
19265 cat >>conftest.$ac_ext <<_ACEOF
19266 /* end confdefs.h. */
19267 /* Define libewf_get_bytes_per_sector to an innocuous variant, in case <limits.h> declares libewf_get_bytes_per_sector.
19268 For example, HP-UX 11i <limits.h> declares gettimeofday. */
19269 #define libewf_get_bytes_per_sector innocuous_libewf_get_bytes_per_sector
19270
19271 /* System header to define __stub macros and hopefully few prototypes,
19272 which can conflict with char libewf_get_bytes_per_sector (); below.
19273 Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
19274 <limits.h> exists even on freestanding compilers. */
19275
19276 #ifdef __STDC__
19277 # include <limits.h>
19278 #else
19279 # include <assert.h>
19280 #endif
19281
19282 #undef libewf_get_bytes_per_sector
19283
19284 /* Override any GCC internal prototype to avoid an error.
19285 Use char because int might match the return type of a GCC
19286 builtin and then its argument prototype would still apply. */
19287 #ifdef __cplusplus
19288 extern "C"
19289 #endif
19290 char libewf_get_bytes_per_sector ();
19291 /* The GNU C library defines this for functions which it implements
19292 to always fail with ENOSYS. Some functions are actually named
19293 something starting with __ and the normal name is an alias. */
19294 #if defined __stub_libewf_get_bytes_per_sector || defined __stub___libewf_get_bytes_per_sector
19295 choke me
19296 #endif
19297
19298 int
19299 main ()
19300 {
19301 return libewf_get_bytes_per_sector ();
19302 ;
19303 return 0;
19304 }
19305 _ACEOF
19306 rm -f conftest.$ac_objext conftest$ac_exeext
19307 if { (ac_try="$ac_link"
19308 case "(($ac_try" in
19309 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
19310 *) ac_try_echo=$ac_try;;
19311 esac
19312 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
19313 (eval "$ac_link") 2>conftest.er1
19314 ac_status=$?
19315 grep -v '^ *+' conftest.er1 >conftest.err
19316 rm -f conftest.er1
19317 cat conftest.err >&5
19318 echo "$as_me:$LINENO: \$? = $ac_status" >&5
19319 (exit $ac_status); } && {
19320 test -z "$ac_c_werror_flag" ||
19321 test ! -s conftest.err
19322 } && test -s conftest$ac_exeext &&
19323 $as_test_x conftest$ac_exeext; then
19324 ac_cv_func_libewf_get_bytes_per_sector=yes
19325 else
19326 echo "$as_me: failed program was:" >&5
19327 sed 's/^/| /' conftest.$ac_ext >&5
19328
19329 ac_cv_func_libewf_get_bytes_per_sector=no
19330 fi
19331
19332 rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
19333 conftest$ac_exeext conftest.$ac_ext
19334 fi
19335 { echo "$as_me:$LINENO: result: $ac_cv_func_libewf_get_bytes_per_sector" >&5
19336 echo "${ECHO_T}$ac_cv_func_libewf_get_bytes_per_sector" >&6; }
19337 if test $ac_cv_func_libewf_get_bytes_per_sector = yes; then
19338
19339 cat >>confdefs.h <<\_ACEOF
19340 #define HAVE_LIBEWF_GET_BYTES_PER_SECTOR 1
19341 _ACEOF
19342
19343 ac_ext=c
19344 ac_cpp='$CPP $CPPFLAGS'
19345 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
19346 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
19347 ac_compiler_gnu=$ac_cv_c_compiler_gnu
19348
19349 { echo "$as_me:$LINENO: checking if libewf_get_bytes_per_sector takes size as an argument." >&5
19350 echo $ECHO_N "checking if libewf_get_bytes_per_sector takes size as an argument.... $ECHO_C" >&6; }
19351 cat >conftest.$ac_ext <<_ACEOF
19352 /* confdefs.h. */
19353 _ACEOF
19354 cat confdefs.h >>conftest.$ac_ext
19355 cat >>conftest.$ac_ext <<_ACEOF
19356 /* end confdefs.h. */
19357 #include <libewf.h>
19358 int
19359 main ()
19360 {
19361 libewf_get_bytes_per_sector(NULL,NULL);
19362 ;
19363 return 0;
19364 }
19365 _ACEOF
19366 rm -f conftest.$ac_objext conftest$ac_exeext
19367 if { (ac_try="$ac_link"
19368 case "(($ac_try" in
19369 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
19370 *) ac_try_echo=$ac_try;;
19371 esac
19372 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
19373 (eval "$ac_link") 2>conftest.er1
19374 ac_status=$?
19375 grep -v '^ *+' conftest.er1 >conftest.err
19376 rm -f conftest.er1
19377 cat conftest.err >&5
19378 echo "$as_me:$LINENO: \$? = $ac_status" >&5
19379 (exit $ac_status); } && {
19380 test -z "$ac_c_werror_flag" ||
19381 test ! -s conftest.err
19382 } && test -s conftest$ac_exeext &&
19383 $as_test_x conftest$ac_exeext; then
19384 { echo "$as_me:$LINENO: result: yes" >&5
19385 echo "${ECHO_T}yes" >&6; }
19386
19387 cat >>confdefs.h <<\_ACEOF
19388 #define HAVE_LIBEWF_GET_BYTES_PER_SECTOR_ARGUMENT_VALUE 1
19389 _ACEOF
19390
19391 else
19392 echo "$as_me: failed program was:" >&5
19393 sed 's/^/| /' conftest.$ac_ext >&5
19394
19395 { echo "$as_me:$LINENO: result: no" >&5
19396 echo "${ECHO_T}no" >&6; }
19397 fi
19398
19399 rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
19400 conftest$ac_exeext conftest.$ac_ext
19401 ac_ext=c
19402 ac_cpp='$CPP $CPPFLAGS'
19403 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
19404 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
19405 ac_compiler_gnu=$ac_cv_c_compiler_gnu
19406
19407 fi
19408
19409
19410
19411 cat >>confdefs.h <<\_ACEOF
19412 #define USE_LIBEWF 1
19413 _ACEOF
19414
19415 fi
1941618683
1941718684
1941818685 ################################################################
2226321530
2226421531 ac_config_files="$ac_config_files afflib.spec"
2226521532
21533
2226621534 ac_config_headers="$ac_config_headers affconfig.h"
2226721535
2226821536
2272721995 # report actual input values of CONFIG_FILES etc. instead of their
2272821996 # values after options handling.
2272921997 ac_log="
22730 This file was extended by AFFLIB $as_me 3.5.12, which was
21998 This file was extended by AFFLIB $as_me 3.6.2, which was
2273121999 generated by GNU Autoconf 2.61. Invocation command line was
2273222000
2273322001 CONFIG_FILES = $CONFIG_FILES
2278022048 _ACEOF
2278122049 cat >>$CONFIG_STATUS <<_ACEOF
2278222050 ac_cs_version="\\
22783 AFFLIB config.status 3.5.12
22051 AFFLIB config.status 3.6.2
2278422052 configured by $0, generated by GNU Autoconf 2.61,
2278522053 with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
2278622054
44 # and http://www.openismus.com/documents/linux/automake/automake.shtml
55
66
7 AC_INIT([AFFLIB],[3.5.12],[bugs@afflib.org])
7 AC_INIT([AFFLIB],[3.6.2],[bugs@afflib.org])
88 AM_INIT_AUTOMAKE
99 AM_MAINTAINER_MODE
1010
6969
7070
7171 # Specific headers that I plan to use
72 AC_CHECK_HEADERS([arpa/inet.h assert.h ctype.h dmalloc.h err.h errno.h fcntl.h getopt.h inttypes.h linux/fs.h malloc.h ncurses/term.h netinet/in.h regex.h signal.h stdio.h stdlib.h string.h sys/cdefs.h sys/disk.h sys/file.h sys/ioctl.h sys/ioctl.h sys/param.h sys/param.h sys/socket.h sys/signal.h sys/stat.h sys/time.h sys/types.h sys/vfs.h sysexits.h term.h time.h unistd.h zlib.h])
72 AC_CHECK_HEADERS([arpa/inet.h assert.h ctype.h dmalloc.h err.h errno.h fcntl.h getopt.h inttypes.h linux/fs.h malloc.h ncurses/term.h netinet/in.h regex.h signal.h stdint.h stdio.h stdlib.h string.h sys/cdefs.h sys/disk.h sys/file.h sys/ioctl.h sys/ioctl.h sys/param.h sys/param.h sys/socket.h sys/signal.h sys/stat.h sys/time.h sys/types.h sys/vfs.h sysexits.h term.h time.h unistd.h zlib.h])
73
74 AC_CHECK_LIB([regex],[regcomp]) # see if we need -lregex
7375
7476 AC_CHECK_MEMBER([struct sockaddr_in.sin_len],
7577 [ AC_DEFINE(HAVE_SOCKADDR_SIN_LEN, 1, [Do we have sockaddr.sin_len?]) ],
9294 AC_LANG_PUSH([C++])
9395 AC_CHECK_HEADERS([cstring])
9496 AC_LANG_POP([C++])
95
96
97
98 ################################################################
99 ## LIBEWF support
100 dnl Function to test if a libewf_get_media_size takes value as an argument
101 AC_DEFUN([AFF_CHECK_LIBEWF_GET_MEDIA_SIZE],
102 [AC_CHECK_FUNC(
103 [libewf_get_media_size],
104 [AC_DEFINE(
105 [HAVE_LIBEWF_GET_MEDIA_SIZE],
106 [1],
107 [Define to 1 if you have the libewf_get_media_size function.])
108 AC_LANG_PUSH(C)
109 AC_MSG_CHECKING(
110 [if libewf_get_media_size takes size as an argument.])
111 AC_LINK_IFELSE(
112 [AC_LANG_PROGRAM(
113 [[#include <libewf.h>]],
114 [[libewf_get_media_size(NULL,NULL); ]] )],
115 [AC_MSG_RESULT(
116 [yes])
117 AC_DEFINE(
118 [HAVE_LIBEWF_GET_MEDIA_SIZE_ARGUMENT_VALUE],
119 [1],
120 [Define to 1 if libewf_get_media_size takes value as an argument.])],
121 [AC_MSG_RESULT(
122 [no])] )
123 AC_LANG_POP(C) ])
124 ])
125
126 dnl Function to test if a libewf_get_chunk_size takes value as an argument
127 AC_DEFUN([AFF_CHECK_LIBEWF_GET_CHUNK_SIZE],
128 [AC_CHECK_FUNC(
129 [libewf_get_chunk_size],
130 [AC_DEFINE(
131 [HAVE_LIBEWF_GET_CHUNK_SIZE],
132 [1],
133 [Define to 1 if you have the libewf_get_chunk_size function.])
134 AC_LANG_PUSH(C)
135 AC_MSG_CHECKING(
136 [if libewf_get_chunk_size takes size as an argument.])
137 AC_LINK_IFELSE(
138 [AC_LANG_PROGRAM(
139 [[#include <libewf.h>]],
140 [[libewf_get_chunk_size(NULL,NULL); ]] )],
141 [AC_MSG_RESULT(
142 [yes])
143 AC_DEFINE(
144 [HAVE_LIBEWF_GET_CHUNK_SIZE_ARGUMENT_VALUE],
145 [1],
146 [Define to 1 if libewf_get_chunk_size takes value as an argument.])],
147 [AC_MSG_RESULT(
148 [no])] )
149 AC_LANG_POP(C) ])
150 ])
151
152 dnl Function to test if a libewf_get_bytes_per_sector takes value as an argument
153 AC_DEFUN([AFF_CHECK_LIBEWF_GET_BYTES_PER_SECTOR],
154 [AC_CHECK_FUNC(
155 [libewf_get_bytes_per_sector],
156 [AC_DEFINE(
157 [HAVE_LIBEWF_GET_BYTES_PER_SECTOR],
158 [1],
159 [Define to 1 if you have the libewf_get_bytes_per_sector function.])
160 AC_LANG_PUSH(C)
161 AC_MSG_CHECKING(
162 [if libewf_get_bytes_per_sector takes size as an argument.])
163 AC_LINK_IFELSE(
164 [AC_LANG_PROGRAM(
165 [[#include <libewf.h>]],
166 [[libewf_get_bytes_per_sector(NULL,NULL); ]] )],
167 [AC_MSG_RESULT(
168 [yes])
169 AC_DEFINE(
170 [HAVE_LIBEWF_GET_BYTES_PER_SECTOR_ARGUMENT_VALUE],
171 [1],
172 [Define to 1 if libewf_get_bytes_per_sector takes value as an argument.])],
173 [AC_MSG_RESULT(
174 [no])] )
175 AC_LANG_POP(C) ])
176 ])
177
178
179 AC_ARG_ENABLE([libewf],
180 AC_HELP_STRING([--enable-libewf=yes], [Use libewf for reading EnCase files(default yes)]),
181 [enable_libewf=$enableval], [enable_libewf=yes])
182
183 if test "${enable_libewf}" = "yes" ; then
184 AC_CHECK_HEADERS([libewf.h],,[enable_libewf=no])
185 fi
186
187 if test "${enable_libewf}" = "yes" ; then
188 AC_MSG_NOTICE([On linux, libewf has a dependency which forces linking with -luuid])
189 AC_MSG_NOTICE([so if we are running on linux and that version of libewf is installed,])
190 AC_MSG_NOTICE([make sure the libuuid is installed])
191
192 if test -r /usr/lib/libewf.la ; then
193 if grep luuid /usr/lib/libewf.la ; then
194 AC_MSG_NOTICE([Installed libewf requires libuuid.])
195 AC_CHECK_LIB([uuid],[uuid_generate_random],,[enable_libewf=no])
196 fi
197 fi
198 fi
199
200 if test "${enable_libewf}" = "yes" ; then
201 AC_CHECK_LIB([ewf],[libewf_get_version],,[enable_libewf=no])
202 fi
203
204 if test "${enable_libewf}" = "yes" ; then
205 AFF_CHECK_LIBEWF_GET_MEDIA_SIZE
206 AFF_CHECK_LIBEWF_GET_CHUNK_SIZE
207 AFF_CHECK_LIBEWF_GET_BYTES_PER_SECTOR
208 AC_DEFINE([USE_LIBEWF],1,[Use libewf to read EnCase files])
209 fi
210
21197
21298 ################################################################
21399 # For AFF tools
416302 tests/Makefile doc/Makefile pyaff/Makefile man/Makefile lib/version.h])
417303 dnl Have configure make distribution specific files
418304 AC_CONFIG_FILES([afflib.spec])
305
419306 dnl Have configure write its configuration
420307 AM_CONFIG_HEADER([affconfig.h])
421308
3838 af_open() and af_read() instead of fopen() and fread(). You can
3939 then read the AFF files directly. If you don't have source code,
4040 but have a scanner that can read from standard input, you can
41 use the "afcat" program to copy the contents of an AFF file to
41 use the "affcat" program to copy the contents of an AFF file to
4242 standard output.
4343
4444 Eventually, we plan to have a version of samba that is modified to
0 bin_PROGRAMS = aftest
0 EXTRA_PROGRAMS = aftest
1 TESTS = aftest
2
3 CLEANFILES = aftest
4
15 aftest_SOURCES = aftest.cpp
26 aftest_LDADD = libafflib.la
3
4 TESTS = aftest
5
67 aftest_LDFLAGS = $(PTHREAD_CFLAGS) -static # easier debugging
78
89 AFFLIB_SOURCES = aff_db.cpp aff_db.h aff_toc.cpp \
1314 vnode_aff.cpp vnode_aff.h \
1415 vnode_afd.cpp vnode_afd.h \
1516 vnode_afm.cpp vnode_afm.h \
16 vnode_ewf.cpp vnode_ewf.h \
1717 vnode_raw.cpp vnode_raw.h \
1818 vnode_split_raw.cpp vnode_split_raw.h \
1919 aftimer.h \
5656 endif
5757
5858 if MAYBE_S3
59 bin_PROGRAMS += s3
59 EXTRA_PROGRAMS += s3
6060 libafflib_la_SOURCES += vnode_s3.cpp vnode_s3.h s3_glue.cpp
6161 s3_SOURCES = s3.cpp
6262 s3_LDADD = libafflib.la
1212 # PARTICULAR PURPOSE.
1313
1414 @SET_MAKE@
15
1615
1716 VPATH = @srcdir@
1817 pkgdatadir = $(datadir)/@PACKAGE@
3231 POST_UNINSTALL = :
3332 build_triplet = @build@
3433 host_triplet = @host@
35 bin_PROGRAMS = aftest$(EXEEXT) $(am__EXEEXT_1)
34 EXTRA_PROGRAMS = aftest$(EXEEXT) $(am__EXEEXT_1)
3635 TESTS = aftest$(EXEEXT)
3736 @MAYBE_QEMU_TRUE@am__append_1 = $(QEMU_SOURCES)
3837 @MAYBE_S3_TRUE@am__append_2 = s3
5453 *) f=$$p;; \
5554 esac;
5655 am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
57 am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)"
56 am__installdirs = "$(DESTDIR)$(libdir)"
5857 libLTLIBRARIES_INSTALL = $(INSTALL)
5958 LTLIBRARIES = $(lib_LTLIBRARIES)
6059 libafflib_la_LIBADD =
6362 afflib_pages.cpp afflib_stream.cpp afflib_util.cpp crypto.cpp \
6463 base64.cpp base64.h lzma_glue.cpp s3_glue.h vnode_aff.cpp \
6564 vnode_aff.h vnode_afd.cpp vnode_afd.h vnode_afm.cpp \
66 vnode_afm.h vnode_ewf.cpp vnode_ewf.h vnode_raw.cpp \
67 vnode_raw.h vnode_split_raw.cpp vnode_split_raw.h aftimer.h \
68 utils.cpp utils.h display.cpp vnode_qemu.cpp vnode_qemu.h \
69 qemu/aes.h qemu/aff-block-vmdk.h qemu/block-bochs.c \
70 qemu/block-cloop.c qemu/block-cow.c qemu/block-dmg.c \
71 qemu/block-parallels.c qemu/block-qcow.c qemu/block-qcow2.c \
72 qemu/block-raw-posix.c qemu/block-vmdk.c qemu/block-vpc.c \
73 qemu/block-vvfat.c qemu/block.c qemu/block.h qemu/block_int.h \
74 qemu/bswap.h qemu/config-host.h qemu/console.h qemu/exec-all.h \
75 qemu/osdep.h qemu/qemu-common.h qemu/qemu-timer.h \
76 qemu/qemu_glue.c vnode_s3.cpp vnode_s3.h s3_glue.cpp \
65 vnode_afm.h vnode_raw.cpp vnode_raw.h vnode_split_raw.cpp \
66 vnode_split_raw.h aftimer.h utils.cpp utils.h display.cpp \
67 vnode_qemu.cpp vnode_qemu.h qemu/aes.h qemu/aff-block-vmdk.h \
68 qemu/block-bochs.c qemu/block-cloop.c qemu/block-cow.c \
69 qemu/block-dmg.c qemu/block-parallels.c qemu/block-qcow.c \
70 qemu/block-qcow2.c qemu/block-raw-posix.c qemu/block-vmdk.c \
71 qemu/block-vpc.c qemu/block-vvfat.c qemu/block.c qemu/block.h \
72 qemu/block_int.h qemu/bswap.h qemu/config-host.h \
73 qemu/console.h qemu/exec-all.h qemu/osdep.h qemu/qemu-common.h \
74 qemu/qemu-timer.h qemu/qemu_glue.c vnode_s3.cpp vnode_s3.h \
75 s3_glue.cpp \
7776 @top_srcdir@/lzma443/C/7zip/Compress/LZMA_Alone/LzmaBench.cpp \
7877 @top_srcdir@/lzma443/C/7zip/Compress/LZMA_Alone/LzmaRam.cpp \
7978 @top_srcdir@/lzma443/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.c \
9796 am__objects_1 = aff_db.lo aff_toc.lo afflib.lo afflib_os.lo \
9897 afflib_pages.lo afflib_stream.lo afflib_util.lo crypto.lo \
9998 base64.lo lzma_glue.lo vnode_aff.lo vnode_afd.lo vnode_afm.lo \
100 vnode_ewf.lo vnode_raw.lo vnode_split_raw.lo utils.lo \
101 display.lo
99 vnode_raw.lo vnode_split_raw.lo utils.lo display.lo
102100 am__objects_2 = vnode_qemu.lo libafflib_la-block-bochs.lo \
103101 libafflib_la-block-cloop.lo libafflib_la-block-cow.lo \
104102 libafflib_la-block-dmg.lo libafflib_la-block-parallels.lo \
118116 $(am__objects_4) $(am__objects_5)
119117 libafflib_la_OBJECTS = $(am_libafflib_la_OBJECTS)
120118 @MAYBE_S3_TRUE@am__EXEEXT_1 = s3$(EXEEXT)
121 binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
122 PROGRAMS = $(bin_PROGRAMS)
123119 am_aftest_OBJECTS = aftest.$(OBJEXT)
124120 aftest_OBJECTS = $(am_aftest_OBJECTS)
125121 aftest_DEPENDENCIES = libafflib.la
299295 target_alias = @target_alias@
300296 top_builddir = @top_builddir@
301297 top_srcdir = @top_srcdir@
298 CLEANFILES = aftest
302299 aftest_SOURCES = aftest.cpp
303300 aftest_LDADD = libafflib.la
304301 aftest_LDFLAGS = $(PTHREAD_CFLAGS) -static # easier debugging
310307 vnode_aff.cpp vnode_aff.h \
311308 vnode_afd.cpp vnode_afd.h \
312309 vnode_afm.cpp vnode_afm.h \
313 vnode_ewf.cpp vnode_ewf.h \
314310 vnode_raw.cpp vnode_raw.h \
315311 vnode_split_raw.cpp vnode_split_raw.h \
316312 aftimer.h \
447443 done
448444 libafflib.la: $(libafflib_la_OBJECTS) $(libafflib_la_DEPENDENCIES)
449445 $(CXXLINK) -rpath $(libdir) $(libafflib_la_OBJECTS) $(libafflib_la_LIBADD) $(LIBS)
450 install-binPROGRAMS: $(bin_PROGRAMS)
451 @$(NORMAL_INSTALL)
452 test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
453 @list='$(bin_PROGRAMS)'; for p in $$list; do \
454 p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
455 if test -f $$p \
456 || test -f $$p1 \
457 ; then \
458 f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
459 echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
460 $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
461 else :; fi; \
462 done
463
464 uninstall-binPROGRAMS:
465 @$(NORMAL_UNINSTALL)
466 @list='$(bin_PROGRAMS)'; for p in $$list; do \
467 f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
468 echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
469 rm -f "$(DESTDIR)$(bindir)/$$f"; \
470 done
471
472 clean-binPROGRAMS:
473 @list='$(bin_PROGRAMS)'; for p in $$list; do \
474 f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
475 echo " rm -f $$p $$f"; \
476 rm -f $$p $$f ; \
477 done
478446 aftest$(EXEEXT): $(aftest_OBJECTS) $(aftest_DEPENDENCIES)
479447 @rm -f aftest$(EXEEXT)
480448 $(aftest_LINK) $(aftest_OBJECTS) $(aftest_LDADD) $(LIBS)
539507 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vnode_afd.Plo@am__quote@
540508 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vnode_aff.Plo@am__quote@
541509 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vnode_afm.Plo@am__quote@
542 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vnode_ewf.Plo@am__quote@
543510 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vnode_qemu.Plo@am__quote@
544511 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vnode_raw.Plo@am__quote@
545512 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vnode_s3.Plo@am__quote@
974941 check-am: all-am
975942 $(MAKE) $(AM_MAKEFLAGS) check-TESTS
976943 check: check-am
977 all-am: Makefile $(LTLIBRARIES) $(PROGRAMS)
978 install-binPROGRAMS: install-libLTLIBRARIES
979
944 all-am: Makefile $(LTLIBRARIES)
980945 installdirs:
981 for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)"; do \
946 for dir in "$(DESTDIR)$(libdir)"; do \
982947 test -z "$$dir" || $(MKDIR_P) "$$dir"; \
983948 done
984949 install: install-am
998963 mostlyclean-generic:
999964
1000965 clean-generic:
966 -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
1001967
1002968 distclean-generic:
1003969 -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
1007973 @echo "it deletes files that may require special tools to rebuild."
1008974 clean: clean-am
1009975
1010 clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
1011 clean-libtool mostlyclean-am
976 clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
977 mostlyclean-am
1012978
1013979 distclean: distclean-am
1014980 -rm -rf ./$(DEPDIR)
1030996
1031997 install-dvi: install-dvi-am
1032998
1033 install-exec-am: install-binPROGRAMS install-libLTLIBRARIES
999 install-exec-am: install-libLTLIBRARIES
10341000 @$(NORMAL_INSTALL)
10351001 $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
10361002
10641030
10651031 ps-am:
10661032
1067 uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES
1033 uninstall-am: uninstall-libLTLIBRARIES
10681034
10691035 .MAKE: install-am install-exec-am install-strip
10701036
10711037 .PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
1072 clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
1073 clean-libtool ctags distclean distclean-compile \
1074 distclean-generic distclean-libtool distclean-tags distdir dvi \
1075 dvi-am html html-am info info-am install install-am \
1076 install-binPROGRAMS install-data install-data-am install-dvi \
1077 install-dvi-am install-exec install-exec-am install-exec-hook \
1078 install-html install-html-am install-info install-info-am \
1079 install-libLTLIBRARIES install-man install-pdf install-pdf-am \
1080 install-ps install-ps-am install-strip installcheck \
1081 installcheck-am installdirs maintainer-clean \
1082 maintainer-clean-generic mostlyclean mostlyclean-compile \
1083 mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
1084 tags uninstall uninstall-am uninstall-binPROGRAMS \
1085 uninstall-libLTLIBRARIES
1038 clean-generic clean-libLTLIBRARIES clean-libtool ctags \
1039 distclean distclean-compile distclean-generic \
1040 distclean-libtool distclean-tags distdir dvi dvi-am html \
1041 html-am info info-am install install-am install-data \
1042 install-data-am install-dvi install-dvi-am install-exec \
1043 install-exec-am install-exec-hook install-html install-html-am \
1044 install-info install-info-am install-libLTLIBRARIES \
1045 install-man install-pdf install-pdf-am install-ps \
1046 install-ps-am install-strip installcheck installcheck-am \
1047 installdirs maintainer-clean maintainer-clean-generic \
1048 mostlyclean mostlyclean-compile mostlyclean-generic \
1049 mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
1050 uninstall-am uninstall-libLTLIBRARIES
10861051
10871052
10881053 install-exec-hook:
8989 while(1){
9090 char segname[AF_MAX_NAME_LEN];
9191 size_t segname_len=sizeof(segname);
92 off_t pos = ftello(af->aseg);
92 uint64_t pos = ftello(af->aseg);
9393 size_t datalen=0;
9494
9595 int r = af_get_next_seg(af,segname,segname_len,0,0,&datalen);
5151 #include "vnode_afm.h"
5252 #include "vnode_aff.h"
5353 #include "vnode_afd.h"
54 #include "vnode_ewf.h"
5554
5655 #ifdef USE_QEMU
5756 #include "vnode_qemu.h"
7877 &vnode_afd,
7978 &vnode_afm, // must be before aff
8079 &vnode_aff,
81 #ifdef USE_LIBEWF
82 &vnode_ewf, // libewf
83 #endif
8480 #ifdef USE_QEMU
8581 &vnode_vmdk,
8682 &vnode_dmg,
354350 }
355351
356352 /* Set up the encryption if requested and if this support metadata */
357 if(AF_SEALING_VNODE(af)){
353 if(AF_SEALING_VNODE(af) && ((flags & AF_NO_CRYPTO)==0)){
358354 bool can_decrypt = false;
359355 if(af->password){
360356 struct af_vnode_info vni;
555551 errno = EINVAL;
556552 return -1; // this is bad
557553 }
558 int ret = ((int64_t)af->pos >= vni.imagesize);
554 int ret = (int64_t)af->pos >= (int64_t)vni.imagesize;
559555 AF_UNLOCK(af);
560556 return ret;
561557 }
676672 }
677673
678674
679
680 /*TK: Here for locking */
681675
682676 /* Decrypt data and perform unblocking if necessary.
683677 * This could eliminate a memory copy by doing the decryption for everything
44 * afflib.h:
55 *
66 * This file describes the public AFFLIB interface.
7 * The interface to reading AFF files, Raw files, and EnCase file (if libewf is compiled in).
7 * The interface to reading AFF files and Raw files.
88 */
99
1010 /* Figure out what kind of OS we are running on */
1111
1212 /* These are both needed; no need to bother with affconfig.h #defines */
1313 #include <stdio.h>
14 #ifdef HAVE_STDINT_H
15 #include <stdint.h>
16 #endif
1417 #include <sys/types.h>
1518
1619 #ifdef HAVE_SYS_CDEFS_H
3235
3336 /** WIN32 is defined by the NMAKE makefile for Visual C++ under Windows and by mingw **/
3437 #ifdef WIN32
38 #include <basetsd.h>
3539 #include <io.h> // gets isatty
3640 typedef unsigned int uint;
3741 typedef unsigned int u_int;
6367 #define PRIu64 "I64u"
6468 #endif
6569
66 //int64 ftello(FILE *stream); /* Functions that Microsoft forgot */
67 //int fseeko(FILE *stream,int64 offset,int whence);
70
71 #if defined(__MINGW_H)
6872 #define ftello ftello64
6973 #define fseeko fseeko64
70 #endif
74 #else
75 #define ftello _ftelli64 /* replaces ftello64 in VC2008 */
76 #define fseeko _fseeki64
77 #endif
78
79 #endif
7180 /** END OF WIN32 DEFINES **/
7281
7382
8998 };
9099
91100 struct af_vnode_info {
92 int64_t imagesize; // size of this image
101 uint64_t imagesize; // size of this image
93102 int pagesize; // what is the natural page size?
94103 u_int supports_compression:1; // supports writing compressed segments
95104 u_int has_pages:1; // does system support page segments?
174183 #define AF_OPEN_PRIMITIVE (1<<31) // only open primtive, not compound files
175184 #define AF_BADBLOCK_FILL (1<<30) // fill unallocated (sparse) with BADBLOCK flag
176185 #define AF_HALF_OPEN (1<<29) // return af before calling af->v->open;
186 #define AF_NO_CRYPTO (1<<28) // disable encryption layer
177187
178188 /* navigating within the data segments as if they were a single file */
179 ssize_t af_read(AFFILE *af,unsigned char *buf,ssize_t count);
189 #ifdef _WIN32
190 SSIZE_T af_read(AFFILE *af,unsigned char *buf,SSIZE_T count);
191 #else
192 ssize_t af_read(AFFILE *af,unsigned char *buf,ssize_t count);
193 #endif
180194 uint64_t af_seek(AFFILE *af,int64_t pos,int whence); // returns new position
181195 uint64_t af_tell(AFFILE *af);
182 int af_eof(AFFILE *af); // is the virtual file at the end?
196 int af_eof(AFFILE *af); // is the virtual file at the end?
183197
184198 /* Additional routines for writing */
185199 void af_set_callback(AFFILE *af, void (*cb)(struct affcallback_info *acbi));
114114 #endif
115115
116116 #ifdef WIN32
117 #if !defined(__MINGW_H)
117118 #pragma warning(disable: 4996) /* Don't warn on Windows about using POSIX open() instead of _open() */
119 #endif
118120 #include <malloc.h>
119121 #include <windows.h>
120122 #include <winsock.h> // htonl()
318320 struct aff_pagebuf *pbcache; // array of pagebufs
319321 int num_pbufs; // number of pagebufs; default is 1
320322 int afftime; // for updating last
321 int64_t cur_page; // used by vnode_raw and vnode_ewf to fake pages
322 // must be able to go negative
323 int64_t cur_page; // used by vnode_raw to fake pages must be able to go negative.
323324
324325 int debug; // for debugging, of course
325326 unsigned int badflag_set:1; // is badflag set?
515516 #define AF_IDENTIFY_EVD 4 // file is a .E01 file when there are more files following
516517 #define AF_IDENTIFY_SPLIT_RAW 5 // file is a split raw file
517518 #define AF_IDENTIFY_AFM 6 // file is raw file with metadata
518 #define AF_IDENTIFY_EWF 7 // libewf
519 #define AF_IDENTIFY_EWF 7 // libewf; deprecated
519520 #define AF_IDENTIFY_S3 8 // is an s3:/// file
520521 #define AF_IDENTIFY_VMDK 9 // QEMU support for VMDK format
521522 #define AF_IDENTIFY_DMG 10 // QEMU support for Apple DMG format
593594 * Note: pagename to string translation happens inside afflib.cpp, not inside
594595 * the vnode driver.
595596 */
597 #define af_page_size(af) (af_get_pagesize(af)) /* backwards compatability */
596598 void af_read_sizes(AFFILE *af); // sets up values if we can get them.
597599 int af_set_pagesize(AFFILE *af,u_long pagesize); // sets the pagesize; fails with -1 if imagesize >=0
598600 int af_set_sectorsize(AFFILE *AF,int sectorsize); // fails with -1 if imagesize>=0
599601 int af_get_sectorsize(AFFILE *AF); // returns sector size
600602 int af_has_pages(AFFILE *af); // does the underlying system support pages?
601 int af_page_size(AFFILE *af); // returns page size, or -1
603 int af_get_pagesize(AFFILE *af); // returns page size, or -1
602604 int af_get_page_raw(AFFILE *af,int64_t pagenum,unsigned long *arg,u_char *data,size_t *bytes);
603605 int af_get_page(AFFILE *af,int64_t pagenum,u_char *data,size_t *bytes);
604606 #define AF_SIGFLAG_NOSIG 0x0001 // do not write signatures with af_update_segf()
3131 *** Extra code for Windows...
3232 ****************************************************************/
3333
34 /* No longer needed with VC2008 */
35 #if 0
3436 #if defined(WIN32) and !defined(__MINGW_H)
3537 #pragma warning(disable: 4996)
3638 int64 ftello(FILE *stream)
5961 }
6062 return fsetpos(stream,&offset);
6163 }
64 #endif
6265 #endif
6366
6467
33
44 #ifdef __cplusplus
55 #ifndef WIN32
6 #ifndef __STDC_FORMAT_MACROS
7 #define __STDC_FORMAT_MACROS
8 #endif
69 #include <inttypes.h>
710 #include <sys/time.h>
811 #endif
1313 #include <signal.h>
1414 #include <assert.h>
1515 #include <sys/types.h>
16 #ifdef HAVE_STDINT_H
1617 #include <stdint.h>
18 #endif
1719
1820 #ifndef MIN
1921 #define MIN(x,y) ((x)<(y)?(x):(y))
203203 static int afd_identify_file(const char *filename,int exists)
204204 {
205205 if(filename==0 || strlen(filename)==0) return 0; // zero-length filenames aren't welcome
206 if(strncmp(filename,"file://",7)==0){
207 /* Move file pointer past file:// then find a '/' and take the next character */
208 filename += 7;
209 while(*filename && *filename!='/'){
210 filename++;
211 }
212 /* At this point if *filename==0 then we never found the end of the URL.
213 * return 0, since it's not an AFF file.
214 */
215 if(*filename==0) return 0;
216
217 /* So *filename must == '/' */
218 assert(*filename == '/');
219 filename++;
220 }
206221 if(exists && access(filename,R_OK)!=0) return 0; // needs to exist and it doesn't
207222
208223 /* If it ends with a '/', remove it */
268283
269284 int new_file = access(fname,F_OK)!=0; // Is this a new file?
270285
271 AFFILE *af2 = af_open(fname,af->openflags,af->openmode);
286 AFFILE *af2 = af_open(fname,af->openflags|AF_NO_CRYPTO,af->openmode);
272287 if(af2==0){
273288 (*af->error_reporter)("open(%s,%d,%d) failed: %s\n",
274289 fname,af->openflags,af->openmode,strerror(errno));
287302 af_update_seg(af,AF_AFF_FILE_TYPE,0,(const u_char *)"AFD",3);
288303
289304 /* If this is the second file, copy over additional metadata from first... */
290 if(ap->num_afs>0){
305 if(ap->num_afs>1){
291306 AFFILE *af0 = ap->afs[0];
292307 memcpy(af2->badflag,af0->badflag,af->image_sectorsize);
293308 af2->bytes_memcpy += af->image_sectorsize;
517532
518533 struct af_vnode vnode_afd = {
519534 AF_IDENTIFY_AFD, //
520 AF_VNODE_TYPE_COMPOUND|AF_VNODE_TYPE_RELIABLE|AF_VNODE_NO_SEALING, //
535 AF_VNODE_TYPE_COMPOUND|AF_VNODE_TYPE_RELIABLE, //
521536 "AFF Directory",
522537 afd_identify_file,
523538 afd_open, // open
167167
168168 fseeko(af->aseg,adm->offset,SEEK_SET);
169169 int ret = aff_get_next_seg(af,next,sizeof(next),arg,data,datalen);
170 assert(strcmp(next,name)==0); // hopefully this is what they asked for
170 assert(ret!=0 || strcmp(next,name)==0); // hopefully this is what they asked for
171171 return ret;
172172 }
173173
197197 return AF_ERROR_INVALID_ARG;
198198 }
199199
200 off_t start = ftello(af->aseg);
200 uint64_t start = ftello(af->aseg);
201201 size_t data_len;
202202
203203 int r = af_probe_next_seg(af,segname,segname_len,arg,&data_len,0,0);
+0
-376
lib/vnode_ewf.cpp less more
0 /**
1 ** AFF/libewf glue
2 **
3 ** (C) 2006 by Simson L. Garfinkel
4 **
5 **
6 **/
7
8
9
10 #include "affconfig.h"
11 #include "afflib.h"
12 #include "afflib_i.h"
13
14 #ifdef USE_LIBEWF
15
16 #include <ctype.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include "vnode_ewf.h"
21
22 #ifdef HAVE_CSTRING
23 #include <cstring>
24 #endif
25
26 /* We're gonna include libewf.h now, which causes problems, because libewf.h currently
27 * includes an autoconf-generated affconfig.h file
28 */
29
30 #undef PACKAGE
31 #undef PACKAGE_BUGREPORT
32 #undef PACKAGE_NAME
33 #undef PACKAGE_STRING
34 #undef PACKAGE_TARNAME
35 #undef PACKAGE_VERSION
36 #undef VERSION
37
38 #ifdef HAVE_LIBEWF_H
39 #include "libewf.h"
40 #else
41 #error EWF support requires libewf, but HAVE_LIBEWF_H is not defined
42 #endif
43
44
45
46 /****************************************************************
47 *** Service routines
48 ****************************************************************/
49
50 #define EWF_HANDLE(af) ((libewf_handle_t *)af->vnodeprivate)
51
52 /****************************************************************
53 *** AFFLIB Glue Follows
54 ****************************************************************/
55
56
57 /* Return 1 if a file is a ewf file... */
58 static int ewf_identify_file(const char *filename,int exists)
59 {
60 return libewf_check_file_signature(filename)==1 ? 1 : 0;
61 }
62
63 static int ewf_open(AFFILE *af)
64 {
65
66 if(strchr(af->fname,'.')==0) return -1; // need a '.' in the filename
67
68 /* Find all of the EWF files to open*/
69 char **files = (char **)malloc(sizeof(char *));
70 int nfiles = 1;
71 files[0] = strdup(af->fname);
72
73 char fname[MAXPATHLEN+1];
74 strlcpy(fname,af->fname,sizeof(fname));
75 char *ext = strrchr(fname,'.')+1;
76 if(ext-fname > MAXPATHLEN-4){
77 warn("ewf_open: %s: filename too long",af->fname);
78 return -1;
79 }
80
81 /* Now open .E02 through .E99 and then .AAA through .ZZZ if they exist... */
82 for(int i=2;i<=99;i++){
83 sprintf(ext+1,"%02d",i);
84 if(access(fname,R_OK)!=0) break;
85 files = (char **)realloc(files,(nfiles+1) * sizeof(char *));
86 files[nfiles] = strdup(fname);
87 nfiles++;
88 }
89 for(int i=4*26*26;i<=26*26*26;i++){
90 sprintf(ext, "%c%c%c", i/26/26%26+'A', i/26%26+'A', i%26+'A');
91 if(access(fname,R_OK)!=0) break; // file can't be read
92 files = (char **)realloc(files,(nfiles+1) * sizeof(char *));
93 files[nfiles] = strdup(fname);
94 nfiles++;
95 }
96
97
98 LIBEWF_HANDLE *handle = libewf_open( files, nfiles, LIBEWF_OPEN_READ );
99
100 if(!handle){
101 warn("Unable to open EWF image file");
102 for(int i=0;i<nfiles;i++) free(files[i]);
103 free(files);
104 return -1;
105 }
106 #if defined( HAVE_LIBEWF_GET_MEDIA_SIZE_ARGUMENT_VALUE ) || (LIBEWF_VERSION>=20080501)
107 int r = libewf_get_media_size(handle,&af->image_size);
108 if(r < 0){
109 warn("EFW error: image size==0?");
110 for(int i=0;i<nfiles;i++) free(files[i]);
111 free(files);
112 return -1;
113 }
114 #else
115 af->image_size = libewf_get_media_size(handle);
116
117 if( af->image_size == 0 ){
118 warn("EFW error: image size==0?");
119 for(int i=0;i<nfiles;i++) free(files[i]);
120 free(files);
121 return -1;
122 }
123 #endif
124
125 af->vnodeprivate = (void *)handle;
126 #if defined( HAVE_LIBEWF_GET_CHUNK_SIZE_ARGUMENT_VALUE ) || LIBEWF_VERSION>=20080501
127 libewf_get_chunk_size(handle,(size32_t *)&af->image_pagesize);
128 #else
129 af->image_pagesize = libewf_get_chunk_size(handle);
130 #endif
131 for(int i=0;i<nfiles;i++) free(files[i]);
132 free(files);
133 return 0;
134 }
135
136
137 static int ewf_vstat(AFFILE *af,struct af_vnode_info *vni)
138 {
139 LIBEWF_HANDLE *handle = EWF_HANDLE(af);
140 #if defined( HAVE_LIBEWF_GET_MEDIA_SIZE_ARGUMENT_VALUE ) || LIBEWF_VERSION>=20080501
141 libewf_get_media_size(handle,(size64_t *)&vni->imagesize);
142 #else
143 vni->imagesize = (int64_t) libewf_get_media_size(handle);
144 #endif
145
146 vni->pagesize = 0;
147 #if defined( HAVE_LIBEWF_GET_CHUNK_SIZE_ARGUMENT_VALUE ) || LIBEWF_VERSION>=20080501
148 libewf_get_chunk_size(handle,(size32_t *)&vni->pagesize);
149 #else
150 vni->pagesize = libewf_get_chunk_size(handle);
151 #endif
152 vni->supports_metadata = 1;
153 vni->changable_pagesize = 0;
154 vni->changable_sectorsize = 0;
155 vni->supports_compression = 1;
156 vni->has_pages = 1; // debatable
157 return 0;
158 }
159
160 static int ewf_read(AFFILE *af, unsigned char *buf, uint64_t pos,size_t count)
161 {
162 LIBEWF_HANDLE *handle = EWF_HANDLE(af);
163 return libewf_read_random(handle,buf,(uint64_t)count,pos);
164 }
165
166 static int ewf_write(AFFILE *af, unsigned char *buf, uint64_t pos,size_t count)
167 {
168 LIBEWF_HANDLE *handle = EWF_HANDLE(af);
169 return libewf_write_random(handle,buf,(uint64_t)count,pos);
170 }
171
172 static int ewf_close(AFFILE *af)
173 {
174 LIBEWF_HANDLE *handle = EWF_HANDLE(af);
175 if(libewf_close(handle)<0) return -1;
176 return 0;
177 }
178
179
180 static int ewf_rewind_seg(AFFILE *af)
181 {
182 af->cur_page = -1; // starts at the metadata
183 return 0;
184 }
185
186
187 /* return the length of a string up to a max */
188 static int strlenp(const unsigned char *data,int max)
189 {
190 for(int i=0;i<max;i++){
191 if(data[i]==0) return i;
192 }
193 return max;
194 }
195
196 static uint32_t ewf_bytes_per_sector(LIBEWF_HANDLE *handle)
197 {
198 uint32_t bps = 0;
199 #if defined( HAVE_LIBEWF_GET_BYTES_PER_SECTOR_ARGUMENT_VALUE ) || LIBEWF_VERSION>=20080501
200 libewf_get_bytes_per_sector(handle,&bps);
201 #else
202 bps=libewf_get_bytes_per_sector(handle);
203 #endif
204 return bps;
205 }
206
207 static int ewf_get_seg(AFFILE *af,const char *name, unsigned long *arg,
208 unsigned char *data,size_t *datalen)
209 {
210 LIBEWF_HANDLE *handle = EWF_HANDLE(af);
211
212 /* Is the user asking for a page? */
213 int64_t segnum = af_segname_page_number(name);
214 if(segnum>=0){
215 /* Get the segment number */
216 if(data==0){
217 /* Need to make sure that the segment exists */
218 if(segnum*af->image_pagesize+af->image_pagesize > af->image_size ) return -1; // this segment does not exist
219 if(datalen) *datalen = af->image_pagesize; // just return the chunk size
220 return 0;
221 }
222 size_t r = libewf_read_random(handle,data,*datalen,segnum * af->image_pagesize);
223 return r>0 ? 0 : -1; // should probably put in some error checking
224 }
225
226 /* See if it is a page name we understand */
227 if(strcmp(name,AF_PAGESIZE)==0){
228 if(arg) *arg = af->image_pagesize;
229 return 0;
230 }
231 if(strcmp(name,AF_IMAGESIZE)==0){
232 if(arg) *arg = 0;
233 if(datalen==0) return 0;
234 if(*datalen==0){
235 *datalen = 8; // the structure is 8 bytes long
236 return 0;
237 }
238 if(*datalen<8) return -2;
239
240 struct aff_quad q;
241 q.low = htonl((unsigned long)(af->image_size & 0xffffffff));
242 q.high = htonl((unsigned long)(af->image_size >> 32));
243 memcpy(data,&q,8);
244 return 0;
245 }
246 if(strcmp(name,AF_SECTORSIZE)==0){
247 if(arg) *arg=(unsigned long)ewf_bytes_per_sector(handle);
248 if(datalen) *datalen = 0;
249 return 0;
250 }
251 if(strcmp(name,AF_DEVICE_SECTORS)==0){
252 /* Is this in flag or a quad word? */
253 uint32_t bps = ewf_bytes_per_sector(handle);
254 if(arg && bps>0) *arg = af->image_size / bps;
255 if(datalen) *datalen = 0;
256 return 0;
257 }
258
259
260 /* They are asking for a metdata segment. If we have wide character type
261 * compiled in for libewf, just ignore it, because afflib doesn't do wide characters
262 * at the moment...
263 */
264
265 #if !defined(LIBEWF_WIDE_CHARACTER_TYPE) && defined(LIBEWF_VERSION) && (LIBEWF_VERSION >= 20080322)
266 /* Can't guarentee character type in older versions of libewf */
267 if(strcmp(name,AF_CASE_NUM)==0){
268 if(data && datalen){
269 libewf_get_header_value_case_number(handle,(char *)data,*datalen);
270 *datalen = strlenp(data,*datalen);
271 if(arg) *arg = 0;
272 }
273 return 0;
274 }
275 if(strcmp(name,AF_IMAGE_GID)==0){
276 if(data && datalen){
277 libewf_get_guid(handle,data,*datalen);
278 if(arg) *arg = 0;
279 }
280 return 0;
281 }
282 if(strcmp(name,AF_ACQUISITION_NOTES)==0){
283 if(data && datalen){
284 libewf_get_header_value_notes(handle,(char *)data,*datalen);
285 *datalen = strlenp(data,*datalen);
286 }
287 if(data==0 && datalen){
288 /* Caller wants to learn size of the notes */
289 unsigned char tmp[128];
290 memset(tmp,0,sizeof(tmp));
291 *datalen = sizeof(tmp);
292 libewf_get_header_value_notes(handle,(char *)tmp,*datalen);
293 *datalen = strlenp(tmp,*datalen);
294 }
295 if(arg) *arg = 0;
296 return 0;
297 }
298 #endif
299 return -1; // don't know this header
300 }
301
302 static const char *emap[] = {
303 AF_PAGESIZE,
304 AF_IMAGESIZE,
305 AF_SECTORSIZE,
306 AF_DEVICE_SECTORS,
307 AF_CASE_NUM,
308 AF_IMAGE_GID,
309 AF_ACQUISITION_NOTES,
310 0
311 };
312
313
314 static int ewf_get_next_seg(AFFILE *af,char *segname,size_t segname_len,unsigned long *arg,
315 unsigned char *data,size_t *datalen)
316 {
317 /* Figure out what the next segment would be, then get it */
318 /* Metadata first */
319 if(af->cur_page<0){
320 /* Find out how many mapped segments there are */
321 int mapped=0;
322 for(mapped=0;emap[mapped];mapped++){
323 }
324 if(-af->cur_page >= mapped ){
325 af->cur_page = 0;
326 goto get_next_data_seg;
327 }
328 int which = 0 - af->cur_page; // which one to get
329 af->cur_page--; // go to the next one
330 if(segname_len < strlen(emap[which])) return -2; // not enough room for segname
331 strlcpy(segname,emap[which],segname_len); // give caller the name of the mapped segment.
332 return ewf_get_seg(af,segname,arg,data,datalen);
333 }
334
335 get_next_data_seg:
336 if(af->cur_page * af->image_pagesize >= af->image_size) return -1; // end of list
337 /* Make the segment name */
338 char pagename[AF_MAX_NAME_LEN]; //
339 memset(pagename,0,sizeof(pagename));
340 snprintf(pagename,sizeof(pagename),AF_PAGE,af->cur_page++);
341
342 int r = 0;
343 /* Get the segment, if it is wanted */
344 if(data) r = ewf_get_seg(af,pagename,arg,data,datalen);
345
346 /* If r==0 and there is room for copying in the segment name, return it */
347 if(r==0){
348 if(strlen(pagename)+1 < segname_len){
349 strlcpy(segname,pagename,segname_len);
350 return 0;
351 }
352 /* segname wasn't big enough */
353 return -2;
354 }
355 return r; // some other error
356 }
357
358 struct af_vnode vnode_ewf = {
359 AF_IDENTIFY_EWF,
360 AF_VNODE_TYPE_PRIMITIVE|AF_VNODE_NO_SIGNING|AF_VNODE_NO_SEALING,
361 "LIBEWF",
362 ewf_identify_file,
363 ewf_open,
364 ewf_close,
365 ewf_vstat,
366 ewf_get_seg, // get seg
367 ewf_get_next_seg, // get_next_seg
368 ewf_rewind_seg, // rewind_seg
369 0, // update_seg
370 0, // del_seg
371 ewf_read, // read
372 ewf_write // write
373 };
374
375 #endif
+0
-1
lib/vnode_ewf.h less more
0 extern struct af_vnode vnode_ewf; /* vnode_ewf.cpp */
182182 int fd;
183183 struct stat sb;
184184
185 fd = open(srp->first_raw_fname, af->openflags|O_BINARY, 0666);
185 fd = open(srp->first_raw_fname, af->openflags|O_BINARY, af->openmode);
186186 if (fd < 0) {
187187 (*af->error_reporter)("split_raw_open_internal: open(%s): ",af->fname);
188188 return -1;
374374 if (af->maxsize) { // do we need to possibly split into multiple file writes?
375375 /* Figure out which file number we will need to write to... */
376376 if (pos >= (af->maxsize * srp->num_raw_files)) {
377 int fd = open(srp->next_raw_fname, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0666);
377 int fd = open(srp->next_raw_fname, O_RDWR | O_CREAT | O_EXCL | O_BINARY, af->openmode);
378378 if (fd < 0) {
379379 (*af->error_reporter)("split_raw_write: open(%s): ",af->fname);
380380 if (ret) return ret;
0 dist_man_MANS = afcat.1
0 dist_man_MANS = affcat.1
187187 target_alias = @target_alias@
188188 top_builddir = @top_builddir@
189189 top_srcdir = @top_srcdir@
190 dist_man_MANS = afcat.1
190 dist_man_MANS = affcat.1
191191 all: all-am
192192
193193 .SUFFIXES:
+0
-46
man/afcat.1 less more
0 .\" Process this file with
1 .\" groff -man -Tascii foo.1
2 .\"
3 .TH AFCAT 1 "OCT 2008" "User Manuals"
4 .SH NAME
5 afcat \- Output contents of an image file to stdout.
6 .SH SYNOPSIS
7 .B afcat [options]
8 .I image [images]
9 .SH DESCRIPTION
10 .B affcat
11 outputs the contents of an image file to stdout. Image files that are not raw but are recognized
12 by AFF will be output in raw format. Missing pages will not be padded, but the fact that they are missing
13 will be noted on STDERR.
14
15 The options are as follows:
16 .IP "-s name"
17 Output the named segment, instead of the image data. This is a way to output metadata.
18 .IP "-p nnn"
19 Just output page number
20 .B nnn
21 .IP "-S nnn"
22 Just output data sector number
23 .B nnn.
24 Sector #0 is the first sector.
25 .IP "-q"
26 Quiet mode. Don't print to STDERR if a page is skipped because it is not present.
27 .IP "-n"
28 Noisy mode. Tell when pages are skipped.
29 .IP "-l"
30 List all the segment names, rather than outputing data.
31 .IP "-L"
32 List Long. Prints segment names, lengths, and args.
33 .IP "-d"
34 Debug mode. Print the page numbers to stderr as data goes to stdout.
35 .IP "-b"
36 Output BADFALG for bad blocks (default is to output NULLs).
37 .IP "-v"
38 Just print the version number and exit.
39 .IP "-r offset:count"
40 Seek to the given byte offset and output count characters in each file; may be repeated.
41 .SH HISTORY
42 .BR "afcat" " first appeared in " "AFFLIB" " v1.00."
43 .SH AUTHOR
44 Simson Garfinkel <simsong@acm.org>
45
0 .\" Process this file with
1 .\" groff -man -Tascii foo.1
2 .\"
3 .TH AFCAT 1 "OCT 2008" "User Manuals"
4 .SH NAME
5 afcat \- Output contents of an image file to stdout.
6 .SH SYNOPSIS
7 .B afcat [options]
8 .I image [images]
9 .SH DESCRIPTION
10 .B affcat
11 outputs the contents of an image file to stdout. Image files that are not raw but are recognized
12 by AFF will be output in raw format. Missing pages will not be padded, but the fact that they are missing
13 will be noted on STDERR.
14
15 The options are as follows:
16 .IP "-s name"
17 Output the named segment, instead of the image data. This is a way to output metadata.
18 .IP "-p nnn"
19 Just output page number
20 .B nnn
21 .IP "-S nnn"
22 Just output data sector number
23 .B nnn.
24 Sector #0 is the first sector.
25 .IP "-q"
26 Quiet mode. Don't print to STDERR if a page is skipped because it is not present.
27 .IP "-n"
28 Noisy mode. Tell when pages are skipped.
29 .IP "-l"
30 List all the segment names, rather than outputing data.
31 .IP "-L"
32 List Long. Prints segment names, lengths, and args.
33 .IP "-d"
34 Debug mode. Print the page numbers to stderr as data goes to stdout.
35 .IP "-b"
36 Output BADFALG for bad blocks (default is to output NULLs).
37 .IP "-v"
38 Just print the version number and exit.
39 .IP "-r offset:count"
40 Seek to the given byte offset and output count characters in each file; may be repeated.
41 .SH HISTORY
42 .BR "afcat" " first appeared in " "AFFLIB" " v1.00."
43 .SH AUTHOR
44 Simson Garfinkel <simsong@acm.org>
45
55 srcdir=.
66 fi
77
8 if ( ../tools/afcompare file://:password@/$srcdir/encrypted.aff $srcdir/encrypted.iso ) ; then
8 if ( ../tools/affcompare file://:password@/$srcdir/encrypted.aff $srcdir/encrypted.iso ) ; then
99 echo Verifies with correct decryption passphrase.
1010 else
1111 echo Does not verify with correct decryption passphrase.
1313 fi
1414
1515
16 echo This next afcompare should generate an error:
17 if ( ../tools/afcompare file://:wrongphrase@/$srcdir/encrypted.aff $srcdir/encrypted.iso ) ; then
16 echo This next affcompare should generate an error:
17 if ( ../tools/affcompare file://:wrongphrase@/$srcdir/encrypted.aff $srcdir/encrypted.iso ) ; then
1818 echo Does not verify with correct decryption passphrase.
1919 exit 1
2020 else
1616 cmd("rm -rf %s %s %s %s" % (iso,iso2,i1,i2))
1717 cmd("./makeimage %s 100000",(iso))
1818 cmd("../aimage/aimage %s -q -E %s %s" % (maxsize,iso,i1))
19 cmd("../tools/afconvert %s -o %s %s" % (maxsize,i2,iso))
20 cmd("../tools/afinfo -mS %s" % (i1))
21 cmd("../tools/afinfo -mS %s" % (i2))
22 cmd("../tools/afcompare %s %s" % (iso,i1))
23 cmd("../tools/afcompare %s %s" % (iso,i2))
24 cmd("../tools/afconvert -r -o %s %s" % (iso,i1))
25 cmd("../tools/afcat %s > %s" % (i2,iso2))
19 cmd("../tools/affconvert %s -o %s %s" % (maxsize,i2,iso))
20 cmd("../tools/affinfo -mS %s" % (i1))
21 cmd("../tools/affinfo -mS %s" % (i2))
22 cmd("../tools/affcompare %s %s" % (iso,i1))
23 cmd("../tools/affcompare %s %s" % (iso,i2))
24 cmd("../tools/affconvert -r -o %s %s" % (iso,i1))
25 cmd("../tools/affcat %s > %s" % (i2,iso2))
2626 cmd("cmp %s %s" % (iso,iso2))
2727 cmd("rm -rf %s %s %s %s" % (iso,iso2,i1,i2))
2828
0 bin_PROGRAMS = afcat afcompare afconvert afcopy afcrypto affix afinfo afsegment \
1 afstats afverify afxml affuse afrecover afsign afdiskprint
0 bin_PROGRAMS = affcat affcompare affconvert affcopy affcrypto affix affinfo affsegment \
1 affstats affverify affxml affuse affrecover affsign affdiskprint
22
33 EXTRA_DIST = test_make_random_iso.sh test_crypto.sh test_signing.sh test_recovery.sh \
44 test_passphrase.sh test_afsegment.sh
99
1010 AM_LDFLAGS = -static # staticly link our tools (easier debugging)
1111
12 afcat_SOURCES = afcat.cpp
12 affcat_SOURCES = affcat.cpp
1313
14 afcrypto_SOURCES = afcrypto.cpp
15 afcompare_SOURCES = afcompare.cpp unix4win32.h
16 afconvert_SOURCES = afconvert.cpp unix4win32.h
17 afcopy_SOURCES = afcopy.cpp unix4win32.h aff_bom.h aff_bom.cpp
18 afdiskprint_SOURCES = afdiskprint.cpp unix4win32.h hashextent.h
14 affcrypto_SOURCES = affcrypto.cpp
15 affcompare_SOURCES = affcompare.cpp unix4win32.h
16 affconvert_SOURCES = affconvert.cpp unix4win32.h
17 affcopy_SOURCES = affcopy.cpp unix4win32.h aff_bom.h aff_bom.cpp
18 affdiskprint_SOURCES = affdiskprint.cpp unix4win32.h hashextent.h
1919 affix_SOURCES = affix.cpp unix4win32.h
2020 affuse_SOURCES = affuse.c
21 afinfo_SOURCES = afinfo.cpp unix4win32.h
22 afrecover_SOURCES = afrecover.cpp unix4win32.h
23 afsegment_SOURCES = afsegment.cpp
24 afsign_SOURCES = afsign.cpp aff_bom.h aff_bom.cpp
25 afstats_SOURCES = afstats.cpp
26 afverify_SOURCES = afverify.cpp aff_bom.h aff_bom.cpp
27 afxml_SOURCES = afxml.cpp unix4win32.h
21 affinfo_SOURCES = affinfo.cpp unix4win32.h
22 affrecover_SOURCES = affrecover.cpp unix4win32.h
23 affsegment_SOURCES = affsegment.cpp
24 affsign_SOURCES = affsign.cpp aff_bom.h aff_bom.cpp
25 affstats_SOURCES = affstats.cpp
26 affverify_SOURCES = affverify.cpp aff_bom.h aff_bom.cpp
27 affxml_SOURCES = affxml.cpp unix4win32.h
2828
2929 INCLUDES = -I@top_srcdir@/lib/
3030 LDADD = @top_builddir@/lib/libafflib.la
3131 POST_UNINSTALL = :
3232 build_triplet = @build@
3333 host_triplet = @host@
34 bin_PROGRAMS = afcat$(EXEEXT) afcompare$(EXEEXT) afconvert$(EXEEXT) \
35 afcopy$(EXEEXT) afcrypto$(EXEEXT) affix$(EXEEXT) \
36 afinfo$(EXEEXT) afsegment$(EXEEXT) afstats$(EXEEXT) \
37 afverify$(EXEEXT) afxml$(EXEEXT) affuse$(EXEEXT) \
38 afrecover$(EXEEXT) afsign$(EXEEXT) afdiskprint$(EXEEXT)
34 bin_PROGRAMS = affcat$(EXEEXT) affcompare$(EXEEXT) affconvert$(EXEEXT) \
35 affcopy$(EXEEXT) affcrypto$(EXEEXT) affix$(EXEEXT) \
36 affinfo$(EXEEXT) affsegment$(EXEEXT) affstats$(EXEEXT) \
37 affverify$(EXEEXT) affxml$(EXEEXT) affuse$(EXEEXT) \
38 affrecover$(EXEEXT) affsign$(EXEEXT) affdiskprint$(EXEEXT)
3939 subdir = tools
4040 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
4141 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
4949 am__installdirs = "$(DESTDIR)$(bindir)"
5050 binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
5151 PROGRAMS = $(bin_PROGRAMS)
52 am_afcat_OBJECTS = afcat.$(OBJEXT)
53 afcat_OBJECTS = $(am_afcat_OBJECTS)
54 afcat_LDADD = $(LDADD)
55 afcat_DEPENDENCIES = @top_builddir@/lib/libafflib.la
56 am_afcompare_OBJECTS = afcompare.$(OBJEXT)
57 afcompare_OBJECTS = $(am_afcompare_OBJECTS)
58 afcompare_LDADD = $(LDADD)
59 afcompare_DEPENDENCIES = @top_builddir@/lib/libafflib.la
60 am_afconvert_OBJECTS = afconvert.$(OBJEXT)
61 afconvert_OBJECTS = $(am_afconvert_OBJECTS)
62 afconvert_LDADD = $(LDADD)
63 afconvert_DEPENDENCIES = @top_builddir@/lib/libafflib.la
64 am_afcopy_OBJECTS = afcopy.$(OBJEXT) aff_bom.$(OBJEXT)
65 afcopy_OBJECTS = $(am_afcopy_OBJECTS)
66 afcopy_LDADD = $(LDADD)
67 afcopy_DEPENDENCIES = @top_builddir@/lib/libafflib.la
68 am_afcrypto_OBJECTS = afcrypto.$(OBJEXT)
69 afcrypto_OBJECTS = $(am_afcrypto_OBJECTS)
70 afcrypto_LDADD = $(LDADD)
71 afcrypto_DEPENDENCIES = @top_builddir@/lib/libafflib.la
72 am_afdiskprint_OBJECTS = afdiskprint.$(OBJEXT)
73 afdiskprint_OBJECTS = $(am_afdiskprint_OBJECTS)
74 afdiskprint_LDADD = $(LDADD)
75 afdiskprint_DEPENDENCIES = @top_builddir@/lib/libafflib.la
52 am_affcat_OBJECTS = affcat.$(OBJEXT)
53 affcat_OBJECTS = $(am_affcat_OBJECTS)
54 affcat_LDADD = $(LDADD)
55 affcat_DEPENDENCIES = @top_builddir@/lib/libafflib.la
56 am_affcompare_OBJECTS = affcompare.$(OBJEXT)
57 affcompare_OBJECTS = $(am_affcompare_OBJECTS)
58 affcompare_LDADD = $(LDADD)
59 affcompare_DEPENDENCIES = @top_builddir@/lib/libafflib.la
60 am_affconvert_OBJECTS = affconvert.$(OBJEXT)
61 affconvert_OBJECTS = $(am_affconvert_OBJECTS)
62 affconvert_LDADD = $(LDADD)
63 affconvert_DEPENDENCIES = @top_builddir@/lib/libafflib.la
64 am_affcopy_OBJECTS = affcopy.$(OBJEXT) aff_bom.$(OBJEXT)
65 affcopy_OBJECTS = $(am_affcopy_OBJECTS)
66 affcopy_LDADD = $(LDADD)
67 affcopy_DEPENDENCIES = @top_builddir@/lib/libafflib.la
68 am_affcrypto_OBJECTS = affcrypto.$(OBJEXT)
69 affcrypto_OBJECTS = $(am_affcrypto_OBJECTS)
70 affcrypto_LDADD = $(LDADD)
71 affcrypto_DEPENDENCIES = @top_builddir@/lib/libafflib.la
72 am_affdiskprint_OBJECTS = affdiskprint.$(OBJEXT)
73 affdiskprint_OBJECTS = $(am_affdiskprint_OBJECTS)
74 affdiskprint_LDADD = $(LDADD)
75 affdiskprint_DEPENDENCIES = @top_builddir@/lib/libafflib.la
76 am_affinfo_OBJECTS = affinfo.$(OBJEXT)
77 affinfo_OBJECTS = $(am_affinfo_OBJECTS)
78 affinfo_LDADD = $(LDADD)
79 affinfo_DEPENDENCIES = @top_builddir@/lib/libafflib.la
7680 am_affix_OBJECTS = affix.$(OBJEXT)
7781 affix_OBJECTS = $(am_affix_OBJECTS)
7882 affix_LDADD = $(LDADD)
7983 affix_DEPENDENCIES = @top_builddir@/lib/libafflib.la
84 am_affrecover_OBJECTS = affrecover.$(OBJEXT)
85 affrecover_OBJECTS = $(am_affrecover_OBJECTS)
86 affrecover_LDADD = $(LDADD)
87 affrecover_DEPENDENCIES = @top_builddir@/lib/libafflib.la
88 am_affsegment_OBJECTS = affsegment.$(OBJEXT)
89 affsegment_OBJECTS = $(am_affsegment_OBJECTS)
90 affsegment_LDADD = $(LDADD)
91 affsegment_DEPENDENCIES = @top_builddir@/lib/libafflib.la
92 am_affsign_OBJECTS = affsign.$(OBJEXT) aff_bom.$(OBJEXT)
93 affsign_OBJECTS = $(am_affsign_OBJECTS)
94 affsign_LDADD = $(LDADD)
95 affsign_DEPENDENCIES = @top_builddir@/lib/libafflib.la
96 am_affstats_OBJECTS = affstats.$(OBJEXT)
97 affstats_OBJECTS = $(am_affstats_OBJECTS)
98 affstats_LDADD = $(LDADD)
99 affstats_DEPENDENCIES = @top_builddir@/lib/libafflib.la
80100 am_affuse_OBJECTS = affuse-affuse.$(OBJEXT)
81101 affuse_OBJECTS = $(am_affuse_OBJECTS)
82102 affuse_DEPENDENCIES = @top_builddir@/lib/libafflib.la
83 am_afinfo_OBJECTS = afinfo.$(OBJEXT)
84 afinfo_OBJECTS = $(am_afinfo_OBJECTS)
85 afinfo_LDADD = $(LDADD)
86 afinfo_DEPENDENCIES = @top_builddir@/lib/libafflib.la
87 am_afrecover_OBJECTS = afrecover.$(OBJEXT)
88 afrecover_OBJECTS = $(am_afrecover_OBJECTS)
89 afrecover_LDADD = $(LDADD)
90 afrecover_DEPENDENCIES = @top_builddir@/lib/libafflib.la
91 am_afsegment_OBJECTS = afsegment.$(OBJEXT)
92 afsegment_OBJECTS = $(am_afsegment_OBJECTS)
93 afsegment_LDADD = $(LDADD)
94 afsegment_DEPENDENCIES = @top_builddir@/lib/libafflib.la
95 am_afsign_OBJECTS = afsign.$(OBJEXT) aff_bom.$(OBJEXT)
96 afsign_OBJECTS = $(am_afsign_OBJECTS)
97 afsign_LDADD = $(LDADD)
98 afsign_DEPENDENCIES = @top_builddir@/lib/libafflib.la
99 am_afstats_OBJECTS = afstats.$(OBJEXT)
100 afstats_OBJECTS = $(am_afstats_OBJECTS)
101 afstats_LDADD = $(LDADD)
102 afstats_DEPENDENCIES = @top_builddir@/lib/libafflib.la
103 am_afverify_OBJECTS = afverify.$(OBJEXT) aff_bom.$(OBJEXT)
104 afverify_OBJECTS = $(am_afverify_OBJECTS)
105 afverify_LDADD = $(LDADD)
106 afverify_DEPENDENCIES = @top_builddir@/lib/libafflib.la
107 am_afxml_OBJECTS = afxml.$(OBJEXT)
108 afxml_OBJECTS = $(am_afxml_OBJECTS)
109 afxml_LDADD = $(LDADD)
110 afxml_DEPENDENCIES = @top_builddir@/lib/libafflib.la
103 am_affverify_OBJECTS = affverify.$(OBJEXT) aff_bom.$(OBJEXT)
104 affverify_OBJECTS = $(am_affverify_OBJECTS)
105 affverify_LDADD = $(LDADD)
106 affverify_DEPENDENCIES = @top_builddir@/lib/libafflib.la
107 am_affxml_OBJECTS = affxml.$(OBJEXT)
108 affxml_OBJECTS = $(am_affxml_OBJECTS)
109 affxml_LDADD = $(LDADD)
110 affxml_DEPENDENCIES = @top_builddir@/lib/libafflib.la
111111 DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
112112 depcomp = $(SHELL) $(top_srcdir)/depcomp
113113 am__depfiles_maybe = depfiles
129129 CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
130130 --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
131131 $(LDFLAGS) -o $@
132 SOURCES = $(afcat_SOURCES) $(afcompare_SOURCES) $(afconvert_SOURCES) \
133 $(afcopy_SOURCES) $(afcrypto_SOURCES) $(afdiskprint_SOURCES) \
134 $(affix_SOURCES) $(affuse_SOURCES) $(afinfo_SOURCES) \
135 $(afrecover_SOURCES) $(afsegment_SOURCES) $(afsign_SOURCES) \
136 $(afstats_SOURCES) $(afverify_SOURCES) $(afxml_SOURCES)
137 DIST_SOURCES = $(afcat_SOURCES) $(afcompare_SOURCES) \
138 $(afconvert_SOURCES) $(afcopy_SOURCES) $(afcrypto_SOURCES) \
139 $(afdiskprint_SOURCES) $(affix_SOURCES) $(affuse_SOURCES) \
140 $(afinfo_SOURCES) $(afrecover_SOURCES) $(afsegment_SOURCES) \
141 $(afsign_SOURCES) $(afstats_SOURCES) $(afverify_SOURCES) \
142 $(afxml_SOURCES)
132 SOURCES = $(affcat_SOURCES) $(affcompare_SOURCES) \
133 $(affconvert_SOURCES) $(affcopy_SOURCES) $(affcrypto_SOURCES) \
134 $(affdiskprint_SOURCES) $(affinfo_SOURCES) $(affix_SOURCES) \
135 $(affrecover_SOURCES) $(affsegment_SOURCES) $(affsign_SOURCES) \
136 $(affstats_SOURCES) $(affuse_SOURCES) $(affverify_SOURCES) \
137 $(affxml_SOURCES)
138 DIST_SOURCES = $(affcat_SOURCES) $(affcompare_SOURCES) \
139 $(affconvert_SOURCES) $(affcopy_SOURCES) $(affcrypto_SOURCES) \
140 $(affdiskprint_SOURCES) $(affinfo_SOURCES) $(affix_SOURCES) \
141 $(affrecover_SOURCES) $(affsegment_SOURCES) $(affsign_SOURCES) \
142 $(affstats_SOURCES) $(affuse_SOURCES) $(affverify_SOURCES) \
143 $(affxml_SOURCES)
143144 ETAGS = etags
144145 CTAGS = ctags
145146 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
289290
290291 # See http://www.gnu.org/software/libtool/manual.html # Using-Automake
291292 AM_LDFLAGS = -static # staticly link our tools (easier debugging)
292 afcat_SOURCES = afcat.cpp
293 afcrypto_SOURCES = afcrypto.cpp
294 afcompare_SOURCES = afcompare.cpp unix4win32.h
295 afconvert_SOURCES = afconvert.cpp unix4win32.h
296 afcopy_SOURCES = afcopy.cpp unix4win32.h aff_bom.h aff_bom.cpp
297 afdiskprint_SOURCES = afdiskprint.cpp unix4win32.h hashextent.h
293 affcat_SOURCES = affcat.cpp
294 affcrypto_SOURCES = affcrypto.cpp
295 affcompare_SOURCES = affcompare.cpp unix4win32.h
296 affconvert_SOURCES = affconvert.cpp unix4win32.h
297 affcopy_SOURCES = affcopy.cpp unix4win32.h aff_bom.h aff_bom.cpp
298 affdiskprint_SOURCES = affdiskprint.cpp unix4win32.h hashextent.h
298299 affix_SOURCES = affix.cpp unix4win32.h
299300 affuse_SOURCES = affuse.c
300 afinfo_SOURCES = afinfo.cpp unix4win32.h
301 afrecover_SOURCES = afrecover.cpp unix4win32.h
302 afsegment_SOURCES = afsegment.cpp
303 afsign_SOURCES = afsign.cpp aff_bom.h aff_bom.cpp
304 afstats_SOURCES = afstats.cpp
305 afverify_SOURCES = afverify.cpp aff_bom.h aff_bom.cpp
306 afxml_SOURCES = afxml.cpp unix4win32.h
301 affinfo_SOURCES = affinfo.cpp unix4win32.h
302 affrecover_SOURCES = affrecover.cpp unix4win32.h
303 affsegment_SOURCES = affsegment.cpp
304 affsign_SOURCES = affsign.cpp aff_bom.h aff_bom.cpp
305 affstats_SOURCES = affstats.cpp
306 affverify_SOURCES = affverify.cpp aff_bom.h aff_bom.cpp
307 affxml_SOURCES = affxml.cpp unix4win32.h
307308 INCLUDES = -I@top_srcdir@/lib/
308309 LDADD = @top_builddir@/lib/libafflib.la
309310 affuse_CFLAGS = @FUSE_CFLAGS@
373374 echo " rm -f $$p $$f"; \
374375 rm -f $$p $$f ; \
375376 done
376 afcat$(EXEEXT): $(afcat_OBJECTS) $(afcat_DEPENDENCIES)
377 @rm -f afcat$(EXEEXT)
378 $(CXXLINK) $(afcat_OBJECTS) $(afcat_LDADD) $(LIBS)
379 afcompare$(EXEEXT): $(afcompare_OBJECTS) $(afcompare_DEPENDENCIES)
380 @rm -f afcompare$(EXEEXT)
381 $(CXXLINK) $(afcompare_OBJECTS) $(afcompare_LDADD) $(LIBS)
382 afconvert$(EXEEXT): $(afconvert_OBJECTS) $(afconvert_DEPENDENCIES)
383 @rm -f afconvert$(EXEEXT)
384 $(CXXLINK) $(afconvert_OBJECTS) $(afconvert_LDADD) $(LIBS)
385 afcopy$(EXEEXT): $(afcopy_OBJECTS) $(afcopy_DEPENDENCIES)
386 @rm -f afcopy$(EXEEXT)
387 $(CXXLINK) $(afcopy_OBJECTS) $(afcopy_LDADD) $(LIBS)
388 afcrypto$(EXEEXT): $(afcrypto_OBJECTS) $(afcrypto_DEPENDENCIES)
389 @rm -f afcrypto$(EXEEXT)
390 $(CXXLINK) $(afcrypto_OBJECTS) $(afcrypto_LDADD) $(LIBS)
391 afdiskprint$(EXEEXT): $(afdiskprint_OBJECTS) $(afdiskprint_DEPENDENCIES)
392 @rm -f afdiskprint$(EXEEXT)
393 $(CXXLINK) $(afdiskprint_OBJECTS) $(afdiskprint_LDADD) $(LIBS)
377 affcat$(EXEEXT): $(affcat_OBJECTS) $(affcat_DEPENDENCIES)
378 @rm -f affcat$(EXEEXT)
379 $(CXXLINK) $(affcat_OBJECTS) $(affcat_LDADD) $(LIBS)
380 affcompare$(EXEEXT): $(affcompare_OBJECTS) $(affcompare_DEPENDENCIES)
381 @rm -f affcompare$(EXEEXT)
382 $(CXXLINK) $(affcompare_OBJECTS) $(affcompare_LDADD) $(LIBS)
383 affconvert$(EXEEXT): $(affconvert_OBJECTS) $(affconvert_DEPENDENCIES)
384 @rm -f affconvert$(EXEEXT)
385 $(CXXLINK) $(affconvert_OBJECTS) $(affconvert_LDADD) $(LIBS)
386 affcopy$(EXEEXT): $(affcopy_OBJECTS) $(affcopy_DEPENDENCIES)
387 @rm -f affcopy$(EXEEXT)
388 $(CXXLINK) $(affcopy_OBJECTS) $(affcopy_LDADD) $(LIBS)
389 affcrypto$(EXEEXT): $(affcrypto_OBJECTS) $(affcrypto_DEPENDENCIES)
390 @rm -f affcrypto$(EXEEXT)
391 $(CXXLINK) $(affcrypto_OBJECTS) $(affcrypto_LDADD) $(LIBS)
392 affdiskprint$(EXEEXT): $(affdiskprint_OBJECTS) $(affdiskprint_DEPENDENCIES)
393 @rm -f affdiskprint$(EXEEXT)
394 $(CXXLINK) $(affdiskprint_OBJECTS) $(affdiskprint_LDADD) $(LIBS)
395 affinfo$(EXEEXT): $(affinfo_OBJECTS) $(affinfo_DEPENDENCIES)
396 @rm -f affinfo$(EXEEXT)
397 $(CXXLINK) $(affinfo_OBJECTS) $(affinfo_LDADD) $(LIBS)
394398 affix$(EXEEXT): $(affix_OBJECTS) $(affix_DEPENDENCIES)
395399 @rm -f affix$(EXEEXT)
396400 $(CXXLINK) $(affix_OBJECTS) $(affix_LDADD) $(LIBS)
401 affrecover$(EXEEXT): $(affrecover_OBJECTS) $(affrecover_DEPENDENCIES)
402 @rm -f affrecover$(EXEEXT)
403 $(CXXLINK) $(affrecover_OBJECTS) $(affrecover_LDADD) $(LIBS)
404 affsegment$(EXEEXT): $(affsegment_OBJECTS) $(affsegment_DEPENDENCIES)
405 @rm -f affsegment$(EXEEXT)
406 $(CXXLINK) $(affsegment_OBJECTS) $(affsegment_LDADD) $(LIBS)
407 affsign$(EXEEXT): $(affsign_OBJECTS) $(affsign_DEPENDENCIES)
408 @rm -f affsign$(EXEEXT)
409 $(CXXLINK) $(affsign_OBJECTS) $(affsign_LDADD) $(LIBS)
410 affstats$(EXEEXT): $(affstats_OBJECTS) $(affstats_DEPENDENCIES)
411 @rm -f affstats$(EXEEXT)
412 $(CXXLINK) $(affstats_OBJECTS) $(affstats_LDADD) $(LIBS)
397413 affuse$(EXEEXT): $(affuse_OBJECTS) $(affuse_DEPENDENCIES)
398414 @rm -f affuse$(EXEEXT)
399415 $(affuse_LINK) $(affuse_OBJECTS) $(affuse_LDADD) $(LIBS)
400 afinfo$(EXEEXT): $(afinfo_OBJECTS) $(afinfo_DEPENDENCIES)
401 @rm -f afinfo$(EXEEXT)
402 $(CXXLINK) $(afinfo_OBJECTS) $(afinfo_LDADD) $(LIBS)
403 afrecover$(EXEEXT): $(afrecover_OBJECTS) $(afrecover_DEPENDENCIES)
404 @rm -f afrecover$(EXEEXT)
405 $(CXXLINK) $(afrecover_OBJECTS) $(afrecover_LDADD) $(LIBS)
406 afsegment$(EXEEXT): $(afsegment_OBJECTS) $(afsegment_DEPENDENCIES)
407 @rm -f afsegment$(EXEEXT)
408 $(CXXLINK) $(afsegment_OBJECTS) $(afsegment_LDADD) $(LIBS)
409 afsign$(EXEEXT): $(afsign_OBJECTS) $(afsign_DEPENDENCIES)
410 @rm -f afsign$(EXEEXT)
411 $(CXXLINK) $(afsign_OBJECTS) $(afsign_LDADD) $(LIBS)
412 afstats$(EXEEXT): $(afstats_OBJECTS) $(afstats_DEPENDENCIES)
413 @rm -f afstats$(EXEEXT)
414 $(CXXLINK) $(afstats_OBJECTS) $(afstats_LDADD) $(LIBS)
415 afverify$(EXEEXT): $(afverify_OBJECTS) $(afverify_DEPENDENCIES)
416 @rm -f afverify$(EXEEXT)
417 $(CXXLINK) $(afverify_OBJECTS) $(afverify_LDADD) $(LIBS)
418 afxml$(EXEEXT): $(afxml_OBJECTS) $(afxml_DEPENDENCIES)
419 @rm -f afxml$(EXEEXT)
420 $(CXXLINK) $(afxml_OBJECTS) $(afxml_LDADD) $(LIBS)
416 affverify$(EXEEXT): $(affverify_OBJECTS) $(affverify_DEPENDENCIES)
417 @rm -f affverify$(EXEEXT)
418 $(CXXLINK) $(affverify_OBJECTS) $(affverify_LDADD) $(LIBS)
419 affxml$(EXEEXT): $(affxml_OBJECTS) $(affxml_DEPENDENCIES)
420 @rm -f affxml$(EXEEXT)
421 $(CXXLINK) $(affxml_OBJECTS) $(affxml_LDADD) $(LIBS)
421422
422423 mostlyclean-compile:
423424 -rm -f *.$(OBJEXT)
425426 distclean-compile:
426427 -rm -f *.tab.c
427428
428 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afcat.Po@am__quote@
429 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afcompare.Po@am__quote@
430 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afconvert.Po@am__quote@
431 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afcopy.Po@am__quote@
432 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afcrypto.Po@am__quote@
433 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afdiskprint.Po@am__quote@
434429 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aff_bom.Po@am__quote@
430 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affcat.Po@am__quote@
431 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affcompare.Po@am__quote@
432 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affconvert.Po@am__quote@
433 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affcopy.Po@am__quote@
434 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affcrypto.Po@am__quote@
435 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affdiskprint.Po@am__quote@
436 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affinfo.Po@am__quote@
435437 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affix.Po@am__quote@
438 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affrecover.Po@am__quote@
439 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affsegment.Po@am__quote@
440 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affsign.Po@am__quote@
441 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affstats.Po@am__quote@
436442 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affuse-affuse.Po@am__quote@
437 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afinfo.Po@am__quote@
438 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afrecover.Po@am__quote@
439 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afsegment.Po@am__quote@
440 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afsign.Po@am__quote@
441 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afstats.Po@am__quote@
442 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afverify.Po@am__quote@
443 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afxml.Po@am__quote@
443 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affverify.Po@am__quote@
444 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affxml.Po@am__quote@
444445
445446 .c.o:
446447 @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+0
-399
tools/afcat.cpp less more
0 /*
1 * afcat.cpp:
2 *
3 * cat the contents of an AFF file...
4 */
5
6 /*
7 * Copyright (c) 2005, 2006
8 * Simson L. Garfinkel and Basis Technology, Inc.
9 * All rights reserved.
10 *
11 * This code is derrived from software contributed by
12 * Simson L. Garfinkel
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by Simson L. Garfinkel
25 * and Basis Technology Corp.
26 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
27 * contributors to this program may be used to endorse or promote
28 * products derived from this software without specific prior written
29 * permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
32 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
34 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
36 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 */
45
46 #include "affconfig.h"
47 #include "afflib.h"
48 #include "afflib_i.h"
49
50 #include <stdio.h>
51 #include <algorithm>
52 #include <vector>
53 #include <string>
54 #ifdef HAVE_CSTRING
55 #include <cstring>
56 #endif
57
58
59 using namespace std;
60
61 vector <int64_t> pages;
62
63 const char *progname = "afcat";
64 int opt_info = 0;
65 char *opt_segname=0;
66 int64_t opt_pagenum = -1;
67 int opt_quiet = 1;
68 int opt_list= 0 ;
69 int opt_list_long = 0;
70 int opt_debug = 0;
71 int64_t opt_sector = -1;
72 int opt_badflag = 0;
73 vector<string> opt_r;
74
75
76 void usage()
77 {
78 printf("afcat version %s\n",PACKAGE_VERSION);
79 printf("usage: afcat [options] infile [... more infiles]\n");
80 printf("options:\n");
81 printf(" -s name --- Just output segment name\n");
82 printf(" -p ### --- just output data page number ###\n");
83 printf(" -S ### --- Just output data sector ### (assumes 512-byte sectors). Sector #0 is first\n");
84 printf(" -q --- quiet; don't print to STDERR if a page is skipped\n");
85 printf(" -n --- noisy; tell when pages are skipped.\n");
86 printf(" -l --- List all of the segment names\n");
87 printf(" -L --- List segment names, lengths, and args\n");
88 printf(" -d --- debug. Print the page numbers to stderr as data goes to stdout\n");
89 printf(" -b --- Output BADFALG for bad blocks (default is NULLs)\n");
90 printf(" -v --- Just print the version number and exit.\n");
91 printf(" -r offset:count --- seek to offset and output count characters in each file; may be repeated\n");
92 exit(0);
93 }
94
95
96 const char *current_fname = 0;
97 int64_t current_page = -1;
98 void sig_info(int arg)
99 {
100 fprintf(stderr,"afcat ");
101 if(current_fname) fprintf(stderr,"%s: ",current_fname);
102 if(current_page>=0) fprintf(stderr,"[%"PRId64"] ",current_page);
103 fflush(stderr);
104 }
105
106
107
108 int compar(const void *a_,const void *b_)
109 {
110 int64_t a = *(int *)a_;
111 int64_t b = *(int *)b_;
112 if(a<b) return -1;
113 if(a>b) return 1;
114 return 0;
115 }
116
117 struct afm_private {
118 AFFILE *aff; // the AFFILE we use for the actual metadata
119 AFFILE *sr; // the AFFILE we use for the splitraw
120 int sr_initialized; // has the split-raw been setup from AFM?
121 };
122
123 int output_page(AFFILE *af,FILE *outfile,int64_t pagenum)
124 {
125 current_fname = af_filename(af);
126 current_page = pagenum;
127 unsigned char *buf = (unsigned char *)malloc(af->image_pagesize);
128 if(buf==0){
129 err(1,"malloc(%d) failed",(int)af->image_pagesize);
130 }
131 uint64_t offset = (uint64_t)pagenum * af->image_pagesize; // go to that location
132
133
134 af_seek(af,offset,SEEK_SET);
135
136
137 int bytes = af_read(af,buf,af->image_pagesize); // read what we can
138
139 if(bytes<0){
140 if(opt_debug) fprintf(stderr,"afcat: cannot read page %"I64d"\n",pagenum);
141 return -1;
142 }
143
144 if(opt_debug){
145 fprintf(stderr,"afcat: page:%"I64d" bytes: %d offset:%"I64d"\n",
146 pagenum, bytes,offset);
147 }
148
149 /* Check each sector to see if it is badflag or not.
150 * If it is and if opt_badflag is not set, make it all NULs.
151 */
152 for(unsigned char *cc=buf;cc<buf+bytes;cc+=af->image_sectorsize){
153 if(af_is_badsector(af,cc) && opt_badflag==0){
154 memset(cc,0,af->image_sectorsize);
155 }
156 }
157
158 if(opt_debug) fprintf(stderr," outputing %d bytes\n",bytes);
159 int count = fwrite(buf,1,bytes,outfile); // send to the output
160 if(count!=bytes) fprintf(stderr,"fwrite(buf,1,%d,outfile) only wrote %d bytes\n",bytes,count);
161 free(buf);
162 return bytes;
163 }
164
165
166 int afcat(AFFILE *af)
167 {
168 int64_t total_bytes_written = 0;
169
170 /* Read all of the pages from beginning to end and capture
171 * all the segment numbers...
172 */
173
174 #ifdef WIN32
175 _setmode(fileno(stdout),_O_BINARY);
176 #endif
177 if(opt_debug) fprintf(stderr,"afcat(%s)\n",af_filename(af));
178
179 if(opt_segname){
180 /* First figure out how big the segment is */
181 size_t datalen = 0;
182 if(af_get_seg(af,opt_segname,0,0,&datalen)){
183 fprintf(stderr,"%s: segment '%s' does not exist\n",
184 af_filename(af),opt_segname);
185 return -1;
186 }
187 unsigned char *data = (unsigned char *)malloc(datalen);
188 if(data==0) err(1,"malloc");
189 if(af_get_seg(af,opt_segname,0,data,&datalen)){
190 free(data);
191 fprintf(stderr,"%s: could not read segment '%s'\n",
192 af_filename(af),opt_segname);
193 return -1;
194 }
195 int count = fwrite(data,1,datalen,stdout);
196 if(count!=(ssize_t)datalen){
197 fprintf(stderr,"fwrite(buf,1,%zd,outfile) only wrote %d bytes\n",datalen,count);
198 }
199 free(data);
200 return 0;
201 }
202
203 if(opt_pagenum != -1){ // just write a particular page?
204 int r = output_page(af,stdout,opt_pagenum);
205 return r>=0 ? 0 : -1;
206 }
207
208 if(opt_sector>=0){
209 unsigned char *buf = (unsigned char *)malloc(af->image_sectorsize);
210 af_seek(af,(uint64_t)opt_sector*af->image_sectorsize,SEEK_SET);
211 int bytes_read = af_read(af,buf,af->image_sectorsize);
212 if(bytes_read>0){
213 int bytes_written = fwrite(buf,1,bytes_read,stdout);
214 if(bytes_read!=bytes_written){
215 fprintf(stderr,"fwrite(buf,1,%d,outfile) only wrote %d bytes\n",
216 bytes_read,bytes_written);
217 }
218 }
219 free(buf);
220 return 0;
221 }
222
223 /* Get a list of all the segments. If we are doing a list, just print them.
224 * If we are not doing a list, capture the data pages and put their numbers
225 * into an array.
226 */
227
228 if(opt_debug) fprintf(stderr,"af_rewind_seg()\n");
229
230 if(opt_r.size()>0){
231 unsigned char *buf = (unsigned char *)malloc(af->image_pagesize);
232 for(vector<string>::const_iterator offset_count=opt_r.begin(); offset_count != opt_r.end(); offset_count++){
233 string opts = *offset_count;
234 const char *opt = opts.c_str();
235 uint64_t offset=0;
236 int count=0;
237 if(sscanf(opt,"%"I64u":%d",&offset,&count)!=2){
238 err(1,"Cannot decode '%s'\n",opt);
239 }
240 af_seek(af,offset,SEEK_SET);
241 int r= af_read(af,buf,count);
242 if(r>0){
243 int bytes_written = fwrite(buf,1,r,stdout);
244 if(bytes_written!=r) {
245 fprintf(stderr,"fwrite(buf,1,%d,outfile) only wrote %d bytes\n",r,bytes_written);
246 }
247
248 }
249 }
250 free(buf);
251 return 0;
252 }
253
254
255 af_rewind_seg(af); // start at the beginning
256 char segname[AF_MAX_NAME_LEN];
257 unsigned long arg;
258 size_t datalen = 0;
259 memset(segname,0,sizeof(segname));
260
261 int encrypted_segments = 0;
262 while(af_get_next_seg(af,segname,sizeof(segname),&arg,0,&datalen)==0){
263 if(opt_debug) fprintf(stderr,"af_get_next_seg found segment %s\n",segname);
264 if(segname[0]==0) continue; // ignore sector
265 if(opt_list){
266 printf("%s",segname);
267 if(opt_list_long){
268 printf("\targ:%lu\tlen:%d",arg,(int)datalen);
269 }
270 putchar('\n');
271 }
272 else {
273 int64_t pagenum = af_segname_page_number(segname);
274 if(pagenum>=0) pages.push_back(pagenum);
275 if(af_is_encrypted_segment(segname)) encrypted_segments++;
276 }
277 datalen = 0; // allow to get the next one
278 }
279 if(opt_list) return 0; // that's all that was wanted.
280
281
282 sort(pages.begin(),pages.end());
283
284 if(pages.size()==0 && encrypted_segments){
285 fprintf(stderr,"afcat: This file has %d encrypted segments.\n",encrypted_segments);
286 fprintf(stderr,"afcat: No unencrypted pages could be found.\n");
287 }
288
289 /* Now I have a list of pages; cat each one */
290 int next_page = 0; // starting page number
291 int64_t imagesize = af_get_imagesize(af);
292 for(vector<int64_t>::iterator i = pages.begin(); i != pages.end(); i++){
293
294 int page = *i;
295 if(page != next_page && opt_quiet==0){
296 if(page == next_page+1 ){
297 fprintf(stderr,"afcat: page %d not in file\n",next_page);
298 }
299 else{
300 fprintf(stderr,"afcat: pages %d through %d not in file\n",
301 next_page,page-1);
302 }
303 }
304 int r = output_page(af,stdout,page);
305 if(r<0) return -1;
306 total_bytes_written += r;
307 next_page = page + 1; // note what should be next
308
309 //fprintf(stderr,"bytes written=%qd imagesize=%qd\n",total_bytes_written,imagesize);
310 if((total_bytes_written > imagesize) && (imagesize>0)){
311 err(1,"afcat internal error. bytes written=%"I64d" imagesize=%" I64d,
312 (int64_t)total_bytes_written,
313 (int64_t)imagesize);
314 return -1;
315 }
316 }
317 return 0;
318 }
319
320
321 int64_t atoi64(const char *buf)
322 {
323 int64_t r=0;
324 char ch;
325 if(sscanf(buf,"%"I64d"%c",&r,&ch)==1) return r;
326 fprintf(stderr,"Cannot parse '%s'\n",buf);
327 exit(0);
328 }
329
330
331 int main(int argc,char **argv)
332 {
333 int bflag, ch;
334
335 #ifdef SIGINFO
336 signal(SIGINFO,sig_info);
337 #endif
338
339 bflag = 0;
340 while ((ch = getopt(argc, argv, "s:S:p:lLh?dqnvr:")) != -1) {
341 switch (ch) {
342 case 's':
343 opt_segname = optarg;
344 break;
345 case 'S':
346 opt_sector = atoi64(optarg);
347 break;
348 case 'p':
349 opt_pagenum = atoi64(optarg);
350 break;
351 case 'q':
352 opt_quiet = 1;
353 break;
354 case 'n':
355 opt_quiet = 0;
356 break;
357 case 'l':
358 opt_list = 1;
359 break;
360 case 'r':
361 opt_r.push_back(optarg);
362 break;
363 case 'L':
364 opt_list = 1;
365 opt_list_long = 1;
366 break;
367 case 'b':
368 opt_badflag = 1;
369 break;
370 case 'd':
371 opt_debug++;
372 break;
373 case 'h':
374 case '?':
375 default:
376 usage();
377 break;
378 case 'v':
379 printf("%s version %s\n",progname,PACKAGE_VERSION);
380 exit(0);
381 }
382 }
383 argc -= optind;
384 argv += optind;
385
386 if(argc<1){
387 usage();
388 }
389
390 while(*argv){
391 AFFILE *af = af_open(*argv,O_RDONLY,0);
392 if(!af) af_err(1,"afcat(%s)",*argv);
393 if(afcat(af)) err(1,"afcat");
394 af_close(af);
395 argv++;
396 argc--;
397 }
398 }
+0
-831
tools/afcompare.cpp less more
0 /*
1 * acompare.cpp:
2 *
3 * Compare the contents of an ISO file to an AFF file.
4 * Optionally, if they are equal, delete the ISO file
5 */
6
7 /*
8 * Copyright (c) 2005--2008
9 * Simson L. Garfinkel and Basis Technology, Inc.
10 * All rights reserved.
11 *
12 * This code is derrived from software contributed by
13 * Simson L. Garfinkel
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 * 3. All advertising materials mentioning features or use of this software
24 * must display the following acknowledgement:
25 * This product includes software developed by Simson L. Garfinkel
26 * and Basis Technology Corp.
27 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
28 * contributors to this program may be used to endorse or promote
29 * products derived from this software without specific prior written
30 * permission.
31 *
32 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
33 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
34 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
35 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
37 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
40 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
41 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
42 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
43 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44 * SUCH DAMAGE.
45 */
46
47 #include "affconfig.h"
48 #include "afflib.h"
49 #include "afflib_i.h"
50 #include "utils.h"
51
52 using namespace std;
53 using namespace aff;
54
55
56 #ifdef WIN32
57 #include "unix4win32.h"
58 #endif
59
60
61 #ifdef UNIX
62 #include <sys/signal.h>
63 #include <unistd.h>
64 #endif
65
66 #include <ctype.h>
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <sys/types.h>
70 #include <sys/stat.h>
71 #include <fcntl.h>
72 #include <limits.h>
73 #include <string.h>
74 #include <zlib.h>
75 #include <openssl/md5.h>
76 #include <openssl/sha.h>
77 #include <assert.h>
78
79 #ifdef HAVE_CSTRING
80 #include <cstring>
81 #endif
82
83 #ifdef linux
84 #include <sys/time.h>
85 #endif
86
87
88
89 const char *progname = "afcompare";
90
91 int opt_quiet = 0;
92 int opt_all = 0;
93 int opt_print_sectors = 0;
94 int opt_print_sector_contents = 0;
95 int opt_page = -1;
96 int opt_preen = 0;
97 int opt_exist = 0;
98 int opt_ignore_metadata = 0;
99 int opt_s3 = 0;
100 int opt_verbose = 0;
101 const char *batch_ext = "";
102
103 vector<string> errors;
104
105 const char *current_source = 0;
106
107 void sig_info(int arg)
108 {
109 if(current_source){
110 printf("%s... ",current_source);
111 }
112 printf("\n");
113 fflush(stdout);
114 }
115
116 void print_title(char *title)
117 {
118 if(title[0]){
119 puts(title);
120 title[0] = 0;
121 }
122 }
123
124 void usage()
125 {
126 printf("afcompare version %s\n",PACKAGE_VERSION);
127 printf("\n");
128 printf("usage: afcompare [options] file1 file2\n");
129 printf(" compares file1 with file2\n");
130 printf("\n");
131 printf("or afcompare [options] -r dir1 dir2\n");
132 printf(" comparses similarly-named files in dir1 and dir2\n");
133 printf("\n");
134 printf("or afcompare [options] -s file1 file2...\n");
135 printf(" Reports if file was successfully copied to Amazon S3\n");
136 printf(" checking only for existence, not reading back the bytes.\n");
137 printf(" (Because all writes to S3 are validated by the MD5 of the object\n");
138 #ifndef USE_S3
139 printf(" NOTE: S3 support is not provided in this version\n");
140 #endif
141
142 printf("fast options:\n");
143 printf("(These compare segments but not their contents.)\n");
144 printf(" -p --- report about the results of preening\n");
145 printf(" -e --- Just report about existence (use with -r)\n");
146 printf(" -s --- Just see if all of the segments are present, but don't\n");
147 printf(" validate the contents. (Primarily for use with Amazon S3)\n");
148
149 printf("other options:\n");
150 printf(" -V --- just print the version number and exit\n");
151 printf(" -v --- Verbose; each file as it is compared.\n");
152 printf(" -q --- Quiet. No output except for errors\n");
153 printf(" -a --- print what's the same (all)\n");
154 printf(" -b --- print the numbers of differing sectors\n");
155 printf(" -c --- print the contents of differing sectors\n");
156 printf(" -m --- Just report about the data (ignore metadata)\n");
157 printf(" -P ### --- Just examine the differences on page ###\n");
158 printf(" -q --- Quiet; no output except for errors.\n");
159 printf("\n");
160 printf("Options documented above:\n");
161 printf(" -r dir1 dir2 --- recursively compare what's in dir1 with dir2, and\n");
162 printf(" report what's in dir1 that's not in dir2\n");
163 printf(" -s --- Check to see if named files are on Amazon S3\n");
164 printf("\n");
165 printf(" afcompare file1.aff file2.aff --- compare file1.aff and file2.aff\n");
166 printf(" afcompare f1.aff f2.aff dir1/ --- compare f1.aff with dir1/f1.aff and f2.aff with dir2/f2.aff\n");
167 printf(" note: dir1/ must end with a slash.\n");
168 printf(" afcompare -b img file.aff --- compare file.aff and file.img\n");
169 printf(" afcompare -b img file1.aff file2.aff... --- compare file1.aff, file1.img, etc.\n");
170 printf(" afcompare -re dir1 dir2 --- report AFF files in dir1 but not in dir2\n");
171 printf(" afcompare -rse dir1 s3:/// --- report AFF files in dir1 but not on S3 (low bandwidth)\n");
172 printf(" afcompare -rs dir1 s3:/// --- report AFF files in dir1 but incomplete on on S3 (more bandwidth)\n");
173 printf("\n");
174 exit(0);
175 }
176
177 void print_sector(AFFILE *af,unsigned char *buf)
178 {
179 for(unsigned int i=0;i<af->image_sectorsize;i++){
180 if(isprint(buf[i])){
181 putchar(buf[i]);
182 }
183 else {
184 putchar('.');
185 }
186 if(i%64==63) putchar('\n');
187 }
188 }
189
190
191 void print_info(char dir,const char *segname,unsigned long arg,size_t len,
192 unsigned char *data,int mcr)
193 {
194 printf(" %c %s arg=%lu len=%d\n",dir,segname,arg,(int)len);
195 printf(" ");
196 if((arg == AF_SEG_QUADWORD) && (len==8)){
197 printf("data=%"I64d" as a 64-bit value\n",af_decode_q(data));
198 return;
199 }
200 /* Otherwise, just print some stuff... */
201 for(unsigned int i=0;i<len && i<60;i++){
202 if(data[i]==' '){
203 putchar(' ');
204 continue;
205 }
206 if(!isprint(data[i])){
207 putchar('.');
208 continue;
209 }
210 putchar(data[i]);
211 }
212 putchar('\n');
213 }
214
215 int compare_aff_metadata_segments(char *title,AFFILE *af1,AFFILE *af2,const char *segname,int mode)
216 {
217 int ret = 0;
218
219 unsigned long arg1 = 0;
220 size_t data1_len = 0;
221 int r1 = af_get_seg(af1,segname,&arg1,0,&data1_len);
222
223 unsigned long arg2 = 0;
224 size_t data2_len = 0;
225 int r2 = af_get_seg(af2,segname,&arg2,0,&data2_len);
226
227 if(r1==0 && r2!=0){
228 if(mode==1){
229 print_title(title);
230 printf(" %s \n",segname);
231 }
232 return 1;
233 }
234
235 if(r1!=0 && r2==0){
236 if(mode==2){
237 print_title(title);
238 printf(" %s \n",segname);
239 }
240 return 1;
241 }
242 if(mode!=3) return 0; // only report differences in mode 3
243 /* Get the actual data... */
244
245 unsigned char *data1 = (unsigned char *)malloc(data1_len);
246 unsigned char *data2 = (unsigned char *)malloc(data2_len);
247
248 int s1 = af_get_seg(af1,segname,&arg1,data1,&data1_len);
249 if(s1!=0) err(1,"Couldn't read data segment %s in %s",segname,af_filename(af1));
250
251 int s2 = af_get_seg(af2,segname,&arg2,data2,&data2_len);
252 if(s2!=0) err(1,"Couldn't read data segment %s in %s",segname,af_filename(af2));
253
254 int mcr = 0;
255
256 if(data1_len != data2_len) mcr = 1;
257 else mcr = memcmp(data1,data2,data1_len);
258 if(arg1!=arg2 || data1_len!=data2_len || mcr!=0){
259 print_title(title);
260 print_info('<',segname,arg1,data1_len,data1,mcr);
261 print_info('>',segname,arg2,data2_len,data2,mcr);
262 if(mcr){
263 printf(" *** Metadata segment are different ");
264 if(strcmp(segname,AF_BADFLAG)==0){
265 printf("(bad flags should be different!)");
266 }
267 putchar('\n');
268 }
269 putchar('\n');
270 ret = 1;
271 }
272 else {
273 if(opt_all){
274 print_title(title);
275 printf(" %s (same in both) \n",segname);
276 }
277 }
278 free(data1);
279 free(data2);
280 return ret;
281 }
282
283 int compare_aff_data_segments(char *title,AFFILE *af1,AFFILE *af2,int64_t pagenum,int mode)
284 {
285 int ret = 0;
286 char pagename[65];
287 snprintf(pagename,sizeof(pagename),AF_PAGE,pagenum);
288
289 char segname[65];
290 snprintf(segname,sizeof(segname),AF_SEG_D,pagenum);
291
292 unsigned long arg1=0;
293 size_t data1_len=0;
294 int r1 = af_get_seg(af1,pagename,&arg1,0,&data1_len);
295 if(r1==-1) r1=af_get_seg(af1,segname,&arg1,0,&data1_len);
296
297 unsigned long arg2=0;
298 size_t data2_len=0;
299 int r2 = af_get_seg(af2,pagename,&arg2,0,&data2_len);
300 if(r2 == -1) r2=af_get_seg(af2,segname,&arg2,0,&data2_len);
301
302 if(r1<0 && r2<0) return 0; // no data segment in either file
303 if(r1==0 && r2!=0){
304 if(mode==1){
305 print_title(title);
306 printf(" %s \n",pagename);
307 }
308 return 1;
309 }
310
311 if(r2==0 && r1!=0){
312 if(mode==2){
313 print_title(title);
314 printf(" %s \n",pagename);
315 }
316 return 1;
317 }
318 if(mode!=3) return 0; // only report differences in mode 3
319
320 /* Get the actual data... */
321 unsigned char *data1 = (unsigned char *)malloc(af_page_size(af1));
322 unsigned char *data2 = (unsigned char *)malloc(af_page_size(af2));
323
324 data1_len = af_page_size(af1);
325 data2_len = af_page_size(af2);
326
327 uint64_t start_sector_number = (pagenum * data1_len) / af1->image_sectorsize;
328
329 /* Find the size of each page, then get the page */
330 if(af_get_page(af1,pagenum,0,&data1_len)<0)
331 err(1,"Cannot read page %"I64d" size from %s\n",pagenum,af_filename(af1));
332 if(af_get_page(af1,pagenum,data1,&data1_len)<0)
333 err(1,"Cannot read page %"I64d" from %s",pagenum,af_filename(af1));
334
335 if(af_get_page(af2,pagenum,0,&data2_len)<0)
336 err(1,"Cannot read page %"I64d" size from %s\n",pagenum,af_filename(af2));
337 if(af_get_page(af2,pagenum,data2,&data2_len)<0)
338 err(1,"Cannot read page %"I64d" from %s",pagenum,af_filename(af2));
339
340 if(data1_len != data2_len){
341 printf("page %"I64d" size %zd != size %zd\n",pagenum,data1_len,data2_len);
342 return 1;
343 }
344
345 /* Now look at the pages sector-by-sector. */
346 int af1_bad=0;
347 int af2_bad=0;
348 int matching_bad_sectors = 0;
349 int matching_sectors = 0;
350 int total_sectors = 0;
351 int no_match = 0;
352 vector<uint64_t> different_sectors;
353
354 for(unsigned int offset=0;offset<data1_len;offset+=af1->image_sectorsize){
355 uint64_t this_sector = start_sector_number + offset/af1->image_sectorsize;
356 total_sectors++;
357 if(af_is_badsector(af1,data1+offset) &&
358 af_is_badsector(af2,data2+offset)){
359 matching_bad_sectors++;
360 continue;
361 }
362 if(af_is_badsector(af1,data1+offset)){
363 af1_bad++;
364 continue;
365 }
366 if(af_is_badsector(af2,data2+offset)){
367 af2_bad++;
368 continue;
369 }
370 if(memcmp(data1+offset,data2+offset,af1->image_sectorsize)==0){
371 matching_sectors++;
372 continue;
373 }
374 no_match++;
375 different_sectors.push_back(this_sector);
376 }
377
378 char outline[256];
379 outline[0] = 0;
380 if(opt_all || (no_match>0) || af1_bad || af2_bad){
381 snprintf(outline,sizeof(outline),
382 " page%"I64d" sectors:%4d matching: %3d different:%3d",
383 pagenum,total_sectors,matching_sectors,no_match);
384 }
385 if(af1_bad){
386 snprintf(outline+strlen(outline),sizeof(outline)-strlen(outline),
387 " file 1 bad: %3d ",af1_bad);
388 }
389 if(af2_bad){
390 snprintf(outline+strlen(outline),sizeof(outline)-strlen(outline),
391 " file 2 bad: %3d ",af2_bad);
392 }
393 if(matching_bad_sectors){
394 if(opt_all){
395 snprintf(outline+strlen(outline),sizeof(outline)-strlen(outline),
396 " bad both:%3d ",matching_bad_sectors);
397 }
398 }
399
400 if(outline[0]){
401 print_title(title);
402 puts(outline);
403 }
404 if(opt_print_sectors && different_sectors.size()>0){
405 print_title(title);
406 printf(" Sectors with differences:");
407 int i=0;
408 for(vector<uint64_t>::iterator j = different_sectors.begin();
409 j != different_sectors.end();
410 j++){
411 if(i==0){
412 printf("\n ");
413 }
414 printf(" %"I64d,*j);
415 i = (i+1) % 10;
416 }
417 putchar('\n');
418 ret = 1;
419 }
420 if(opt_print_sector_contents && different_sectors.size()>0){
421 print_title(title);
422 printf(" Sectors with differences:");
423 for(vector<uint64_t>::iterator j = different_sectors.begin();
424 j != different_sectors.end(); j++){
425 int offset = (*j - start_sector_number)*af1->image_sectorsize;
426 char b2[16];
427 printf("offset=%d\n",offset);
428
429 memcpy(b2,data1+offset,16);
430 b2[15]=0;
431
432 printf("=== sector %"I64d" (offset=%d) ===\n",*j,offset);
433 printf(" %s:\n",af_filename(af1));
434 print_sector(af1,data1+offset);
435 printf("-------------------------------------\n");
436 printf(" %s:\n",af_filename(af2));
437 print_sector(af2,data2+offset);
438 printf("=====================================\n\n");
439 }
440 ret = 1;
441 }
442 free(data1);
443 free(data2);
444 return ret;
445 }
446
447 /* Compare the results of two files that were preened */
448 int compare_preen(AFFILE *af1,AFFILE *af2)
449 {
450 vector<int64_t> pages;
451 int comp_zero=0;
452 int comp_lzma=0;
453 int comp_unchanged=0;
454 uint64_t bytes_old = 0;
455 uint64_t bytes_new = 0;
456
457 af_rewind_seg(af1);
458 /* Build a list of all the pages */
459 char segname[AF_MAX_NAME_LEN];
460 while(af_get_next_seg(af1,segname,sizeof(segname),0,0,0)==0){
461 int64_t pagenumber = af_segname_page_number(segname);
462 if(pagenumber>=0) pages.push_back(pagenumber);
463 }
464 /* Now, compare each one */
465 for(vector<int64_t>::const_iterator i = pages.begin(); i != pages.end(); i++){
466 unsigned long arg1,arg2;
467 size_t len1,len2;
468
469 if(af_get_page_raw(af1,*i,&arg1,0,&len1)){
470 err(1,"Could not read page %"I64d" in file %s\n",*i,af_filename(af1));
471 }
472 if(af_get_page_raw(af2,*i,&arg2,0,&len2)){
473 err(1,"Page %"I64d" is in file %s but not in %s\n",*i,af_filename(af1),
474 af_filename(af2));
475 }
476 if(arg1==arg2 && len1==len2){
477 comp_unchanged++;
478 continue;
479 }
480 if((arg2 & AF_PAGE_COMP_ALG_MASK)==AF_PAGE_COMP_ALG_ZERO){
481 comp_zero++;
482 continue;
483 }
484 if((arg2 & AF_PAGE_COMP_ALG_MASK)==AF_PAGE_COMP_ALG_LZMA){
485 comp_lzma++;
486 bytes_old += len1;
487 bytes_new += len2;
488 continue;
489 }
490 }
491 printf("%s -> %s Nochg: %d NUL: %d LZMA: %d old: %"I64d" new: %"I64d" LZred: %6.2f%%\n",
492 af_filename(af1),
493 af_filename(af2),
494 comp_unchanged,comp_zero,comp_lzma,bytes_old,bytes_new,(bytes_old-bytes_new)*100.0/bytes_old);
495 return 0;
496 }
497
498
499 /* Compare two AFF files.
500 * Return 0 if they are equal.
501 */
502 int compare_aff_aff(const char *file1,const char *file2)
503 {
504 bool no_data_segments = false;
505 int ret = 0;
506
507 current_source = file1;
508
509 if(opt_all) printf("compare %s and %s:\n",file1,file2);
510
511 AFFILE *af1 = af_open(file1,O_RDONLY,0);
512 if(!af1) af_err(1,"af_open(%s)",file1);
513
514 AFFILE *af2 = af_open(file2,O_RDONLY,0);
515 if(!af2) af_err(1,"af_open(%s)",file2);
516
517 af_vnode_info vni1,vni2;
518
519 if(af_vstat(af1,&vni1) || af_vstat(af2,&vni2)){
520 err(1,"af_vstat failed?");
521 }
522
523 if(af_cannot_decrypt(af1) != af_cannot_decrypt(af2)){
524 printf("%s: %s decrypt\n",file1,af_cannot_decrypt(af1) ? "cannot" : "can");
525 printf("%s: %s decrypt\n",file2,af_cannot_decrypt(af2) ? "cannot" : "can");
526 fprintf(stderr,"afcompare must be able to decrypt both files or neither of the files.\n");
527 exit(1);
528 }
529
530 if(af1->image_pagesize != af2->image_pagesize){
531 fprintf(stderr,"Currently, %s requires that both images have the "
532 "same image datsegsize.\n"
533 "pagesize(%s)=%ld\n"
534 "pagesize(%s)=%ld\n",
535 progname,file1,af1->image_pagesize,
536 file2,af2->image_pagesize);
537 fprintf(stderr,"Data segments will be ignored.\n");
538 no_data_segments = true;
539 }
540
541 if(af1->image_sectorsize != af2->image_sectorsize){
542 fprintf(stderr,"Currently, %s requires that both images have the "
543 "same image sectorsize.\n"
544 "sectorsize(%s)=%ld\n"
545 "sectorsize(%s)=%ld\n",
546 progname,file1,af1->image_sectorsize, file2,af2->image_sectorsize);
547 fprintf(stderr,"Data segments will be ignored.\n");
548 no_data_segments = true;
549 }
550
551 if(opt_preen){
552 compare_preen(af1,af2);
553 af_close(af1);
554 af_close(af2);
555 return 0;
556 }
557
558 if(opt_s3){
559 printf("bypass\n");
560 seglist list1(af1);
561 seglist list2(af2);
562
563 /* Just compare the presence/absence of each segment */
564 char title[1024];
565 snprintf(title,sizeof(title),"\nPresent in %s but not %s:",af_filename(af1),af_filename(af2));
566 for(seglist::const_iterator i=list1.begin(); i!=list1.end(); i++){
567 if(find(list2.begin(),list2.end(),*i)==list2.end()){
568 print_title(title);
569 printf(" %s\n",(*i).name.c_str());
570 }
571 }
572 snprintf(title,sizeof(title),"\nPresent in %s but not %s:",af_filename(af2),af_filename(af1));
573 for(seglist::const_iterator i=list2.begin(); i!=list2.end(); i++){
574 if(find(list1.begin(),list1.end(),*i)==list1.end()){
575 print_title(title);
576 printf(" %s\n",(*i).name.c_str());
577 }
578 }
579 return 0;
580 }
581
582 /* Compare all of the metadata segments in af1 with a2.
583 * Report those that are missing or different. Then report
584 * all of the segments in a2 but not in af1
585 */
586
587 /* First build a list of the segments in each */
588
589 vector <string> segs_with_dups;
590
591 AFFILE *af[2] = {af1,af2};
592 for(int i=0;i<2;i++){
593 if(opt_verbose) printf("\n%s:\n",af_filename(af[i]));
594 af_rewind_seg(af[i]);
595 char segname[AF_MAX_NAME_LEN];
596 while(af_get_next_seg(af[i],segname,sizeof(segname),0,0,0)==0){
597 if(segname[0]){
598 string s;
599 s = segname;
600 segs_with_dups.push_back(s); // may give duplicates
601 if(opt_verbose) printf(" %s\n",segname);
602 }
603 }
604 }
605 sort(segs_with_dups.begin(),segs_with_dups.end());
606 vector<string>segs;
607
608 /* Make a list of segs without duplicates */
609 string last;
610 for(vector<string>::iterator i = segs_with_dups.begin();
611 i != segs_with_dups.end(); i++){
612 if(last != *i){
613 segs.push_back(*i);
614 }
615 last = *i;
616 }
617
618 int lowest_page = -1;
619 int highest_page = -1;
620 /* Scan for the lowest and highest numbers */
621 for(vector<string>::iterator i = segs.begin();i != segs.end(); i++){
622 int64_t num = af_segname_page_number(i->c_str());
623 if(num!=-1){
624 if(num<lowest_page ||lowest_page==-1) lowest_page = num;
625 if(num>highest_page||highest_page==-1) highest_page = num;
626 }
627 }
628
629
630 if(opt_page != -1){
631 lowest_page = opt_page;
632 highest_page = opt_page;
633 }
634
635
636 if(opt_page == -1
637 && vni1.supports_metadata
638 && vni2.supports_metadata
639 && opt_ignore_metadata==0 ){
640 if(opt_all) puts("Inspecting metadata...");
641 for(int mode=1;mode<=3;mode++){
642 const char *title = "Metadata segments ";
643 char mode_title[1024];
644 switch(mode){
645 case 1:
646 snprintf(mode_title,sizeof(mode_title)," %s only in %s:\n",
647 title,af_filename(af1));
648 break;
649 case 2:
650 snprintf(mode_title,sizeof(mode_title)," %s only in %s:\n",
651 title,af_filename(af2));
652 break;
653 case 3:
654 snprintf(mode_title,sizeof(mode_title)," %s in both files:\n",title);
655 break;
656 }
657
658 for(vector<string>::iterator i = segs.begin();i != segs.end();i++){
659 int64_t num = af_segname_page_number(i->c_str());
660 if(num==-1){
661 int r = compare_aff_metadata_segments(mode_title, af1,af2,
662 i->c_str(),mode);
663 if(r!=0) ret = r;
664 }
665 }
666 }
667 }
668
669 if(no_data_segments==false){
670 if(opt_all) puts("Inspecting data...");
671 for(int mode=1;mode<=3;mode++){
672 char mode_title[1024];
673 switch(mode){
674 case 1: snprintf(mode_title,sizeof(mode_title),
675 " Pages only in %s:\n", af_filename(af1));break;
676 case 2: snprintf(mode_title,sizeof(mode_title),
677 " Pages only in %s:\n", af_filename(af2));break;
678 case 3: snprintf(mode_title,sizeof(mode_title)," Pages in both files:\n");break;
679 }
680
681 for(int i=lowest_page;i<=highest_page;i++){
682 int r = compare_aff_data_segments(mode_title,af1,af2,i,mode);
683 if(r!=0) ret = r;
684 }
685 }
686 }
687 current_source = 0;
688 #ifdef HAVE_ISATTY
689 if(ret==0 && isatty(fileno(stdout))) printf("%s and %s: files compare okay\n",file1,file2);
690 #endif
691 return ret;
692 }
693
694 int recurse(const char *dir1,const char *dir2)
695 {
696 vector<string> only_in_dir1;
697
698 DIR *dirp = opendir(dir1);
699 struct dirent *dp;
700 if(!dirp) err(1,"opendir: %s",dir1);
701 while ((dp = readdir(dirp)) != NULL){
702
703 char fn1[MAXPATHLEN+1]; memset(fn1,0,sizeof(fn1));
704 char fn2[MAXPATHLEN+1]; memset(fn2,0,sizeof(fn2));
705
706 strlcpy(fn1,dir1,sizeof(fn1));
707 if(fn1[strlen(fn1)-1]!='/') strlcat(fn1,"/",sizeof(fn1));
708 strlcat(fn1,dp->d_name,sizeof(fn1));
709
710 current_source = fn1;
711 if(opt_verbose) printf("%s...\n",fn1);
712
713 switch(af_identify_file_type(fn1,1)){
714 case AF_IDENTIFY_ERR:
715 case AF_IDENTIFY_NOEXIST:
716 only_in_dir1.push_back(fn1);
717 break;
718 case AF_IDENTIFY_AFF:
719 case AF_IDENTIFY_AFD:
720 case AF_IDENTIFY_AFM:
721 strlcpy(fn2,dir2,sizeof(fn2));
722 if(fn2[strlen(fn2)-1]!='/') strlcat(fn2,"/",sizeof(fn2));
723 strlcat(fn2,dp->d_name,sizeof(fn2));
724 if(af_identify_file_type(fn2,1)<0){
725 char buf[1024];
726 snprintf(buf,sizeof(buf),"%s not in %s\n",dp->d_name,dir2);
727 errors.push_back(buf);
728 break;
729 }
730 if(opt_exist==0){
731 compare_aff_aff(fn1,fn2);
732 }
733 break;
734 default:
735 break;
736 }
737 }
738 closedir(dirp);
739 printf("========================\n");
740 printf("Only in %s\n",dir1);
741 for(vector<string>::const_iterator i = only_in_dir1.begin();
742 i != only_in_dir1.end();
743 i++){
744 printf("%s\n",i->c_str());
745 }
746 return 0;
747 }
748
749 int main(int argc,char **argv)
750 {
751 int bflag, ch;
752 int opt_recurse=0;
753
754 #ifdef SIGINFO
755 signal(SIGINFO,sig_info);
756 #endif
757
758 bflag = 0;
759 while ((ch = getopt(argc, argv, "P:Vabcempqrsh?v")) != -1) {
760 switch (ch) {
761 case 'P': opt_page = atoi(optarg); break;
762 case 'V': printf("%s version %s\n",progname,PACKAGE_VERSION); exit(0);
763 case 'a': opt_all++; break;
764 case 'b': opt_print_sectors=1; break;
765 case 'c': opt_print_sector_contents=1; break;
766 case 'e': opt_exist++; break;
767 case 'm': opt_ignore_metadata++; break;
768 case 'p': opt_preen++; break;
769 case 'q': opt_quiet++; break;
770 case 'r': opt_recurse++; break;
771 case 's': opt_s3++;break;
772 case 'v': opt_verbose++;break;
773 case 'h':
774 case '?':
775 default:
776 usage();
777 }
778 }
779 argc -= optind;
780 argv += optind;
781
782 if(opt_recurse){
783 if(argc!=2) usage();
784 char *dir1 = *argv++;
785 char *dir2 = *argv++;
786 recurse(dir1,dir2);
787 if(errors.size()>0){
788 fprintf(stderr,"================================\n");
789 fprintf(stderr,"%zd afcompare errors:\n",errors.size());
790 for(vector<string>::const_iterator i=errors.begin();
791 i!=errors.end();
792 i++){
793 fputs(i->c_str(),stderr);
794 }
795 exit(1);
796 }
797 exit(0);
798 }
799
800 if(argc>1){
801 char *last = argv[argc-1];
802 if(last[strlen(last)-1]=='/'){
803 while(argc>1){
804 char *file1 = *argv;
805 char *name1 = file1;
806 char *cc;
807
808 cc = strrchr(file1,'/');
809 if(cc) name1 = cc+1;
810
811 char file2[MAXPATHLEN+1];
812 strlcpy(file2,last,sizeof(file2));
813 strlcat(file2,name1,sizeof(file2));
814 int e_code = compare_aff_aff(file1,file2);
815 if(e_code) exit(e_code);
816 argv++;
817 argc--;
818 }
819 }
820 }
821
822 if(argc!=2) usage(); // if just 2, compare them
823
824 char *file1 = *argv++;
825 char *file2 = *argv++;
826
827 if(opt_verbose) printf("%s...\n",file1);
828 int e_code = compare_aff_aff(file1,file2);
829 exit(e_code);
830 }
+0
-743
tools/afconvert.cpp less more
0 /*
1 * afconvert.cpp:
2 *
3 * Convert raw -> aff
4 * aff -> raw
5 * aff -> aff (recompressing/uncompressing)
6 */
7
8 /*
9 * Copyright (c) 2005--2008
10 * Simson L. Garfinkel and Basis Technology, Inc.
11 * All rights reserved.
12 *
13 * This code is derrived from software contributed by
14 * Simson L. Garfinkel
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. All advertising materials mentioning features or use of this software
25 * must display the following acknowledgement:
26 * This product includes software developed by Simson L. Garfinkel,
27 * Basis Technology, and its contributors.
28 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
29 * contributors to this program may be used to endorse or promote
30 * products derived from this software without specific prior written
31 * permission.
32 *
33 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
34 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
35 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
36 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
38 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
39 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
41 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
42 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
43 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
44 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 */
47
48
49
50 #include "affconfig.h"
51 #include "afflib.h"
52 #include "afflib_i.h" // we do enough mucking, we need the internal version
53 #include "utils.h"
54
55 #include <openssl/md5.h>
56 #include <openssl/sha.h>
57
58 #ifdef WIN32
59 #include "unix4win32.h"
60 #endif
61
62 #ifdef HAVE_CURSES_H
63 #include <curses.h>
64 #endif
65
66 #ifdef HAVE_TERM_H
67 #include <term.h>
68 #endif
69
70
71 #ifdef HAVE_SYS_TIME_H
72 #include <sys/time.h>
73 #endif
74
75 #include <sys/stat.h>
76 #include <string>
77
78 #ifdef HAVE_UNISTD_H
79 #include <unistd.h>
80 #endif
81
82 #ifdef HAVE_GETOPT_H
83 #include <getopt.h>
84 #endif
85
86
87
88 const char *progname = "afconvert";
89
90 int image_pagesize = 16*1024*1024; // default seg size --- 16MB
91 int opt_compression_alg = AF_COMPRESSION_ALG_ZLIB;
92 int opt_compress_level = AF_COMPRESSION_DEFAULT;
93 int64_t bytes_to_convert = 0;
94 int opt_batch = 1;
95 int opt_zap = 0;
96 int opt_quiet = 0;
97 int opt_write_raw = 0; // output
98 int opt_probe_compressed = 1; // probe for compressed files
99 const char *opt_write_raw_ext = "raw";
100 const char *opt_outdir = 0;
101 const char *opt_aff_ext = "aff";
102 int64_t opt_maxsize = 0;
103 int opt_yes = 0;
104 int opt_debug = 0;
105 std::string command_line;
106
107
108 char *append(char *base,const char *str)
109 {
110 base = (char *)realloc(base,strlen(base)+strlen(str)+1);
111 strcat(base,str); // can't fail
112 return base;
113 }
114
115
116
117 void usage()
118 {
119 printf("%s version %s\n",progname,PACKAGE_VERSION);
120 printf("\n");
121 printf("usage: %s [options] file1 [... files] \n",progname);
122 printf("\n");
123 printf("examples:\n");
124 printf(" %s file1.iso --- convert file1.iso to file1.aff\n",progname);
125 printf(" %s file1.iso file2.iso file3.iso... --- batch convert files\n",progname);
126 printf(" %s -r -e iso image.aff --- convert image.aff to image.iso\n",progname);
127 printf(" %s -M4g -o/media/dvd.afd bigfile.aff --- split an AFF file into 4GB chunks for archiving to DVD\n",
128 progname);
129 //printf(" %s -p image.aff --- recompress image.aff to maximum compression\n",progname);
130 printf("\n");
131 printf("\nGeneral options:\n");
132 printf(" -q -- Quiet mode. Don't ask questions, don't print status.\n");
133
134 printf("\nAFF output options:\n");
135 printf(" -a ext -- use 'ext' for aff files (default is %s)\n",opt_aff_ext);
136 printf(" (use .afd for AFD files)\n");
137 printf(" -Mn[kgm] -- set maximum size of output file. Suffix with g, m or k.\n");
138 printf(" -sn -- set the image_pagesize (default %d)\n",image_pagesize);
139 printf(" -x -- don't compress AFF file.\n");
140 printf(" -O dir -- use 'dir' as the output directory\n");
141 printf(" -o file -- output to 'file' (can only convert one at a time)\n");
142 printf(" File is AFF is file ends .aff; otherwise assumes raw.\n");
143 printf(" -Xn -- Set compression to n; default is 7\n");
144 printf(" -L -- Use the LZMA compression algorithm (better but slower)\n");
145
146 printf("\nRaw output options:\n");
147 printf(" -r -- force raw output. \n");
148 printf(" -e ext -- use 'ext' for the raw files (default %s)\n",opt_write_raw_ext);
149 printf(" (implies -r)\n");
150
151 printf("\nDangerous input options:\n");
152 printf(" -z -- zap; delete the output file if it already exists.\n");
153 printf(" -Z -- Do not automatically probe for gzip/bzip2 compression.\n");
154 printf(" -y -- Always answer yes/no questions 'yes.'\n");
155 printf(" -V = Just print the version number and exit.\n");
156 printf("\n");
157 exit(0);
158 }
159
160
161 /* probe_gzip():
162 * Is this a gzip file?
163 * Right now it just looks at the file extension.
164 */
165
166 int probe_gzip(const char *infile)
167 {
168 int len = strlen(infile);
169
170 if(len>3 && strcmp(infile+len-3,".gz")==0){
171 return 1;
172 }
173 return 0;
174 }
175
176 int probe_bzip2(const char *infile)
177 {
178 int len = strlen(infile);
179
180 if(len>4 && strcmp(infile+len-4,".bz2")==0){
181 return 1;
182 }
183 return 0;
184 }
185
186 /* yesno():
187 * As a yes/no question. Return 1 if yes, 0 if no.
188 */
189
190 int yesno(const char *statement,const char *question,const char *affirmative)
191 {
192 if(opt_yes){
193 if(!opt_quiet) printf("%s. %s.\n",statement,affirmative);
194 return 1;
195 }
196
197 printf("%s. ",statement);
198 char buf[256];
199 do {
200 printf("%s [y/n]: ",question);
201 memset(buf,0,sizeof(buf));
202 if(fgets(buf,sizeof(buf)-1,stdin)==0) return 0;
203 if(buf[0]=='y' || buf[0]=='Y'){
204 printf("%s.\n",affirmative);
205 return 1;
206 }
207 } while(buf[0]!='n' && buf[0]!='N');
208 return 0;
209 }
210
211
212 /*
213 * Basic conversion:
214 * We have an input, which may be raw or aff,
215 * and we have an output, which may be raw or aff.
216 * We are going to want to read a segment at a time.
217 */
218
219
220 #include <algorithm>
221 #include <cstdlib>
222 #include <vector>
223 #include <string>
224
225 #ifdef HAVE_CSTRING
226 #include <cstring>
227 #endif
228
229
230 using namespace std;
231
232 /** Do the conversion.
233 * return 0 if success, code if fail.
234 */
235 int convert(const char *infile,char *outfile)
236 {
237
238 if(opt_debug) fprintf(stderr,"convert(%s,%s)\n",infile,outfile);
239
240 if(infile && outfile && strcmp(infile,outfile)==0){
241 errx(1,"Can't convert a file to itself\n");
242 }
243
244 /****************************************************************
245 *** Open Input
246 ****************************************************************/
247
248 AFFILE *a_in = 0; // input file, if aff
249
250 #ifdef UNIX
251 /* Check to see if it is a gzip file... */
252 if(opt_probe_compressed
253 && probe_gzip(infile)
254 && yesno("infile looks like a gzip file","Uncompress it","Uncompressing")){
255 /* Open with a subprocess. We will need to use zlib when we move to Windows. */
256 if(af_hasmeta(infile)) return -1; // don't covert with shell metacharacters
257 char buf[256];
258 snprintf(buf,sizeof(buf),"gzcat %s",infile);
259 a_in = af_popen(buf,"r");
260 }
261
262 /* Check to see if it is a bzip2 file... */
263 if(!a_in
264 && opt_probe_compressed
265 && probe_bzip2(infile)
266 && yesno("infile looks like a bzip2 file","Uncompress it","Uncompressing")){
267 /* Open with a subprocess. We will need to use bzip2zlib when we move to Windows. */
268 if(af_hasmeta(infile)) return -1; // don't covert with shell metacharacters
269 char buf[256];
270 snprintf(buf,sizeof(buf),"bzcat %s",infile);
271 a_in = af_popen(buf,"r");
272 }
273 #endif
274
275 /* If the file isn't open, try to open it... */
276 if(!a_in){
277 a_in = af_open(infile,O_RDONLY,0);
278 if(!a_in) af_err(1,"%s",infile); // give up
279 if(af_identify(a_in)==AF_IDENTIFY_RAW){
280 af_set_pagesize(a_in,image_pagesize); // match the page size we want to use
281 }
282 else {
283 image_pagesize = a_in->image_pagesize; // that's what we are using
284 }
285 }
286
287 const char *ain_fn = af_filename(a_in);
288 struct stat si;
289 memset((char *)&si,0,sizeof(si));
290 if(ain_fn && stat(ain_fn,&si)){
291 warn("Cannot stat %s",ain_fn);
292 }
293
294
295 /****************************************************************
296 *** Open Ouptut
297 ****************************************************************/
298
299
300 if(opt_zap) unlink(outfile); // we were told to zap it
301
302 AFFILE *a_out = 0; // output file, if aff or raw...
303 if(access(outfile,F_OK)==0){
304 /* If outfile is a device, ask user... */
305 struct stat so;
306 if(stat(outfile,&so)){
307 err(1,"%s exists but can't be stat?",outfile);
308 }
309 if((so.st_mode & S_IFMT)==S_IFCHR ||
310 (so.st_mode & S_IFMT)==S_IFBLK){
311 char buf[1024];
312 snprintf(buf,sizeof(buf),"%s is a raw device.\n",outfile);
313 if(yesno(buf,"Overwrite raw device?","yes")){
314 goto doit;
315 }
316 }
317 fprintf(stderr,"%s: file exists. Delete it before converting.\n",outfile);
318 exit(-1);
319 }
320 /* Check for splitraw names */
321 if(af_ext_is(outfile,"afm")){
322 char file000[MAXPATHLEN+1];
323 strlcpy(file000,outfile,sizeof(file000));
324 char *cc = strrchr(file000,'.');
325 if(!cc) err(1,"Cannot file '.' in %s\n",file000);
326 for(int i=0;i<2;i++){
327 sprintf(cc,".%03d",i);
328 if(access(file000,F_OK)==0){
329 fprintf(stderr,"%s: file exists. Delete it before converting.\n",file000);
330 fprintf(stderr,"NOTE: -z option will not delete %s\n",file000);
331 return -1;
332 }
333 }
334 }
335
336 doit:;
337
338 if(opt_write_raw){
339 /* Easy way to make a raw output is to reopen an existing output file... */
340 FILE *f = fopen(outfile,"w+b");
341 if(!f){
342 err(1,"%s",outfile);
343 }
344 a_out = af_freopen(f);
345 }
346 else {
347 a_out = af_open(outfile,O_RDWR|O_CREAT|O_BINARY,0777);
348 if(!a_out) af_err(1,"%s",outfile);
349 if(opt_maxsize){
350 af_set_maxsize(a_out,opt_maxsize);
351 }
352
353 }
354 if(a_out == 0) af_err(1,"af_open: %s",outfile);
355
356 if(!opt_quiet) printf("convert %s --> %s\n",infile,outfile);
357
358 af_update_seg(a_out,AF_ACQUISITION_COMMAND_LINE,0,
359 (const u_char *)command_line.c_str(),
360 command_line.size());
361
362 /****************************************************************
363 *** Set up the AFF file (assuming it's an aff file)
364 *** stuff that we keep at the beginning of the file...
365 ****************************************************************/
366
367 MD5_CTX md5;
368 MD5_Init(&md5);
369
370 SHA_CTX sha;
371 SHA1_Init(&sha);
372
373 /* Setup writing */
374 if(a_in->image_pagesize){
375 image_pagesize = a_in->image_pagesize;
376 }
377 af_set_pagesize(a_out,image_pagesize);
378 af_set_sectorsize(a_out,a_in->image_sectorsize);
379
380 struct af_vnode_info vni;
381 af_vstat(a_out,&vni);
382 if(vni.supports_compression){
383 if(opt_compression_alg){
384 af_enable_compression(a_out,opt_compression_alg,opt_compress_level);
385 }
386 else{
387 af_enable_compression(a_out,0,0);
388 }
389 }
390
391 /* Get a list of all the metadata segments and the pages
392 * (if this is a raw file, then the vnode raw driver will give us those segments)
393 */
394
395 char segname[AF_MAX_NAME_LEN];
396 vector <string> metadata_segments;
397 vector <int64_t> pages;
398 af_rewind_seg(a_in); // start at the beginning
399 int64_t highest_pagenum = 0;
400 while(af_get_next_seg(a_in,segname,sizeof(segname),0,0,0)==0){
401 int64_t page_num = af_segname_page_number(segname);
402 if(page_num>=0){
403 pages.push_back(page_num);
404 if(page_num>highest_pagenum) highest_pagenum = page_num;
405 }
406 else {
407 metadata_segments.push_back(segname);
408 }
409 }
410
411 /* Copy over all of the metadata segments.
412 * But don't bother if we are creating raw output
413 */
414 if(opt_write_raw==0){
415 for(vector<string>::iterator i = metadata_segments.begin();
416 i != metadata_segments.end();
417 i++){
418 strlcpy(segname,i->c_str(),sizeof(segname));
419 size_t data_len = 0;
420 unsigned long arg;
421
422 /* First find out how big the segment is */
423 if(af_get_seg(a_in,segname,&arg,0,&data_len)){
424 warn("af_get_seg_1");
425 continue;
426 }
427 /* Now get the data */
428 unsigned char *data = (unsigned char *)malloc(data_len);
429 if(af_get_seg(a_in,segname,0,data,&data_len)){
430 warn("af_get_seg_2");
431 free(data);
432 continue;
433 }
434 /* Now put the data */
435 if(af_update_seg(a_out,segname,arg,data,data_len)){
436 err(1,"af_update_seg");
437 }
438 free(data);
439 }
440 }
441
442 /* Now sort the pages and copy them over. If there is no break,
443 * we can compute the hashes...
444 */
445 sort(pages.begin(),pages.end());
446
447 int64_t prev_pagenum = -1;
448 bool hash_valid = true;
449 uint64_t last_byte_in_image = 0;
450 uint64_t total_bytes_converted = 0;
451
452 bool copy_by_pages = af_has_pages(a_in);
453
454 unsigned char *data = (unsigned char *)malloc(image_pagesize);
455 if(copy_by_pages){
456 /* Copy over data one page at a time */
457 for(vector<int64_t>::iterator i = pages.begin(); i != pages.end(); i++){
458
459 int64_t pagenum = *i;
460
461 if(!opt_quiet) printf("Converting page %"I64d" of %"I64d"\r",pagenum,highest_pagenum);fflush(stdout);
462
463 size_t data_len = image_pagesize;
464 if(af_get_page(a_in,pagenum,data,&data_len)){
465 err(1,"af_get_page(file=%s,page=%"I64d")",
466 af_filename(a_in),pagenum);
467 }
468 if(af_update_page(a_out,pagenum,data,data_len)){
469 err(1,"af_update_page(file=%s,page=%"I64d")",
470 af_filename(a_out),pagenum);
471 }
472
473 if(pagenum != prev_pagenum + 1) hash_valid = false;
474
475 if(hash_valid && vni.supports_metadata){
476 MD5_Update(&md5,data,data_len);
477 SHA1_Update(&sha,data,data_len);
478 prev_pagenum = pagenum;
479 }
480 last_byte_in_image = (int64_t)image_pagesize * pagenum + (int64_t)data_len;
481 total_bytes_converted += data_len;
482 }
483 /* Go back and update the image size (necessary since I have been writing page-by-page) */
484 if(af_update_segq(a_out,AF_IMAGESIZE,last_byte_in_image)
485 && errno!=ENOTSUP){
486 err(1,"Could not upate AF_IMAGESIZE");
487 }
488 } else {
489 /* No page support; Copy from beginning to end */
490 while(!af_eof(a_in)){
491 int data_len = af_read(a_in,data,image_pagesize);
492 if(data_len>0){
493 if(!opt_quiet){
494 printf("Writing to page %" I64d " with %d bytes read from input... \r",
495 total_bytes_converted / image_pagesize,data_len);
496 fflush(stdout);
497 }
498 if(af_write(a_out,data,data_len)!=data_len){
499 err(1,"af_write");
500 }
501 if(vni.supports_metadata){
502 MD5_Update(&md5,data,data_len);
503 SHA1_Update(&sha,data,data_len);
504 }
505 }
506 if(data_len<0) err(1,"af_read");
507 if(data_len==0){
508 if(!opt_quiet) printf("af_read returned 0. Reached a sparse region or end of pipe.\n");
509 break;
510 }
511 last_byte_in_image += data_len;
512 total_bytes_converted += data_len;
513 }
514 }
515 free(data);
516 if(!opt_quiet) printf("\n");
517
518 /* Write out the new hash if it is valid */
519 if(hash_valid && vni.supports_metadata){
520 u_char md5_buf[32],sha1_buf[40];
521 char buf[256];
522 MD5_Final(md5_buf,&md5);
523 if(af_update_seg(a_out,AF_MD5,0,md5_buf,16) && errno!=ENOTSUP){
524 err(1,"Could not update AF_MD5");
525 }
526 if(!opt_quiet) printf("md5: %s\n",af_hexbuf(buf,sizeof(buf),md5_buf,16,1));
527
528 SHA1_Final(sha1_buf,&sha);
529 if(af_update_seg(a_out,AF_SHA1,0,sha1_buf,20) && errno!=ENOTSUP){
530 err(1,"Could not update AF_SHA1");
531 }
532 if(!opt_quiet) printf("sha1: %s\n",af_hexbuf(buf,sizeof(buf),sha1_buf,20,1));
533 }
534
535 /* Finish the hash calculations and write to the db */
536 if(!opt_quiet){
537 printf("bytes converted: %"I64d" \n",total_bytes_converted);
538 /* If the vnode implementation tracked segments written, report it. */
539 if(a_out->pages_written || a_out->pages_compressed){
540 printf("Total pages: %"I64u" (%"I64u" compressed)\n",
541 a_out->pages_written,a_out->pages_compressed);
542 }
543 }
544
545 if(vni.supports_metadata){
546 /* make an AF_IMAGE_GID if it doesn't exist */
547 af_make_gid(a_out);
548 af_set_acquisition_date(a_out,si.st_mtime);
549 }
550
551 /* Make a copy of the a_out filename if we can get it */
552 char *a_out_fn=0; // output filename, to remember for utimes
553 const char *a_ = af_filename(a_out); // remember the output filename
554 if(a_){
555 a_out_fn = strdup(a_); // make a copy of it
556 }
557 if(af_close(a_out)) err(1,"af_close(a_out)");
558
559 if(!opt_quiet){
560 printf("Conversion finished.\n");
561 if(af_cannot_decrypt(a_in)){
562 printf("*** encrypted pages are present which could not be decrypted ***\n");
563 }
564 printf("\n\n");
565 }
566 if(af_close(a_in)) err(1,"af_close(a_in)");
567
568 /* Set the utime on the resulting file if we can stat it */
569 struct timeval times[2];
570
571 memset(times,0,sizeof(times));
572 times[0].tv_sec = si.st_atime;
573 times[1].tv_sec = si.st_mtime;
574 #ifdef HAVE_UTIMES
575 if(a_out_fn){
576 if(utimes(a_out_fn,times)) warn("utimes(%s):",outfile);
577 free(a_out_fn);
578 a_out_fn = 0;
579 }
580 #endif
581 return(0);
582 }
583
584
585 int64_t atoi64(const char *buf)
586 {
587 int64_t r=0;
588 sscanf(buf,"%"I64d,&r);
589 return r;
590 }
591
592 int64_t atoi64m(const char *optarg)
593 {
594 int multiplier;
595 switch(optarg[strlen(optarg)-1]){
596 case 'g':
597 case 'G':
598 multiplier=1024*1024*1024;break;
599 case 'm':
600 case 'M':
601 multiplier=1024*1024; break;
602 case 'k':
603 case 'K':
604 multiplier=1024; break;
605 case 'b':
606 case 'B':
607 multiplier=1;break;
608 default:
609 err(1,"Specify multiplier units of g, m, k or b in '%s'\n",optarg);
610 }
611 return atoi64(optarg) * multiplier;
612 }
613
614
615 int main(int argc,char **argv)
616 {
617 char *outfile = 0;
618 int ch;
619
620 command_line = aff::command_line(argc,argv);
621 while ((ch = getopt(argc, argv, "a:e:Lo:zqrs:xX:Zh?M:O::ydV")) != -1) {
622 switch (ch) {
623 case 'a':
624 opt_aff_ext = optarg;
625 break;
626 case 'e':
627 opt_write_raw++;
628 opt_write_raw_ext = optarg;
629 break;
630 case 'o':
631 outfile = optarg;
632 break;
633 case 'z':
634 opt_zap ++;
635 break;
636 case 'q':
637 opt_quiet++;
638 break;
639 case 'L':
640 opt_compression_alg = AF_COMPRESSION_ALG_LZMA;
641 break;
642 case 'r':
643 opt_write_raw++;
644 break;
645 case 's':
646 image_pagesize = atoi64m(optarg);
647 break;
648 case 'x':
649 opt_compression_alg=AF_COMPRESSION_ALG_NONE;
650 break;
651 case 'X':
652 opt_compress_level = atoi(optarg);
653 break;
654 case 'Z':
655 opt_probe_compressed = 0;
656 break;
657 case 'y':
658 opt_yes = 1;
659 break;
660 case 'M':
661 opt_maxsize = atoi64m(optarg);
662 break;
663 case 'O':
664 if(!optarg) err(1,"-O flag requires a directory");
665 opt_outdir = optarg;
666 break;
667 case 'd':
668 opt_debug++;
669 break;
670 case 'h':
671 case '?':
672 default:
673 usage();
674 exit(0);
675 case 'V':
676 printf("%s version %s\n",progname,PACKAGE_VERSION);
677 exit(0);
678
679 }
680 }
681 argc -= optind;
682 argv += optind;
683
684 if(argc<1){
685 usage();
686 }
687
688 if(outfile){
689 return convert(*argv,outfile);
690 }
691
692 /* Check for "-o filename" at the end of the command line... */
693 if(argc==3 && !strcmp(argv[1],"-o")){
694 return convert(argv[0],argv[2]);
695 }
696
697 /* Convert each file*/
698
699 while(*argv){
700 char outfile[MAXPATHLEN+1];
701 memset(outfile,0,sizeof(outfile));
702
703 const char *ext = opt_write_raw ? opt_write_raw_ext : opt_aff_ext;
704 char *infile = *argv;
705 argv++;
706 argc--;
707
708 /* Copy over the filename and change the extension */
709 strlcpy(outfile,infile,sizeof(outfile));
710 char *cc = strrchr(outfile,'.'); // to strip off extension
711 if(cc){
712 /* Found an extension; copy over mine. */
713 strlcpy(cc+1,ext,sizeof(outfile)-(cc-outfile));
714 }
715 else {
716 /* No extension; make one */
717 strlcat(outfile,".",sizeof(outfile));
718 strlcat(outfile,ext,sizeof(outfile));
719 }
720
721 /* The user might want us to put things
722 * in a different directory. Pull off the filename...
723 */
724 if(opt_outdir){
725 cc = strrchr(outfile,'/');
726 char filename[PATH_MAX];
727 if(cc){
728 strlcpy(filename,cc+1,sizeof(filename)); // just the filename
729 }
730 else{
731 strlcpy(filename,outfile,sizeof(filename)); // the outfile is the filename
732 }
733 strlcpy(outfile,opt_outdir,sizeof(outfile));
734 strlcat(outfile,"/",sizeof(outfile));
735 strlcat(outfile,filename,sizeof(outfile));
736 }
737 if(convert(infile,outfile)){
738 exit(1);
739 }
740 }
741 exit(0);
742 }
+0
-708
tools/afcopy.cpp less more
0 /*
1 * afcopy.cpp:
2 *
3 * Copy one AFF file to another.
4 * Resulting file is re-ordered and possibly re-compressed.
5 */
6
7 /*
8 * Copyright (c) 2006
9 * Simson L. Garfinkel
10 * All rights reserved.
11 *
12 * This code is derrived from software contributed by
13 * Simson L. Garfinkel
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 * 3. [Omitted]
24 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
25 * contributors to this program may be used to endorse or promote
26 * products derived from this software without specific prior written
27 * permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL AND CONTRIBUTORS ``AS
30 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SIMSON
33 * GARFINKEL, BAIS TECHNOLOGy, OR CONTRIBUTORS BE LIABLE FOR ANY
34 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
36 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
38 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
39 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 */
42
43
44 #include "affconfig.h"
45 #include "afflib.h"
46 #include "afflib_i.h"
47 #include "utils.h"
48 #include "base64.h"
49 #include "aff_bom.h"
50
51 using namespace std;
52 using namespace aff;
53
54 #ifdef HAVE_SYS_SIGNAL_H
55 #include <sys/signal.h>
56 #endif
57
58 #ifdef HAVE_TIME_H
59 #include <time.h>
60 #endif
61
62 #ifdef HAVE_SYS_TIME_H
63 #include <sys/time.h>
64 #endif
65
66 #include <ctype.h>
67 #include <zlib.h>
68 #include <openssl/md5.h>
69 #include <openssl/sha.h>
70 #include <assert.h>
71
72 #ifdef HAVE_UNISTD_H
73 #include <unistd.h>
74 #endif
75
76 #ifdef HAVE_TERM_H
77 #include <term.h>
78 #endif
79
80 #ifdef HAVE_NCURSES_TERM_H
81 #include <ncurses/term.h>
82 #endif
83
84 #ifdef WIN32
85 #include "unix4win32.h"
86 #endif
87
88 const char *progname = "afcopy";
89
90 int opt_verbose = 0;
91 int opt_debug = 0;
92 int opt_x = 0;
93 int opt_X = AF_COMPRESSION_DEFAULT;
94 int opt_noverify = 0;
95 int opt_preen = 0;
96 int opt_zap =0;
97 int opt_missing = 0;
98 int opt_preen_alg_arg = 0; // algorithm for recompressing
99 int opt_preen_alg_flag = 0;
100 int opt_sign = 0;
101
102 int opt_note = 0;
103 const char *opt_sign_key_file = 0;
104 const char *opt_sign_cert_file = 0;
105
106 void usage()
107 {
108 printf("%s version %s\n",progname,PACKAGE_VERSION);
109 printf("usage: %s [options] file1 file\n",progname);
110 printf(" Copies file1 to file2\n");
111 printf(" %s [options] file1 file2 file3 ... dir\n",progname);
112 printf(" Copies file1.. into dir\n");
113 printf(" %s [options] file1 file2 file3 ... dir1 dir2...\n",progname);
114 printf(" Copies file1.. into dirs1, dir2, ...\n");
115 printf("\n");
116 printf("By default, all page MACs are verified on read and all segments\n");
117 printf("are verified after write.\n");
118
119 printf("Options:\n");
120 printf(" -v = verbose: print each file as it is copied\n");
121 printf(" -vv = very verbose: print each segment as it is copied\n");
122 printf(" -d = print debugging information as well\n");
123 printf(" -x = don't verify hashes on reads\n");
124 printf(" -y = don't verify writes\n");
125 printf(" -Xn = recompress pages (preen) with zlib level n\n");
126 printf(" -L = recompress pages (preen) with LZMA (smaller but slower)\n");
127 printf("\n");
128 printf(" -h = help; print this message.\n");
129 printf(" -V = print the program version and exit.\n");
130 printf(" -z = zap; copy even if the destination exists.\n");
131 printf(" -m = just copy the missing segments\n");
132 printf("\nSignature Options:\n");
133 printf(" -k filename.key = specify private key for signing\n");
134 printf(" -c filename.cer = specify a X.509 certificate that matches the private key\n");
135 printf(" (by default, the file is assumed to be the same one\n");
136 printf(" provided with the -k option.)");
137 printf(" -n = read notes to accompany the copy from standard in.\n");
138 printf("\n");
139 printf("\nEncryption Options:");
140 printf(" Specify passphrase encryption for filename.aff with:\n");
141 printf(" file://:passphrase@/filename.aff\n");
142 printf("\n");
143 printf("Examples:\n");
144 printf(" %s file.aff file://:mypassword@/file-encrypted.aff - encrypt file.aff\n",progname);
145 #ifdef USE_S3
146 printf(" %s -vy -X9 *.aff s3:/// Copy all files in current\n",progname);
147 printf(" directory to S3 default bucket with X9 compression\n");
148 #endif
149 exit(1);
150 }
151
152
153 const char *current_source = 0;
154 const char *current_dest = 0;
155 const char *current_seg = 0;
156 void sig_info(int arg)
157 {
158 if(current_source){
159 printf("Copying %s ",current_source);
160 if(current_dest){
161 printf("--> %s",current_dest);
162 if(current_seg) printf(" (%s) ",current_seg);
163 }
164 }
165 printf("\n");
166 }
167
168
169 void unlink_outfiles(vector<string> outfiles)
170 {
171 int failure=0;
172 for(vector<string>::const_iterator o = outfiles.begin();
173 o != outfiles.end();
174 o++){
175 char *protocol=0;
176 char *path = 0;
177 af_parse_url(o->c_str(),&protocol,0,0,0,0,&path);
178 if(strcmp(protocol,"file")==0){
179 unlink(path);
180 }
181 else{
182 fprintf(stderr,"Cannot unlink %s\n",o->c_str());
183 failure=1;
184 }
185 if(protocol) free(protocol);
186 if(path) free(path);
187 }
188 if(failure) exit(1);
189 }
190
191 #if !defined( __BSD_VISIBLE) && !defined(isnumber)
192 #define isnumber(x) isdigit(x)
193 #endif
194
195 #ifdef WIN32
196 #include <windows.h>
197 #include <windowsx.h>
198 int gettimeofday (struct timeval *tv, void* tz)
199 {
200 union {
201 int64_t ns100; /*time since 1 Jan 1601 in 100ns units */
202 FILETIME ft;
203 } now;
204
205 GetSystemTimeAsFileTime (&now.ft);
206 tv->tv_usec = (long) ((now.ns100 / 10LL) % 1000000LL);
207 tv->tv_sec = (long) ((now.ns100 - 116444736000000000LL) / 10000000LL);
208 return (0);
209 }
210 #endif
211
212 void open_outfiles(AFFILE *ain,outlist &afouts,const vector<string> &outfiles)
213 {
214 /* Open every output file */
215 for(vector<string>::const_iterator o = outfiles.begin();
216 o != outfiles.end(); o++){
217
218 const char *outfilename = o->c_str();
219 outelement out;
220
221 /* First see if the output file exists */
222 out.af = 0;
223 int ident = af_identify_file_type(outfilename,1);
224 if(ident!=AF_IDENTIFY_NOEXIST){
225 fprintf(stderr,"%s: file exists... ",outfilename);
226 if(opt_zap==0 && opt_missing==0){
227 fprintf(stderr,"\n Will not overwrite; use -m or -z\n");
228 continue;
229 }
230 if(opt_missing){
231 fprintf(stderr,"Will fill in missing segments...\n");
232 out.af = af_open(outfilename,O_RDWR|O_EXCL,0666);
233 if(!out.af) af_err(1,outfilename);
234 if(af_page_size(ain) != af_page_size(out.af)){
235 fprintf(stderr,"%s and %s have different page sizes (%d != %d)\n",
236 af_filename(ain),
237 af_filename(out.af),
238 af_page_size(ain),
239 af_page_size(out.af));
240 af_close(out.af);
241 out.af=0;
242 continue;
243 }
244 }
245 }
246
247
248
249 if(out.af==0){
250 out.af = af_open(outfilename,O_RDWR|O_EXCL|O_CREAT,0666);
251 if(!out.af){
252 warn("%s",outfilename);
253 continue;
254 }
255 if(af_set_pagesize(out.af,af_page_size(ain))){
256 errx(1,"%s: cannot set page size to %d\n", af_filename(out.af),af_page_size(ain));
257 }
258 }
259 if(o != outfiles.begin()) printf("\t ");
260 if(opt_verbose){
261 printf(" => %s ",outfilename);
262 if(opt_preen) printf(" (preening) ");
263 printf("\n");
264 }
265 if(opt_missing) out.segs.get_seglist(out.af);
266 afouts.push_back(out);
267 }
268 }
269
270 /* Copy pagenumber from ain to aout.
271 * Return 0 if success, -1 if can't do it.
272 * Properly handles signing and preening if requested.
273 */
274 int copy_page(AFFILE *ain,AFFILE *aout,int64_t pagenum,unsigned long arg,u_char *seghash,u_int *seghash_len)
275 {
276 /* If we are preening but not signing, see if we can get out fast */
277 if(opt_sign==0 && opt_preen==0) return -1; // not preening and not signing
278
279 /* If we are not signing, don't bother decompressing and recompressing*/
280 if(opt_sign==0 && opt_preen){
281 int alg = (arg & AF_PAGE_COMP_ALG_MASK);
282 if(alg==AF_PAGE_COMP_ALG_ZERO) return -1; // don't preen ZERO
283 if(alg==opt_preen_alg_arg) return -1; // don't decompress then re-compress with old alg
284 }
285
286 /* If we get here, page must be read into memory and decompressed */
287 size_t pagesize = af_page_size(ain);
288 if(pagesize<=0) return -1; // couldn't get pagesize
289
290 u_char *pagebuf = (unsigned char *)malloc(pagesize);
291 if(!pagebuf) return -1; // couldn't allocate memory for page?
292
293 if(af_get_page(ain,pagenum,pagebuf,&pagesize)){ // note --- this may make pagesize smaller
294 free(pagebuf);
295 return -1;
296 }
297
298 if(opt_preen){ // set compression if we are preening
299 af_enable_compression(aout,opt_preen_alg_flag,opt_X);
300 }
301
302 #ifdef USE_AFFSIGS
303 /* If calculating a bom, calculate the bom! */
304 if(opt_sign){
305 char segname[AF_MAX_NAME_LEN];
306 sprintf(segname,AF_PAGE,pagenum);
307 aff_bom::make_hash(seghash,arg,segname,pagebuf,pagesize);
308 }
309 #endif
310
311 /* Write out the page */
312 int ret = af_update_page(aout,pagenum,pagebuf,pagesize);
313 free(pagebuf);
314 return ret;
315 }
316
317 string base64(const u_char *buf,size_t buflen)
318 {
319 size_t len = buflen*2+1;
320 char *str = (char *)malloc(len);
321 b64_ntop(buf,buflen,str,len);
322 string ret = string(str);
323 free(str);
324 return ret;
325 }
326
327 #ifndef HAVE_ISATTY
328 int isatty(int fd)
329 {
330 return 1; // have to assume it's a tty
331 }
332 #endif
333
334 int afcopy(char *infile,vector<string> &outfiles)
335 {
336 #ifdef SIGINFO
337 signal(SIGINFO,sig_info);
338 #endif
339 hashMapT hashMap;
340
341 /* Open the input file */
342 AFFILE *ain = af_open(infile,O_RDONLY,0);
343 if(opt_debug) printf("af_open(%s,O_RDONLY)=%p\n",infile,ain);
344 if(!ain) af_err(1,"%s",infile);
345 seglist segments(ain);
346
347 if(opt_zap) unlink_outfiles(outfiles);
348
349 outlist afouts; // vector of output AFFs
350 vector<int64_t>preened_pages;
351 open_outfiles(ain,afouts,outfiles);
352
353 /* Now, try to open the output files, to see if they exist */
354 current_source = infile;
355 if(opt_verbose) printf("%s: ",infile);
356 if(opt_verbose>1) putchar('\n');
357
358 /* If we couldn't open any output files, return */
359 if(afouts.size()==0){
360 af_close(ain); // close the input file
361 return -1;
362 }
363
364 #ifdef USE_AFFSIGS
365 /* If we are signing, initialize the signing machinery */
366 aff_bom bom(opt_note);
367 if(opt_sign){
368 if(bom.read_files(opt_sign_cert_file,opt_sign_key_file)){
369 opt_sign = 0; // can't sign
370 }
371 }
372 #endif
373
374 /* Now the files are open. For each output file:
375 * 1. Initialize signing if options were set and the segments aren't already signed.
376 * 2. Sign all of the segments that are unsigned
377 */
378 for(outlist::iterator aout = afouts.begin(); aout != afouts.end(); aout++){
379 if(opt_sign_key_file && segments.has_signed_segments()==false){
380 if(af_set_sign_files(aout->af,opt_sign_key_file,opt_sign_cert_file)){
381 err(1,"%s",opt_sign_key_file);
382 }
383 af_sign_all_unsigned_segments(aout->af);
384 opt_sign = true;
385 }
386 }
387
388 /* Start the copying */
389 struct timeval t0,t1;
390 gettimeofday(&t0,0);
391 for(seglist::const_iterator seg = segments.begin(); seg!= segments.end();seg++){
392 /* For each segment, get the size of the segment */
393 const char *segname = seg->name.c_str();
394 current_seg = segname; // for printing
395 size_t seglen=0;
396
397 if(af_get_seg(ain,segname,0,0,&seglen)){
398 unlink_outfiles(outfiles);
399 err(1,"Cannot read length of segment '%s' on input file %s", segname,af_filename(ain));
400 }
401 unsigned char *segbuf = (unsigned char *)malloc(seglen);
402 if(!segbuf){
403 unlink_outfiles(outfiles);
404 err(1,"Cannot allocated %d bytes for segment '%s' in %s",
405 (int)seglen,segname,af_filename(ain));
406 }
407
408 /* Now get the raw source segment */
409 unsigned long arg=0;
410 if(af_get_seg(ain,segname,&arg,segbuf,&seglen)){
411 unlink_outfiles(outfiles); // failure; unlink the output files
412 err(1,"Cannot read segment '%s' in %s. Deleteing output file", segname,af_filename(ain));
413 }
414
415 /* Calculate the MD5 of this segment and remember it in the map */
416 md5blob md5;
417 MD5(segbuf,seglen,md5.buf);
418 hashMap[segname] = md5;
419
420 /* See if this is a page; if so, it is handled specially */
421 int64_t pagenumber = af_segname_page_number(segname);
422
423 /* Write the segment to each file */
424 for(outlist::iterator aout = afouts.begin(); aout != afouts.end(); aout++){
425 current_dest = af_filename(aout->af);
426 if(opt_verbose>1 || opt_debug){
427 if(aout != afouts.begin()) printf("\n ");
428 printf(" %s -> %s:%s ...", segname,af_filename(aout->af),segname);
429 }
430
431 /** COPY THE DATA **/
432
433 u_char seghash[32]; /* resultant message digest; could be any size */
434 unsigned int seghash_len = sizeof(seghash); /* big enough to hold SHA256 */
435 int sigmode = AF_SIGNATURE_MODE0;
436
437 memset(seghash,0,sizeof(seghash));
438
439 bool copied = false;
440
441 /* If we are preening, signing, or building a ToC, we need to copy the raw page */
442 if(pagenumber>=0 && (opt_preen || opt_sign_key_file)){
443 if(copy_page(ain,aout->af,pagenumber,arg,seghash,&seghash_len)==0){
444 preened_pages.push_back(pagenumber); // preened pages won't be verified by md5
445 if(opt_debug && opt_preen) printf(" (PREENED) ");
446 sigmode = AF_SIGNATURE_MODE1;
447 copied = true;
448 }
449 }
450
451 /* Copy the page if it is not in the destination */
452 if(copied==false){
453 if(!aout->segs.contains(segname)){
454 if(af_update_seg(aout->af,segname,arg,segbuf,seglen)){
455 unlink_outfiles(outfiles);
456 err(1,"Cannot write segment '%s' to %s.", segname,af_filename(aout->af));
457 }
458
459 #ifdef USE_AFFSIGS
460 if(opt_sign){
461 aff_bom::make_hash(seghash,arg,segname,segbuf,seglen);
462 }
463 #endif
464 }
465 else{
466 if(opt_verbose>1 || opt_debug) printf(" [already in %s] ",af_filename(aout->af));
467 }
468 }
469 #ifdef USE_AFFSIGS
470 if(opt_sign) bom.add(segname,sigmode,seghash,seghash_len);
471 #endif
472 }
473 free(segbuf);
474 current_dest = 0;
475 if(opt_verbose>1 || opt_debug) putchar('\n');
476 }
477 current_seg = 0;
478
479 #ifdef USE_AFFSIGS
480 /* For each open file, make an AF_IMAGE_GID if one doesn't exist */
481 for(outlist::iterator aout = afouts.begin(); aout != afouts.end(); aout++){
482 if(af_make_gid(aout->af)>0){
483 if(opt_sign){
484 af_sign_seg(aout->af,AF_IMAGE_GID); // make sure the GID is signed
485 bom.add(aout->af,AF_IMAGE_GID);
486 bom.add(aout->af,AF_IMAGE_GID AF_SIG256_SUFFIX);
487
488 }
489 }
490 }
491
492 if(opt_sign){
493 bom.close();
494 /* Now write to each of the output files */
495 for(outlist::iterator aout = afouts.begin(); aout != afouts.end(); aout++){
496 bom.write(aout->af,segments);
497 }
498 }
499 #endif
500
501 gettimeofday(&t1,0);
502 if(afouts.size()==1){
503 AFFILE *af = afouts.begin()->af;
504 uint64_t w = af->bytes_written;
505 double sec = ((t1.tv_sec-t0.tv_sec)+(t1.tv_usec-t0.tv_usec)/1000000.0);
506 printf("%s: %"I64d" bytes transfered in %.2f seconds. xfer rate: %.2f MBytes/sec\n",
507 af_filename(af),w,sec,(w/1000000.0) / sec);
508 }
509
510 if(opt_noverify==0){
511 current_seg = "VERIFYING";
512 /* Now verify all of the hashes */
513 if(opt_verbose || opt_debug) printf("\n\nFiles copied. Verifying...\n");
514 for(seglist::const_iterator seg = segments.begin(); seg!= segments.end();seg++){
515
516 const char *segname = seg->name.c_str();
517 for(outlist::iterator aout = afouts.begin(); aout != afouts.end(); aout++){
518 size_t seglen=0;
519 char b2[1024];
520
521 if((aout->af)->v->flag & AF_VNODE_TYPE_RELIABLE){
522 continue; // no need to verify a reliable write
523 }
524 if(opt_verbose>1 || opt_debug) printf(" verifying %s...\n",segname);
525
526 again:
527 if(af_get_seg(aout->af,segname,0,0,&seglen)){
528 if(segname != b2 &&
529 segname[0]=='s' && segname[1]=='e' && segname[2]=='g' &&
530 isnumber(segname[3])){
531 /* Looks like a legacy segname name was renamed.
532 * Try the new name
533 */
534 snprintf(b2,sizeof(b2),"page%s",segname+3);
535 if(opt_verbose) printf(" Couldn't read %s; looking for %s\n",
536 segname,b2);
537 segname = b2;
538 goto again;
539 }
540 unlink_outfiles(outfiles);
541 errx(1,"Cannot read length of segment '%s' in output file %s",
542 segname,af_filename(aout->af));
543 }
544 int64_t pagenumber = af_segname_page_number(segname);
545 if(find(preened_pages.begin(),preened_pages.end(),pagenumber) !=preened_pages.end()){
546 /* TK: page pagenumber was preened.
547 * It should probably be checked against the original hash...
548 */
549 continue;
550 }
551
552 unsigned char *segbuf = (unsigned char *)malloc(seglen);
553 if(!segbuf){
554 err(1,"Cannot allocated %d bytes for segment '%s' in %s",
555 (int)seglen,segname,af_filename(ain));
556 }
557 unsigned long arg;
558 if(af_get_seg(aout->af,segname,&arg,segbuf,&seglen)){
559 err(1,"Cannot read segment '%s' in %s",
560 segname,af_filename(aout->af));
561 }
562
563 /* Calculate the MD5 of this segment and see if it matches the map.
564 * (But don't do this for preened segments.
565 */
566 unsigned char md5_read[16];
567 MD5(segbuf,seglen,md5_read);
568 if(memcmp(hashMap[segname].buf,md5_read,16)!=0){
569 unlink_outfiles(outfiles);
570 errx(1,"Hash read from %s for segment %s doesn't validate.",
571 af_filename(aout->af),segname);
572 }
573 free(segbuf); // free the buffer
574 }
575 }
576 }
577
578 /* Finally, close the output files*/
579 for(outlist::iterator aout = afouts.begin(); aout != afouts.end(); aout++){
580 af_close(aout->af);
581 }
582 af_close(ain);
583 if(opt_verbose>1 || opt_debug) printf("==============================\n");
584 current_source = 0;
585 return 0;
586 }
587
588 int main(int argc,char **argv)
589 {
590 int ch;
591
592 setvbuf(stdout,0,_IONBF,0); // turn off buffering on stdout
593 while ((ch = getopt(argc, argv, "vdVxyh?zmX:Lp:P:k:c:n")) != -1) {
594 switch (ch) {
595 case 'v': opt_verbose++; break;
596 case 'd': opt_debug++; break;
597 case 'X':
598 opt_preen =1;
599 opt_X = optarg[0] - '0';
600 opt_preen_alg_arg = AF_PAGE_COMP_ALG_ZLIB;
601 opt_preen_alg_flag = AF_COMPRESSION_ALG_ZLIB;
602 if(opt_X<0 || opt_X>9) opt_X = AF_COMPRESSION_DEFAULT;
603 break;
604 case 'L':
605 opt_preen=1;
606 opt_preen_alg_arg = AF_PAGE_COMP_ALG_LZMA;
607 opt_preen_alg_flag = AF_COMPRESSION_ALG_LZMA;
608 break;
609 case 'x': opt_x++;break;
610 case 'y': opt_noverify++;break;
611 case 'z': opt_zap++;break;
612 case 'm': opt_missing++;break;
613 case 'n': opt_note++;break;
614 case 'k':
615 if(access(optarg,R_OK)) err(1,"%s",optarg);
616 opt_sign_key_file = optarg;
617 if(opt_sign_cert_file==0) opt_sign_cert_file=optarg;
618 opt_sign = true;
619 break;
620 case 'c':
621 if(access(optarg,R_OK)) err(1,"%s",optarg);
622 opt_sign_cert_file = optarg;
623 break;
624 case 'V':
625 printf("%s version %s\n",progname,PACKAGE_VERSION);
626 exit(0);
627 case 'h':
628 case '?':
629 default:
630 usage();
631 break;
632 }
633 }
634 argc -= optind;
635 argv += optind;
636
637 if(argc<2){ // at this point, we need at least two args
638 usage();
639 }
640
641 /* We either need both a key file and a cert file, or neither */
642 if((opt_sign_key_file==0) != (opt_sign_cert_file==0)){
643 errx(1,"Both a private key and a certificate must be specified.");
644 }
645
646 /* Find any directories */
647 vector<string> dirlist;
648 for(int i=argc-1;i>0;i--){
649 struct stat st;
650
651 // s3 names that do not end with ".aff" are directories
652 const char *last4 = strlen(argv[i])>4 ? argv[i]+strlen(argv[i])-4 : "";
653 if(strncmp(argv[i],"s3://",5)==0 &&
654 strcmp(last4,".aff")!=0){
655 dirlist.push_back(argv[i]);
656 argc--;
657 continue;
658 }
659
660 if(stat(argv[i],&st)!=0) break; // out of directories
661 if((st.st_mode & S_IFMT)!=S_IFDIR) break; // found a non-dir
662 dirlist.push_back(argv[i]);
663 argc--; // ignore the last
664 }
665
666 /* If I found no directories, then there better just be two values */
667 if(dirlist.size()==0){
668 if(argc!=2){
669 fprintf(stderr,"Please specify a directory or just two AFF files.\n\n");
670 usage();
671 }
672 /* Must be copying from file1 to file2. Make sure file2 does not exist */
673 if(access(argv[1],R_OK)==0){
674 fprintf(stderr,"File exists: %s\n",argv[1]);
675 if(!opt_zap) exit(1);
676 }
677
678 vector<string> outfiles;
679 outfiles.push_back(argv[1]);
680 return afcopy(argv[0],outfiles);
681 }
682
683 /* Loop for each file and each directory */
684
685 while(argc--){
686 /* Open the output files */
687 vector<string> outfiles;
688 for(u_int i=0;i<dirlist.size();i++){
689 string outfilename;
690 const char *name = strrchr(*argv,'/');
691 if(name) name++;
692 else name = *argv;
693
694 outfilename.append(dirlist[i]);
695 if(outfilename[outfilename.size()-1]!='/') {
696 outfilename.append("/");
697 }
698 outfilename.append(name);
699 outfiles.push_back(outfilename);
700 }
701 afcopy(argv[0],outfiles); // old outfiles will get GCed
702 argv++;
703 }
704 exit(0);
705 }
706
707
+0
-569
tools/afcrypto.cpp less more
0 /*
1 * afcrypto.cpp:
2 *
3 * command for dealing with encryption issues
4 */
5
6 /*
7 * Copyright (c) 2007, 2008
8 * Simson L. Garfinkel
9 * All rights reserved.
10 *
11 * This code is derrived from software contributed by
12 * Simson L. Garfinkel
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. [omitted]
23 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
24 * contributors to this program may be used to endorse or promote
25 * products derived from this software without specific prior written
26 * permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL
29 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
30 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
31 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
32 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
33 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
36 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
37 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
38 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
39 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
41 */
42
43 #include "affconfig.h"
44 #include "afflib.h"
45 #include "afflib_i.h"
46 #include "utils.h"
47
48 #include <stdio.h>
49 #include <algorithm>
50 #include <vector>
51
52 const char *progname = "afcrypto";
53 #define DEFAULT_PASSPHRASE_FILE ".affpassphrase"
54 int opt_debug = 0;
55 int opt_verbose = 0;
56 int opt_just_print_encrypted_count = 0;
57 int opt_just_print_unencrypted_count = 0;
58 char *opt_unsealing_private_key_file= 0;
59 int opt_xml = 0;
60
61 void change_passphrase(const char *fn,const char *old_passphrase,const char *new_passphrase)
62 {
63 int fail = 0;
64
65 AFFILE *af = af_open(fn,O_RDWR,0666);
66 if(!af) af_err(1,fn);
67 if(af_change_aes_passphrase(af,old_passphrase,new_passphrase)){
68 warnx("%s: af_change_aes_passphrase failed",fn);
69 fail = 1;
70 }
71 af_close(af);
72 if(!fail) printf("%s: passphrase changed.\n",fn);
73 }
74
75 void get_and_change_passphrase(const char *fn)
76 {
77 char old_passphrase[1024];
78 char new_passphrase[1024];
79
80 memset(old_passphrase,0,sizeof(old_passphrase));
81 memset(new_passphrase,0,sizeof(new_passphrase));
82
83 printf("Enter old passphrase: ");
84 if(fgets(old_passphrase,sizeof(old_passphrase),stdin)==0) return;
85 char *cc = strchr(old_passphrase,'\n');if(cc) *cc='\000';
86
87 /* See if this passphrase works*/
88
89 AFFILE *af = af_open(fn,O_RDONLY,0666);
90 if(!af) af_err(1,fn);
91 if(af_use_aes_passphrase(af,old_passphrase)){
92 errx(1,"passphrase incorrect");
93 }
94 af_close(af);
95
96 printf("Enter new passphrase: ");
97 if(fgets(new_passphrase,sizeof(new_passphrase),stdin)==0) return;
98 cc = strchr(new_passphrase,'\n');if(cc) *cc='\000';
99 change_passphrase(fn,old_passphrase,new_passphrase);
100 }
101
102 void usage()
103 {
104 printf("afcrypto version %s\n",PACKAGE_VERSION);
105 printf("usage: afcrypto [options] filename.aff [filename2.aff ... ]\n");
106 printf(" prints if each file is encrypted or not.\n");
107 printf("options:\n");
108 printf(" -x --- output in XML\n");
109 printf(" -j --- Just print the number of encrypted segments\n");
110 printf(" -J --- Just print the number of unencrypted segments\n");
111
112 printf("\nData conversion options:\n");
113 printf(" -e --- encrypt the unencrypted non-signature segments\n");
114 printf(" -d --- decrypt the encrypted non-signature segments\n");
115 printf(" -r --- change passphrase (take old and new from stdin)\n");
116 printf(" -O old --- specify old passphrase\n");
117 printf(" -N new --- specify new passphrase\n");
118 printf(" -K mykey.key -- specifies a private keyfile for unsealing (may not be repeated)\n");
119 printf(" -C mycert.crt -- specifies a certificate file for sealing (may be repeated)\n");
120 printf(" -S --- add symmetric encryptiong (passphrase) to AFFILE encrypted with public key\n");
121 printf(" (requires a private key and a specified passphrase).\n");
122 printf(" -A --- add asymmetric encryption to a AFFILE encrypted with a passphrase\n");
123 printf(" (requires a certificate file spcified with the -C option\n");
124
125
126 printf("\nPassword Cracking Options:\n");
127 printf(" -p passphrase --- checks to see if passphrase is the passphrase of the file\n");
128 printf(" exit code is 0 if it is, -1 if it is not\n");
129 printf(" -k --- attempt to crack passwords by reading a list of passwords from ~/.affpassphrase\n");
130 printf(" -f file --- Crack passwords but read them from file.\n");
131
132 printf("\nDebugging:\n");
133 printf(" -V --- Just print the version number and exit.\n");
134 printf(" -D --- debug; print out each key as it is tried\n");
135 printf(" -l --- List the installed hash and encryption algorithms \n");
136 printf("Note: This program ignores the environment variables:\n");
137 puts(AFFLIB_PASSPHRASE);
138 puts(AFFLIB_PASSPHRASE_FILE);
139 puts(AFFLIB_PASSPHRASE_FD);
140 puts(AFFLIB_DECRYPTING_PRIVATE_KEYFILE);
141 exit(0);
142 }
143
144 /* Try each of the passphrases in the file against the passphrase. If it is found, return it. */
145 char *check_file(AFFILE *af,const char *passphrase_file)
146 {
147 char *ret = 0;
148 FILE *f = fopen(passphrase_file,"r");
149 if(!f) return 0;
150
151 char buf[1024];
152 memset(buf,0,sizeof(buf));
153 while(fgets(buf,sizeof(buf)-1,f)){
154 char *cc = strchr(buf,'\n');
155 if(cc) *cc = 0;
156 if(opt_debug){
157 if(opt_debug) printf("checking with '%s' ... ",buf);
158 fflush(stdout);
159 }
160 int r= af_use_aes_passphrase(af,buf);
161 if(r==0){
162 if(opt_debug) printf("YES!\n");
163 ret = strdup(buf);
164 break;
165 }
166 }
167 fclose(f);
168 return ret;
169 }
170
171 /**
172 * This will eventually decrypt non-signature segments that are
173 * encrypted
174 *
175 * @param af - the AFFILE to open
176 * @param count - The number of pages actually encrypted
177 */
178 int af_decrypt_encrypted_segments(AFFILE *af, int *count, int mode)
179 {
180 af_set_option(af,AF_OPTION_AUTO_ENCRYPT,0);
181 af_set_option(af,AF_OPTION_AUTO_DECRYPT,0); // turn off auto decryption
182 aff::seglist sl(af); // get the list of the segments
183 af_set_option(af,AF_OPTION_AUTO_DECRYPT,1); // turn auto decryption back on
184 for(aff::seglist::const_iterator si = sl.begin();si!=sl.end();si++){
185 if(opt_debug) printf(" checking segment %s",si->name.c_str());
186 if(af_is_encrypted_segment(si->name.c_str())){
187
188 if(mode == O_RDONLY){ // if readonly, just tally
189 (*count) ++;
190 if(opt_debug) printf(" would decrypt segment\n");
191 continue;
192 }
193
194 /* Generate the name of the unencrypted segment */
195 char segname[AF_MAX_NAME_LEN];
196 strcpy(segname,si->name.c_str());
197 char *cc = strstr(segname,AF_AES256_SUFFIX);
198 if(!cc){
199 if(opt_debug) printf(" will not decrypt AFFKEY segments; will be deleted later.\n");
200 continue; // something is wrong; can't find the /aes256
201 }
202 *cc = '\000'; // truncate off the /aes256
203
204 /* Get the segment and put it, which will force the decryption to take place */
205 if(opt_debug) printf(" decrypting segment\n");
206 u_char *buf = (u_char *)malloc(si->len);
207 if(!buf) warn("malloc(%zd) failed", si->len);
208 else {
209 unsigned long arg;
210 size_t datalen = si->len;
211 if(af_get_seg(af,segname,&arg,buf,&datalen)){
212 warn("Could not read segment '%s'",segname);
213 }
214 else{
215 /* si->datalen >= datalen.
216 * si->datalen is the length of the encrypted segment.
217 * datalen is the length of the decrypted segment.
218 */
219 assert(si->len >= datalen);
220 assert(si->arg==arg);
221 if(af_update_seg(af,segname,arg,buf,datalen)){
222 warn("Could not decrypt segment '%s'",si->name.c_str());
223 } else {
224 (*count) ++;
225 }
226 }
227 free(buf);
228 }
229 } else {
230 if(opt_debug) printf(" not encrypted\n");
231 }
232 }
233 /* Delete the AF_AFFKEY segment */
234 if(af_get_seg(af,AF_AFFKEY,0,0,0)==0) af_del_seg(af,AF_AFFKEY);
235 /* Delete all of the EVP segments */
236 for(int i=0;;i++){
237 char segname[1024];
238 snprintf(segname,sizeof(segname),AF_AFFKEY_EVP,i);
239 if(af_get_seg(af,segname,0,0,0)!=0) break; // found the last segment
240 if(af_del_seg(af,segname)) warn("Cannot delete segment %s",segname);
241 }
242 return 0;
243 }
244
245
246 /**
247 * Encrypts the non-signature segments that are not encrypted.
248 * There is no reason to encrypt the signature segments.
249 *
250 * @param af - the AFFILE to open
251 * @param count - The number of pages actually encrypted
252 */
253
254 int af_encrypt_unencrypted_nonsignature_segments(AFFILE *af,int *count,int mode)
255 {
256 af_set_option(af,AF_OPTION_AUTO_DECRYPT,0); // do not automatically decrypt
257 aff::seglist sl(af);
258 for(aff::seglist::const_iterator si = sl.begin();si!=sl.end();si++){
259 if(si->name == AF_AFFKEY) continue; // don't encrypt the affkey!
260 if(strstr(si->name.c_str(),"affkey_evp")) continue;
261 if(!af_is_encrypted_segment(si->name.c_str()) &&
262 !af_is_signature_segment(si->name.c_str())){
263
264 if(mode == O_RDONLY){ // if readonly, just tally
265 (*count) ++;
266 continue;
267 }
268
269 /* Get the segment and put it, which will force the encryption to take place */
270 if(opt_debug) printf(" encrypting segment %s\n",si->name.c_str());
271 u_char *buf = (u_char *)malloc(si->len);
272 if(!buf) warn("Cannot encrypt segment '%s' --- too large (%zd bytes) --- malloc failed",
273 si->name.c_str(),si->len);
274 else {
275 unsigned long arg;
276 size_t datalen = si->len;
277 if(af_get_seg(af,si->name.c_str(),&arg,buf,&datalen)){
278 warn("Could not read segment '%s'",si->name.c_str());
279 }
280 else{
281 /* make sure that what we read is what we thought we were going to read */
282 assert(si->len==datalen);
283 assert(si->arg==arg);
284 if(af_update_seg(af,si->name.c_str(),arg,buf,datalen)){
285 warn("Could not encrypt segment '%s'",si->name.c_str());
286 } else {
287 (*count) ++;
288 }
289 }
290 free(buf);
291 }
292 } else {
293 if(opt_debug) printf(" already encrypted or signed: %s\n",si->name.c_str());
294 }
295 }
296 af_set_option(af,AF_OPTION_AUTO_DECRYPT,1); // go back to automatically decrypting
297 return 0;
298 }
299
300 void list_openssl_hashes()
301 {
302 const char *digests[] = {"md5","sha1","sha256",0};
303 OpenSSL_add_all_algorithms();
304 for(int i=0;digests[i];i++){
305 printf("OpenSSL has %s: %s\n",digests[i],EVP_get_digestbyname(digests[i]) ? "YES" : "NO");
306 }
307 exit(0);
308 }
309
310 int main(int argc,char **argv)
311 {
312 int bflag, ch;
313 const char *old_passphrase=0;
314 const char *new_passphrase=0;
315 const char *check_passphrase = 0;
316 char *passphrase_file = 0;
317 const char *progname = argv[0];
318 int opt_encrypt = 0;
319 int opt_decrypt = 0;
320 int opt_add_passphrase_to_public_key = 0;
321 int opt_add_public_key_to_passphrase = 0;
322
323 int mode = O_RDONLY; // mode for opening AFF file
324 const char **certificates = (const char **)malloc(0);
325 int num_certificates = 0;
326 const char *envvars[] = {AFFLIB_PASSPHRASE,AFFLIB_PASSPHRASE_FILE,AFFLIB_PASSPHRASE_FD,
327 AFFLIB_DECRYPTING_PRIVATE_KEYFILE,0};
328 for(int i=0;envvars[i];i++){
329 /* Don't use auto-supplied passphrases */
330 #ifdef HAVE_UNSETENV
331 unsetenv(envvars[i]);
332 #else
333 if(getenv(envvars[i])){
334 fprintf(stderr,"Please unset %s and restart\n",envvars[i]);
335 exit(1);
336 }
337 #endif
338 }
339
340 bflag = 0;
341 int opt_change = 0;
342 const char *home = getenv("HOME");
343
344 while ((ch = getopt(argc, argv, "zreC:SAO:N:p:f:kdDh?VK:vljJx:")) != -1) {
345 switch (ch) {
346 case 'x': opt_xml = 1; break;
347 case 'j': opt_just_print_encrypted_count =1;break;
348 case 'J': opt_just_print_unencrypted_count =1;break;
349
350 /* These options make the mode read-write */
351 case 'r': opt_change = 1; mode = O_RDWR; break;
352 case 'e': opt_encrypt = 1; mode = O_RDWR; break;
353 case 'd': opt_decrypt = 1; mode = O_RDWR; break;
354 case 'S': opt_add_passphrase_to_public_key = 1; mode = O_RDWR; break;
355 case 'A': opt_add_public_key_to_passphrase = 1; mode = O_RDWR; break;
356 /* These just set up variables */
357 case 'C':
358 certificates = (const char **)realloc(certificates,sizeof(int *)*(num_certificates+1));
359 certificates[num_certificates] = optarg;
360 num_certificates++;
361 break;
362 case 'K': opt_unsealing_private_key_file = optarg;break;
363 case 'O': old_passphrase = optarg;break;
364 case 'N': new_passphrase = optarg;break;
365 case 'p': check_passphrase = optarg;break;
366 case 'f': passphrase_file = optarg;break;
367 case 'k':
368 if(!home) home = "/";
369 passphrase_file = (char *)malloc(strlen(home)+strlen(DEFAULT_PASSPHRASE_FILE)+2);
370 strcpy(passphrase_file,home);
371 strcat(passphrase_file,"/");
372 strcat(passphrase_file,DEFAULT_PASSPHRASE_FILE);
373 break;
374 case 'D': opt_debug = 1;break;
375 case 'v': opt_verbose = 1;break;
376 case 'l': list_openssl_hashes(); exit(0);
377 case 'h':
378 case '?':
379 default:
380 usage();
381 break;
382 case 'V':
383 printf("%s version %s\n",progname,PACKAGE_VERSION);
384 exit(0);
385 }
386 }
387 argc -= optind;
388 argv += optind;
389 if(argc<1){
390 fprintf(stderr,"No image file specified\n");
391 usage();
392 }
393
394 if(opt_just_print_encrypted_count && opt_just_print_unencrypted_count){
395 errx(1,"Options -j and -J conflict\n");
396 }
397
398 if(num_certificates>0 && (opt_encrypt==0 && opt_decrypt==0 && opt_add_public_key_to_passphrase==0)){
399 errx(1,"Encryption certificates specified but neither -e nor -d option not set. "
400 "What do you want me to do with these certificates? ");
401 }
402
403 if((check_passphrase || passphrase_file) && opt_encrypt){
404 err(1,"Sorry, can't both encrypt and password crack. Pick one.\n");
405 }
406
407 if(opt_encrypt && (new_passphrase==0 && num_certificates==0) && mode!=O_RDONLY){
408 err(1,"Currently -e requires that the passphrase be specified on the command line\n"
409 "or that one or more encryption certificates be provided\n");
410 }
411
412 while(argc--){
413 const char *fname = *argv++;
414
415 if(opt_change){
416 if(old_passphrase && new_passphrase) change_passphrase(fname,old_passphrase,new_passphrase);
417 else get_and_change_passphrase(fname);
418 }
419
420 /* Get the information */
421 AFFILE *af = af_open(fname,mode,0);
422 if(!af) af_err(1,"af_open(%s)",fname);
423 if(af_identify(af)!=AF_IDENTIFY_AFF && af_identify(af)!=AF_IDENTIFY_AFD){
424 errx(1,"Cannot encrypt %s: %s only supports AFF and AFD files.",af_filename(af),progname);
425 }
426
427 if(opt_encrypt && new_passphrase){
428 int r = af_establish_aes_passphrase(af,new_passphrase);
429 switch(r){
430 case AF_ERROR_NO_AES: errx(1,"AFFLIB: AES256 not available; cannot continue");
431 case AF_ERROR_NO_SHA256: errx(1,"AFFLIB: SHA256 not available; cannot continue");
432 default: err(1,"%s: cannot establish passphrase (error %d)",fname,r);
433 case 0:
434 case AF_ERROR_AFFKEY_EXISTS:
435 /* no matter if we established it or if a phrase already exists, try to use it now */
436 /* File already has a passphrase; see if this is it. */
437 break;
438 }
439 r = af_use_aes_passphrase(af,new_passphrase);
440 switch(r){
441 case 0: break; // everything okay
442 case AF_ERROR_WRONG_PASSPHRASE: errx(1,"%s: wrong passphrase",fname);
443 default: errx(1,"%s: passphrase already established (error %d)",fname,r);
444 }
445 }
446
447 if(opt_decrypt && old_passphrase){
448 int r = af_use_aes_passphrase(af, old_passphrase);
449 switch(r){
450 case 0: printf("Passphrase is good!\n"); break;
451 case AF_ERROR_WRONG_PASSPHRASE: errx(1,"%s: wrong passphrase",fname);
452 }
453 }
454
455 if (opt_add_public_key_to_passphrase){
456 if(!num_certificates) errx(1,"You must specify a certificate with the -C option");
457 if(!check_passphrase) errx(1,"You must specify a passphrase with the -p option");
458 printf("Attepmting to add public key to AFFILE...\n");
459 if(af->crypto->sealing_key_set) return AF_ERROR_KEY_SET; // already enabled
460 unsigned char affkey[32];
461 int r = af_get_aes_key_from_passphrase(af,check_passphrase,affkey);
462 if(r) errx(1, "%s: cannot get aes key. Failed to add Public Key", fname);
463 af_seal_affkey_using_certificates(af, certificates, num_certificates, affkey);
464 printf("...Public key added successfully.\n");
465 }
466
467 if(opt_encrypt && num_certificates){
468 if(af_set_seal_certificates(af,certificates,num_certificates)){
469 errx(1,"%s: can't set encryption certificate%s",fname,num_certificates==1 ? "" : "s");
470 }
471 }
472 if(opt_encrypt){
473 int count = 0;
474 if(af_encrypt_unencrypted_nonsignature_segments(af,&count,mode)){
475 errx(1,"%s: can't encrypt unsigned, unencrypted segments",fname);
476 }
477 if(mode==O_RDONLY){ // if it is readonly just print the number of segments that would be changed.
478 printf("%d\n",count);
479 af_close(af);
480 continue;
481 }
482 }
483 if(opt_decrypt){
484 int count = 0;
485 if(af_decrypt_encrypted_segments(af, &count, mode)){
486 }
487 if(mode==O_RDONLY){
488 printf("%d\n",count);
489 af_close(af);
490 continue;
491 }
492 }
493
494 if(opt_add_passphrase_to_public_key) {
495 if(!new_passphrase) errx(1,"You must specify a new passphrase with the -N option");
496 printf("Attempting to add passphrase...\n");
497 u_char affkey[32];
498 if(af_get_affkey_using_keyfile(af, opt_unsealing_private_key_file,affkey)){
499 errx(1,"%s: cannot unseal AFFKEY",fname);
500 }
501 if(af_save_aes_key_with_passphrase(af,new_passphrase,affkey)){
502 af_err(1,"%s: could not set the passphrase",fname);
503 }
504 printf("... new passphrase established.\n");
505 }
506
507
508 af_vnode_info vni;
509 memset(&vni,0,sizeof(vni));
510 if(af_vstat(af,&vni)) err(1,"%s: af_vstat failed: ",fname);
511 const char *the_passphrase = 0; // the correct passphrase
512
513 if(opt_just_print_encrypted_count){
514 printf("%d\n",vni.segment_count_encrypted);
515 af_close(af);
516 continue;
517 }
518
519 if(opt_just_print_unencrypted_count){
520 printf("%d\n",vni.segment_count_total-vni.segment_count_encrypted);
521 af_close(af);
522 continue;
523 }
524
525
526 /* were we supposed to try a check_passphrase? */
527 if(check_passphrase){
528 if(af_use_aes_passphrase(af,check_passphrase)==0){
529 the_passphrase = check_passphrase;
530 }
531 af_use_aes_passphrase(af,0); // clear the passphrase
532 }
533
534 /* Is a passphrase file provided? */
535 if(!the_passphrase && passphrase_file){
536 the_passphrase = check_file(af,passphrase_file);
537 if(the_passphrase){
538 af_use_aes_passphrase(af,0); // clear the passphrase
539 }
540 }
541
542 if(opt_xml){
543 /* This should be replaced with our xml.cpp object */
544 printf("<afcrypto>\n");
545 printf(" <image_filename>%s</image_filename>\n",fname);
546 printf(" <segment_count_total>%d</segment_count_total>\n",vni.segment_count_total);
547 printf(" <segment_count_signed>%d</segment_count_signed>\n",vni.segment_count_signed);
548 printf(" <segment_count_encrypted>%d</segment_count_encrypted>\n",vni.segment_count_encrypted);
549 printf(" <page_count_total>%d</page_count_total>\n",vni.page_count_total);
550 printf(" <page_count_encrypted>%d</page_count_encrypted>\n",vni.page_count_encrypted);
551 if(the_passphrase){
552 printf(" <passphrase correct='1'>%s</passphrase>\n",the_passphrase);
553 }
554 printf("</afcrypto>\n");
555 }
556 else{
557 /* re-run vstat because counts may have changed */
558 if(af_vstat(af,&vni)) err(1,"%s: af_vstat failed: ",fname);
559 printf("%s: %5d segments; %5d signed; %5d encrypted; %5d pages; %5d encrypted pages",
560 fname,vni.segment_count_total,vni.segment_count_signed,vni.segment_count_encrypted,
561 vni.page_count_total,vni.page_count_encrypted );
562 if(the_passphrase) printf("passphrase correct (\"%s\")",the_passphrase);
563 putchar('\n');
564 }
565 af_close(af);
566 }
567 return(0);
568 }
+0
-453
tools/afdiskprint.cpp less more
0 /*
1 * afdiskprint.cpp:
2 *
3 * Creates a diskprint AFF structure
4 */
5
6 /*
7 * PUBLIC DOMAIN
8 * By Simson L. Garfinkel
9 *
10 * The software provided here is released by the Naval Postgraduate
11 * School (NPS), an agency of the U.S. Department of Navy.The software
12 * bears no warranty, either expressed or implied. NPS does not assume
13 * legal liability nor responsibility for a User's use of the software
14 * or the results of such use.
15 *
16 * Please note that within the United States, copyright protection,
17 * under Section 105 of the United States Code, Title 17, is not
18 * available for any work of the United States Government and/or for
19 * any works created by United States Government employees. User
20 * acknowledges that this software contains work which was created by
21 * NPS employees and is therefore in the public domain and not
22 * subject to copyright.
23 */
24
25
26 #include "affconfig.h"
27 #include "afflib.h"
28 #include "afflib_i.h"
29 #include "base64.h"
30 #include "hashextent.h"
31
32 #ifdef HAVE_EXPAT
33
34 #include <openssl/evp.h>
35
36 #ifdef WIN32
37 #include "unix4win32.h"
38 #endif
39
40 #include <vector>
41 #include <string>
42 #include <iostream>
43 #include <sstream>
44 #include <map>
45 #include <set>
46
47 #ifdef HAVE_CSTRING
48 #include <cstring>
49 #endif
50
51 const char *hashes[] = {"SHA256","SHA1",0}; // what should we hash?
52
53 using namespace std;
54
55 #if HAVE_CTYPE_H
56 #include <ctype.h>
57 #endif
58
59 #if !defined(HAVE_ISALPHANUM) && defined(HAVE_ISALNUM)
60 #define isalphanum(c) isalnum(c)
61 #endif
62
63 #if !defined(HAVE_ISALPHANUM) && !defined(HAVE_ISALNUM)
64 #define isalphanum(c) (isalpha(c)||isdigit(c))
65 #endif
66
67 #if !defined(O_BINARY)
68 #define O_BINARY 0
69 #endif
70
71 const char *progname = "afdiskprint";
72 const char *xml_special_chars = "<>\r\n&'\"";
73
74 void usage()
75 {
76 printf("%s version %s\n",progname,PACKAGE_VERSION);
77 printf("usage: %s [options] infile \n",progname);
78 printf(" -x XML = Verify the diskprint\n");
79 printf(" -V = Just print the version number and exit.\n");
80 printf(" -h = Print this help.\n");
81 exit(0);
82 }
83
84 /****************************************************************
85 ** Support routines...
86 */
87
88 /**
89 * Return a random 64-bit number
90 */
91 uint64_t random64()
92 {
93 return (((uint64_t)random())<<32) | random();
94 }
95
96 uint64_t atoi64(const char *buf)
97 {
98 uint64_t ret=0;
99 sscanf(buf,"%"PRIu64,&ret);
100 return ret;
101 }
102
103
104 static int *hexcharvals = 0;
105 static void nsrl_bloom_init()
106 {
107 if(hexcharvals==0){
108 /* Need to initialize this */
109 int i;
110 hexcharvals = (int *)calloc(sizeof(int),256);
111 for(i=0;i<10;i++){
112 hexcharvals['0'+i] = i;
113 }
114 for(i=10;i<16;i++){
115 hexcharvals['A'+i-10] = i;
116 hexcharvals['a'+i-10] = i;
117 }
118 }
119 }
120
121
122 /**
123 * Convert a hex representation to binary, and return
124 * the number of bits converted.
125 * @param binbuf output buffer
126 * @param binbuf_size size of output buffer in bytes.
127 * @param hex input buffer (in hex)
128 */
129 int nsrl_hex2bin(unsigned char *binbuf,size_t hexbuf_size,const char *hex)
130 {
131 int bits = 0;
132 if(hexcharvals==0) nsrl_bloom_init();
133 while(hex[0] && hex[1] && hexbuf_size>0){
134 *binbuf++ = ((hexcharvals[(unsigned char)hex[0]]<<4) |
135 hexcharvals[(unsigned char)hex[1]]);
136 hex += 2;
137 bits += 8;
138 hexbuf_size -= 1;
139 }
140 if(hexbuf_size>0) binbuf[0] = 0; // might as well null-terminate if there is room
141 return bits;
142 }
143
144
145
146 /**
147 * Strip an XML string as necessary for a tag name.
148 */
149
150 void out_xmlstr(ostream &ostr,int indent,const char *tag,const char *value)
151 {
152 for(int i=0;i<indent;i++) ostr << " ";
153 ostr << "<" << tag << ">";
154 for(const char *ch=value;*ch;ch++){
155 if(isprint(*ch) && !strchr(xml_special_chars,*ch)){
156 ostr << *ch;
157 }
158 }
159 ostr << "</" << tag << ">";
160 }
161
162 void out_xmlhex(ostream &ostr,int indent,const char *tag,const char **attribs,
163 unsigned char *md,int len)
164 {
165 for(int i=0;i<indent;i++) ostr << ' ';
166 ostr << "<" << tag << " coding='base16'";
167 for(int i=0;attribs && attribs[i];i++){
168 ostr << " ";
169 ostr << attribs[i];
170 }
171 ostr << ">" << hashextent::bin2hex(md,len) << "</" << tag << ">\n";
172 }
173
174 /**
175 * Calculate the disk fingerprint for a spcific file and output it to stdout.
176 * Includes other named segments.
177 *
178 * @param infile the file to process.
179 */
180
181 int diskprint(const char *infile)
182 {
183 /** segments to include in output.
184 */
185 const char *segments[] = {AF_MD5,AF_SHA1,AF_SHA256,AF_CREATOR,AF_CASE_NUM,AF_IMAGE_GID,
186 AF_ACQUISITION_ISO_COUNTRY,
187 AF_ACQUISITION_COMMAND_LINE,AF_ACQUISITION_DATE,
188 AF_ACQUISITION_NOTES,AF_ACQUISITION_TECHNICIAN,
189 AF_BATCH_NAME,AF_BATCH_ITEM_NAME,0};
190 AFFILE *af = af_open(infile,O_RDONLY,0);
191 if(!af){
192 warn("%s",infile);
193 return -1;
194 }
195
196 cout << "<!-- XML generated by " << progname << " version " << PACKAGE_VERSION << " -->\n";
197 cout << "<diskprint image_filename='" << infile << "'>\n";
198
199 /* First handle the imagesize */
200 int64_t imagesize = af_get_imagesize(af);
201 if(imagesize>0){
202 char buf[32];
203 snprintf(buf,sizeof(buf),"%"PRIu64,imagesize);
204 out_xmlstr(cout,2,AF_IMAGESIZE,buf);
205 cout << "\n";
206 }
207 /* Get sector size and number of sectors */
208 unsigned long sectorsize=512; // default sectorsize
209 af_get_seg(af,AF_SECTORSIZE,&sectorsize,0,0);
210 if(sectorsize==0) sectorsize=512; // default sectorsize
211 int64_t sectors = imagesize/sectorsize;
212 if(sectors>0){
213 char buf[32];
214 snprintf(buf,sizeof(buf),"%lu",sectorsize);
215 out_xmlstr(cout,2,AF_SECTORSIZE,buf);
216 cout << "\n";
217 }
218
219 /* Output specific named segments */
220 for(int i=0;segments[i];i++){
221 char buf[65536];
222 size_t buflen = sizeof(buf);
223 if(af_get_seg(af,segments[i],0,(u_char *)buf,&buflen)==0){
224 buf[buflen] = 0; // null terminate it
225 if(af_display_as_hex(segments[i])){
226 out_xmlhex(cout,2,segments[i],0,(u_char *)buf,buflen);
227 } else {
228 out_xmlstr(cout,2,segments[i],buf);
229 }
230 }
231 }
232
233 /**
234 * The list of segments to hash is defined by:
235 * 1. The first 128K sectors.
236 * 2. The last 128K sectors.
237 * 3. A random set of 64K sectors.
238 */
239 hashvector hashextents;
240
241 for(int i=0;i<8;i++){
242 hashextents.push_back(hashextent(131072*i,131072));
243 }
244 for(int i=0;i<8;i++){
245 hashextents.push_back(hashextent(imagesize-131072*(8-i),131072));
246 }
247
248 /* Pick some random hashextents as well */
249 for(int i=0;i<100;i++){
250 uint64_t sector = random64() % (sectors-128);
251 hashextents.push_back(hashextent(sector*sectorsize,65536));
252 }
253
254 /** Sort the segments for maximal seek efficiency.
255 */
256 sort(hashextents.begin(),hashextents.end(),hashextent::compare);
257
258 /** Send the hashes to stdout using print_hash.
259 */
260 cout << " <hashes>\n";
261 for(hashvector::iterator it=hashextents.begin(); it!=hashextents.end(); it++){
262 for(int i=0;hashes[i];i++){
263 if((*it).compute_digest(af,hashes[i])==0){
264 cout << " " << (*it).toXML() << "\n";
265 }
266 }
267 }
268 cout << " </hashes>\n";
269 cout << "</diskprint>\n";
270 af_close(af);
271 return 0;
272 }
273
274
275 /**
276 * Code for reading the hashvector XML structure.
277 */
278 #include <expat.h>
279
280 class diskprintReader {
281 public:
282 /* General EXPAT stuff */
283 XML_Parser parser;
284 bool get_cdata; // this is cdata worth getting
285 string cdata; // the cdata that has been gotten
286 diskprintReader():get_cdata(false),hash(0){
287 parser = XML_ParserCreate(NULL);
288 XML_SetUserData(parser,this);
289 XML_SetElementHandler(parser,startElement,endElement);
290 XML_SetCharacterDataHandler(parser,cHandler);
291 }
292 int parse(const char *buf,int len) { return XML_Parse(parser, buf, len, 1);}
293 void clear(){
294 cdata = "";
295 get_cdata = false;
296 }
297
298 /* Specific stuff for XML diskprint */
299 hashextent *hash; // current hash
300 hashvector hashextents; // all discovered hashes
301 /* Turn the static functions into method calls */
302 static void startElement(void *userData,const char *name,const char **attrs){
303 ((diskprintReader *)userData)->startElement(name,attrs);
304 }
305 static void endElement(void *userData,const char *name){
306 ((diskprintReader *)userData)->endElement(name);
307 }
308 static void cHandler(void *userData,const XML_Char *s,int len){
309 diskprintReader *dh = (diskprintReader *)userData;
310 if(dh->get_cdata) dh->cdata.append(s,len);
311 }
312 void startElement(string name,const char **attrs){
313 clear();
314 /* If this is an element that we want, indicate such */
315 if(name=="hash"){
316 hash = new hashextent();
317 for(int i=0;attrs[i];i+=2){
318 if(strcmp(attrs[i],"coding")==0){ hash->coding = attrs[i+1]; continue;}
319 if(strcmp(attrs[i],"start")==0){ hash->start = atoi64(attrs[i+1]); continue;}
320 if(strcmp(attrs[i],"bytes")==0){ hash->bytes = atoi64(attrs[i+1]); continue;}
321 if(strcmp(attrs[i],"alg")==0){ hash->digest_name = attrs[i+1]; continue;}
322 }
323 get_cdata = true;
324 }
325 }
326 void endElement(const char *name){
327 if(get_cdata==false) return; // don't care about it.
328 if(!strcmp(name,"hash")){
329 if(hash->coding=="base16"){
330 hash->hexdigest = cdata;
331 }
332 hashextents.push_back(*hash);
333 }
334 if(!strcmp(name,"diskprint")){
335 XML_StopParser(parser,0); // stop the parser
336 return;
337 }
338 get_cdata = false;
339 }
340 };
341
342 void diskprint_verify(const char *filename,const char *xmlfile)
343 {
344 AFFILE *af = af_open(filename,O_RDONLY,0);
345 if(!af) err(1,"af_open(%s): ",filename);
346
347 /* Let's read the XML file */
348 int fd = open(xmlfile,O_RDONLY|O_BINARY);
349 if(!fd) err(1,"open: %s",xmlfile);
350 struct stat st;
351 if(fstat(fd,&st)) err(1,"stat: %s",xmlfile);
352 char *buf = (char *)malloc(st.st_size+1);
353 if(!buf) err(1,"malloc");
354
355 if(read(fd,buf,st.st_size)!=st.st_size) err(1,"cannot read XML file");
356 buf[st.st_size]=0; // terminate the buffer (not strictly needed)
357
358 diskprintReader dp;
359 dp.parse(buf,st.st_size);
360 cout << "Number of digests read: "<< dp.hashextents.size() << "\n";
361 const EVP_MD *strongest = dp.hashextents.strongest_available();
362 cout << "Strongest hash available: " << EVP_MD_name(strongest) << "\n";
363 /* Now verify each hash */
364 int matched=0;
365 int notmatched=0;
366 for(hashvector::iterator it = dp.hashextents.begin(); it!=dp.hashextents.end() && notmatched==0;it++){
367 if(EVP_MD_name(strongest) == (*it).digest_name){
368 hashextent &hp = (*it); // hash print
369 hashextent hs(af,hp.digest_name,hp.start,hp.bytes);
370 //cout << "hp: " << hp << "\n";
371 //cout << "hs: " << hs << "\n";
372 if(hp==hs){
373 matched++;
374 } else {
375 notmatched++;
376 }
377 }
378 }
379 if(notmatched){
380 cout << "Diskprint does not match.\n";
381 }
382 if(notmatched==0 && matched){
383 cout << "Diskprint matches.\n";
384 }
385 if(notmatched==0 && matched==0){
386 cout << "Cannot verify Diskprint; no available hash functions.\n";
387 }
388 exit(0);
389 }
390
391 int main(int argc,char **argv)
392 {
393 int ch;
394 const char *opt_x=0;
395
396 /* Initialize */
397 #ifdef HAVE_SRANDOMEDEV
398 srandomdev();
399 #endif
400 OpenSSL_add_all_digests();/* Dynamically loads the digests */
401
402
403 /* Parse arguments */
404 while ((ch = getopt(argc, argv, "x:h?V")) != -1) {
405 switch (ch) {
406 case 'h':
407 case '?':
408 default:
409 usage();
410 break;
411 case 'x': opt_x = optarg; break;
412 case 'V':
413 printf("%s version %s\n",progname,PACKAGE_VERSION);
414 exit(0);
415 }
416 }
417 argc -= optind;
418 argv += optind;
419
420 if(argc!=1){ // currently only generates for one file
421 usage();
422 }
423
424 if(opt_x){
425 diskprint_verify(argv[0],opt_x);
426 return(0);
427 }
428
429 /* Loop through all of the files */
430 printf("<?xml version='1.0' encoding='UTF-8'?>\n");
431 printf("<diskprints>\n");
432 while(*argv){
433 if(opt_x){
434 diskprint_verify(*argv,opt_x);
435 }
436 else {
437 diskprint(*argv);
438 }
439 argv++;
440 argc--;
441 }
442 printf("</diskprints>\n");
443 exit(0);
444 }
445 #else
446 int main(int argc,char **argv)
447 {
448 fprintf(stderr,"afdiskprint requires EXPAT. Cannot continue.\n");
449 exit(-1);
450 }
451 #endif
452
0 /*
1 * afcat.cpp:
2 *
3 * cat the contents of an AFF file...
4 */
5
6 /*
7 * Copyright (c) 2005, 2006
8 * Simson L. Garfinkel and Basis Technology, Inc.
9 * All rights reserved.
10 *
11 * This code is derrived from software contributed by
12 * Simson L. Garfinkel
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by Simson L. Garfinkel
25 * and Basis Technology Corp.
26 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
27 * contributors to this program may be used to endorse or promote
28 * products derived from this software without specific prior written
29 * permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
32 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
34 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
36 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 */
45
46 #include "affconfig.h"
47 #include "afflib.h"
48 #include "afflib_i.h"
49
50 #include <stdio.h>
51 #include <algorithm>
52 #include <vector>
53 #include <string>
54 #ifdef HAVE_CSTRING
55 #include <cstring>
56 #endif
57
58
59 using namespace std;
60
61 vector <int64_t> pages;
62
63 const char *progname = "afcat";
64 int opt_info = 0;
65 char *opt_segname=0;
66 int64_t opt_pagenum = -1;
67 int opt_quiet = 1;
68 int opt_list= 0 ;
69 int opt_list_long = 0;
70 int opt_debug = 0;
71 int64_t opt_sector = -1;
72 int opt_badflag = 0;
73 vector<string> opt_r;
74
75
76 void usage()
77 {
78 printf("afcat version %s\n",PACKAGE_VERSION);
79 printf("usage: afcat [options] infile [... more infiles]\n");
80 printf("options:\n");
81 printf(" -s name --- Just output segment name\n");
82 printf(" -p ### --- just output data page number ###\n");
83 printf(" -S ### --- Just output data sector ### (assumes 512-byte sectors). Sector #0 is first\n");
84 printf(" -q --- quiet; don't print to STDERR if a page is skipped\n");
85 printf(" -n --- noisy; tell when pages are skipped.\n");
86 printf(" -l --- List all of the segment names\n");
87 printf(" -L --- List segment names, lengths, and args\n");
88 printf(" -d --- debug. Print the page numbers to stderr as data goes to stdout\n");
89 printf(" -b --- Output BADFALG for bad blocks (default is NULLs)\n");
90 printf(" -v --- Just print the version number and exit.\n");
91 printf(" -r offset:count --- seek to offset and output count characters in each file; may be repeated\n");
92 exit(0);
93 }
94
95
96 const char *current_fname = 0;
97 int64_t current_page = -1;
98 void sig_info(int arg)
99 {
100 fprintf(stderr,"afcat ");
101 if(current_fname) fprintf(stderr,"%s: ",current_fname);
102 if(current_page>=0) fprintf(stderr,"[%"PRId64"] ",current_page);
103 fflush(stderr);
104 }
105
106
107
108 int compar(const void *a_,const void *b_)
109 {
110 int64_t a = *(int *)a_;
111 int64_t b = *(int *)b_;
112 if(a<b) return -1;
113 if(a>b) return 1;
114 return 0;
115 }
116
117 struct afm_private {
118 AFFILE *aff; // the AFFILE we use for the actual metadata
119 AFFILE *sr; // the AFFILE we use for the splitraw
120 int sr_initialized; // has the split-raw been setup from AFM?
121 };
122
123 int output_page(AFFILE *af,FILE *outfile,int64_t pagenum)
124 {
125 current_fname = af_filename(af);
126 current_page = pagenum;
127 unsigned char *buf = (unsigned char *)malloc(af->image_pagesize);
128 if(buf==0){
129 err(1,"malloc(%d) failed",(int)af->image_pagesize);
130 }
131 uint64_t offset = (uint64_t)pagenum * af->image_pagesize; // go to that location
132
133
134 af_seek(af,offset,SEEK_SET);
135
136
137 int bytes = af_read(af,buf,af->image_pagesize); // read what we can
138
139 if(bytes<0){
140 if(opt_debug) fprintf(stderr,"afcat: cannot read page %"I64d"\n",pagenum);
141 return -1;
142 }
143
144 if(opt_debug){
145 fprintf(stderr,"afcat: page:%"I64d" bytes: %d offset:%"I64d"\n",
146 pagenum, bytes,offset);
147 }
148
149 /* Check each sector to see if it is badflag or not.
150 * If it is and if opt_badflag is not set, make it all NULs.
151 */
152 for(unsigned char *cc=buf;cc<buf+bytes;cc+=af->image_sectorsize){
153 if(af_is_badsector(af,cc) && opt_badflag==0){
154 memset(cc,0,af->image_sectorsize);
155 }
156 }
157
158 if(opt_debug) fprintf(stderr," outputing %d bytes\n",bytes);
159 int count = fwrite(buf,1,bytes,outfile); // send to the output
160 if(count!=bytes) fprintf(stderr,"fwrite(buf,1,%d,outfile) only wrote %d bytes\n",bytes,count);
161 free(buf);
162 return bytes;
163 }
164
165
166 int afcat(AFFILE *af)
167 {
168 int64_t total_bytes_written = 0;
169
170 /* Read all of the pages from beginning to end and capture
171 * all the segment numbers...
172 */
173
174 #ifdef WIN32
175 _setmode(fileno(stdout),_O_BINARY);
176 #endif
177 if(opt_debug) fprintf(stderr,"afcat(%s)\n",af_filename(af));
178
179 if(opt_segname){
180 /* First figure out how big the segment is */
181 size_t datalen = 0;
182 if(af_get_seg(af,opt_segname,0,0,&datalen)){
183 fprintf(stderr,"%s: segment '%s' does not exist\n",
184 af_filename(af),opt_segname);
185 return -1;
186 }
187 unsigned char *data = (unsigned char *)malloc(datalen);
188 if(data==0) err(1,"malloc");
189 if(af_get_seg(af,opt_segname,0,data,&datalen)){
190 free(data);
191 fprintf(stderr,"%s: could not read segment '%s'\n",
192 af_filename(af),opt_segname);
193 return -1;
194 }
195 int count = fwrite(data,1,datalen,stdout);
196 if(count!=(ssize_t)datalen){
197 fprintf(stderr,"fwrite(buf,1,%zd,outfile) only wrote %d bytes\n",datalen,count);
198 }
199 free(data);
200 return 0;
201 }
202
203 if(opt_pagenum != -1){ // just write a particular page?
204 int r = output_page(af,stdout,opt_pagenum);
205 return r>=0 ? 0 : -1;
206 }
207
208 if(opt_sector>=0){
209 unsigned char *buf = (unsigned char *)malloc(af->image_sectorsize);
210 af_seek(af,(uint64_t)opt_sector*af->image_sectorsize,SEEK_SET);
211 int bytes_read = af_read(af,buf,af->image_sectorsize);
212 if(bytes_read>0){
213 int bytes_written = fwrite(buf,1,bytes_read,stdout);
214 if(bytes_read!=bytes_written){
215 fprintf(stderr,"fwrite(buf,1,%d,outfile) only wrote %d bytes\n",
216 bytes_read,bytes_written);
217 }
218 }
219 free(buf);
220 return 0;
221 }
222
223 /* Get a list of all the segments. If we are doing a list, just print them.
224 * If we are not doing a list, capture the data pages and put their numbers
225 * into an array.
226 */
227
228 if(opt_debug) fprintf(stderr,"af_rewind_seg()\n");
229
230 if(opt_r.size()>0){
231 unsigned char *buf = (unsigned char *)malloc(af->image_pagesize);
232 for(vector<string>::const_iterator offset_count=opt_r.begin(); offset_count != opt_r.end(); offset_count++){
233 string opts = *offset_count;
234 const char *opt = opts.c_str();
235 uint64_t offset=0;
236 int count=0;
237 if(sscanf(opt,"%"I64u":%d",&offset,&count)!=2){
238 err(1,"Cannot decode '%s'\n",opt);
239 }
240 af_seek(af,offset,SEEK_SET);
241 int r= af_read(af,buf,count);
242 if(r>0){
243 int bytes_written = fwrite(buf,1,r,stdout);
244 if(bytes_written!=r) {
245 fprintf(stderr,"fwrite(buf,1,%d,outfile) only wrote %d bytes\n",r,bytes_written);
246 }
247
248 }
249 }
250 free(buf);
251 return 0;
252 }
253
254
255 af_rewind_seg(af); // start at the beginning
256 char segname[AF_MAX_NAME_LEN];
257 unsigned long arg;
258 size_t datalen = 0;
259 memset(segname,0,sizeof(segname));
260
261 int encrypted_segments = 0;
262 while(af_get_next_seg(af,segname,sizeof(segname),&arg,0,&datalen)==0){
263 if(opt_debug) fprintf(stderr,"af_get_next_seg found segment %s\n",segname);
264 if(segname[0]==0) continue; // ignore sector
265 if(opt_list){
266 printf("%s",segname);
267 if(opt_list_long){
268 printf("\targ:%lu\tlen:%d",arg,(int)datalen);
269 }
270 putchar('\n');
271 }
272 else {
273 int64_t pagenum = af_segname_page_number(segname);
274 if(pagenum>=0) pages.push_back(pagenum);
275 if(af_is_encrypted_segment(segname)) encrypted_segments++;
276 }
277 datalen = 0; // allow to get the next one
278 }
279 if(opt_list) return 0; // that's all that was wanted.
280
281
282 sort(pages.begin(),pages.end());
283
284 if(pages.size()==0 && encrypted_segments){
285 fprintf(stderr,"afcat: This file has %d encrypted segments.\n",encrypted_segments);
286 fprintf(stderr,"afcat: No unencrypted pages could be found.\n");
287 }
288
289 /* Now I have a list of pages; cat each one */
290 int next_page = 0; // starting page number
291 int64_t imagesize = af_get_imagesize(af);
292 for(vector<int64_t>::iterator i = pages.begin(); i != pages.end(); i++){
293
294 int page = *i;
295 if(page != next_page && opt_quiet==0){
296 if(page == next_page+1 ){
297 fprintf(stderr,"afcat: page %d not in file\n",next_page);
298 }
299 else{
300 fprintf(stderr,"afcat: pages %d through %d not in file\n",
301 next_page,page-1);
302 }
303 }
304 int r = output_page(af,stdout,page);
305 if(r<0) return -1;
306 total_bytes_written += r;
307 next_page = page + 1; // note what should be next
308
309 //fprintf(stderr,"bytes written=%qd imagesize=%qd\n",total_bytes_written,imagesize);
310 if((total_bytes_written > imagesize) && (imagesize>0)){
311 err(1,"afcat internal error. bytes written=%"I64d" imagesize=%" I64d,
312 (int64_t)total_bytes_written,
313 (int64_t)imagesize);
314 return -1;
315 }
316 }
317 return 0;
318 }
319
320
321 int64_t atoi64(const char *buf)
322 {
323 int64_t r=0;
324 char ch;
325 if(sscanf(buf,"%"I64d"%c",&r,&ch)==1) return r;
326 fprintf(stderr,"Cannot parse '%s'\n",buf);
327 exit(0);
328 }
329
330
331 int main(int argc,char **argv)
332 {
333 int bflag, ch;
334
335 #ifdef SIGINFO
336 signal(SIGINFO,sig_info);
337 #endif
338
339 bflag = 0;
340 while ((ch = getopt(argc, argv, "s:S:p:lLh?dqnvr:")) != -1) {
341 switch (ch) {
342 case 's':
343 opt_segname = optarg;
344 break;
345 case 'S':
346 opt_sector = atoi64(optarg);
347 break;
348 case 'p':
349 opt_pagenum = atoi64(optarg);
350 break;
351 case 'q':
352 opt_quiet = 1;
353 break;
354 case 'n':
355 opt_quiet = 0;
356 break;
357 case 'l':
358 opt_list = 1;
359 break;
360 case 'r':
361 opt_r.push_back(optarg);
362 break;
363 case 'L':
364 opt_list = 1;
365 opt_list_long = 1;
366 break;
367 case 'b':
368 opt_badflag = 1;
369 break;
370 case 'd':
371 opt_debug++;
372 break;
373 case 'h':
374 case '?':
375 default:
376 usage();
377 break;
378 case 'v':
379 printf("%s version %s\n",progname,PACKAGE_VERSION);
380 exit(0);
381 }
382 }
383 argc -= optind;
384 argv += optind;
385
386 if(argc<1){
387 usage();
388 }
389
390 while(*argv){
391 AFFILE *af = af_open(*argv,O_RDONLY,0);
392 if(!af) af_err(1,"afcat(%s)",*argv);
393 if(afcat(af)) err(1,"afcat");
394 af_close(af);
395 argv++;
396 argc--;
397 }
398 }
0 /*
1 * acompare.cpp:
2 *
3 * Compare the contents of an ISO file to an AFF file.
4 * Optionally, if they are equal, delete the ISO file
5 */
6
7 /*
8 * Copyright (c) 2005--2008
9 * Simson L. Garfinkel and Basis Technology, Inc.
10 * All rights reserved.
11 *
12 * This code is derrived from software contributed by
13 * Simson L. Garfinkel
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 * 3. All advertising materials mentioning features or use of this software
24 * must display the following acknowledgement:
25 * This product includes software developed by Simson L. Garfinkel
26 * and Basis Technology Corp.
27 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
28 * contributors to this program may be used to endorse or promote
29 * products derived from this software without specific prior written
30 * permission.
31 *
32 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
33 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
34 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
35 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
37 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
40 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
41 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
42 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
43 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44 * SUCH DAMAGE.
45 */
46
47 #include "affconfig.h"
48 #include "afflib.h"
49 #include "afflib_i.h"
50 #include "utils.h"
51
52 using namespace std;
53 using namespace aff;
54
55
56 #ifdef WIN32
57 #include "unix4win32.h"
58 #endif
59
60
61 #ifdef UNIX
62 #include <sys/signal.h>
63 #include <unistd.h>
64 #endif
65
66 #include <ctype.h>
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <sys/types.h>
70 #include <sys/stat.h>
71 #include <fcntl.h>
72 #include <limits.h>
73 #include <string.h>
74 #include <zlib.h>
75 #include <openssl/md5.h>
76 #include <openssl/sha.h>
77 #include <assert.h>
78
79 #ifdef HAVE_CSTRING
80 #include <cstring>
81 #endif
82
83 #ifdef linux
84 #include <sys/time.h>
85 #endif
86
87
88
89 const char *progname = "affcompare";
90
91 int opt_quiet = 0;
92 int opt_all = 0;
93 int opt_print_sectors = 0;
94 int opt_print_sector_contents = 0;
95 int opt_page = -1;
96 int opt_preen = 0;
97 int opt_exist = 0;
98 int opt_ignore_metadata = 0;
99 int opt_s3 = 0;
100 int opt_verbose = 0;
101 const char *batch_ext = "";
102
103 vector<string> errors;
104
105 const char *current_source = 0;
106
107 void sig_info(int arg)
108 {
109 if(current_source){
110 printf("%s... ",current_source);
111 }
112 printf("\n");
113 fflush(stdout);
114 }
115
116 void print_title(char *title)
117 {
118 if(title[0]){
119 puts(title);
120 title[0] = 0;
121 }
122 }
123
124 void usage()
125 {
126 printf("affcompare version %s\n",PACKAGE_VERSION);
127 printf("\n");
128 printf("usage: affcompare [options] file1 file2\n");
129 printf(" compares file1 with file2\n");
130 printf("\n");
131 printf("or affcompare [options] -r dir1 dir2\n");
132 printf(" comparses similarly-named files in dir1 and dir2\n");
133 printf("\n");
134 printf("or affcompare [options] -s file1 file2...\n");
135 printf(" Reports if file was successfully copied to Amazon S3\n");
136 printf(" checking only for existence, not reading back the bytes.\n");
137 printf(" (Because all writes to S3 are validated by the MD5 of the object\n");
138 #ifndef USE_S3
139 printf(" NOTE: S3 support is not provided in this version\n");
140 #endif
141
142 printf("fast options:\n");
143 printf("(These compare segments but not their contents.)\n");
144 printf(" -p --- report about the results of preening\n");
145 printf(" -e --- Just report about existence (use with -r)\n");
146 printf(" -s --- Just see if all of the segments are present, but don't\n");
147 printf(" validate the contents. (Primarily for use with Amazon S3)\n");
148
149 printf("other options:\n");
150 printf(" -V --- just print the version number and exit\n");
151 printf(" -v --- Verbose; each file as it is compared.\n");
152 printf(" -q --- Quiet. No output except for errors\n");
153 printf(" -a --- print what's the same (all)\n");
154 printf(" -b --- print the numbers of differing sectors\n");
155 printf(" -c --- print the contents of differing sectors\n");
156 printf(" -m --- Just report about the data (ignore metadata)\n");
157 printf(" -P ### --- Just examine the differences on page ###\n");
158 printf(" -q --- Quiet; no output except for errors.\n");
159 printf("\n");
160 printf("Options documented above:\n");
161 printf(" -r dir1 dir2 --- recursively compare what's in dir1 with dir2, and\n");
162 printf(" report what's in dir1 that's not in dir2\n");
163 printf(" -s --- Check to see if named files are on Amazon S3\n");
164 printf("\n");
165 printf(" affcompare file1.aff file2.aff --- compare file1.aff and file2.aff\n");
166 printf(" affcompare f1.aff f2.aff dir1/ --- compare f1.aff with dir1/f1.aff and f2.aff with dir2/f2.aff\n");
167 printf(" note: dir1/ must end with a slash.\n");
168 printf(" affcompare -b img file.aff --- compare file.aff and file.img\n");
169 printf(" affcompare -b img file1.aff file2.aff... --- compare file1.aff, file1.img, etc.\n");
170 printf(" affcompare -re dir1 dir2 --- report AFF files in dir1 but not in dir2\n");
171 printf(" affcompare -rse dir1 s3:/// --- report AFF files in dir1 but not on S3 (low bandwidth)\n");
172 printf(" affcompare -rs dir1 s3:/// --- report AFF files in dir1 but incomplete on on S3 (more bandwidth)\n");
173 printf("\n");
174 exit(0);
175 }
176
177 void print_sector(AFFILE *af,unsigned char *buf)
178 {
179 for(unsigned int i=0;i<af->image_sectorsize;i++){
180 if(isprint(buf[i])){
181 putchar(buf[i]);
182 }
183 else {
184 putchar('.');
185 }
186 if(i%64==63) putchar('\n');
187 }
188 }
189
190
191 void print_info(char dir,const char *segname,unsigned long arg,size_t len,
192 unsigned char *data,int mcr)
193 {
194 printf(" %c %s arg=%lu len=%d\n",dir,segname,arg,(int)len);
195 printf(" ");
196 if((arg == AF_SEG_QUADWORD) && (len==8)){
197 printf("data=%"I64d" as a 64-bit value\n",af_decode_q(data));
198 return;
199 }
200 /* Otherwise, just print some stuff... */
201 for(unsigned int i=0;i<len && i<60;i++){
202 if(data[i]==' '){
203 putchar(' ');
204 continue;
205 }
206 if(!isprint(data[i])){
207 putchar('.');
208 continue;
209 }
210 putchar(data[i]);
211 }
212 putchar('\n');
213 }
214
215 int compare_aff_metadata_segments(char *title,AFFILE *af1,AFFILE *af2,const char *segname,int mode)
216 {
217 int ret = 0;
218
219 unsigned long arg1 = 0;
220 size_t data1_len = 0;
221 int r1 = af_get_seg(af1,segname,&arg1,0,&data1_len);
222
223 unsigned long arg2 = 0;
224 size_t data2_len = 0;
225 int r2 = af_get_seg(af2,segname,&arg2,0,&data2_len);
226
227 if(r1==0 && r2!=0){
228 if(mode==1){
229 print_title(title);
230 printf(" %s \n",segname);
231 }
232 return 1;
233 }
234
235 if(r1!=0 && r2==0){
236 if(mode==2){
237 print_title(title);
238 printf(" %s \n",segname);
239 }
240 return 1;
241 }
242 if(mode!=3) return 0; // only report differences in mode 3
243 /* Get the actual data... */
244
245 unsigned char *data1 = (unsigned char *)malloc(data1_len);
246 unsigned char *data2 = (unsigned char *)malloc(data2_len);
247
248 int s1 = af_get_seg(af1,segname,&arg1,data1,&data1_len);
249 if(s1!=0) err(1,"Couldn't read data segment %s in %s",segname,af_filename(af1));
250
251 int s2 = af_get_seg(af2,segname,&arg2,data2,&data2_len);
252 if(s2!=0) err(1,"Couldn't read data segment %s in %s",segname,af_filename(af2));
253
254 int mcr = 0;
255
256 if(data1_len != data2_len) mcr = 1;
257 else mcr = memcmp(data1,data2,data1_len);
258 if(arg1!=arg2 || data1_len!=data2_len || mcr!=0){
259 print_title(title);
260 print_info('<',segname,arg1,data1_len,data1,mcr);
261 print_info('>',segname,arg2,data2_len,data2,mcr);
262 if(mcr){
263 printf(" *** Metadata segment are different ");
264 if(strcmp(segname,AF_BADFLAG)==0){
265 printf("(bad flags should be different!)");
266 }
267 putchar('\n');
268 }
269 putchar('\n');
270 ret = 1;
271 }
272 else {
273 if(opt_all){
274 print_title(title);
275 printf(" %s (same in both) \n",segname);
276 }
277 }
278 free(data1);
279 free(data2);
280 return ret;
281 }
282
283 int compare_aff_data_segments(char *title,AFFILE *af1,AFFILE *af2,int64_t pagenum,int mode)
284 {
285 int ret = 0;
286 char pagename[65];
287 snprintf(pagename,sizeof(pagename),AF_PAGE,pagenum);
288
289 char segname[65];
290 snprintf(segname,sizeof(segname),AF_SEG_D,pagenum);
291
292 unsigned long arg1=0;
293 size_t data1_len=0;
294 int r1 = af_get_seg(af1,pagename,&arg1,0,&data1_len);
295 if(r1==-1) r1=af_get_seg(af1,segname,&arg1,0,&data1_len);
296
297 unsigned long arg2=0;
298 size_t data2_len=0;
299 int r2 = af_get_seg(af2,pagename,&arg2,0,&data2_len);
300 if(r2 == -1) r2=af_get_seg(af2,segname,&arg2,0,&data2_len);
301
302 if(r1<0 && r2<0) return 0; // no data segment in either file
303 if(r1==0 && r2!=0){
304 if(mode==1){
305 print_title(title);
306 printf(" %s \n",pagename);
307 }
308 return 1;
309 }
310
311 if(r2==0 && r1!=0){
312 if(mode==2){
313 print_title(title);
314 printf(" %s \n",pagename);
315 }
316 return 1;
317 }
318 if(mode!=3) return 0; // only report differences in mode 3
319
320 /* Get the actual data... */
321 unsigned char *data1 = (unsigned char *)malloc(af_page_size(af1));
322 unsigned char *data2 = (unsigned char *)malloc(af_page_size(af2));
323
324 data1_len = af_page_size(af1);
325 data2_len = af_page_size(af2);
326
327 uint64_t start_sector_number = (pagenum * data1_len) / af1->image_sectorsize;
328
329 /* Find the size of each page, then get the page */
330 if(af_get_page(af1,pagenum,0,&data1_len)<0)
331 err(1,"Cannot read page %"I64d" size from %s\n",pagenum,af_filename(af1));
332 if(af_get_page(af1,pagenum,data1,&data1_len)<0)
333 err(1,"Cannot read page %"I64d" from %s",pagenum,af_filename(af1));
334
335 if(af_get_page(af2,pagenum,0,&data2_len)<0)
336 err(1,"Cannot read page %"I64d" size from %s\n",pagenum,af_filename(af2));
337 if(af_get_page(af2,pagenum,data2,&data2_len)<0)
338 err(1,"Cannot read page %"I64d" from %s",pagenum,af_filename(af2));
339
340 if(data1_len != data2_len){
341 printf("page %"I64d" size %zd != size %zd\n",pagenum,data1_len,data2_len);
342 return 1;
343 }
344
345 /* Now look at the pages sector-by-sector. */
346 int af1_bad=0;
347 int af2_bad=0;
348 int matching_bad_sectors = 0;
349 int matching_sectors = 0;
350 int total_sectors = 0;
351 int no_match = 0;
352 vector<uint64_t> different_sectors;
353
354 for(unsigned int offset=0;offset<data1_len;offset+=af1->image_sectorsize){
355 uint64_t this_sector = start_sector_number + offset/af1->image_sectorsize;
356 total_sectors++;
357 if(af_is_badsector(af1,data1+offset) &&
358 af_is_badsector(af2,data2+offset)){
359 matching_bad_sectors++;
360 continue;
361 }
362 if(af_is_badsector(af1,data1+offset)){
363 af1_bad++;
364 continue;
365 }
366 if(af_is_badsector(af2,data2+offset)){
367 af2_bad++;
368 continue;
369 }
370 if(memcmp(data1+offset,data2+offset,af1->image_sectorsize)==0){
371 matching_sectors++;
372 continue;
373 }
374 no_match++;
375 different_sectors.push_back(this_sector);
376 }
377
378 char outline[256];
379 outline[0] = 0;
380 if(opt_all || (no_match>0) || af1_bad || af2_bad){
381 snprintf(outline,sizeof(outline),
382 " page%"I64d" sectors:%4d matching: %3d different:%3d",
383 pagenum,total_sectors,matching_sectors,no_match);
384 }
385 if(af1_bad){
386 snprintf(outline+strlen(outline),sizeof(outline)-strlen(outline),
387 " file 1 bad: %3d ",af1_bad);
388 }
389 if(af2_bad){
390 snprintf(outline+strlen(outline),sizeof(outline)-strlen(outline),
391 " file 2 bad: %3d ",af2_bad);
392 }
393 if(matching_bad_sectors){
394 if(opt_all){
395 snprintf(outline+strlen(outline),sizeof(outline)-strlen(outline),
396 " bad both:%3d ",matching_bad_sectors);
397 }
398 }
399
400 if(outline[0]){
401 print_title(title);
402 puts(outline);
403 }
404 if(opt_print_sectors && different_sectors.size()>0){
405 print_title(title);
406 printf(" Sectors with differences:");
407 int i=0;
408 for(vector<uint64_t>::iterator j = different_sectors.begin();
409 j != different_sectors.end();
410 j++){
411 if(i==0){
412 printf("\n ");
413 }
414 printf(" %"I64d,*j);
415 i = (i+1) % 10;
416 }
417 putchar('\n');
418 ret = 1;
419 }
420 if(opt_print_sector_contents && different_sectors.size()>0){
421 print_title(title);
422 printf(" Sectors with differences:");
423 for(vector<uint64_t>::iterator j = different_sectors.begin();
424 j != different_sectors.end(); j++){
425 int offset = (*j - start_sector_number)*af1->image_sectorsize;
426 char b2[16];
427 printf("offset=%d\n",offset);
428
429 memcpy(b2,data1+offset,16);
430 b2[15]=0;
431
432 printf("=== sector %"I64d" (offset=%d) ===\n",*j,offset);
433 printf(" %s:\n",af_filename(af1));
434 print_sector(af1,data1+offset);
435 printf("-------------------------------------\n");
436 printf(" %s:\n",af_filename(af2));
437 print_sector(af2,data2+offset);
438 printf("=====================================\n\n");
439 }
440 ret = 1;
441 }
442 free(data1);
443 free(data2);
444 return ret;
445 }
446
447 /* Compare the results of two files that were preened */
448 int compare_preen(AFFILE *af1,AFFILE *af2)
449 {
450 vector<int64_t> pages;
451 int comp_zero=0;
452 int comp_lzma=0;
453 int comp_unchanged=0;
454 uint64_t bytes_old = 0;
455 uint64_t bytes_new = 0;
456
457 af_rewind_seg(af1);
458 /* Build a list of all the pages */
459 char segname[AF_MAX_NAME_LEN];
460 while(af_get_next_seg(af1,segname,sizeof(segname),0,0,0)==0){
461 int64_t pagenumber = af_segname_page_number(segname);
462 if(pagenumber>=0) pages.push_back(pagenumber);
463 }
464 /* Now, compare each one */
465 for(vector<int64_t>::const_iterator i = pages.begin(); i != pages.end(); i++){
466 unsigned long arg1,arg2;
467 size_t len1,len2;
468
469 if(af_get_page_raw(af1,*i,&arg1,0,&len1)){
470 err(1,"Could not read page %"I64d" in file %s\n",*i,af_filename(af1));
471 }
472 if(af_get_page_raw(af2,*i,&arg2,0,&len2)){
473 err(1,"Page %"I64d" is in file %s but not in %s\n",*i,af_filename(af1),
474 af_filename(af2));
475 }
476 if(arg1==arg2 && len1==len2){
477 comp_unchanged++;
478 continue;
479 }
480 if((arg2 & AF_PAGE_COMP_ALG_MASK)==AF_PAGE_COMP_ALG_ZERO){
481 comp_zero++;
482 continue;
483 }
484 if((arg2 & AF_PAGE_COMP_ALG_MASK)==AF_PAGE_COMP_ALG_LZMA){
485 comp_lzma++;
486 bytes_old += len1;
487 bytes_new += len2;
488 continue;
489 }
490 }
491 printf("%s -> %s Nochg: %d NUL: %d LZMA: %d old: %"I64d" new: %"I64d" LZred: %6.2f%%\n",
492 af_filename(af1),
493 af_filename(af2),
494 comp_unchanged,comp_zero,comp_lzma,bytes_old,bytes_new,(bytes_old-bytes_new)*100.0/bytes_old);
495 return 0;
496 }
497
498
499 /* Compare two AFF files.
500 * Return 0 if they are equal.
501 */
502 int compare_aff_aff(const char *file1,const char *file2)
503 {
504 bool no_data_segments = false;
505 int ret = 0;
506
507 current_source = file1;
508
509 if(opt_all) printf("compare %s and %s:\n",file1,file2);
510
511 AFFILE *af1 = af_open(file1,O_RDONLY,0);
512 if(!af1) af_err(1,"af_open(%s)",file1);
513
514 AFFILE *af2 = af_open(file2,O_RDONLY,0);
515 if(!af2) af_err(1,"af_open(%s)",file2);
516
517 af_vnode_info vni1,vni2;
518
519 if(af_vstat(af1,&vni1) || af_vstat(af2,&vni2)){
520 err(1,"af_vstat failed?");
521 }
522
523 if(af_cannot_decrypt(af1) != af_cannot_decrypt(af2)){
524 printf("%s: %s decrypt\n",file1,af_cannot_decrypt(af1) ? "cannot" : "can");
525 printf("%s: %s decrypt\n",file2,af_cannot_decrypt(af2) ? "cannot" : "can");
526 fprintf(stderr,"affcompare must be able to decrypt both files or neither of the files.\n");
527 exit(1);
528 }
529
530 if(af1->image_pagesize != af2->image_pagesize){
531 fprintf(stderr,"Currently, %s requires that both images have the "
532 "same image datsegsize.\n"
533 "pagesize(%s)=%ld\n"
534 "pagesize(%s)=%ld\n",
535 progname,file1,af1->image_pagesize,
536 file2,af2->image_pagesize);
537 fprintf(stderr,"Data segments will be ignored.\n");
538 no_data_segments = true;
539 }
540
541 if(af1->image_sectorsize != af2->image_sectorsize){
542 fprintf(stderr,"Currently, %s requires that both images have the "
543 "same image sectorsize.\n"
544 "sectorsize(%s)=%ld\n"
545 "sectorsize(%s)=%ld\n",
546 progname,file1,af1->image_sectorsize, file2,af2->image_sectorsize);
547 fprintf(stderr,"Data segments will be ignored.\n");
548 no_data_segments = true;
549 }
550
551 if(opt_preen){
552 compare_preen(af1,af2);
553 af_close(af1);
554 af_close(af2);
555 return 0;
556 }
557
558 if(opt_s3){
559 printf("bypass\n");
560 seglist list1(af1);
561 seglist list2(af2);
562
563 /* Just compare the presence/absence of each segment */
564 char title[1024];
565 snprintf(title,sizeof(title),"\nPresent in %s but not %s:",af_filename(af1),af_filename(af2));
566 for(seglist::const_iterator i=list1.begin(); i!=list1.end(); i++){
567 if(find(list2.begin(),list2.end(),*i)==list2.end()){
568 print_title(title);
569 printf(" %s\n",(*i).name.c_str());
570 }
571 }
572 snprintf(title,sizeof(title),"\nPresent in %s but not %s:",af_filename(af2),af_filename(af1));
573 for(seglist::const_iterator i=list2.begin(); i!=list2.end(); i++){
574 if(find(list1.begin(),list1.end(),*i)==list1.end()){
575 print_title(title);
576 printf(" %s\n",(*i).name.c_str());
577 }
578 }
579 return 0;
580 }
581
582 /* Compare all of the metadata segments in af1 with a2.
583 * Report those that are missing or different. Then report
584 * all of the segments in a2 but not in af1
585 */
586
587 /* First build a list of the segments in each */
588
589 vector <string> segs_with_dups;
590
591 AFFILE *af[2] = {af1,af2};
592 for(int i=0;i<2;i++){
593 if(opt_verbose) printf("\n%s:\n",af_filename(af[i]));
594 af_rewind_seg(af[i]);
595 char segname[AF_MAX_NAME_LEN];
596 while(af_get_next_seg(af[i],segname,sizeof(segname),0,0,0)==0){
597 if(segname[0]){
598 string s;
599 s = segname;
600 segs_with_dups.push_back(s); // may give duplicates
601 if(opt_verbose) printf(" %s\n",segname);
602 }
603 }
604 }
605 sort(segs_with_dups.begin(),segs_with_dups.end());
606 vector<string>segs;
607
608 /* Make a list of segs without duplicates */
609 string last;
610 for(vector<string>::iterator i = segs_with_dups.begin();
611 i != segs_with_dups.end(); i++){
612 if(last != *i){
613 segs.push_back(*i);
614 }
615 last = *i;
616 }
617
618 int lowest_page = -1;
619 int highest_page = -1;
620 /* Scan for the lowest and highest numbers */
621 for(vector<string>::iterator i = segs.begin();i != segs.end(); i++){
622 int64_t num = af_segname_page_number(i->c_str());
623 if(num!=-1){
624 if(num<lowest_page ||lowest_page==-1) lowest_page = num;
625 if(num>highest_page||highest_page==-1) highest_page = num;
626 }
627 }
628
629
630 if(opt_page != -1){
631 lowest_page = opt_page;
632 highest_page = opt_page;
633 }
634
635
636 if(opt_page == -1
637 && vni1.supports_metadata
638 && vni2.supports_metadata
639 && opt_ignore_metadata==0 ){
640 if(opt_all) puts("Inspecting metadata...");
641 for(int mode=1;mode<=3;mode++){
642 const char *title = "Metadata segments ";
643 char mode_title[1024];
644 switch(mode){
645 case 1:
646 snprintf(mode_title,sizeof(mode_title)," %s only in %s:\n",
647 title,af_filename(af1));
648 break;
649 case 2:
650 snprintf(mode_title,sizeof(mode_title)," %s only in %s:\n",
651 title,af_filename(af2));
652 break;
653 case 3:
654 snprintf(mode_title,sizeof(mode_title)," %s in both files:\n",title);
655 break;
656 }
657
658 for(vector<string>::iterator i = segs.begin();i != segs.end();i++){
659 int64_t num = af_segname_page_number(i->c_str());
660 if(num==-1){
661 int r = compare_aff_metadata_segments(mode_title, af1,af2,
662 i->c_str(),mode);
663 if(r!=0) ret = r;
664 }
665 }
666 }
667 }
668
669 if(no_data_segments==false){
670 if(opt_all) puts("Inspecting data...");
671 for(int mode=1;mode<=3;mode++){
672 char mode_title[1024];
673 switch(mode){
674 case 1: snprintf(mode_title,sizeof(mode_title),
675 " Pages only in %s:\n", af_filename(af1));break;
676 case 2: snprintf(mode_title,sizeof(mode_title),
677 " Pages only in %s:\n", af_filename(af2));break;
678 case 3: snprintf(mode_title,sizeof(mode_title)," Pages in both files:\n");break;
679 }
680
681 for(int i=lowest_page;i<=highest_page;i++){
682 int r = compare_aff_data_segments(mode_title,af1,af2,i,mode);
683 if(r!=0) ret = r;
684 }
685 }
686 }
687 current_source = 0;
688 #ifdef HAVE_ISATTY
689 if(ret==0 && isatty(fileno(stdout))) printf("%s and %s: files compare okay\n",file1,file2);
690 #endif
691 return ret;
692 }
693
694 int recurse(const char *dir1,const char *dir2)
695 {
696 vector<string> only_in_dir1;
697
698 DIR *dirp = opendir(dir1);
699 struct dirent *dp;
700 if(!dirp) err(1,"opendir: %s",dir1);
701 while ((dp = readdir(dirp)) != NULL){
702
703 char fn1[MAXPATHLEN+1]; memset(fn1,0,sizeof(fn1));
704 char fn2[MAXPATHLEN+1]; memset(fn2,0,sizeof(fn2));
705
706 strlcpy(fn1,dir1,sizeof(fn1));
707 if(fn1[strlen(fn1)-1]!='/') strlcat(fn1,"/",sizeof(fn1));
708 strlcat(fn1,dp->d_name,sizeof(fn1));
709
710 current_source = fn1;
711 if(opt_verbose) printf("%s...\n",fn1);
712
713 switch(af_identify_file_type(fn1,1)){
714 case AF_IDENTIFY_ERR:
715 case AF_IDENTIFY_NOEXIST:
716 only_in_dir1.push_back(fn1);
717 break;
718 case AF_IDENTIFY_AFF:
719 case AF_IDENTIFY_AFD:
720 case AF_IDENTIFY_AFM:
721 strlcpy(fn2,dir2,sizeof(fn2));
722 if(fn2[strlen(fn2)-1]!='/') strlcat(fn2,"/",sizeof(fn2));
723 strlcat(fn2,dp->d_name,sizeof(fn2));
724 if(af_identify_file_type(fn2,1)<0){
725 char buf[1024];
726 snprintf(buf,sizeof(buf),"%s not in %s\n",dp->d_name,dir2);
727 errors.push_back(buf);
728 break;
729 }
730 if(opt_exist==0){
731 compare_aff_aff(fn1,fn2);
732 }
733 break;
734 default:
735 break;
736 }
737 }
738 closedir(dirp);
739 printf("========================\n");
740 printf("Only in %s\n",dir1);
741 for(vector<string>::const_iterator i = only_in_dir1.begin();
742 i != only_in_dir1.end();
743 i++){
744 printf("%s\n",i->c_str());
745 }
746 return 0;
747 }
748
749 int main(int argc,char **argv)
750 {
751 int bflag, ch;
752 int opt_recurse=0;
753
754 #ifdef SIGINFO
755 signal(SIGINFO,sig_info);
756 #endif
757
758 bflag = 0;
759 while ((ch = getopt(argc, argv, "P:Vabcempqrsh?v")) != -1) {
760 switch (ch) {
761 case 'P': opt_page = atoi(optarg); break;
762 case 'V': printf("%s version %s\n",progname,PACKAGE_VERSION); exit(0);
763 case 'a': opt_all++; break;
764 case 'b': opt_print_sectors=1; break;
765 case 'c': opt_print_sector_contents=1; break;
766 case 'e': opt_exist++; break;
767 case 'm': opt_ignore_metadata++; break;
768 case 'p': opt_preen++; break;
769 case 'q': opt_quiet++; break;
770 case 'r': opt_recurse++; break;
771 case 's': opt_s3++;break;
772 case 'v': opt_verbose++;break;
773 case 'h':
774 case '?':
775 default:
776 usage();
777 }
778 }
779 argc -= optind;
780 argv += optind;
781
782 if(opt_recurse){
783 if(argc!=2) usage();
784 char *dir1 = *argv++;
785 char *dir2 = *argv++;
786 recurse(dir1,dir2);
787 if(errors.size()>0){
788 fprintf(stderr,"================================\n");
789 fprintf(stderr,"%zd affcompare errors:\n",errors.size());
790 for(vector<string>::const_iterator i=errors.begin();
791 i!=errors.end();
792 i++){
793 fputs(i->c_str(),stderr);
794 }
795 exit(1);
796 }
797 exit(0);
798 }
799
800 if(argc>1){
801 char *last = argv[argc-1];
802 if(last[strlen(last)-1]=='/'){
803 while(argc>1){
804 char *file1 = *argv;
805 char *name1 = file1;
806 char *cc;
807
808 cc = strrchr(file1,'/');
809 if(cc) name1 = cc+1;
810
811 char file2[MAXPATHLEN+1];
812 strlcpy(file2,last,sizeof(file2));
813 strlcat(file2,name1,sizeof(file2));
814 int e_code = compare_aff_aff(file1,file2);
815 if(e_code) exit(e_code);
816 argv++;
817 argc--;
818 }
819 }
820 }
821
822 if(argc!=2) usage(); // if just 2, compare them
823
824 char *file1 = *argv++;
825 char *file2 = *argv++;
826
827 if(opt_verbose) printf("%s...\n",file1);
828 int e_code = compare_aff_aff(file1,file2);
829 exit(e_code);
830 }
0 /*
1 * affconvert.cpp:
2 *
3 * Convert raw -> aff
4 * aff -> raw
5 * aff -> aff (recompressing/uncompressing)
6 */
7
8 /*
9 * Copyright (c) 2005--2008
10 * Simson L. Garfinkel and Basis Technology, Inc.
11 * All rights reserved.
12 *
13 * This code is derrived from software contributed by
14 * Simson L. Garfinkel
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. All advertising materials mentioning features or use of this software
25 * must display the following acknowledgement:
26 * This product includes software developed by Simson L. Garfinkel,
27 * Basis Technology, and its contributors.
28 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
29 * contributors to this program may be used to endorse or promote
30 * products derived from this software without specific prior written
31 * permission.
32 *
33 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
34 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
35 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
36 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
38 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
39 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
41 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
42 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
43 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
44 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 */
47
48
49
50 #include "affconfig.h"
51 #include "afflib.h"
52 #include "afflib_i.h" // we do enough mucking, we need the internal version
53 #include "utils.h"
54
55 #include <openssl/md5.h>
56 #include <openssl/sha.h>
57
58 #ifdef WIN32
59 #include "unix4win32.h"
60 #endif
61
62 #ifdef HAVE_CURSES_H
63 #include <curses.h>
64 #endif
65
66 #ifdef HAVE_TERM_H
67 #include <term.h>
68 #endif
69
70
71 #ifdef HAVE_SYS_TIME_H
72 #include <sys/time.h>
73 #endif
74
75 #include <sys/stat.h>
76 #include <string>
77
78 #ifdef HAVE_UNISTD_H
79 #include <unistd.h>
80 #endif
81
82 #ifdef HAVE_GETOPT_H
83 #include <getopt.h>
84 #endif
85
86
87
88 const char *progname = "affconvert";
89
90 int image_pagesize = 16*1024*1024; // default seg size --- 16MB
91 int opt_compression_alg = AF_COMPRESSION_ALG_ZLIB;
92 int opt_compress_level = AF_COMPRESSION_DEFAULT;
93 int64_t bytes_to_convert = 0;
94 int opt_batch = 1;
95 int opt_zap = 0;
96 int opt_quiet = 0;
97 int opt_write_raw = 0; // output
98 int opt_probe_compressed = 1; // probe for compressed files
99 const char *opt_write_raw_ext = "raw";
100 const char *opt_outdir = 0;
101 const char *opt_aff_ext = "aff";
102 int64_t opt_maxsize = 0;
103 int opt_yes = 0;
104 int opt_debug = 0;
105 std::string command_line;
106
107
108 char *append(char *base,const char *str)
109 {
110 base = (char *)realloc(base,strlen(base)+strlen(str)+1);
111 strcat(base,str); // can't fail
112 return base;
113 }
114
115
116
117 void usage()
118 {
119 printf("%s version %s\n",progname,PACKAGE_VERSION);
120 printf("\n");
121 printf("usage: %s [options] file1 [... files] \n",progname);
122 printf("\n");
123 printf("examples:\n");
124 printf(" %s file1.iso --- convert file1.iso to file1.aff\n",progname);
125 printf(" %s file1.iso file2.iso file3.iso... --- batch convert files\n",progname);
126 printf(" %s -r -e iso image.aff --- convert image.aff to image.iso\n",progname);
127 printf(" %s -M4g -o/media/dvd.afd bigfile.aff --- split an AFF file into 4GB chunks for archiving to DVD\n",
128 progname);
129 //printf(" %s -p image.aff --- recompress image.aff to maximum compression\n",progname);
130 printf("\n");
131 printf("\nGeneral options:\n");
132 printf(" -q -- Quiet mode. Don't ask questions, don't print status.\n");
133
134 printf("\nAFF output options:\n");
135 printf(" -a ext -- use 'ext' for aff files (default is %s)\n",opt_aff_ext);
136 printf(" (use .afd for AFD files)\n");
137 printf(" -Mn[kgm] -- set maximum size of output file. Suffix with g, m or k.\n");
138 printf(" -sn -- set the image_pagesize (default %d)\n",image_pagesize);
139 printf(" -x -- don't compress AFF file.\n");
140 printf(" -O dir -- use 'dir' as the output directory\n");
141 printf(" -o file -- output to 'file' (can only convert one at a time)\n");
142 printf(" File is AFF is file ends .aff; otherwise assumes raw.\n");
143 printf(" -Xn -- Set compression to n; default is 7\n");
144 printf(" -L -- Use the LZMA compression algorithm (better but slower)\n");
145
146 printf("\nRaw output options:\n");
147 printf(" -r -- force raw output. \n");
148 printf(" -e ext -- use 'ext' for the raw files (default %s)\n",opt_write_raw_ext);
149 printf(" (implies -r)\n");
150
151 printf("\nDangerous input options:\n");
152 printf(" -z -- zap; delete the output file if it already exists.\n");
153 printf(" -Z -- Do not automatically probe for gzip/bzip2 compression.\n");
154 printf(" -y -- Always answer yes/no questions 'yes.'\n");
155 printf(" -V = Just print the version number and exit.\n");
156 printf("\n");
157 exit(0);
158 }
159
160
161 /* probe_gzip():
162 * Is this a gzip file?
163 * Right now it just looks at the file extension.
164 */
165
166 int probe_gzip(const char *infile)
167 {
168 int len = strlen(infile);
169
170 if(len>3 && strcmp(infile+len-3,".gz")==0){
171 return 1;
172 }
173 return 0;
174 }
175
176 int probe_bzip2(const char *infile)
177 {
178 int len = strlen(infile);
179
180 if(len>4 && strcmp(infile+len-4,".bz2")==0){
181 return 1;
182 }
183 return 0;
184 }
185
186 /* yesno():
187 * As a yes/no question. Return 1 if yes, 0 if no.
188 */
189
190 int yesno(const char *statement,const char *question,const char *affirmative)
191 {
192 if(opt_yes){
193 if(!opt_quiet) printf("%s. %s.\n",statement,affirmative);
194 return 1;
195 }
196
197 printf("%s. ",statement);
198 char buf[256];
199 do {
200 printf("%s [y/n]: ",question);
201 memset(buf,0,sizeof(buf));
202 if(fgets(buf,sizeof(buf)-1,stdin)==0) return 0;
203 if(buf[0]=='y' || buf[0]=='Y'){
204 printf("%s.\n",affirmative);
205 return 1;
206 }
207 } while(buf[0]!='n' && buf[0]!='N');
208 return 0;
209 }
210
211
212 /*
213 * Basic conversion:
214 * We have an input, which may be raw or aff,
215 * and we have an output, which may be raw or aff.
216 * We are going to want to read a segment at a time.
217 */
218
219
220 #include <algorithm>
221 #include <cstdlib>
222 #include <vector>
223 #include <string>
224
225 #ifdef HAVE_CSTRING
226 #include <cstring>
227 #endif
228
229
230 using namespace std;
231
232 /** Do the conversion.
233 * return 0 if success, code if fail.
234 */
235 int convert(const char *infile,char *outfile)
236 {
237
238 if(opt_debug) fprintf(stderr,"convert(%s,%s)\n",infile,outfile);
239
240 if(infile && outfile && strcmp(infile,outfile)==0){
241 errx(1,"Can't convert a file to itself\n");
242 }
243
244 /****************************************************************
245 *** Open Input
246 ****************************************************************/
247
248 AFFILE *a_in = 0; // input file, if aff
249
250 #ifdef UNIX
251 /* Check to see if it is a gzip file... */
252 if(opt_probe_compressed
253 && probe_gzip(infile)
254 && yesno("infile looks like a gzip file","Uncompress it","Uncompressing")){
255 /* Open with a subprocess. We will need to use zlib when we move to Windows. */
256 if(af_hasmeta(infile)) return -1; // don't covert with shell metacharacters
257 char buf[256];
258 snprintf(buf,sizeof(buf),"gzcat %s",infile);
259 a_in = af_popen(buf,"r");
260 }
261
262 /* Check to see if it is a bzip2 file... */
263 if(!a_in
264 && opt_probe_compressed
265 && probe_bzip2(infile)
266 && yesno("infile looks like a bzip2 file","Uncompress it","Uncompressing")){
267 /* Open with a subprocess. We will need to use bzip2zlib when we move to Windows. */
268 if(af_hasmeta(infile)) return -1; // don't covert with shell metacharacters
269 char buf[256];
270 snprintf(buf,sizeof(buf),"bzcat %s",infile);
271 a_in = af_popen(buf,"r");
272 }
273 #endif
274
275 /* If the file isn't open, try to open it... */
276 if(!a_in){
277 a_in = af_open(infile,O_RDONLY,0);
278 if(!a_in) af_err(1,"%s",infile); // give up
279 if(af_identify(a_in)==AF_IDENTIFY_RAW){
280 af_set_pagesize(a_in,image_pagesize); // match the page size we want to use
281 }
282 else {
283 image_pagesize = a_in->image_pagesize; // that's what we are using
284 }
285 }
286
287 const char *ain_fn = af_filename(a_in);
288 struct stat si;
289 memset((char *)&si,0,sizeof(si));
290 if(ain_fn && stat(ain_fn,&si)){
291 warn("Cannot stat %s",ain_fn);
292 }
293
294
295 /****************************************************************
296 *** Open Ouptut
297 ****************************************************************/
298
299
300 if(opt_zap) unlink(outfile); // we were told to zap it
301
302 AFFILE *a_out = 0; // output file, if aff or raw...
303 if(access(outfile,F_OK)==0){
304 /* If outfile is a device, ask user... */
305 struct stat so;
306 if(stat(outfile,&so)){
307 err(1,"%s exists but can't be stat?",outfile);
308 }
309 if((so.st_mode & S_IFMT)==S_IFCHR ||
310 (so.st_mode & S_IFMT)==S_IFBLK){
311 char buf[1024];
312 snprintf(buf,sizeof(buf),"%s is a raw device.\n",outfile);
313 if(yesno(buf,"Overwrite raw device?","yes")){
314 goto doit;
315 }
316 }
317 fprintf(stderr,"%s: file exists. Delete it before converting.\n",outfile);
318 exit(-1);
319 }
320 /* Check for splitraw names */
321 if(af_ext_is(outfile,"afm")){
322 char file000[MAXPATHLEN+1];
323 strlcpy(file000,outfile,sizeof(file000));
324 char *cc = strrchr(file000,'.');
325 if(!cc) err(1,"Cannot file '.' in %s\n",file000);
326 for(int i=0;i<2;i++){
327 sprintf(cc,".%03d",i);
328 if(access(file000,F_OK)==0){
329 fprintf(stderr,"%s: file exists. Delete it before converting.\n",file000);
330 fprintf(stderr,"NOTE: -z option will not delete %s\n",file000);
331 return -1;
332 }
333 }
334 }
335
336 doit:;
337
338 if(opt_write_raw){
339 /* Easy way to make a raw output is to reopen an existing output file... */
340 FILE *f = fopen(outfile,"w+b");
341 if(!f){
342 err(1,"%s",outfile);
343 }
344 a_out = af_freopen(f);
345 }
346 else {
347 a_out = af_open(outfile,O_RDWR|O_CREAT|O_BINARY,0777);
348 if(!a_out) af_err(1,"%s",outfile);
349 if(opt_maxsize){
350 af_set_maxsize(a_out,opt_maxsize);
351 }
352
353 }
354 if(a_out == 0) af_err(1,"af_open: %s",outfile);
355
356 if(!opt_quiet) printf("convert %s --> %s\n",infile,outfile);
357
358 af_update_seg(a_out,AF_ACQUISITION_COMMAND_LINE,0,
359 (const u_char *)command_line.c_str(),
360 command_line.size());
361
362 /****************************************************************
363 *** Set up the AFF file (assuming it's an aff file)
364 *** stuff that we keep at the beginning of the file...
365 ****************************************************************/
366
367 MD5_CTX md5;
368 MD5_Init(&md5);
369
370 SHA_CTX sha;
371 SHA1_Init(&sha);
372
373 /* Setup writing */
374 if(a_in->image_pagesize){
375 image_pagesize = a_in->image_pagesize;
376 }
377 af_set_pagesize(a_out,image_pagesize);
378 af_set_sectorsize(a_out,a_in->image_sectorsize);
379
380 struct af_vnode_info vni;
381 af_vstat(a_out,&vni);
382 if(vni.supports_compression){
383 if(opt_compression_alg){
384 af_enable_compression(a_out,opt_compression_alg,opt_compress_level);
385 }
386 else{
387 af_enable_compression(a_out,0,0);
388 }
389 }
390
391 /* Get a list of all the metadata segments and the pages
392 * (if this is a raw file, then the vnode raw driver will give us those segments)
393 */
394
395 char segname[AF_MAX_NAME_LEN];
396 vector <string> metadata_segments;
397 vector <int64_t> pages;
398 af_rewind_seg(a_in); // start at the beginning
399 int64_t highest_pagenum = 0;
400 while(af_get_next_seg(a_in,segname,sizeof(segname),0,0,0)==0){
401 int64_t page_num = af_segname_page_number(segname);
402 if(page_num>=0){
403 pages.push_back(page_num);
404 if(page_num>highest_pagenum) highest_pagenum = page_num;
405 }
406 else {
407 metadata_segments.push_back(segname);
408 }
409 }
410
411 /* Copy over all of the metadata segments.
412 * But don't bother if we are creating raw output
413 */
414 if(opt_write_raw==0){
415 for(vector<string>::iterator i = metadata_segments.begin();
416 i != metadata_segments.end();
417 i++){
418 strlcpy(segname,i->c_str(),sizeof(segname));
419 size_t data_len = 0;
420 unsigned long arg;
421
422 /* First find out how big the segment is */
423 if(af_get_seg(a_in,segname,&arg,0,&data_len)){
424 warn("af_get_seg_1");
425 continue;
426 }
427 /* Now get the data */
428 unsigned char *data = (unsigned char *)malloc(data_len);
429 if(af_get_seg(a_in,segname,0,data,&data_len)){
430 warn("af_get_seg_2");
431 free(data);
432 continue;
433 }
434 /* Now put the data */
435 if(af_update_seg(a_out,segname,arg,data,data_len)){
436 err(1,"af_update_seg");
437 }
438 free(data);
439 }
440 }
441
442 /* Now sort the pages and copy them over. If there is no break,
443 * we can compute the hashes...
444 */
445 sort(pages.begin(),pages.end());
446
447 int64_t prev_pagenum = -1;
448 bool hash_valid = true;
449 uint64_t last_byte_in_image = 0;
450 uint64_t total_bytes_converted = 0;
451
452 bool copy_by_pages = af_has_pages(a_in);
453
454 unsigned char *data = (unsigned char *)malloc(image_pagesize);
455 if(copy_by_pages){
456 /* Copy over data one page at a time */
457 for(vector<int64_t>::iterator i = pages.begin(); i != pages.end(); i++){
458
459 int64_t pagenum = *i;
460
461 if(!opt_quiet) printf("Converting page %"I64d" of %"I64d"\r",pagenum,highest_pagenum);fflush(stdout);
462
463 size_t data_len = image_pagesize;
464 if(af_get_page(a_in,pagenum,data,&data_len)){
465 err(1,"af_get_page(file=%s,page=%"I64d")",
466 af_filename(a_in),pagenum);
467 }
468 if(af_update_page(a_out,pagenum,data,data_len)){
469 err(1,"af_update_page(file=%s,page=%"I64d")",
470 af_filename(a_out),pagenum);
471 }
472
473 if(pagenum != prev_pagenum + 1) hash_valid = false;
474
475 if(hash_valid && vni.supports_metadata){
476 MD5_Update(&md5,data,data_len);
477 SHA1_Update(&sha,data,data_len);
478 prev_pagenum = pagenum;
479 }
480 last_byte_in_image = (int64_t)image_pagesize * pagenum + (int64_t)data_len;
481 total_bytes_converted += data_len;
482 }
483 /* Go back and update the image size (necessary since I have been writing page-by-page) */
484 if(af_update_segq(a_out,AF_IMAGESIZE,last_byte_in_image)
485 && errno!=ENOTSUP){
486 err(1,"Could not upate AF_IMAGESIZE");
487 }
488 } else {
489 /* No page support; Copy from beginning to end */
490 while(!af_eof(a_in)){
491 int data_len = af_read(a_in,data,image_pagesize);
492 if(data_len>0){
493 if(!opt_quiet){
494 printf("Writing to page %" I64d " with %d bytes read from input... \r",
495 total_bytes_converted / image_pagesize,data_len);
496 fflush(stdout);
497 }
498 if(af_write(a_out,data,data_len)!=data_len){
499 err(1,"af_write");
500 }
501 if(vni.supports_metadata){
502 MD5_Update(&md5,data,data_len);
503 SHA1_Update(&sha,data,data_len);
504 }
505 }
506 if(data_len<0) err(1,"af_read");
507 if(data_len==0){
508 if(!opt_quiet) printf("af_read returned 0. Reached a sparse region or end of pipe.\n");
509 break;
510 }
511 last_byte_in_image += data_len;
512 total_bytes_converted += data_len;
513 }
514 }
515 free(data);
516 if(!opt_quiet) printf("\n");
517
518 /* Write out the new hash if it is valid */
519 if(hash_valid && vni.supports_metadata){
520 u_char md5_buf[32],sha1_buf[40];
521 char buf[256];
522 MD5_Final(md5_buf,&md5);
523 if(af_update_seg(a_out,AF_MD5,0,md5_buf,16) && errno!=ENOTSUP){
524 err(1,"Could not update AF_MD5");
525 }
526 if(!opt_quiet) printf("md5: %s\n",af_hexbuf(buf,sizeof(buf),md5_buf,16,1));
527
528 SHA1_Final(sha1_buf,&sha);
529 if(af_update_seg(a_out,AF_SHA1,0,sha1_buf,20) && errno!=ENOTSUP){
530 err(1,"Could not update AF_SHA1");
531 }
532 if(!opt_quiet) printf("sha1: %s\n",af_hexbuf(buf,sizeof(buf),sha1_buf,20,1));
533 }
534
535 /* Finish the hash calculations and write to the db */
536 if(!opt_quiet){
537 printf("bytes converted: %"I64d" \n",total_bytes_converted);
538 /* If the vnode implementation tracked segments written, report it. */
539 if(a_out->pages_written || a_out->pages_compressed){
540 printf("Total pages: %"I64u" (%"I64u" compressed)\n",
541 a_out->pages_written,a_out->pages_compressed);
542 }
543 }
544
545 if(vni.supports_metadata){
546 /* make an AF_IMAGE_GID if it doesn't exist */
547 af_make_gid(a_out);
548 af_set_acquisition_date(a_out,si.st_mtime);
549 }
550
551 /* Make a copy of the a_out filename if we can get it */
552 char *a_out_fn=0; // output filename, to remember for utimes
553 const char *a_ = af_filename(a_out); // remember the output filename
554 if(a_){
555 a_out_fn = strdup(a_); // make a copy of it
556 }
557 if(af_close(a_out)) err(1,"af_close(a_out)");
558
559 if(!opt_quiet){
560 printf("Conversion finished.\n");
561 if(af_cannot_decrypt(a_in)){
562 printf("*** encrypted pages are present which could not be decrypted ***\n");
563 }
564 printf("\n\n");
565 }
566 if(af_close(a_in)) err(1,"af_close(a_in)");
567
568 /* Set the utime on the resulting file if we can stat it */
569 struct timeval times[2];
570
571 memset(times,0,sizeof(times));
572 times[0].tv_sec = si.st_atime;
573 times[1].tv_sec = si.st_mtime;
574 #ifdef HAVE_UTIMES
575 if(a_out_fn){
576 if(utimes(a_out_fn,times)) warn("utimes(%s):",outfile);
577 free(a_out_fn);
578 a_out_fn = 0;
579 }
580 #endif
581 return(0);
582 }
583
584
585 int64_t atoi64(const char *buf)
586 {
587 int64_t r=0;
588 sscanf(buf,"%"I64d,&r);
589 return r;
590 }
591
592 int64_t atoi64m(const char *optarg)
593 {
594 int multiplier;
595 switch(optarg[strlen(optarg)-1]){
596 case 'g':
597 case 'G':
598 multiplier=1024*1024*1024;break;
599 case 'm':
600 case 'M':
601 multiplier=1024*1024; break;
602 case 'k':
603 case 'K':
604 multiplier=1024; break;
605 case 'b':
606 case 'B':
607 multiplier=1;break;
608 default:
609 err(1,"Specify multiplier units of g, m, k or b in '%s'\n",optarg);
610 }
611 return atoi64(optarg) * multiplier;
612 }
613
614
615 int main(int argc,char **argv)
616 {
617 char *outfile = 0;
618 int ch;
619
620 command_line = aff::command_line(argc,argv);
621 while ((ch = getopt(argc, argv, "a:e:Lo:zqrs:xX:Zh?M:O::ydV")) != -1) {
622 switch (ch) {
623 case 'a':
624 opt_aff_ext = optarg;
625 break;
626 case 'e':
627 opt_write_raw++;
628 opt_write_raw_ext = optarg;
629 break;
630 case 'o':
631 outfile = optarg;
632 break;
633 case 'z':
634 opt_zap ++;
635 break;
636 case 'q':
637 opt_quiet++;
638 break;
639 case 'L':
640 opt_compression_alg = AF_COMPRESSION_ALG_LZMA;
641 break;
642 case 'r':
643 opt_write_raw++;
644 break;
645 case 's':
646 image_pagesize = atoi64m(optarg);
647 break;
648 case 'x':
649 opt_compression_alg=AF_COMPRESSION_ALG_NONE;
650 break;
651 case 'X':
652 opt_compress_level = atoi(optarg);
653 break;
654 case 'Z':
655 opt_probe_compressed = 0;
656 break;
657 case 'y':
658 opt_yes = 1;
659 break;
660 case 'M':
661 opt_maxsize = atoi64m(optarg);
662 break;
663 case 'O':
664 if(!optarg) err(1,"-O flag requires a directory");
665 opt_outdir = optarg;
666 break;
667 case 'd':
668 opt_debug++;
669 break;
670 case 'h':
671 case '?':
672 default:
673 usage();
674 exit(0);
675 case 'V':
676 printf("%s version %s\n",progname,PACKAGE_VERSION);
677 exit(0);
678
679 }
680 }
681 argc -= optind;
682 argv += optind;
683
684 if(argc<1){
685 usage();
686 }
687
688 if(outfile){
689 return convert(*argv,outfile);
690 }
691
692 /* Check for "-o filename" at the end of the command line... */
693 if(argc==3 && !strcmp(argv[1],"-o")){
694 return convert(argv[0],argv[2]);
695 }
696
697 /* Convert each file*/
698
699 while(*argv){
700 char outfile[MAXPATHLEN+1];
701 memset(outfile,0,sizeof(outfile));
702
703 const char *ext = opt_write_raw ? opt_write_raw_ext : opt_aff_ext;
704 char *infile = *argv;
705 argv++;
706 argc--;
707
708 /* Copy over the filename and change the extension */
709 strlcpy(outfile,infile,sizeof(outfile));
710 char *cc = strrchr(outfile,'.'); // to strip off extension
711 if(cc){
712 /* Found an extension; copy over mine. */
713 strlcpy(cc+1,ext,sizeof(outfile)-(cc-outfile));
714 }
715 else {
716 /* No extension; make one */
717 strlcat(outfile,".",sizeof(outfile));
718 strlcat(outfile,ext,sizeof(outfile));
719 }
720
721 /* The user might want us to put things
722 * in a different directory. Pull off the filename...
723 */
724 if(opt_outdir){
725 cc = strrchr(outfile,'/');
726 char filename[PATH_MAX];
727 if(cc){
728 strlcpy(filename,cc+1,sizeof(filename)); // just the filename
729 }
730 else{
731 strlcpy(filename,outfile,sizeof(filename)); // the outfile is the filename
732 }
733 strlcpy(outfile,opt_outdir,sizeof(outfile));
734 strlcat(outfile,"/",sizeof(outfile));
735 strlcat(outfile,filename,sizeof(outfile));
736 }
737 if(convert(infile,outfile)){
738 exit(1);
739 }
740 }
741 exit(0);
742 }
0 /*
1 * afcopy.cpp:
2 *
3 * Copy one AFF file to another.
4 * Resulting file is re-ordered and possibly re-compressed.
5 */
6
7 /*
8 * Copyright (c) 2006
9 * Simson L. Garfinkel
10 * All rights reserved.
11 *
12 * This code is derrived from software contributed by
13 * Simson L. Garfinkel
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 * 3. [Omitted]
24 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
25 * contributors to this program may be used to endorse or promote
26 * products derived from this software without specific prior written
27 * permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL AND CONTRIBUTORS ``AS
30 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SIMSON
33 * GARFINKEL, BAIS TECHNOLOGy, OR CONTRIBUTORS BE LIABLE FOR ANY
34 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
36 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
38 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
39 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 */
42
43
44 #include "affconfig.h"
45 #include "afflib.h"
46 #include "afflib_i.h"
47 #include "utils.h"
48 #include "base64.h"
49 #include "aff_bom.h"
50
51 using namespace std;
52 using namespace aff;
53
54 #ifdef HAVE_SYS_SIGNAL_H
55 #include <sys/signal.h>
56 #endif
57
58 #ifdef HAVE_TIME_H
59 #include <time.h>
60 #endif
61
62 #ifdef HAVE_SYS_TIME_H
63 #include <sys/time.h>
64 #endif
65
66 #include <ctype.h>
67 #include <zlib.h>
68 #include <openssl/md5.h>
69 #include <openssl/sha.h>
70 #include <assert.h>
71
72 #ifdef HAVE_UNISTD_H
73 #include <unistd.h>
74 #endif
75
76 #ifdef HAVE_TERM_H
77 #include <term.h>
78 #endif
79
80 #ifdef HAVE_NCURSES_TERM_H
81 #include <ncurses/term.h>
82 #endif
83
84 #ifdef WIN32
85 #include "unix4win32.h"
86 #endif
87
88 const char *progname = "afcopy";
89
90 int opt_verbose = 0;
91 int opt_debug = 0;
92 int opt_x = 0;
93 int opt_X = AF_COMPRESSION_DEFAULT;
94 int opt_noverify = 0;
95 int opt_preen = 0;
96 int opt_zap =0;
97 int opt_missing = 0;
98 int opt_preen_alg_arg = 0; // algorithm for recompressing
99 int opt_preen_alg_flag = 0;
100 int opt_sign = 0;
101
102 int opt_note = 0;
103 const char *opt_sign_key_file = 0;
104 const char *opt_sign_cert_file = 0;
105
106 void usage()
107 {
108 printf("%s version %s\n",progname,PACKAGE_VERSION);
109 printf("usage: %s [options] file1 file\n",progname);
110 printf(" Copies file1 to file2\n");
111 printf(" %s [options] file1 file2 file3 ... dir\n",progname);
112 printf(" Copies file1.. into dir\n");
113 printf(" %s [options] file1 file2 file3 ... dir1 dir2...\n",progname);
114 printf(" Copies file1.. into dirs1, dir2, ...\n");
115 printf("\n");
116 printf("By default, all page MACs are verified on read and all segments\n");
117 printf("are verified after write.\n");
118
119 printf("Options:\n");
120 printf(" -v = verbose: print each file as it is copied\n");
121 printf(" -vv = very verbose: print each segment as it is copied\n");
122 printf(" -d = print debugging information as well\n");
123 printf(" -x = don't verify hashes on reads\n");
124 printf(" -y = don't verify writes\n");
125 printf(" -Xn = recompress pages (preen) with zlib level n\n");
126 printf(" -L = recompress pages (preen) with LZMA (smaller but slower)\n");
127 printf("\n");
128 printf(" -h = help; print this message.\n");
129 printf(" -V = print the program version and exit.\n");
130 printf(" -z = zap; copy even if the destination exists.\n");
131 printf(" -m = just copy the missing segments\n");
132 printf("\nSignature Options:\n");
133 printf(" -k filename.key = specify private key for signing\n");
134 printf(" -c filename.cer = specify a X.509 certificate that matches the private key\n");
135 printf(" (by default, the file is assumed to be the same one\n");
136 printf(" provided with the -k option.)");
137 printf(" -n = read notes to accompany the copy from standard in.\n");
138 printf("\n");
139 printf("\nEncryption Options:");
140 printf(" Specify passphrase encryption for filename.aff with:\n");
141 printf(" file://:passphrase@/filename.aff\n");
142 printf("\n");
143 printf("Examples:\n");
144 printf(" %s file.aff file://:mypassword@/file-encrypted.aff - encrypt file.aff\n",progname);
145 #ifdef USE_S3
146 printf(" %s -vy -X9 *.aff s3:/// Copy all files in current\n",progname);
147 printf(" directory to S3 default bucket with X9 compression\n");
148 #endif
149 exit(1);
150 }
151
152
153 const char *current_source = 0;
154 const char *current_dest = 0;
155 const char *current_seg = 0;
156 void sig_info(int arg)
157 {
158 if(current_source){
159 printf("Copying %s ",current_source);
160 if(current_dest){
161 printf("--> %s",current_dest);
162 if(current_seg) printf(" (%s) ",current_seg);
163 }
164 }
165 printf("\n");
166 }
167
168
169 void unlink_outfiles(vector<string> outfiles)
170 {
171 int failure=0;
172 for(vector<string>::const_iterator o = outfiles.begin();
173 o != outfiles.end();
174 o++){
175 char *protocol=0;
176 char *path = 0;
177 af_parse_url(o->c_str(),&protocol,0,0,0,0,&path);
178 if(strcmp(protocol,"file")==0){
179 unlink(path);
180 }
181 else{
182 fprintf(stderr,"Cannot unlink %s\n",o->c_str());
183 failure=1;
184 }
185 if(protocol) free(protocol);
186 if(path) free(path);
187 }
188 if(failure) exit(1);
189 }
190
191 #if !defined( __BSD_VISIBLE) && !defined(isnumber)
192 #define isnumber(x) isdigit(x)
193 #endif
194
195 #ifdef WIN32
196 #include <windows.h>
197 #include <windowsx.h>
198 int gettimeofday (struct timeval *tv, void* tz)
199 {
200 union {
201 int64_t ns100; /*time since 1 Jan 1601 in 100ns units */
202 FILETIME ft;
203 } now;
204
205 GetSystemTimeAsFileTime (&now.ft);
206 tv->tv_usec = (long) ((now.ns100 / 10LL) % 1000000LL);
207 tv->tv_sec = (long) ((now.ns100 - 116444736000000000LL) / 10000000LL);
208 return (0);
209 }
210 #endif
211
212 void open_outfiles(AFFILE *ain,outlist &afouts,const vector<string> &outfiles)
213 {
214 /* Open every output file */
215 for(vector<string>::const_iterator o = outfiles.begin();
216 o != outfiles.end(); o++){
217
218 const char *outfilename = o->c_str();
219 outelement out;
220
221 /* First see if the output file exists */
222 out.af = 0;
223 int ident = af_identify_file_type(outfilename,1);
224 if(ident!=AF_IDENTIFY_NOEXIST){
225 fprintf(stderr,"%s: file exists... ",outfilename);
226 if(opt_zap==0 && opt_missing==0){
227 fprintf(stderr,"\n Will not overwrite; use -m or -z\n");
228 continue;
229 }
230 if(opt_missing){
231 fprintf(stderr,"Will fill in missing segments...\n");
232 out.af = af_open(outfilename,O_RDWR|O_EXCL,0666);
233 if(!out.af) af_err(1,outfilename);
234 if(af_page_size(ain) != af_page_size(out.af)){
235 fprintf(stderr,"%s and %s have different page sizes (%d != %d)\n",
236 af_filename(ain),
237 af_filename(out.af),
238 af_page_size(ain),
239 af_page_size(out.af));
240 af_close(out.af);
241 out.af=0;
242 continue;
243 }
244 }
245 }
246
247
248
249 if(out.af==0){
250 out.af = af_open(outfilename,O_RDWR|O_EXCL|O_CREAT,0666);
251 if(!out.af){
252 warn("%s",outfilename);
253 continue;
254 }
255 if(af_set_pagesize(out.af,af_page_size(ain))){
256 errx(1,"%s: cannot set page size to %d\n", af_filename(out.af),af_page_size(ain));
257 }
258 }
259 if(o != outfiles.begin()) printf("\t ");
260 if(opt_verbose){
261 printf(" => %s ",outfilename);
262 if(opt_preen) printf(" (preening) ");
263 printf("\n");
264 }
265 if(opt_missing) out.segs.get_seglist(out.af);
266 afouts.push_back(out);
267 }
268 }
269
270 /* Copy pagenumber from ain to aout.
271 * Return 0 if success, -1 if can't do it.
272 * Properly handles signing and preening if requested.
273 */
274 int copy_page(AFFILE *ain,AFFILE *aout,int64_t pagenum,unsigned long arg,u_char *seghash,u_int *seghash_len)
275 {
276 /* If we are preening but not signing, see if we can get out fast */
277 if(opt_sign==0 && opt_preen==0) return -1; // not preening and not signing
278
279 /* If we are not signing, don't bother decompressing and recompressing*/
280 if(opt_sign==0 && opt_preen){
281 int alg = (arg & AF_PAGE_COMP_ALG_MASK);
282 if(alg==AF_PAGE_COMP_ALG_ZERO) return -1; // don't preen ZERO
283 if(alg==opt_preen_alg_arg) return -1; // don't decompress then re-compress with old alg
284 }
285
286 /* If we get here, page must be read into memory and decompressed */
287 size_t pagesize = af_page_size(ain);
288 if(pagesize<=0) return -1; // couldn't get pagesize
289
290 u_char *pagebuf = (unsigned char *)malloc(pagesize);
291 if(!pagebuf) return -1; // couldn't allocate memory for page?
292
293 if(af_get_page(ain,pagenum,pagebuf,&pagesize)){ // note --- this may make pagesize smaller
294 free(pagebuf);
295 return -1;
296 }
297
298 if(opt_preen){ // set compression if we are preening
299 af_enable_compression(aout,opt_preen_alg_flag,opt_X);
300 }
301
302 #ifdef USE_AFFSIGS
303 /* If calculating a bom, calculate the bom! */
304 if(opt_sign){
305 char segname[AF_MAX_NAME_LEN];
306 sprintf(segname,AF_PAGE,pagenum);
307 aff_bom::make_hash(seghash,arg,segname,pagebuf,pagesize);
308 }
309 #endif
310
311 /* Write out the page */
312 int ret = af_update_page(aout,pagenum,pagebuf,pagesize);
313 free(pagebuf);
314 return ret;
315 }
316
317 string base64(const u_char *buf,size_t buflen)
318 {
319 size_t len = buflen*2+1;
320 char *str = (char *)malloc(len);
321 b64_ntop(buf,buflen,str,len);
322 string ret = string(str);
323 free(str);
324 return ret;
325 }
326
327 #ifndef HAVE_ISATTY
328 int isatty(int fd)
329 {
330 return 1; // have to assume it's a tty
331 }
332 #endif
333
334 int afcopy(char *infile,vector<string> &outfiles)
335 {
336 #ifdef SIGINFO
337 signal(SIGINFO,sig_info);
338 #endif
339 hashMapT hashMap;
340
341 /* Open the input file */
342 AFFILE *ain = af_open(infile,O_RDONLY,0);
343 if(opt_debug) printf("af_open(%s,O_RDONLY)=%p\n",infile,ain);
344 if(!ain) af_err(1,"%s",infile);
345 seglist segments(ain);
346
347 if(opt_zap) unlink_outfiles(outfiles);
348
349 outlist afouts; // vector of output AFFs
350 vector<int64_t>preened_pages;
351 open_outfiles(ain,afouts,outfiles);
352
353 /* Now, try to open the output files, to see if they exist */
354 current_source = infile;
355 if(opt_verbose) printf("%s: ",infile);
356 if(opt_verbose>1) putchar('\n');
357
358 /* If we couldn't open any output files, return */
359 if(afouts.size()==0){
360 af_close(ain); // close the input file
361 return -1;
362 }
363
364 #ifdef USE_AFFSIGS
365 /* If we are signing, initialize the signing machinery */
366 aff_bom bom(opt_note);
367 if(opt_sign){
368 if(bom.read_files(opt_sign_cert_file,opt_sign_key_file)){
369 opt_sign = 0; // can't sign
370 }
371 }
372 #endif
373
374 /* Now the files are open. For each output file:
375 * 1. Initialize signing if options were set and the segments aren't already signed.
376 * 2. Sign all of the segments that are unsigned
377 */
378 for(outlist::iterator aout = afouts.begin(); aout != afouts.end(); aout++){
379 if(opt_sign_key_file && segments.has_signed_segments()==false){
380 if(af_set_sign_files(aout->af,opt_sign_key_file,opt_sign_cert_file)){
381 err(1,"%s",opt_sign_key_file);
382 }
383 af_sign_all_unsigned_segments(aout->af);
384 opt_sign = true;
385 }
386 }
387
388 /* Start the copying */
389 struct timeval t0,t1;
390 gettimeofday(&t0,0);
391 for(seglist::const_iterator seg = segments.begin(); seg!= segments.end();seg++){
392 /* For each segment, get the size of the segment */
393 const char *segname = seg->name.c_str();
394 current_seg = segname; // for printing
395 size_t seglen=0;
396
397 if(af_get_seg(ain,segname,0,0,&seglen)){
398 unlink_outfiles(outfiles);
399 err(1,"Cannot read length of segment '%s' on input file %s", segname,af_filename(ain));
400 }
401 unsigned char *segbuf = (unsigned char *)malloc(seglen);
402 if(!segbuf){
403 unlink_outfiles(outfiles);
404 err(1,"Cannot allocated %d bytes for segment '%s' in %s",
405 (int)seglen,segname,af_filename(ain));
406 }
407
408 /* Now get the raw source segment */
409 unsigned long arg=0;
410 if(af_get_seg(ain,segname,&arg,segbuf,&seglen)){
411 unlink_outfiles(outfiles); // failure; unlink the output files
412 err(1,"Cannot read segment '%s' in %s. Deleteing output file", segname,af_filename(ain));
413 }
414
415 /* Calculate the MD5 of this segment and remember it in the map */
416 md5blob md5;
417 MD5(segbuf,seglen,md5.buf);
418 hashMap[segname] = md5;
419
420 /* See if this is a page; if so, it is handled specially */
421 int64_t pagenumber = af_segname_page_number(segname);
422
423 /* Write the segment to each file */
424 for(outlist::iterator aout = afouts.begin(); aout != afouts.end(); aout++){
425 current_dest = af_filename(aout->af);
426 if(opt_verbose>1 || opt_debug){
427 if(aout != afouts.begin()) printf("\n ");
428 printf(" %s -> %s:%s ...", segname,af_filename(aout->af),segname);
429 }
430
431 /** COPY THE DATA **/
432
433 u_char seghash[32]; /* resultant message digest; could be any size */
434 unsigned int seghash_len = sizeof(seghash); /* big enough to hold SHA256 */
435 int sigmode = AF_SIGNATURE_MODE0;
436
437 memset(seghash,0,sizeof(seghash));
438
439 bool copied = false;
440
441 /* If we are preening, signing, or building a ToC, we need to copy the raw page */
442 if(pagenumber>=0 && (opt_preen || opt_sign_key_file)){
443 if(copy_page(ain,aout->af,pagenumber,arg,seghash,&seghash_len)==0){
444 preened_pages.push_back(pagenumber); // preened pages won't be verified by md5
445 if(opt_debug && opt_preen) printf(" (PREENED) ");
446 sigmode = AF_SIGNATURE_MODE1;
447 copied = true;
448 }
449 }
450
451 /* Copy the page if it is not in the destination */
452 if(copied==false){
453 if(!aout->segs.contains(segname)){
454 if(af_update_seg(aout->af,segname,arg,segbuf,seglen)){
455 unlink_outfiles(outfiles);
456 err(1,"Cannot write segment '%s' to %s.", segname,af_filename(aout->af));
457 }
458
459 #ifdef USE_AFFSIGS
460 if(opt_sign){
461 aff_bom::make_hash(seghash,arg,segname,segbuf,seglen);
462 }
463 #endif
464 }
465 else{
466 if(opt_verbose>1 || opt_debug) printf(" [already in %s] ",af_filename(aout->af));
467 }
468 }
469 #ifdef USE_AFFSIGS
470 if(opt_sign) bom.add(segname,sigmode,seghash,seghash_len);
471 #endif
472 }
473 free(segbuf);
474 current_dest = 0;
475 if(opt_verbose>1 || opt_debug) putchar('\n');
476 }
477 current_seg = 0;
478
479 #ifdef USE_AFFSIGS
480 /* For each open file, make an AF_IMAGE_GID if one doesn't exist */
481 for(outlist::iterator aout = afouts.begin(); aout != afouts.end(); aout++){
482 if(af_make_gid(aout->af)>0){
483 if(opt_sign){
484 af_sign_seg(aout->af,AF_IMAGE_GID); // make sure the GID is signed
485 bom.add(aout->af,AF_IMAGE_GID);
486 bom.add(aout->af,AF_IMAGE_GID AF_SIG256_SUFFIX);
487
488 }
489 }
490 }
491
492 if(opt_sign){
493 bom.close();
494 /* Now write to each of the output files */
495 for(outlist::iterator aout = afouts.begin(); aout != afouts.end(); aout++){
496 bom.write(aout->af,segments);
497 }
498 }
499 #endif
500
501 gettimeofday(&t1,0);
502 if(afouts.size()==1){
503 AFFILE *af = afouts.begin()->af;
504 uint64_t w = af->bytes_written;
505 double sec = ((t1.tv_sec-t0.tv_sec)+(t1.tv_usec-t0.tv_usec)/1000000.0);
506 printf("%s: %"I64d" bytes transfered in %.2f seconds. xfer rate: %.2f MBytes/sec\n",
507 af_filename(af),w,sec,(w/1000000.0) / sec);
508 }
509
510 if(opt_noverify==0){
511 current_seg = "VERIFYING";
512 /* Now verify all of the hashes */
513 if(opt_verbose || opt_debug) printf("\n\nFiles copied. Verifying...\n");
514 for(seglist::const_iterator seg = segments.begin(); seg!= segments.end();seg++){
515
516 const char *segname = seg->name.c_str();
517 for(outlist::iterator aout = afouts.begin(); aout != afouts.end(); aout++){
518 size_t seglen=0;
519 char b2[1024];
520
521 if((aout->af)->v->flag & AF_VNODE_TYPE_RELIABLE){
522 continue; // no need to verify a reliable write
523 }
524 if(opt_verbose>1 || opt_debug) printf(" verifying %s...\n",segname);
525
526 again:
527 if(af_get_seg(aout->af,segname,0,0,&seglen)){
528 if(segname != b2 &&
529 segname[0]=='s' && segname[1]=='e' && segname[2]=='g' &&
530 isnumber(segname[3])){
531 /* Looks like a legacy segname name was renamed.
532 * Try the new name
533 */
534 snprintf(b2,sizeof(b2),"page%s",segname+3);
535 if(opt_verbose) printf(" Couldn't read %s; looking for %s\n",
536 segname,b2);
537 segname = b2;
538 goto again;
539 }
540 unlink_outfiles(outfiles);
541 errx(1,"Cannot read length of segment '%s' in output file %s",
542 segname,af_filename(aout->af));
543 }
544 int64_t pagenumber = af_segname_page_number(segname);
545 if(find(preened_pages.begin(),preened_pages.end(),pagenumber) !=preened_pages.end()){
546 /* TK: page pagenumber was preened.
547 * It should probably be checked against the original hash...
548 */
549 continue;
550 }
551
552 unsigned char *segbuf = (unsigned char *)malloc(seglen);
553 if(!segbuf){
554 err(1,"Cannot allocated %d bytes for segment '%s' in %s",
555 (int)seglen,segname,af_filename(ain));
556 }
557 unsigned long arg;
558 if(af_get_seg(aout->af,segname,&arg,segbuf,&seglen)){
559 err(1,"Cannot read segment '%s' in %s",
560 segname,af_filename(aout->af));
561 }
562
563 /* Calculate the MD5 of this segment and see if it matches the map.
564 * (But don't do this for preened segments.
565 */
566 unsigned char md5_read[16];
567 MD5(segbuf,seglen,md5_read);
568 if(memcmp(hashMap[segname].buf,md5_read,16)!=0){
569 unlink_outfiles(outfiles);
570 errx(1,"Hash read from %s for segment %s doesn't validate.",
571 af_filename(aout->af),segname);
572 }
573 free(segbuf); // free the buffer
574 }
575 }
576 }
577
578 /* Finally, close the output files*/
579 for(outlist::iterator aout = afouts.begin(); aout != afouts.end(); aout++){
580 af_close(aout->af);
581 }
582 af_close(ain);
583 if(opt_verbose>1 || opt_debug) printf("==============================\n");
584 current_source = 0;
585 return 0;
586 }
587
588 int main(int argc,char **argv)
589 {
590 int ch;
591
592 setvbuf(stdout,0,_IONBF,0); // turn off buffering on stdout
593 while ((ch = getopt(argc, argv, "vdVxyh?zmX:Lp:P:k:c:n")) != -1) {
594 switch (ch) {
595 case 'v': opt_verbose++; break;
596 case 'd': opt_debug++; break;
597 case 'X':
598 opt_preen =1;
599 opt_X = optarg[0] - '0';
600 opt_preen_alg_arg = AF_PAGE_COMP_ALG_ZLIB;
601 opt_preen_alg_flag = AF_COMPRESSION_ALG_ZLIB;
602 if(opt_X<0 || opt_X>9) opt_X = AF_COMPRESSION_DEFAULT;
603 break;
604 case 'L':
605 opt_preen=1;
606 opt_preen_alg_arg = AF_PAGE_COMP_ALG_LZMA;
607 opt_preen_alg_flag = AF_COMPRESSION_ALG_LZMA;
608 break;
609 case 'x': opt_x++;break;
610 case 'y': opt_noverify++;break;
611 case 'z': opt_zap++;break;
612 case 'm': opt_missing++;break;
613 case 'n': opt_note++;break;
614 case 'k':
615 if(access(optarg,R_OK)) err(1,"%s",optarg);
616 opt_sign_key_file = optarg;
617 if(opt_sign_cert_file==0) opt_sign_cert_file=optarg;
618 opt_sign = true;
619 break;
620 case 'c':
621 if(access(optarg,R_OK)) err(1,"%s",optarg);
622 opt_sign_cert_file = optarg;
623 break;
624 case 'V':
625 printf("%s version %s\n",progname,PACKAGE_VERSION);
626 exit(0);
627 case 'h':
628 case '?':
629 default:
630 usage();
631 break;
632 }
633 }
634 argc -= optind;
635 argv += optind;
636
637 if(argc<2){ // at this point, we need at least two args
638 usage();
639 }
640
641 /* We either need both a key file and a cert file, or neither */
642 if((opt_sign_key_file==0) != (opt_sign_cert_file==0)){
643 errx(1,"Both a private key and a certificate must be specified.");
644 }
645
646 /* Find any directories */
647 vector<string> dirlist;
648 for(int i=argc-1;i>0;i--){
649 struct stat st;
650
651 // s3 names that do not end with ".aff" are directories
652 const char *last4 = strlen(argv[i])>4 ? argv[i]+strlen(argv[i])-4 : "";
653 if(strncmp(argv[i],"s3://",5)==0 &&
654 strcmp(last4,".aff")!=0){
655 dirlist.push_back(argv[i]);
656 argc--;
657 continue;
658 }
659
660 if(stat(argv[i],&st)!=0) break; // out of directories
661 if((st.st_mode & S_IFMT)!=S_IFDIR) break; // found a non-dir
662 dirlist.push_back(argv[i]);
663 argc--; // ignore the last
664 }
665
666 /* If I found no directories, then there better just be two values */
667 if(dirlist.size()==0){
668 if(argc!=2){
669 fprintf(stderr,"Please specify a directory or just two AFF files.\n\n");
670 usage();
671 }
672 /* Must be copying from file1 to file2. Make sure file2 does not exist */
673 if(access(argv[1],R_OK)==0){
674 fprintf(stderr,"File exists: %s\n",argv[1]);
675 if(!opt_zap) exit(1);
676 }
677
678 vector<string> outfiles;
679 outfiles.push_back(argv[1]);
680 return afcopy(argv[0],outfiles);
681 }
682
683 /* Loop for each file and each directory */
684
685 while(argc--){
686 /* Open the output files */
687 vector<string> outfiles;
688 for(u_int i=0;i<dirlist.size();i++){
689 string outfilename;
690 const char *name = strrchr(*argv,'/');
691 if(name) name++;
692 else name = *argv;
693
694 outfilename.append(dirlist[i]);
695 if(outfilename[outfilename.size()-1]!='/') {
696 outfilename.append("/");
697 }
698 outfilename.append(name);
699 outfiles.push_back(outfilename);
700 }
701 afcopy(argv[0],outfiles); // old outfiles will get GCed
702 argv++;
703 }
704 exit(0);
705 }
706
707
0 /*
1 * afcrypto.cpp:
2 *
3 * command for dealing with encryption issues
4 */
5
6 /* Public Domain Software
7 * Simson L. Garfinkel
8 * Naval Postgraduate School
9 *
10 * The software provided here is released by the Naval Postgraduate
11 * School, an agency of the U.S. Department of Navy. The software bears
12 * no warranty, either expressed or implied. NPS does not assume legal
13 * liability nor responsibility for a User's use of the software or the
14 * results of such use.
15 *
16 * Please note that within the United States, copyright protection, under
17 * Section 105 of the United States Code, Title 17, is not available for
18 * any work of the United States Government and/or for any works created
19 * by United States Government employees.
20 */
21
22
23
24 #include "affconfig.h"
25 #include "afflib.h"
26 #include "afflib_i.h"
27 #include "utils.h"
28
29 #include <stdio.h>
30 #include <algorithm>
31 #include <vector>
32
33 const char *progname = "afcrypto";
34 #define DEFAULT_PASSPHRASE_FILE ".affpassphrase"
35 int opt_debug = 0;
36 int opt_verbose = 0;
37 int opt_just_print_encrypted_count = 0;
38 int opt_just_print_unencrypted_count = 0;
39 char *opt_unsealing_private_key_file= 0;
40 int opt_xml = 0;
41
42 void change_passphrase(const char *fn,const char *old_passphrase,const char *new_passphrase)
43 {
44 int fail = 0;
45
46 AFFILE *af = af_open(fn,O_RDWR,0666);
47 if(!af) af_err(1,fn);
48 if(af_change_aes_passphrase(af,old_passphrase,new_passphrase)){
49 warnx("%s: af_change_aes_passphrase failed",fn);
50 fail = 1;
51 }
52 af_close(af);
53 if(!fail) printf("%s: passphrase changed.\n",fn);
54 }
55
56 void get_and_change_passphrase(const char *fn)
57 {
58 char old_passphrase[1024];
59 char new_passphrase[1024];
60
61 memset(old_passphrase,0,sizeof(old_passphrase));
62 memset(new_passphrase,0,sizeof(new_passphrase));
63
64 printf("Enter old passphrase: ");
65 if(fgets(old_passphrase,sizeof(old_passphrase),stdin)==0) return;
66 char *cc = strchr(old_passphrase,'\n');if(cc) *cc='\000';
67
68 /* See if this passphrase works*/
69
70 AFFILE *af = af_open(fn,O_RDONLY,0666);
71 if(!af) af_err(1,fn);
72 if(af_use_aes_passphrase(af,old_passphrase)){
73 errx(1,"passphrase incorrect");
74 }
75 af_close(af);
76
77 printf("Enter new passphrase: ");
78 if(fgets(new_passphrase,sizeof(new_passphrase),stdin)==0) return;
79 cc = strchr(new_passphrase,'\n');if(cc) *cc='\000';
80 change_passphrase(fn,old_passphrase,new_passphrase);
81 }
82
83 void usage()
84 {
85 printf("afcrypto version %s\n",PACKAGE_VERSION);
86 printf("usage: afcrypto [options] filename.aff [filename2.aff ... ]\n");
87 printf(" prints if each file is encrypted or not.\n");
88 printf("options:\n");
89 printf(" -x --- output in XML\n");
90 printf(" -j --- Just print the number of encrypted segments\n");
91 printf(" -J --- Just print the number of unencrypted segments\n");
92
93 printf("\nData conversion options:\n");
94 printf(" -e --- encrypt the unencrypted non-signature segments\n");
95 printf(" -d --- decrypt the encrypted non-signature segments\n");
96 printf(" -r --- change passphrase (take old and new from stdin)\n");
97 printf(" -O old --- specify old passphrase\n");
98 printf(" -N new --- specify new passphrase\n");
99 printf(" -K mykey.key -- specifies a private keyfile for unsealing (may not be repeated)\n");
100 printf(" -C mycert.crt -- specifies a certificate file for sealing (may be repeated)\n");
101 printf(" -S --- add symmetric encryptiong (passphrase) to AFFILE encrypted with public key\n");
102 printf(" (requires a private key and a specified passphrase).\n");
103 printf(" -A --- add asymmetric encryption to a AFFILE encrypted with a passphrase\n");
104 printf(" (requires a certificate file spcified with the -C option\n");
105
106
107 printf("\nPassword Cracking Options:\n");
108 printf(" -p passphrase --- checks to see if passphrase is the passphrase of the file\n");
109 printf(" exit code is 0 if it is, -1 if it is not\n");
110 printf(" -k --- attempt to crack passwords by reading a list of passwords from ~/.affpassphrase\n");
111 printf(" -f file --- Crack passwords but read them from file.\n");
112
113 printf("\nDebugging:\n");
114 printf(" -V --- Just print the version number and exit.\n");
115 printf(" -D --- debug; print out each key as it is tried\n");
116 printf(" -l --- List the installed hash and encryption algorithms \n");
117 printf("Note: This program ignores the environment variables:\n");
118 puts(AFFLIB_PASSPHRASE);
119 puts(AFFLIB_PASSPHRASE_FILE);
120 puts(AFFLIB_PASSPHRASE_FD);
121 puts(AFFLIB_DECRYPTING_PRIVATE_KEYFILE);
122 exit(0);
123 }
124
125 /* Try each of the passphrases in the file against the passphrase. If it is found, return it. */
126 char *check_file(AFFILE *af,const char *passphrase_file)
127 {
128 char *ret = 0;
129 FILE *f = fopen(passphrase_file,"r");
130 if(!f) return 0;
131
132 char buf[1024];
133 memset(buf,0,sizeof(buf));
134 while(fgets(buf,sizeof(buf)-1,f)){
135 char *cc = strchr(buf,'\n');
136 if(cc) *cc = 0;
137 if(opt_debug){
138 if(opt_debug) printf("checking with '%s' ... ",buf);
139 fflush(stdout);
140 }
141 int r= af_use_aes_passphrase(af,buf);
142 if(r==0){
143 if(opt_debug) printf("YES!\n");
144 ret = strdup(buf);
145 break;
146 }
147 }
148 fclose(f);
149 return ret;
150 }
151
152 /**
153 * This will eventually decrypt non-signature segments that are
154 * encrypted
155 *
156 * @param af - the AFFILE to open
157 * @param count - The number of pages actually encrypted
158 */
159 int af_decrypt_encrypted_segments(AFFILE *af, int *count, int mode)
160 {
161 af_set_option(af,AF_OPTION_AUTO_ENCRYPT,0);
162 af_set_option(af,AF_OPTION_AUTO_DECRYPT,0); // turn off auto decryption
163 aff::seglist sl(af); // get the list of the segments
164 af_set_option(af,AF_OPTION_AUTO_DECRYPT,1); // turn auto decryption back on
165 for(aff::seglist::const_iterator si = sl.begin();si!=sl.end();si++){
166 if(opt_debug) printf(" checking segment %s",si->name.c_str());
167 if(af_is_encrypted_segment(si->name.c_str())){
168
169 if(mode == O_RDONLY){ // if readonly, just tally
170 (*count) ++;
171 if(opt_debug) printf(" would decrypt segment\n");
172 continue;
173 }
174
175 /* Generate the name of the unencrypted segment */
176 char segname[AF_MAX_NAME_LEN];
177 strcpy(segname,si->name.c_str());
178 char *cc = strstr(segname,AF_AES256_SUFFIX);
179 if(!cc){
180 if(opt_debug) printf(" will not decrypt AFFKEY segments; will be deleted later.\n");
181 continue; // something is wrong; can't find the /aes256
182 }
183 *cc = '\000'; // truncate off the /aes256
184
185 /* Get the segment and put it, which will force the decryption to take place */
186 if(opt_debug) printf(" decrypting segment\n");
187 u_char *buf = (u_char *)malloc(si->len);
188 if(!buf) warn("malloc(%zd) failed", si->len);
189 else {
190 unsigned long arg;
191 size_t datalen = si->len;
192 if(af_get_seg(af,segname,&arg,buf,&datalen)){
193 warn("Could not read segment '%s'",segname);
194 }
195 else{
196 /* si->datalen >= datalen.
197 * si->datalen is the length of the encrypted segment.
198 * datalen is the length of the decrypted segment.
199 */
200 assert(si->len >= datalen);
201 assert(si->arg==arg);
202 if(af_update_seg(af,segname,arg,buf,datalen)){
203 warn("Could not decrypt segment '%s'",si->name.c_str());
204 } else {
205 (*count) ++;
206 }
207 }
208 free(buf);
209 }
210 } else {
211 if(opt_debug) printf(" not encrypted\n");
212 }
213 }
214 /* Delete the AF_AFFKEY segment */
215 if(af_get_seg(af,AF_AFFKEY,0,0,0)==0) af_del_seg(af,AF_AFFKEY);
216 /* Delete all of the EVP segments */
217 for(int i=0;;i++){
218 char segname[1024];
219 snprintf(segname,sizeof(segname),AF_AFFKEY_EVP,i);
220 if(af_get_seg(af,segname,0,0,0)!=0) break; // found the last segment
221 if(af_del_seg(af,segname)) warn("Cannot delete segment %s",segname);
222 }
223 return 0;
224 }
225
226
227 /**
228 * Encrypts the non-signature segments that are not encrypted.
229 * There is no reason to encrypt the signature segments.
230 *
231 * @param af - the AFFILE to open
232 * @param count - The number of pages actually encrypted
233 */
234
235 int af_encrypt_unencrypted_nonsignature_segments(AFFILE *af,int *count,int mode)
236 {
237 af_set_option(af,AF_OPTION_AUTO_DECRYPT,0); // do not automatically decrypt
238 aff::seglist sl(af);
239 for(aff::seglist::const_iterator si = sl.begin();si!=sl.end();si++){
240 if(si->name == AF_AFFKEY) continue; // don't encrypt the affkey!
241 if(strstr(si->name.c_str(),"affkey_evp")) continue;
242 if(!af_is_encrypted_segment(si->name.c_str()) &&
243 !af_is_signature_segment(si->name.c_str())){
244
245 if(mode == O_RDONLY){ // if readonly, just tally
246 (*count) ++;
247 continue;
248 }
249
250 /* Get the segment and put it, which will force the encryption to take place */
251 if(opt_debug) printf(" encrypting segment %s\n",si->name.c_str());
252 u_char *buf = (u_char *)malloc(si->len);
253 if(!buf) warn("Cannot encrypt segment '%s' --- too large (%zd bytes) --- malloc failed",
254 si->name.c_str(),si->len);
255 else {
256 unsigned long arg;
257 size_t datalen = si->len;
258 if(af_get_seg(af,si->name.c_str(),&arg,buf,&datalen)){
259 warn("Could not read segment '%s'",si->name.c_str());
260 }
261 else{
262 /* make sure that what we read is what we thought we were going to read */
263 assert(si->len==datalen);
264 assert(si->arg==arg);
265 if(af_update_seg(af,si->name.c_str(),arg,buf,datalen)){
266 warn("Could not encrypt segment '%s'",si->name.c_str());
267 } else {
268 (*count) ++;
269 }
270 }
271 free(buf);
272 }
273 } else {
274 if(opt_debug) printf(" already encrypted or signed: %s\n",si->name.c_str());
275 }
276 }
277 af_set_option(af,AF_OPTION_AUTO_DECRYPT,1); // go back to automatically decrypting
278 return 0;
279 }
280
281 void list_openssl_hashes()
282 {
283 const char *digests[] = {"md5","sha1","sha256",0};
284 OpenSSL_add_all_algorithms();
285 for(int i=0;digests[i];i++){
286 printf("OpenSSL has %s: %s\n",digests[i],EVP_get_digestbyname(digests[i]) ? "YES" : "NO");
287 }
288 exit(0);
289 }
290
291 int main(int argc,char **argv)
292 {
293 int bflag, ch;
294 const char *old_passphrase=0;
295 const char *new_passphrase=0;
296 const char *check_passphrase = 0;
297 char *passphrase_file = 0;
298 const char *progname = argv[0];
299 int opt_encrypt = 0;
300 int opt_decrypt = 0;
301 int opt_add_passphrase_to_public_key = 0;
302 int opt_add_public_key_to_passphrase = 0;
303
304 int mode = O_RDONLY; // mode for opening AFF file
305 const char **certificates = (const char **)malloc(0);
306 int num_certificates = 0;
307 const char *envvars[] = {AFFLIB_PASSPHRASE,AFFLIB_PASSPHRASE_FILE,AFFLIB_PASSPHRASE_FD,
308 AFFLIB_DECRYPTING_PRIVATE_KEYFILE,0};
309 for(int i=0;envvars[i];i++){
310 /* Don't use auto-supplied passphrases */
311 #ifdef HAVE_UNSETENV
312 unsetenv(envvars[i]);
313 #else
314 if(getenv(envvars[i])){
315 fprintf(stderr,"Please unset %s and restart\n",envvars[i]);
316 exit(1);
317 }
318 #endif
319 }
320
321 bflag = 0;
322 int opt_change = 0;
323 const char *home = getenv("HOME");
324
325 while ((ch = getopt(argc, argv, "zreC:SAO:N:p:f:kdDh?VK:vljJx:")) != -1) {
326 switch (ch) {
327 case 'x': opt_xml = 1; break;
328 case 'j': opt_just_print_encrypted_count =1;break;
329 case 'J': opt_just_print_unencrypted_count =1;break;
330
331 /* These options make the mode read-write */
332 case 'r': opt_change = 1; mode = O_RDWR; break;
333 case 'e': opt_encrypt = 1; mode = O_RDWR; break;
334 case 'd': opt_decrypt = 1; mode = O_RDWR; break;
335 case 'S': opt_add_passphrase_to_public_key = 1; mode = O_RDWR; break;
336 case 'A': opt_add_public_key_to_passphrase = 1; mode = O_RDWR; break;
337 /* These just set up variables */
338 case 'C':
339 certificates = (const char **)realloc(certificates,sizeof(int *)*(num_certificates+1));
340 certificates[num_certificates] = optarg;
341 num_certificates++;
342 break;
343 case 'K': opt_unsealing_private_key_file = optarg;break;
344 case 'O': old_passphrase = optarg;break;
345 case 'N': new_passphrase = optarg;break;
346 case 'p': check_passphrase = optarg;break;
347 case 'f': passphrase_file = optarg;break;
348 case 'k':
349 if(!home) home = "/";
350 passphrase_file = (char *)malloc(strlen(home)+strlen(DEFAULT_PASSPHRASE_FILE)+2);
351 strcpy(passphrase_file,home);
352 strcat(passphrase_file,"/");
353 strcat(passphrase_file,DEFAULT_PASSPHRASE_FILE);
354 break;
355 case 'D': opt_debug = 1;break;
356 case 'v': opt_verbose = 1;break;
357 case 'l': list_openssl_hashes(); exit(0);
358 case 'h':
359 case '?':
360 default:
361 usage();
362 break;
363 case 'V':
364 printf("%s version %s\n",progname,PACKAGE_VERSION);
365 exit(0);
366 }
367 }
368 argc -= optind;
369 argv += optind;
370 if(argc<1){
371 fprintf(stderr,"No image file specified\n");
372 usage();
373 }
374
375 if(opt_just_print_encrypted_count && opt_just_print_unencrypted_count){
376 errx(1,"Options -j and -J conflict\n");
377 }
378
379 if(num_certificates>0 && (opt_encrypt==0 && opt_decrypt==0 && opt_add_public_key_to_passphrase==0)){
380 errx(1,"Encryption certificates specified but neither -e nor -d option not set. "
381 "What do you want me to do with these certificates? ");
382 }
383
384 if((check_passphrase || passphrase_file) && opt_encrypt){
385 err(1,"Sorry, can't both encrypt and password crack. Pick one.\n");
386 }
387
388 if(opt_encrypt && (new_passphrase==0 && num_certificates==0) && mode!=O_RDONLY){
389 err(1,"Currently -e requires that the passphrase be specified on the command line\n"
390 "or that one or more encryption certificates be provided\n");
391 }
392
393 while(argc--){
394 const char *fname = *argv++;
395
396 if(opt_change){
397 if(old_passphrase && new_passphrase) change_passphrase(fname,old_passphrase,new_passphrase);
398 else get_and_change_passphrase(fname);
399 }
400
401 /* Get the information */
402 AFFILE *af = af_open(fname,mode,0);
403 if(!af) af_err(1,"af_open(%s)",fname);
404 if(af_identify(af)!=AF_IDENTIFY_AFF && af_identify(af)!=AF_IDENTIFY_AFD){
405 errx(1,"Cannot encrypt %s: %s only supports AFF and AFD files.",af_filename(af),progname);
406 }
407
408 if(opt_encrypt && new_passphrase){
409 int r = af_establish_aes_passphrase(af,new_passphrase);
410 switch(r){
411 case AF_ERROR_NO_AES: errx(1,"AFFLIB: AES256 not available; cannot continue");
412 case AF_ERROR_NO_SHA256: errx(1,"AFFLIB: SHA256 not available; cannot continue");
413 default: err(1,"%s: cannot establish passphrase (error %d)",fname,r);
414 case 0:
415 case AF_ERROR_AFFKEY_EXISTS:
416 /* no matter if we established it or if a phrase already exists, try to use it now */
417 /* File already has a passphrase; see if this is it. */
418 break;
419 }
420 r = af_use_aes_passphrase(af,new_passphrase);
421 switch(r){
422 case 0: break; // everything okay
423 case AF_ERROR_WRONG_PASSPHRASE: errx(1,"%s: wrong passphrase",fname);
424 default: errx(1,"%s: passphrase already established (error %d)",fname,r);
425 }
426 }
427
428 if(opt_decrypt && old_passphrase){
429 int r = af_use_aes_passphrase(af, old_passphrase);
430 switch(r){
431 case 0: printf("Passphrase is good!\n"); break;
432 case AF_ERROR_WRONG_PASSPHRASE: errx(1,"%s: wrong passphrase",fname);
433 }
434 }
435
436 if (opt_add_public_key_to_passphrase){
437 if(!num_certificates) errx(1,"You must specify a certificate with the -C option");
438 if(!check_passphrase) errx(1,"You must specify a passphrase with the -p option");
439 printf("Attepmting to add public key to AFFILE...\n");
440 if(af->crypto->sealing_key_set) return AF_ERROR_KEY_SET; // already enabled
441 unsigned char affkey[32];
442 int r = af_get_aes_key_from_passphrase(af,check_passphrase,affkey);
443 if(r) errx(1, "%s: cannot get aes key. Failed to add Public Key", fname);
444 af_seal_affkey_using_certificates(af, certificates, num_certificates, affkey);
445 printf("...Public key added successfully.\n");
446 }
447
448 if(opt_encrypt && num_certificates){
449 if(af_set_seal_certificates(af,certificates,num_certificates)){
450 errx(1,"%s: can't set encryption certificate%s",fname,num_certificates==1 ? "" : "s");
451 }
452 }
453 if(opt_encrypt){
454 int count = 0;
455 if(af_encrypt_unencrypted_nonsignature_segments(af,&count,mode)){
456 errx(1,"%s: can't encrypt unsigned, unencrypted segments",fname);
457 }
458 if(mode==O_RDONLY){ // if it is readonly just print the number of segments that would be changed.
459 printf("%d\n",count);
460 af_close(af);
461 continue;
462 }
463 }
464 if(opt_decrypt){
465 int count = 0;
466 if(af_decrypt_encrypted_segments(af, &count, mode)){
467 }
468 if(mode==O_RDONLY){
469 printf("%d\n",count);
470 af_close(af);
471 continue;
472 }
473 }
474
475 if(opt_add_passphrase_to_public_key) {
476 if(!new_passphrase) errx(1,"You must specify a new passphrase with the -N option");
477 printf("Attempting to add passphrase...\n");
478 u_char affkey[32];
479 if(af_get_affkey_using_keyfile(af, opt_unsealing_private_key_file,affkey)){
480 errx(1,"%s: cannot unseal AFFKEY",fname);
481 }
482 if(af_save_aes_key_with_passphrase(af,new_passphrase,affkey)){
483 af_err(1,"%s: could not set the passphrase",fname);
484 }
485 printf("... new passphrase established.\n");
486 }
487
488
489 af_vnode_info vni;
490 memset(&vni,0,sizeof(vni));
491 if(af_vstat(af,&vni)) err(1,"%s: af_vstat failed: ",fname);
492 const char *the_passphrase = 0; // the correct passphrase
493
494 if(opt_just_print_encrypted_count){
495 printf("%d\n",vni.segment_count_encrypted);
496 af_close(af);
497 continue;
498 }
499
500 if(opt_just_print_unencrypted_count){
501 printf("%d\n",vni.segment_count_total-vni.segment_count_encrypted);
502 af_close(af);
503 continue;
504 }
505
506
507 /* were we supposed to try a check_passphrase? */
508 if(check_passphrase){
509 if(af_use_aes_passphrase(af,check_passphrase)==0){
510 the_passphrase = check_passphrase;
511 }
512 af_use_aes_passphrase(af,0); // clear the passphrase
513 }
514
515 /* Is a passphrase file provided? */
516 if(!the_passphrase && passphrase_file){
517 the_passphrase = check_file(af,passphrase_file);
518 if(the_passphrase){
519 af_use_aes_passphrase(af,0); // clear the passphrase
520 }
521 }
522
523 if(opt_xml){
524 /* This should be replaced with our xml.cpp object */
525 printf("<afcrypto>\n");
526 printf(" <image_filename>%s</image_filename>\n",fname);
527 printf(" <segment_count_total>%d</segment_count_total>\n",vni.segment_count_total);
528 printf(" <segment_count_signed>%d</segment_count_signed>\n",vni.segment_count_signed);
529 printf(" <segment_count_encrypted>%d</segment_count_encrypted>\n",vni.segment_count_encrypted);
530 printf(" <page_count_total>%d</page_count_total>\n",vni.page_count_total);
531 printf(" <page_count_encrypted>%d</page_count_encrypted>\n",vni.page_count_encrypted);
532 if(the_passphrase){
533 printf(" <passphrase correct='1'>%s</passphrase>\n",the_passphrase);
534 }
535 printf("</afcrypto>\n");
536 }
537 else{
538 /* re-run vstat because counts may have changed */
539 if(af_vstat(af,&vni)) err(1,"%s: af_vstat failed: ",fname);
540 printf("%s: %5d segments; %5d signed; %5d encrypted; %5d pages; %5d encrypted pages",
541 fname,vni.segment_count_total,vni.segment_count_signed,vni.segment_count_encrypted,
542 vni.page_count_total,vni.page_count_encrypted );
543 if(the_passphrase) printf("passphrase correct (\"%s\")",the_passphrase);
544 putchar('\n');
545 }
546 af_close(af);
547 }
548 return(0);
549 }
0 /*
1 * afdiskprint.cpp:
2 *
3 * Creates a diskprint AFF structure
4 */
5
6 /*
7 * PUBLIC DOMAIN
8 * By Simson L. Garfinkel
9 *
10 * The software provided here is released by the Naval Postgraduate
11 * School (NPS), an agency of the U.S. Department of Navy.The software
12 * bears no warranty, either expressed or implied. NPS does not assume
13 * legal liability nor responsibility for a User's use of the software
14 * or the results of such use.
15 *
16 * Please note that within the United States, copyright protection,
17 * under Section 105 of the United States Code, Title 17, is not
18 * available for any work of the United States Government and/or for
19 * any works created by United States Government employees. User
20 * acknowledges that this software contains work which was created by
21 * NPS employees and is therefore in the public domain and not
22 * subject to copyright.
23 */
24
25
26 #include "affconfig.h"
27 #include "afflib.h"
28 #include "afflib_i.h"
29 #include "base64.h"
30 #include "hashextent.h"
31
32 #ifdef HAVE_EXPAT
33
34 #include <openssl/evp.h>
35
36 #ifdef WIN32
37 #include "unix4win32.h"
38 #endif
39
40 #include <vector>
41 #include <string>
42 #include <iostream>
43 #include <sstream>
44 #include <map>
45 #include <set>
46
47 #ifdef HAVE_CSTRING
48 #include <cstring>
49 #endif
50
51 const char *hashes[] = {"SHA256","SHA1",0}; // what should we hash?
52
53 using namespace std;
54
55 #if HAVE_CTYPE_H
56 #include <ctype.h>
57 #endif
58
59 #if !defined(HAVE_ISALPHANUM) && defined(HAVE_ISALNUM)
60 #define isalphanum(c) isalnum(c)
61 #endif
62
63 #if !defined(HAVE_ISALPHANUM) && !defined(HAVE_ISALNUM)
64 #define isalphanum(c) (isalpha(c)||isdigit(c))
65 #endif
66
67 #if !defined(O_BINARY)
68 #define O_BINARY 0
69 #endif
70
71 const char *progname = "afdiskprint";
72 const char *xml_special_chars = "<>\r\n&'\"";
73
74 void usage()
75 {
76 printf("%s version %s\n",progname,PACKAGE_VERSION);
77 printf("usage: %s [options] infile \n",progname);
78 printf(" -x XML = Verify the diskprint\n");
79 printf(" -V = Just print the version number and exit.\n");
80 printf(" -h = Print this help.\n");
81 exit(0);
82 }
83
84 /****************************************************************
85 ** Support routines...
86 */
87
88 /**
89 * Return a random 64-bit number
90 */
91 uint64_t random64()
92 {
93 return (((uint64_t)random())<<32) | random();
94 }
95
96 uint64_t atoi64(const char *buf)
97 {
98 uint64_t ret=0;
99 sscanf(buf,"%"PRIu64,&ret);
100 return ret;
101 }
102
103
104 static int *hexcharvals = 0;
105 static void nsrl_bloom_init()
106 {
107 if(hexcharvals==0){
108 /* Need to initialize this */
109 int i;
110 hexcharvals = (int *)calloc(sizeof(int),256);
111 for(i=0;i<10;i++){
112 hexcharvals['0'+i] = i;
113 }
114 for(i=10;i<16;i++){
115 hexcharvals['A'+i-10] = i;
116 hexcharvals['a'+i-10] = i;
117 }
118 }
119 }
120
121
122 /**
123 * Convert a hex representation to binary, and return
124 * the number of bits converted.
125 * @param binbuf output buffer
126 * @param binbuf_size size of output buffer in bytes.
127 * @param hex input buffer (in hex)
128 */
129 int nsrl_hex2bin(unsigned char *binbuf,size_t hexbuf_size,const char *hex)
130 {
131 int bits = 0;
132 if(hexcharvals==0) nsrl_bloom_init();
133 while(hex[0] && hex[1] && hexbuf_size>0){
134 *binbuf++ = ((hexcharvals[(unsigned char)hex[0]]<<4) |
135 hexcharvals[(unsigned char)hex[1]]);
136 hex += 2;
137 bits += 8;
138 hexbuf_size -= 1;
139 }
140 if(hexbuf_size>0) binbuf[0] = 0; // might as well null-terminate if there is room
141 return bits;
142 }
143
144
145
146 /**
147 * Strip an XML string as necessary for a tag name.
148 */
149
150 void out_xmlstr(ostream &ostr,int indent,const char *tag,const char *value)
151 {
152 for(int i=0;i<indent;i++) ostr << " ";
153 ostr << "<" << tag << ">";
154 for(const char *ch=value;*ch;ch++){
155 if(isprint(*ch) && !strchr(xml_special_chars,*ch)){
156 ostr << *ch;
157 }
158 }
159 ostr << "</" << tag << ">";
160 }
161
162 void out_xmlhex(ostream &ostr,int indent,const char *tag,const char **attribs,
163 unsigned char *md,int len)
164 {
165 for(int i=0;i<indent;i++) ostr << ' ';
166 ostr << "<" << tag << " coding='base16'";
167 for(int i=0;attribs && attribs[i];i++){
168 ostr << " ";
169 ostr << attribs[i];
170 }
171 ostr << ">" << hashextent::bin2hex(md,len) << "</" << tag << ">\n";
172 }
173
174 /**
175 * Calculate the disk fingerprint for a spcific file and output it to stdout.
176 * Includes other named segments.
177 *
178 * @param infile the file to process.
179 */
180
181 int diskprint(const char *infile)
182 {
183 /** segments to include in output.
184 */
185 const char *segments[] = {AF_MD5,AF_SHA1,AF_SHA256,AF_CREATOR,AF_CASE_NUM,AF_IMAGE_GID,
186 AF_ACQUISITION_ISO_COUNTRY,
187 AF_ACQUISITION_COMMAND_LINE,AF_ACQUISITION_DATE,
188 AF_ACQUISITION_NOTES,AF_ACQUISITION_TECHNICIAN,
189 AF_BATCH_NAME,AF_BATCH_ITEM_NAME,0};
190 AFFILE *af = af_open(infile,O_RDONLY,0);
191 if(!af){
192 warn("%s",infile);
193 return -1;
194 }
195
196 cout << "<!-- XML generated by " << progname << " version " << PACKAGE_VERSION << " -->\n";
197 cout << "<diskprint image_filename='" << infile << "'>\n";
198
199 /* First handle the imagesize */
200 int64_t imagesize = af_get_imagesize(af);
201 if(imagesize>0){
202 char buf[32];
203 snprintf(buf,sizeof(buf),"%"PRIu64,imagesize);
204 out_xmlstr(cout,2,AF_IMAGESIZE,buf);
205 cout << "\n";
206 }
207 /* Get sector size and number of sectors */
208 unsigned long sectorsize=512; // default sectorsize
209 af_get_seg(af,AF_SECTORSIZE,&sectorsize,0,0);
210 if(sectorsize==0) sectorsize=512; // default sectorsize
211 int64_t sectors = imagesize/sectorsize;
212 if(sectors>0){
213 char buf[32];
214 snprintf(buf,sizeof(buf),"%lu",sectorsize);
215 out_xmlstr(cout,2,AF_SECTORSIZE,buf);
216 cout << "\n";
217 }
218
219 /* Output specific named segments */
220 for(int i=0;segments[i];i++){
221 char buf[65536];
222 size_t buflen = sizeof(buf);
223 if(af_get_seg(af,segments[i],0,(u_char *)buf,&buflen)==0){
224 buf[buflen] = 0; // null terminate it
225 if(af_display_as_hex(segments[i])){
226 out_xmlhex(cout,2,segments[i],0,(u_char *)buf,buflen);
227 } else {
228 out_xmlstr(cout,2,segments[i],buf);
229 }
230 }
231 }
232
233 /**
234 * The list of segments to hash is defined by:
235 * 1. The first 128K sectors.
236 * 2. The last 128K sectors.
237 * 3. A random set of 64K sectors.
238 */
239 hashvector hashextents;
240
241 for(int i=0;i<8;i++){
242 hashextents.push_back(hashextent(131072*i,131072));
243 }
244 for(int i=0;i<8;i++){
245 hashextents.push_back(hashextent(imagesize-131072*(8-i),131072));
246 }
247
248 /* Pick some random hashextents as well */
249 for(int i=0;i<100;i++){
250 uint64_t sector = random64() % (sectors-128);
251 hashextents.push_back(hashextent(sector*sectorsize,65536));
252 }
253
254 /** Sort the segments for maximal seek efficiency.
255 */
256 sort(hashextents.begin(),hashextents.end(),hashextent::compare);
257
258 /** Send the hashes to stdout using print_hash.
259 */
260 cout << " <hashes>\n";
261 for(hashvector::iterator it=hashextents.begin(); it!=hashextents.end(); it++){
262 for(int i=0;hashes[i];i++){
263 if((*it).compute_digest(af,hashes[i])==0){
264 cout << " " << (*it).toXML() << "\n";
265 }
266 }
267 }
268 cout << " </hashes>\n";
269 cout << "</diskprint>\n";
270 af_close(af);
271 return 0;
272 }
273
274
275 /**
276 * Code for reading the hashvector XML structure.
277 */
278 #include <expat.h>
279
280 class diskprintReader {
281 public:
282 /* General EXPAT stuff */
283 XML_Parser parser;
284 bool get_cdata; // this is cdata worth getting
285 string cdata; // the cdata that has been gotten
286 diskprintReader():get_cdata(false),hash(0){
287 parser = XML_ParserCreate(NULL);
288 XML_SetUserData(parser,this);
289 XML_SetElementHandler(parser,startElement,endElement);
290 XML_SetCharacterDataHandler(parser,cHandler);
291 }
292 int parse(const char *buf,int len) { return XML_Parse(parser, buf, len, 1);}
293 void clear(){
294 cdata = "";
295 get_cdata = false;
296 }
297
298 /* Specific stuff for XML diskprint */
299 hashextent *hash; // current hash
300 hashvector hashextents; // all discovered hashes
301 /* Turn the static functions into method calls */
302 static void startElement(void *userData,const char *name,const char **attrs){
303 ((diskprintReader *)userData)->startElement(name,attrs);
304 }
305 static void endElement(void *userData,const char *name){
306 ((diskprintReader *)userData)->endElement(name);
307 }
308 static void cHandler(void *userData,const XML_Char *s,int len){
309 diskprintReader *dh = (diskprintReader *)userData;
310 if(dh->get_cdata) dh->cdata.append(s,len);
311 }
312 void startElement(string name,const char **attrs){
313 clear();
314 /* If this is an element that we want, indicate such */
315 if(name=="hash"){
316 hash = new hashextent();
317 for(int i=0;attrs[i];i+=2){
318 if(strcmp(attrs[i],"coding")==0){ hash->coding = attrs[i+1]; continue;}
319 if(strcmp(attrs[i],"start")==0){ hash->start = atoi64(attrs[i+1]); continue;}
320 if(strcmp(attrs[i],"bytes")==0){ hash->bytes = atoi64(attrs[i+1]); continue;}
321 if(strcmp(attrs[i],"alg")==0){ hash->digest_name = attrs[i+1]; continue;}
322 }
323 get_cdata = true;
324 }
325 }
326 void endElement(const char *name){
327 if(get_cdata==false) return; // don't care about it.
328 if(!strcmp(name,"hash")){
329 if(hash->coding=="base16"){
330 hash->hexdigest = cdata;
331 }
332 hashextents.push_back(*hash);
333 }
334 if(!strcmp(name,"diskprint")){
335 XML_StopParser(parser,0); // stop the parser
336 return;
337 }
338 get_cdata = false;
339 }
340 };
341
342 void diskprint_verify(const char *filename,const char *xmlfile)
343 {
344 AFFILE *af = af_open(filename,O_RDONLY,0);
345 if(!af) err(1,"af_open(%s): ",filename);
346
347 /* Let's read the XML file */
348 int fd = open(xmlfile,O_RDONLY|O_BINARY);
349 if(!fd) err(1,"open: %s",xmlfile);
350 struct stat st;
351 if(fstat(fd,&st)) err(1,"stat: %s",xmlfile);
352 char *buf = (char *)malloc(st.st_size+1);
353 if(!buf) err(1,"malloc");
354
355 if(read(fd,buf,st.st_size)!=st.st_size) err(1,"cannot read XML file");
356 buf[st.st_size]=0; // terminate the buffer (not strictly needed)
357
358 diskprintReader dp;
359 dp.parse(buf,st.st_size);
360 cout << "Number of digests read: "<< dp.hashextents.size() << "\n";
361 const EVP_MD *strongest = dp.hashextents.strongest_available();
362 cout << "Strongest hash available: " << EVP_MD_name(strongest) << "\n";
363 /* Now verify each hash */
364 int matched=0;
365 int notmatched=0;
366 for(hashvector::iterator it = dp.hashextents.begin(); it!=dp.hashextents.end() && notmatched==0;it++){
367 if(EVP_MD_name(strongest) == (*it).digest_name){
368 hashextent &hp = (*it); // hash print
369 hashextent hs(af,hp.digest_name,hp.start,hp.bytes);
370 //cout << "hp: " << hp << "\n";
371 //cout << "hs: " << hs << "\n";
372 if(hp==hs){
373 matched++;
374 } else {
375 notmatched++;
376 }
377 }
378 }
379 if(notmatched){
380 cout << "Diskprint does not match.\n";
381 }
382 if(notmatched==0 && matched){
383 cout << "Diskprint matches.\n";
384 }
385 if(notmatched==0 && matched==0){
386 cout << "Cannot verify Diskprint; no available hash functions.\n";
387 }
388 exit(0);
389 }
390
391 int main(int argc,char **argv)
392 {
393 int ch;
394 const char *opt_x=0;
395
396 /* Initialize */
397 #ifdef HAVE_SRANDOMEDEV
398 srandomdev();
399 #endif
400 OpenSSL_add_all_digests();/* Dynamically loads the digests */
401
402
403 /* Parse arguments */
404 while ((ch = getopt(argc, argv, "x:h?V")) != -1) {
405 switch (ch) {
406 case 'h':
407 case '?':
408 default:
409 usage();
410 break;
411 case 'x': opt_x = optarg; break;
412 case 'V':
413 printf("%s version %s\n",progname,PACKAGE_VERSION);
414 exit(0);
415 }
416 }
417 argc -= optind;
418 argv += optind;
419
420 if(argc!=1){ // currently only generates for one file
421 usage();
422 }
423
424 if(opt_x){
425 diskprint_verify(argv[0],opt_x);
426 return(0);
427 }
428
429 /* Loop through all of the files */
430 printf("<?xml version='1.0' encoding='UTF-8'?>\n");
431 printf("<diskprints>\n");
432 while(*argv){
433 if(opt_x){
434 diskprint_verify(*argv,opt_x);
435 }
436 else {
437 diskprint(*argv);
438 }
439 argv++;
440 argc--;
441 }
442 printf("</diskprints>\n");
443 exit(0);
444 }
445 #else
446 int main(int argc,char **argv)
447 {
448 fprintf(stderr,"afdiskprint requires EXPAT. Cannot continue.\n");
449 exit(-1);
450 }
451 #endif
452
0 /*
1 * afinfo.cpp:
2 *
3 * print information about an aff file
4 */
5
6 /*
7 * Copyright (c) 2005--2008
8 * Simson L. Garfinkel and Basis Technology, Inc.
9 * All rights reserved.
10 *
11 * This code is derrived from software contributed by
12 * Simson L. Garfinkel
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by Simson L. Garfinkel
25 * and Basis Technology Corp.
26 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
27 * contributors to this program may be used to endorse or promote
28 * products derived from this software without specific prior written
29 * permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
32 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
34 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
36 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 */
45
46
47 #include "affconfig.h"
48 #include "afflib.h"
49 #include "utils.h"
50 #include "afflib_i.h"
51
52 #ifdef USE_S3
53 #include "s3_glue.h"
54 #endif
55
56 #include <ctype.h>
57 #include <zlib.h>
58 #include <openssl/md5.h>
59 #include <openssl/sha.h>
60 #include <assert.h>
61
62 #include <algorithm>
63 #include <cstdlib>
64 #include <vector>
65 #include <string>
66
67 #ifdef HAVE_CSTRING
68 #include <cstring>
69 #endif
70
71 using namespace std;
72
73 #ifdef HAVE_CURSES_H
74 #include <curses.h>
75 #endif
76
77 #ifdef HAVE_TERM_H
78 #include <term.h>
79 #endif
80
81 #ifdef HAVE_NCURSES_TERM_H
82 #include <ncurses/term.h>
83 #endif
84
85 #ifdef WIN32
86 #include "unix4win32.h"
87 #endif
88
89 const char *progname = "afinfo";
90
91 #define VALIDATE_MD5 0x01
92 #define VALIDATE_SHA1 0x02
93
94 int opt_validate = 0;
95 int opt_info = 1;
96 int opt_all = 0;
97 int opt_wide = 0;
98 int opt_l = 0;
99 unsigned int cols = 80; // default
100 int opt_x = 0;
101 int opt_b = 0;
102 int opt_identify = 1;
103 int opt_verbose = 0;
104 int opt_y = 0;
105 int opt_hexbuf = AF_HEXBUF_SPACE4 | AF_HEXBUF_UPPERCASE;
106 int opt_page_validate = 0;
107 int opt_no_preview = 0;
108 int opt_preview_md5 = 0;
109 int opt_debug = 0;
110 int opt_figure_media = 0;
111 const char *opt_passphrase = 0;
112
113 vector<string> opt_seglist; // just info these segments
114 bool something_was_decrypted = false;
115 const char *term = 0;
116
117
118 /**
119 * select bold on or off
120 */
121 void bold(int on)
122 {
123 if(!term) return;
124 #if defined(HAVE_LIBNCURSES)
125 #ifdef HAVE_ISATTY
126 if(!isatty(fileno(stdout))) return;
127 #endif
128 if(on) tputs(enter_bold_mode,1,putchar);
129 else tputs(exit_attribute_mode,0,putchar);
130 #endif
131 }
132
133 /**
134 * select a color.
135 * @param num - 0 is black; 1 red; 2 green; 3 yellow; 4 blue; 5 magenta; 6 cyan; 7 white;
136 */
137
138 #define RED 1
139 #define WHITE 7
140
141 void color(int num)
142 {
143 #ifdef HAVE_ISATTY
144 if(!isatty(fileno(stdout))) return;
145 #endif
146 #ifdef HAVE_CURSES_H
147 char *setf = tigetstr((char *)"setf");
148 if(!setf) setf = tigetstr((char *)"setaf");
149 if(setf){
150 putp(tparm(setf,num));
151 }
152 #endif
153 }
154
155
156 void usage()
157 {
158 printf("%s version %s\n",progname,PACKAGE_VERSION);
159 printf("usage: %s [options] infile\n",progname);
160 printf(" -a = print ALL segments (normally data segments are suppressed)\n");
161 printf(" -b = print how many bad blocks in each segment (implies -a)\n");
162 printf(" -i = identify the files, don't do info on them.\n");
163 printf(" -w = wide output; print more than 1 line if necessary.\n");
164 printf(" -s segment = Just print information about 'segment'.\n");
165 printf(" (may be repeated)\n");
166 printf(" -m = validate MD5 hash of entire image\n");
167 printf(" -S = validate SHA1 hash of entire image\n");
168 printf(" -v = validate the hash of each page (if present)\n");
169 printf(" -y = don't print segments of lengths 16 and 20 as hex)\n");
170 printf(" -p<passphrase> = Specify <passphrase> to decrypt file\n");
171 printf(" -l = Just print the segment names and exit\n");
172 printf(" -V = Just print the version number and exit.\n");
173
174 printf("\nPreview Options:\n");
175 printf(" -X = no data preview; just print the segment names\n");
176 printf(" -x = print binary values in hex (default is ASCII)\n");
177 printf("\nMisc:\n");
178 printf(" -d = debug\n");
179 printf(" -A = if infile is a device, print the number of sectors\n");
180 printf(" and sector size to stdout in XML. Otherwise error\n");
181 printf("\nCompilation:\n");
182 printf(" LZMA compression: Enabled\n");
183 #ifdef USE_LIBEWF
184 printf(" LIBEWF enabled\n");
185 #endif
186 #ifdef USE_QEMU
187 printf(" QEMU enabled\n");
188 #endif
189 #ifdef USE_FUSE
190 printf(" FUSE enabled\n");
191 #endif
192 #ifdef USE_S3
193 printf(" Amazon S3 enabled\n");
194 #endif
195 #ifdef HAVE_LIBEXPAT
196 printf(" HAVE_LIBEXPAT ");
197 #endif
198 printf("\n");
199
200 if(opt_debug){
201 for(int i=0;i<9;i++){
202 color(i);printf("Color %d\n",i);color(7);
203 }
204 }
205
206 exit(0);
207 }
208
209
210 AFFILE *af=0;
211
212 void sig_info(int arg)
213 {
214 if(af==0) return;
215 printf("Validating %"I64d" of %"I64d"\n", af->pos,af->image_size);
216 }
217
218
219
220
221 void validate(const char *infile)
222 {
223 af = af_open(infile,O_RDONLY,0);
224 if(!af) af_err(1,infile);
225 switch(af_identify(af)){
226 case AF_IDENTIFY_AFF:
227 case AF_IDENTIFY_AFM:
228 case AF_IDENTIFY_AFD:
229 break;
230 default:
231 printf("%s is not an AFF file\n",infile);
232 af_close(af);
233 return;
234 }
235
236 printf("\nValidating ");
237 if(opt_validate & VALIDATE_MD5) printf("MD5 ");
238 if(opt_validate == (VALIDATE_MD5|VALIDATE_SHA1)) printf("and ");
239 if(opt_validate & VALIDATE_SHA1) printf("SHA1 ");
240 printf("hash codes.\n");
241
242
243 #ifdef SIGINFO
244 signal(SIGINFO,sig_info);
245 #endif
246
247 /* Get a list of all the segments to see if there is a space */
248 af_rewind_seg(af);
249 char segname[AF_MAX_NAME_LEN];
250 vector <int> pages;
251 memset(segname,0,sizeof(segname));
252 while(af_get_next_seg(af,segname,sizeof(segname),0,0,0)==0){
253 int64_t page_num = af_segname_page_number(segname);
254 if(page_num>=0) pages.push_back(page_num);
255 }
256
257 if(pages.size()==0){
258 printf("No pages to validate.\n");
259 af_close(af);
260 }
261
262 sort(pages.begin(),pages.end());
263 vector<int>::iterator i = pages.begin();
264 int last = *i;
265 i++;
266 for(; i!= pages.end();i++){
267 if(last+1 != *i){
268 printf("gap in pages (%d!=%d); %s can't be validated.\n",last+1,*i,infile);
269 af_close(af);
270 return;
271 }
272 last = *i;
273 }
274
275 /* Set up the hash machinery */
276 MD5_CTX md5;
277 MD5_Init(&md5);
278
279 SHA_CTX sha;
280 SHA1_Init(&sha);
281
282 uint64_t total_bytes = 0;
283 while(!af_eof(af)){
284 unsigned char buf[65536]; // a decent size
285 size_t bytes = af_read(af,buf,sizeof(buf));
286 if(bytes==0) break; // reached sparse region of file
287 total_bytes += bytes;
288 if(opt_validate & VALIDATE_MD5) MD5_Update(&md5,buf,bytes);
289 if(opt_validate & VALIDATE_SHA1) SHA1_Update(&sha,buf,bytes);
290 }
291
292 /* Finish the hash calculations and write to the db */
293
294 if(opt_validate & VALIDATE_MD5){
295 unsigned char md5_stored[16];
296 size_t md5len = sizeof(md5_stored);
297 unsigned char md5_computed[16];
298 char buf[256];
299
300 MD5_Final(md5_computed,&md5);
301 printf("computed md5: %s\n",
302 af_hexbuf(buf,sizeof(buf),md5_computed,16,opt_hexbuf));
303 if(af_get_seg(af,AF_MD5,0,md5_stored,&md5len)==0){
304 printf(" stored md5: %s ",
305 af_hexbuf(buf,sizeof(buf),md5_stored,16,opt_hexbuf));
306 if(md5len==16 && !memcmp((const char *)md5_stored,
307 (const char *)md5_computed,16)){
308 printf(" MATCH\n");
309 }
310 else {
311 printf(" NO MATCH!\n");
312 }
313 }
314 else {
315 printf("(no MD5 in AFF file)\n");
316 }
317 }
318
319
320 if(opt_validate & VALIDATE_SHA1){
321 unsigned char sha1_stored[20];
322 size_t sha1len = sizeof(sha1_stored);
323 unsigned char sha1_computed[20];
324 char buf[256];
325
326 SHA1_Final(sha1_computed,&sha);
327 printf("computed sha1: %s \n",af_hexbuf(buf,sizeof(buf),sha1_computed,20,opt_hexbuf));
328 if(af_get_seg(af,AF_SHA1,0,sha1_stored,&sha1len)==0){
329 printf(" stored sha1: %s ",af_hexbuf(buf,sizeof(buf),sha1_stored,20,opt_hexbuf));
330 if(sha1len==20 && !memcmp((const char *)sha1_stored,
331 (const char *)sha1_computed,20)){
332 printf(" MATCH\n");
333 }
334 else {
335 printf(" NO MATCH!\n");
336 }
337 }
338 else {
339 printf("(no SHA1 in AFF file)\n");
340 }
341 }
342
343 af_close(af);
344 }
345
346 #define OUTLINE_LEN 65536
347
348
349 bool display_as_time(const char *segname)
350 {
351 if(strcmp(segname,AF_ACQUISITION_SECONDS)==0) return true;
352 return false;
353 }
354
355 bool display_as_hex(const char *segname,int data_len)
356 {
357 if(af_display_as_hex(segname)) return true;
358 if(data_len==16 && strstr(segname,"md5")) return true;
359 if(data_len==20 && strstr(segname,"sha1")) return true;
360 if(opt_x) return true;
361 if(opt_preview_md5) return true;
362 return false;
363 }
364
365 void badscan(AFFILE *af,int page_number,size_t data_len)
366 {
367 size_t page_size = af->image_pagesize;
368 unsigned char *buf = (unsigned char *)malloc(page_size);
369 if(af_get_page(af,page_number,buf,&page_size)){
370 err(1,"Could not read page %d",page_number);
371 }
372 printf("page_size = %d\n",(int)page_size);
373 int sectors = 0;
374 int bad_sectors = 0;
375 int funny_sectors = 0;
376 for(unsigned int offset=0;offset<page_size;offset+=af->image_sectorsize){
377 sectors++;
378 if(af_is_badsector(af,buf+offset)){
379 bad_sectors ++;
380 continue;
381 }
382 #ifdef __FreeBSD__
383 /* Look for the part of the bad flag that we know and love */
384 if(strnstr((char *)buf+offset,"BAD SECTOR",af->image_sectorsize)){
385 funny_sectors++;
386 continue;
387 }
388 #endif
389 }
390 printf(" sectors scanned: %d bad: %d ", sectors,bad_sectors);
391 if(funny_sectors){
392 printf("suspicious: %d ",funny_sectors);
393 }
394 printf("\n");
395 free(buf);
396 }
397
398
399 /* print_info:
400 * Print the info on a given segment name
401 */
402 void print_info(AFFILE *af,const char *segname)
403 {
404 unsigned long arg;
405 unsigned char *data = 0;
406 int dots = 0;
407 u_int display_len = 0;
408 char *cc = 0;
409
410 /* Check to see if this is a null page. */
411 if(segname[0]==0 && opt_all==0){
412 return;
413 }
414 if(segname[0]=='[' && opt_all){
415 puts(segname);
416 return;
417 }
418
419 /* Check to see if this is a data page */
420 int64_t page_num = af_segname_page_number(segname);
421
422 size_t data_len = 0;
423 /* First find out how big the segment is, then get the data */
424 if(af_get_seg(af,segname,&arg,0,&data_len)){
425 printf("%-25s SEGMENT NOT FOUND\n",segname);
426 return;
427 }
428
429 /* is this an encrypted segment that I have decrypted?
430 * Turn off automatic decryption and see if I can get it again...
431 * If we can get it again, then it wasn't decrypted.
432 */
433 int prev = af_set_option(af,AF_OPTION_AUTO_DECRYPT,0);
434 bool was_decrypted = ( af_get_seg(af,segname,0,0,0)!=0) ;
435 af_set_option(af,AF_OPTION_AUTO_DECRYPT,prev);
436
437 if(was_decrypted){
438 bold(1);
439 something_was_decrypted = true; // print key at bottom
440 }
441
442 /* Start the output line */
443 char output_line[OUTLINE_LEN];
444 memset(output_line,0,sizeof(output_line));
445
446 /* Now append the arg and the data len */
447 sprintf(output_line,"%-24s %8ld %8zd ",segname,arg,data_len);
448
449 if(opt_no_preview){
450 printf("%s\n",output_line);
451 goto done;
452 }
453
454 data = (unsigned char *)malloc(data_len);
455 if(af_get_seg(af,segname,0,data,&data_len)){
456 warn("af_get_seg_2 failed: segname=%s data_len=%zd",segname,data_len);
457 goto done;
458 }
459
460 /* Special handling of values that should be displayed as time */
461 if(display_as_time(segname)){
462 int hours = arg / 3600;
463 int minutes = (arg / 60) % 60;
464 int seconds = arg % 60;
465 printf("%s= %02d:%02d:%02d (hh:mm:ss)\n",output_line,hours,minutes,seconds);
466 goto done;
467 }
468
469 /* Special handling of quadwords that should be printed as such? */
470 if(((arg == AF_SEG_QUADWORD) && (data_len==8)) || af_display_as_quad(segname)){
471 /* Print it as a 64-bit value.
472 * The strcmp is there because early AF_IMAGESIZE segs didn't set
473 * AF_SEG_QUADWORD...
474 */
475 switch(data_len){
476 case 8:
477 printf("%s= %"I64d" (64-bit value)\n",
478 output_line,af_decode_q(data));
479 break;
480 case 0:
481 printf("%s= 0 (0-length segment)\n",output_line);
482 break;
483 default:
484 printf("%s= CANNOT DECODE %d byte segment\n",output_line,(int)data_len);
485 }
486 goto done;
487 }
488
489
490 /* See if I need to truncate */
491 display_len = data_len;
492 if(opt_wide==0 && data_len>32){ // don't bother showing more than first 32 bytes
493 dots = 1;
494 display_len = 32;
495 }
496
497 cc = output_line + strlen(output_line);
498
499 if(opt_preview_md5){
500 u_char md5[32];
501 MD5(data,data_len,md5);
502 memcpy(data,md5,32);
503 data_len = 32;
504 }
505 if(display_as_hex(segname,display_len)){
506 char buf[80];
507 snprintf(cc,sizeof(output_line)-strlen(output_line),
508 "%s%s",af_hexbuf(buf,sizeof(buf),data,display_len,opt_hexbuf),
509 dots ? "..." : "");
510 /* Special code for SHA1 */
511 if(!opt_wide && strcmp(segname,AF_SHA1)==0){
512 int r = fwrite(output_line,1,82,stdout);
513 if(r!=82) fprintf(stderr,"fwrite(output_line,1,82,stdout) returned %d\n",r);
514 printf("\n%62s\n",output_line+82);
515 goto done;
516 }
517 }
518 else {
519 /* Fill it out with some printable data */
520 unsigned int i;
521 if(display_len > sizeof(output_line)-strlen(output_line)){
522 display_len = sizeof(output_line)-strlen(output_line);
523 }
524 for(i=0;i<display_len;i++){
525 *cc = data[i];
526 if(isprint(*cc)==0) *cc='.';
527 if(*cc=='\n' || *cc=='\r') *cc=' ';
528 cc++;
529 }
530 *cc = 0;
531 }
532
533 /* Now print the results... */
534 if(!opt_wide){
535 if(strlen(output_line)>cols){
536 output_line[cols-4] = '.';
537 output_line[cols-3] = '.';
538 output_line[cols-2] = '.';
539 output_line[cols-1] = '\000';
540 }
541 }
542 fputs(output_line,stdout);
543 if(page_num>=0 && opt_b){
544 badscan(af,page_num,data_len);
545 }
546 if(opt_page_validate && page_num>=0){
547 /* Get the page again; this may involve decompression */
548 unsigned char *page_data = (unsigned char *)malloc(af->image_pagesize);
549 size_t page_data_len = af->image_pagesize;
550 if(af_get_page(af,page_num,page_data,&page_data_len)){
551 printf("** COULD NOT READ UNCOMPRESSED PAGE ");
552 goto skip1;
553 }
554
555 char hash_segname[32];
556 unsigned char hash_buf[16];
557 unsigned char hash_calc[16];
558 size_t hash_len = sizeof(hash_buf);
559 snprintf(hash_segname,sizeof(hash_segname),AF_PAGE_MD5,page_num);
560 printf(" ");
561 if(af_get_seg(af,hash_segname,0,hash_buf,&hash_len)){
562 printf("** NO SEGMENT %s ** ",hash_segname);
563 goto skip1;
564 }
565
566 MD5(page_data,page_data_len,hash_calc);
567 if(memcmp(hash_buf,hash_calc,sizeof(hash_buf))!=0){
568 char hb[32];
569 printf("** HASH INVALID **\n%30s Calculated %s\n","",
570 af_hexbuf(hb,sizeof(hb),hash_calc,16,opt_hexbuf));
571 printf("%30s Wanted %s ","",af_hexbuf(hb,sizeof(hb),hash_buf,16,opt_hexbuf));
572 printf("data_len=%d\n",(int)data_len);
573 } else{
574 printf("HASH OK ");
575 }
576 free(page_data);
577 }
578 skip1:;
579 putchar('\n');
580 done:
581 if(data) free(data);
582 bold(0); // make sure bold is off
583
584 //color(WHITE); // make sure we are back to normal color
585 }
586
587
588 /* Print the information on a specific file. */
589 int info_file(const char *infile)
590 {
591 unsigned long total_segs = 0;
592 unsigned long total_pages = 0;
593 unsigned long total_hashes = 0;
594 unsigned long total_signatures =0;
595 unsigned long total_nulls = 0;
596 struct af_vnode_info vni;
597
598 AFFILE *af = af_open(infile,O_RDONLY,0);
599 if(!af) af_err(1,"Cannot open %s",infile);
600 if(af_vstat(af,&vni)) err(1,"%s: af_vstat failed",infile);
601
602 if(opt_l){
603 /* Just list the segments and exit */
604 aff::seglist sl;
605 sl.get_seglist(af);
606 for(aff::seglist::const_iterator i = sl.begin(); i!=sl.end(); i++){
607 printf("%s\n",(*i).name.c_str());
608 }
609 af_close(af);
610 return 0;
611 }
612
613 if(vni.segment_count_encrypted>0 || vni.segment_count_signed>0){
614 printf("%s: has %s%s%ssegments\n",infile,
615 (vni.segment_count_encrypted ? "encrypted " : ""),
616 ((vni.segment_count_encrypted && vni.segment_count_signed) ? "and ": ""),
617 (vni.segment_count_signed ? "signed " : ""));
618 }
619
620
621 if(opt_passphrase){
622 if(af_use_aes_passphrase(af,opt_passphrase)){
623 errx(1,"%s: cannot use passphrase",opt_passphrase);
624 }
625 }
626
627 printf("\n%s\n",af_filename(af));
628 const char *v1 = "data";
629 const char *v2 = "====";
630
631 if(opt_all==0) printf("[skipping data segments]\n");
632 if(opt_all==0 && vni.segment_count_encrypted) printf("[skipping encrypted segments]\n");
633 if(opt_no_preview){
634 v1 = "";
635 v2 = "";
636 }
637 if(opt_preview_md5){
638 v1 = "md5";
639 }
640
641 printf(" data \n");
642 printf("Segment arg length %s\n",v1);
643 printf("======= ========= ======== %s\n",v2);
644
645 /* If a list of segments was specified by the user, just use that list */
646 if(opt_seglist.size()>0){
647 for(vector<string>::iterator i = opt_seglist.begin();
648 i != opt_seglist.end();
649 i++){
650 const char *segname = i->c_str();
651 print_info(af,segname);
652 }
653 af_close(af);
654 return 0;
655 }
656
657 /* Go through the whole file, get all of the segments, put them in a list */
658 vector <string> segments;
659 char segname[AF_MAX_NAME_LEN];
660 af_rewind_seg(af); // start at the beginning
661 int64_t total_datalen = 0;
662 size_t total_segname_len = 0;
663 size_t datalen = 0;
664 int aes_segs=0;
665 while(af_get_next_seg(af,segname,sizeof(segname),0,0,&datalen)==0){
666 total_segs ++;
667 total_datalen += datalen;
668 total_segname_len += strlen(segname);
669 if(segname[0]==0) total_nulls++;
670
671 /* Check to see if this is a regular page or a hash page */
672 char hash[64];
673 int64_t page_num = af_segname_page_number(segname);
674 int64_t hash_num = af_segname_hash_page_number(segname,hash,sizeof(hash));
675 if(page_num>=0) total_pages++;
676 if(hash_num>=0) total_hashes++;
677 if(strstr(segname,AF_SIG256_SUFFIX)) total_signatures++;
678 if(strstr(segname,AF_AES256_SUFFIX)) aes_segs++;
679 if(opt_all==0 && (page_num>=0||hash_num>=0)) continue; // skip
680 if(opt_all==0 && af_is_encrypted_segment(segname)) continue; // skip
681
682 if(segname[0]==0 && datalen>0 && opt_all){
683 snprintf(segname,sizeof(segname),"[null %zd bytes]",datalen);
684 }
685 segments.push_back(segname);
686 }
687
688 /* Now process the segments */
689 for(vector<string>::const_iterator i = segments.begin();
690 i != segments.end(); i++){
691 print_info(af,i->c_str());
692 }
693
694 /* Print the key */
695 if(something_was_decrypted){
696 bold(1);
697 printf("Bold indicates segments that were decrypted.\n");
698 bold(0);
699 }
700
701
702 printf("\n");
703 printf("Total segments: %8lu (%lu real)\n", total_segs,total_segs-total_nulls);
704 if(aes_segs){
705 printf(" Encrypted segments: %8u\n",aes_segs);
706 }
707 printf(" Page segments: %8lu\n",total_pages);
708 printf(" Hash segments: %8lu\n",total_hashes);
709 printf(" Signature segments: %8lu\n",total_signatures);
710 printf(" Null segments: %8lu\n",total_nulls);
711 if(opt_all){
712 printf(" Empty segments: %8lu\n",total_nulls);
713 printf("\n");
714 printf("Total data bytes in segments: %"I64d"\n",total_datalen);
715
716 printf("Total space in file dedicated to segment names: %zd\n",
717 total_segname_len);
718 printf("Total overhead for %lu segments: %zd bytes (%lu*(%zd+%zd))\n",
719 total_segs,
720 (size_t) total_segs*(sizeof(struct af_segment_head) +sizeof(struct af_segment_tail)),
721 total_segs,
722 sizeof(struct af_segment_head),
723 sizeof(struct af_segment_tail));
724 printf("Overhead for AFF file header: %zd bytes\n",sizeof(struct af_head));
725 }
726
727 int64_t device_sectors = 0;
728 af_get_segq(af,AF_DEVICE_SECTORS,&device_sectors);
729 if(device_sectors==0){
730 /* See if we can fake it */
731 unsigned long cylinders=0;
732 unsigned long heads=0;
733 unsigned long sectors_per_track=0;
734 af_get_seg(af,AF_CYLINDERS,&cylinders,0,0);
735 af_get_seg(af,AF_HEADS,&heads,0,0);
736 af_get_seg(af,AF_SECTORS_PER_TRACK,&sectors_per_track,0,0);
737 device_sectors = cylinders * heads * sectors_per_track;
738 }
739 //printf("device_sectors=%"I64d"\n",device_sectors);
740
741
742 int some_missing_pages = 1;
743 if(af->image_pagesize && af->image_sectorsize && device_sectors){
744 int64_t device_bytes = (int64_t)device_sectors * af->image_sectorsize;
745 int64_t device_pages = (device_bytes+af->image_pagesize-1) / af->image_pagesize;
746 int64_t missing_pages = device_pages - total_pages;
747 //printf("device_bytes=%"I64d"\n",device_bytes);
748 //printf("device_pages=%"I64d"\n",device_pages);
749 if(missing_pages!=0){
750 printf("Missing page segments: %8"I64u"\n",missing_pages);
751 }
752 else {
753 some_missing_pages=0;
754 }
755 }
756 if (some_missing_pages){
757 if(((total_pages-1) * af->image_pagesize <= af->image_size) &&
758 ((total_pages) * af->image_pagesize >= af->image_size)){
759 some_missing_pages = 0;
760 }
761 }
762
763 if(some_missing_pages && opt_debug){
764 printf("Cannot calculate missing pages\n");
765 printf(" device_sectors=%"I64d" image_pagesize=%lu sectorsize=%lu\n",
766 device_sectors,af->image_pagesize,af->image_sectorsize);
767 }
768 af_close(af);
769 return 0;
770
771 }
772
773
774 void figure_media(const char *fn)
775 {
776 int fd = open(fn,O_RDONLY,0);
777 if(fd<0) err(1,"open(%s)",fn);
778 struct af_figure_media_buf afb;
779 if(af_figure_media(fd,&afb)){
780 err(1,"af_figure_media(%s)",fn);
781 }
782 printf("<?xml version='1.0' encoding='UTF-8'?>\n");
783 printf("<!DOCTYPE Server >\n");
784 printf("<device name='%s'>\n",fn);
785 printf(" <sector_size>%d</sector_size>\n",afb.sector_size);
786 printf(" <total_sectors>%"PRId64"</total_sectors>\n",afb.total_sectors);
787 printf(" <max_read_blocks>%"PRIu64"</max_read_blocks>\n",afb.max_read_blocks);
788 printf("</device>\n");
789 close(fd);
790 }
791
792 int main(int argc,char **argv)
793 {
794 int ch;
795 const char *infile;
796
797 /* Figure out how many cols the screen has... */
798 #ifdef HAVE_LIBNCURSES
799 term = getenv("TERM");
800 if(term){
801 setupterm((char *)0,1,(int *)0);
802 start_color();
803 cols = tgetnum((char *)"co");
804 }
805 #endif
806
807 while ((ch = getopt(argc, argv, "abh?s:SmiIwj:p:xvVX5dAl")) != -1) {
808 switch (ch) {
809 case 'a': opt_all++; break;
810 case 'b': opt_all ++; opt_b ++; break;
811 case 'i': opt_info=0; opt_identify = 1; break;
812 case 'w': opt_wide++; break;
813 case 'X': opt_no_preview++;break;
814 case 'x': opt_x++; break;
815 case 'y': opt_y++; break;
816 case 'l': opt_l++;break;
817 case 'm': opt_validate |= VALIDATE_MD5; break;
818 case 'S': opt_validate |= VALIDATE_SHA1; break;
819 case 'v': opt_page_validate = 1;break;
820 case 'p': opt_passphrase = optarg; break;
821 case '5': opt_preview_md5 = 1;break;
822 case 'd': opt_debug = 1;break;
823 case 'A': opt_figure_media = 1 ; break;
824
825 case 'h':
826 case '?':
827 default:
828 usage();
829 break;
830 case 's':
831 opt_seglist.push_back(optarg); // add to the list of segments to info
832 break;
833 case 'V':
834 printf("%s version %s\n",progname,PACKAGE_VERSION);
835 exit(0);
836 }
837 }
838 argc -= optind;
839 argv += optind;
840
841 if(argc<1){
842 usage();
843 }
844
845
846 /* Loop through all of the files */
847 while(*argv){
848 infile = *argv++; // get the file
849 argc--; // decrement argument counter
850
851 const char *name = af_identify_file_name(infile,1);
852 if(!name) err(1,"%s",infile);
853
854 if(opt_figure_media){ figure_media(infile);continue;}
855 if(opt_identify) printf("%s is a %s file\n",infile,name);
856 if(opt_info) info_file(infile);
857 if(opt_validate) validate(infile);
858 }
859 #ifdef USE_S3
860 s3_audit(0);
861 #endif
862 return(0);
863 }
864
865
136136 /* See if we can build a TOC */
137137 if(r<0){
138138 printf("AFF file corrupt at %"I64d" out of %"I64d" (%"I64d" bytes from end)\n",
139 ftello(af->aseg),len,len-ftello(af->aseg));
139 ftello(af->aseg),(int64_t)len,len-ftello(af->aseg));
140140 if(opt_fix){
141141 printf("Truncating... %d \n",fileno(af->aseg));
142142 if(ftruncate(fileno(af->aseg),ftello(af->aseg))){
0 /*
1 * afrecover.cpp
2 *
3 * Recover broken pages of an AFF file using the party bits
4 */
5
6 /*
7 * Copyright (c) 2005
8 * Simson L. Garfinkel and Basis Technology, Inc.
9 * All rights reserved.
10 *
11 * This code is derrived from software contributed by
12 * Simson L. Garfinkel
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by Simson L. Garfinkel
25 * and Basis Technology Corp.
26 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
27 * contributors to this program may be used to endorse or promote
28 * products derived from this software without specific prior written
29 * permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
32 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
34 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
36 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 */
45
46
47 #include "affconfig.h"
48 #include "afflib.h"
49 #include "afflib_i.h"
50 #include "utils.h"
51
52 #include <ctype.h>
53
54 #include <zlib.h>
55 #include <openssl/md5.h>
56 #include <openssl/sha.h>
57 #include <assert.h>
58
59 #ifdef HAVE_UNISTD_H
60 #include <unistd.h>
61 #endif
62
63 #ifdef HAVE_TERM_H
64 #include <term.h>
65 #endif
66
67 #ifdef HAVE_NCURSES_TERM_H
68 #include <ncurses/term.h>
69 #endif
70
71 #ifdef WIN32
72 #include "unix4win32.h"
73 #include <malloc.h>
74 #endif
75
76 using namespace std;
77 using namespace aff;
78
79 const char *progname = "affix";
80
81
82 int opt_b = 0;
83
84
85 void usage()
86 {
87 printf("usage: %s filename\n",progname);
88 exit(0);
89 }
90
91
92
93 int recover(const char *fname)
94 {
95 AFFILE *af = af_open(fname,O_RDWR,0);
96 if(!af) af_err(1,fname);
97
98 /* Get the parity page */
99 size_t pagesize = af_page_size(af);
100 u_char *pagebuf = (unsigned char *)calloc(pagesize,1);
101 u_char *parity_buf = (unsigned char *)calloc(pagesize,1);
102 u_char *my_parity_buf = (unsigned char *)calloc(pagesize,1);
103
104
105 if(af_get_seg(af,AF_PARITY0,0,parity_buf,&pagesize)){
106 err(1,"Cannot read %s segment; cannot continue",AF_PARITY0);
107 }
108
109 /* Now, for every page:
110 * 1. Read the page & the signature
111 * 2. If the signature is good, add it into the parity buffer.
112 * - If not, put it on the list of bad segments.
113 */
114 seglist segments(af);
115 seglist bad_sigs;
116 seglist good_sigs;
117 for(seglist::const_iterator seg = segments.begin();
118 seg != segments.end();
119 seg++){
120
121 if (seg->pagenumber()<0) continue; // only look for pages
122 switch(af_sig_verify_seg(af,seg->name.c_str())){
123 case AF_ERROR_SIG_NO_CERT:
124 errx(1,"%s: no public key in AFF file\n",af_filename(af));
125 case AF_ERROR_SIG_READ_ERROR:
126 errx(1,"no signature for segment '%s' --- recovery cannot continue",seg->name.c_str());
127 case AF_ERROR_SIG_BAD:
128 printf("%s has a bad signature\n",af_filename(af));
129 bad_sigs.push_back(*seg);
130 break;
131 case AF_SIG_GOOD:
132 good_sigs.push_back(*seg);
133 /* While the page is in the cache, make our parity buf */
134 pagesize = af_page_size(af);
135 if(af_get_page(af,seg->pagenumber(),pagebuf,&pagesize)){
136 err(1,"cannot read %s\n",seg->name.c_str());
137 }
138 for(u_int i=0;i<pagesize;i++){
139 my_parity_buf[i] ^= pagebuf[i];
140 }
141 break;
142 default:
143 break;
144 }
145 }
146 u_char *new_pagebuf = (unsigned char *)calloc(pagesize,1);
147
148 if(bad_sigs.size()>1) errx(1,"This program can only repair 1 bad page at the moment.");
149 if(bad_sigs.size()==0) errx(1,"There are no bad pages for this program to repair.");
150 printf("Attempting to repair %s\n",bad_sigs[0].name.c_str());
151
152 /* Calculate the page buf */
153 for(u_int i=0;i<pagesize;i++){
154 new_pagebuf[i] = parity_buf[i] ^ my_parity_buf[i];
155 }
156
157 /* Write the page back */
158 if(af_update_page(af,bad_sigs[0].pagenumber(),new_pagebuf,pagesize)){
159 err(1,"Cannot put page back");
160 }
161
162 /* Now verify the signature */
163 int r = af_sig_verify_seg(af,bad_sigs[0].name.c_str());
164 if(r==AF_SIG_GOOD){
165 printf("Page %s successfully repaired\n",bad_sigs[0].name.c_str());
166 }
167 else{
168 printf("Page %s could not be repaired; signature error code=%d\n",bad_sigs[0].name.c_str(),r);
169 exit(1);
170 }
171 af_close(af);
172 return 0;
173 }
174
175
176
177 int main(int argc,char **argv)
178 {
179 setvbuf(stdout,0,_IONBF,0); // turn off buffering
180 int ch;
181 while ((ch = getopt(argc, argv, "bh?v")) != -1) {
182 switch (ch) {
183 case 'h':
184 case '?':
185 default:
186 usage();
187 break;
188 case 'v':
189 printf("%s version %s\n",progname,PACKAGE_VERSION);
190 exit(0);
191
192 }
193 }
194 argc -= optind;
195 argv += optind;
196
197 if(argc<1){
198 usage();
199 }
200
201 recover(argv[0]);
202 exit(0);
203 }
204
205
0 /*
1 * afsegment.cpp
2 *
3 * segment manipulation tool
4 */
5
6 /*
7 * Copyright (c) 2006
8 * Simson L. Garfinkel and Basis Technology, Inc.
9 * All rights reserved.
10 *
11 * This code is derrived from software contributed by
12 * Simson L. Garfinkel
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by Simson L. Garfinkel
25 * and Basis Technology Corp.
26 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
27 * contributors to this program may be used to endorse or promote
28 * products derived from this software without specific prior written
29 * permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
32 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
34 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
36 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 */
45
46
47 #include "affconfig.h"
48 #include "afflib.h"
49 #include "afflib_i.h"
50
51 #include <limits.h>
52
53 #ifdef HAVE_REGEX_H
54 #include <regex.h>
55 #endif
56
57 #include <algorithm>
58 #include <cstdlib>
59 #include <vector>
60 #include <string>
61
62 #ifdef HAVE_CSTRING
63 #include <cstring>
64 #endif
65
66 using namespace std;
67
68
69 const char *progname = "afsegment";
70
71 int opt_create = 0;
72 int opt_quad = 0;
73 int opt_arg = 0;
74 int opt_verbose = 0;
75 int filecount = 0;
76 int opt_debug = 0;
77 int opt_x = 0;
78
79 void usage()
80 {
81 printf("afsegment version %s\n",PACKAGE_VERSION);
82 #ifdef REG_EXTENDED
83 printf("usage: afsegment [options] file1.aff [file2.aff ...]\n");
84 printf("options:\n");
85 printf(" -c Create AFF files if they do not exist\n");
86 printf(" -ssegval Sets the value of a segment; may be repeated\n");
87 printf(" -psegname Prints the contents of the segment name for each file\n");
88 printf(" -V Just print the version number and exit.\n");
89 printf(" -dname Delete segment 'name'\n");
90 printf(" -h, -? Print this message\n");
91 printf(" -Q interpert 8-byte segments as a 64-bit value\n");
92 printf(" -A Print the 32-bit arg, not the segment value\n");
93 printf(" -x Print the segment as a hex string\n");
94 printf("\n");
95 printf("Values for segval:\n");
96 printf("\n");
97 printf("Setting the segment values:\n");
98 printf(" -sname=- Take the new value of segment 'name' from stdin\n");
99 printf(" -sname=val Sets segment 'name' to be 'val' \n");
100 printf(" -sname=<val Sets segment 'name' to be contents of file 'val'\n");
101 printf("\n");
102 printf("Setting the segment args:\n");
103 printf(" -sname/arg Sets segment 'name' arg to be 'arg' (may be repeated)\n");
104 printf("\n");
105 printf("Setting both the segment value and the arg:\n");
106 printf(" -sname/arg=val Sets both arg and val for segment 'name'\n");
107 printf(" -sname/arg=<file Sets the arg and take contents from file 'file'\n");
108 printf(" -sname/arg=- Sets the arg of segment 'name' and take the contents from stdin\n");
109 printf("\n");
110 printf("Note: All deletions are done first, then all updates. Don't specify the\n");
111 printf("same segment twice on one command line.\n");
112 #else
113 printf("afsegment requires a functioning regex package to be installed\n");
114 #endif
115 exit(0);
116 }
117
118 #ifdef REG_EXTENDED
119 int get_segment_from_file(AFFILE *af,const char *segname,unsigned long arg,FILE *in)
120 {
121 u_char *value = (u_char *)malloc(0);
122 int value_len = 0;
123
124 while(!feof(in)){
125 char buf[4096];
126 int count;
127 count = fread(buf,1,sizeof(buf),in);
128 if(count>0){
129 value = (u_char *)realloc(value,value_len+count);
130 memcpy(value+value_len,buf,count);
131 value_len += count;
132 }
133 }
134 int r = af_update_seg(af,segname,arg,value,value_len);
135 free(value);
136 return r;
137 }
138
139
140 void update_segment(AFFILE *af,const char *segname,
141 const char *argstr,const char *segval)
142 {
143 unsigned long arg = 0;
144
145 if(strlen(argstr)>1) arg = atoi(argstr+1);
146
147 if(!strcmp(segval,"=-")){
148 get_segment_from_file(af,segname,arg,stdin);
149 return;
150 }
151 if(!strncmp(segval,"=<",2)){
152 FILE *f = fopen(segval+2,"rb");
153 if(!f) err(1,"fopen(%s)",segval+2);
154 get_segment_from_file(af,segname,arg,f);
155 fclose(f);
156 return;
157 }
158 segval++; // skip past the "="
159 int r = af_update_seg(af,segname,arg,(const u_char *)segval,strlen(segval));
160 if(r) warn("af_update(%s,%s) ",af_filename(af),segname);
161 }
162
163
164 char *make_re_string(const char *buf,regmatch_t *match,int num)
165 {
166 int len = match[num].rm_eo - match[num].rm_so;
167 char *ret = (char *)malloc(len+1);
168 memcpy(ret,buf+match[num].rm_so,len);
169 ret[len] = '\000';
170 return ret;
171 }
172
173
174 vector<string>del_segs;
175 vector<string>new_segs;
176 vector<string>print_segs;
177 int flags=O_RDONLY;
178 int openmode = 0666;
179 regex_t re;
180
181 void process(const char *fn)
182 {
183 AFFILE *af = af_open(fn,flags,openmode);
184 if(af){
185 vector<string>::iterator i;
186
187 for(i=del_segs.begin();i!=del_segs.end();i++){
188 if(af_del_seg(af,i->c_str())){
189 warnx("af_del_seg(%s): cannot delete segment '%s' ",fn,i->c_str());
190 }
191 else {
192 printf("%s: '%s' deleted\n",fn,i->c_str());
193 }
194 }
195 for(i=new_segs.begin();i!=new_segs.end();i++){
196 regmatch_t match[10];
197 memset(match,0,sizeof(match));
198 if(regexec(&re,i->c_str(),10,match,0)==0){
199 char *segname = make_re_string(i->c_str(),match,1);
200 char *argstr = make_re_string(i->c_str(),match,2);
201 char *segval = make_re_string(i->c_str(),match,3);
202 update_segment(af,segname,argstr,segval);
203 free(segname);
204 free(argstr);
205 free(segval);
206 }
207 }
208 for(i=print_segs.begin();i!=print_segs.end();i++){
209 size_t len = 0;
210 const char *segname = i->c_str();
211 if(opt_debug) fprintf(stderr," %s: \n",segname);
212 unsigned char *buf=0;
213 if(af_get_seg(af,segname,0,0,&len)){
214 #if HAVE_ISATTY
215 if(isatty(fileno(stdout))){
216 fprintf(stderr,"%s: segment %s not found\n",fn,segname);
217 continue;
218 }
219 #endif
220 if(opt_debug) fprintf(stderr," <<not found>>\n");
221 continue;
222 }
223
224 buf = (u_char *)malloc(len+1);
225 if(!buf) err(1,"malloc");
226 unsigned long arg = 0;
227 buf[len] = 0;
228 if(af_get_seg(af,segname,&arg,buf,&len)){
229 af_err(1,"af_get_seg"); // this shoudln't fail here
230 free(buf);
231 continue;
232 }
233 if(opt_debug) fprintf(stderr," arg=%lu len=%zd\n",arg,len);
234 int p = 1;
235
236 if(filecount>1) printf("%s:",fn);
237 if(print_segs.size()>1) printf("%s=",segname);
238 if(opt_quad && len==8){
239 uint64_t quad = af_decode_q(buf);
240 printf("%"I64u"\n",quad);
241 p = 0;
242 }
243
244 if(opt_arg){
245 printf("%lu\n",arg);
246 p = 0;
247 }
248
249 if(p){
250 for(u_int i=0;i<len;i++){
251 putchar(buf[i]);
252 }
253 }
254 if(filecount>1) printf("\n");
255 fflush(stdout);
256 if(buf) free(buf);
257 }
258 af_close(af);
259 if(opt_x) printf("\n");
260 }
261 else {
262 af_err(1,"af_open(%s) failed:",fn);
263 }
264 }
265
266 int main(int argc,char **argv)
267 {
268
269 int ch;
270 while ((ch = getopt(argc, argv, "cd:Vp:s::h?QADx")) != -1) {
271 switch (ch) {
272 case 'c':
273 flags |= O_CREAT;
274 openmode = 0666;
275 break;
276 case 'Q': opt_quad=1;break;
277 case 'A': opt_arg=1;break;
278 case 'd':
279 if(optarg==0) usage();
280 del_segs.push_back(optarg); flags |= O_RDWR;break;
281 case 'D':
282 opt_debug=1;
283 break;
284 case 'p':
285 if(optarg==0) usage();
286 print_segs.push_back(optarg); break;
287 case 's':
288 if(optarg==0) usage();
289 if(strlen(optarg)==0) usage();
290 new_segs.push_back(optarg); flags |= O_RDWR;break;
291 case 'x':
292 opt_x++;
293 break;
294 case 'h':
295 case '?':
296 default:
297 usage();
298 exit(0);
299 case 'V':
300 printf("%s version %s\n",progname,PACKAGE_VERSION);
301 exit(0);
302 }
303 }
304 argc -= optind;
305 argv += optind;
306
307 if(argc<1){
308 usage();
309 }
310
311 if(regcomp(&re,"([^/=]*)(/[0-9]+)?(=.*)?",REG_EXTENDED|REG_ICASE)){
312 err(1,"regcomp");
313 }
314
315 filecount = argc;
316 while(*argv){
317 fflush(stdout);
318 if(opt_debug) fprintf(stderr,"%s:\n",*argv);
319 process(*argv);
320 argv++;
321 argc--;
322 }
323 exit(0);
324 }
325 #else
326 int main(int argc,char **argv)
327 {
328 usage();
329 exit(1);
330 }
331 #endif
0 /*
1 * afsign.cpp:
2 *
3 * Sign an existing AFF file.
4 */
5
6 /*
7 * Copyright (c) 2007
8 * Simson L. Garfinkel and Basis Technology, Inc.
9 * All rights reserved.
10 *
11 * This code is derrived from software contributed by
12 * Simson L. Garfinkel
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by Simson L. Garfinkel
25 * and Basis Technology Corp.
26 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
27 * contributors to this program may be used to endorse or promote
28 * products derived from this software without specific prior written
29 * permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
32 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
34 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
36 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 */
45
46 #include "affconfig.h"
47 #include "afflib.h"
48 #include "afflib_i.h"
49
50 #ifdef USE_AFFSIGS
51
52 #include "utils.h"
53 #include "base64.h"
54
55 #include <stdio.h>
56 #include <algorithm>
57 #include <vector>
58 #include <iostream>
59 #include <openssl/pem.h>
60 #include <openssl/x509.h>
61
62
63 #include "aff_bom.h"
64
65 int opt_note = 0;
66 const char *opt_sign_key_file = 0;
67 const char *opt_sign_cert_file = 0;
68
69 using namespace std;
70 using namespace aff;
71
72 const char *progname = "afsign";
73
74 void usage()
75 {
76 printf("%s version %s\n",progname,PACKAGE_VERSION);
77 printf("usage: %s [options] filename.aff\n",progname);
78 printf("This program will:\n");
79 printf(" * Sign each segment if there are no segment signatures.\n");
80 printf(" * Write signed chain-of-custody Bill of Materials segment.\n");
81 printf("\nSignature Options:\n");
82 printf(" -k filename.key = specify private key for signing\n");
83 printf(" -c filename.cer = specify a X.509 certificate that matches the private key\n");
84 printf(" (by default, the file is assumed to be the same one\n");
85 printf(" provided with the -k option.)\n");
86 printf(" -Z = ZAP (remove) all signature segments.\n");
87 printf("options:\n");
88 printf(" -n --- ask for a chain-of-custody note.\n");
89 printf(" -v --- Just print the version number and exit.\n");
90 exit(0);
91 }
92
93
94 int afsign(const char *fn)
95 {
96 AFFILE *af = af_open(fn,O_RDWR,0);
97 if(!af) af_err(1,"%s",fn);
98
99 struct af_vnode_info vni;
100 if(af_vstat(af,&vni)) err(1,"af_vstat");
101
102 if(vni.supports_metadata==0){
103 /* If it is a raw file, we can create an AFM file to sign */
104 if(vni.is_raw==0) errx(1,"%s: file does not support metadata. Cannot sign\n",fn);
105 af_close(af); // afm will open it
106 char afmfile[MAXPATHLEN+1];
107 char file000[MAXPATHLEN+1];
108 char extension[MAXPATHLEN+1];
109 strcpy(afmfile,fn);
110 char *period = strrchr(afmfile,'.');
111 if(!period) errx(1,"%s: file does not support metadata and lacks a file extension,\n"
112 "which is needed to create an AFM file '%s\n",afmfile,fn);
113 strcpy(extension,period+1); // get the extension
114
115 /* If the file being opened is not a .000 file, and a .000 file exists, do not proceed */
116 strcpy(period,".000");
117 strcpy(file000,afmfile); // make the 000 file
118 strcpy(period,".afm");
119
120 if(strcmp(extension,"000")!=0){
121 if(access(file000,F_OK)==0){
122 errx(1,"Can't create .afm file because %s exists.\n",file000);
123 }
124 }
125
126 strcpy(period,".afm"); // we are now going to make an afm file
127 af = af_open(afmfile,O_RDWR|O_CREAT,0600);
128 if(!af) af_err(1,"%s: file does not support metadata and cannot create AFM file '%s\n",fn,afmfile);
129 if(strcmp(extension,"000")!=0){
130 af_update_seg(af,AF_RAW_IMAGE_FILE_EXTENSION,0,(const u_char *)extension,strlen(extension));
131 af_close(af);
132 unlink(file000); // get rid of that .000 file
133 af = af_open(afmfile,O_RDWR,0600);
134 if(!af) af_err(1,"%s: Created AFM file but cannot re-open it\n",fn);
135 /* Read the first byte to force a call to afm_split_raw_setup().
136 * The results of the read don't matter, but we better be able to read.
137 */
138 u_char buf[1];
139 if(af_read(af,buf,1)!=1){
140 err(1,"Cannot read first byte of %s",fn);
141 }
142 af_seek(af,0L,0);
143 }
144 }
145
146 seglist segments(af);
147
148 if(isatty(fileno(stdout))){
149 printf("Signing segments...\n");
150 fflush(stdout);
151 }
152
153 bool signed_unsigned_segments = false;
154 if(segments.has_signed_segments()==false){
155 if(af_set_sign_files(af,opt_sign_key_file,opt_sign_cert_file)){
156 errx(1,"key file '%s' or certificate file '%s' is invalid",
157 opt_sign_key_file,opt_sign_cert_file);
158 }
159 int r = af_sign_all_unsigned_segments(af);
160 if(r<0) af_err(1,"%s: all unsigned segments cannot be signed.",fn);
161 if(r>0) signed_unsigned_segments = true;
162 }
163
164 aff_bom bom(opt_note);
165 if(bom.read_files(opt_sign_cert_file,opt_sign_key_file)) err(1,"Can't read signature files???");
166
167 u_char *pagebuf = (unsigned char *)calloc(af_page_size(af),1);
168 u_char *parity_buf = (unsigned char *)calloc(af_page_size(af),1);
169 bool compute_parity = true; // do we need to compute the parity?
170
171 /* Create the parity buffer if it doesn't exist. If the parity buffer exists, we'll just trust it.
172 * We could do a two-pass here, one for creating the parity buffer, another for creating the BOM.
173 * But that would require reading the data twice; hence this extra layer of complexity.
174 */
175 size_t parity_buf_len = af_page_size(af);
176 if(af_get_seg(af,AF_PARITY0,0,parity_buf,&parity_buf_len)==0){
177 compute_parity = false; // no need to compute it; we read it
178 }
179
180 for(seglist::const_iterator seg = segments.begin(); seg!= segments.end();seg++){
181 const char *segname = seg->name.c_str();
182
183 if(isatty(fileno(stdout))){
184 printf("\rCalculating BOM for segment %s... ",segname);
185 printf("\n");
186 fflush(stdout);
187 }
188
189 u_char seghash[32]; /* resultant message digest; could be any size */
190 unsigned int seghash_len = sizeof(seghash); /* big enough to hold SHA256 */
191 int sigmode = 0;
192 int64_t pagenumber = af_segname_page_number(segname);
193 if(pagenumber>=0){
194 /* Page segments must run in SIGNATURE_MODE1 - the actual data in the page */
195 size_t this_pagesize = af_page_size(af);
196 if(af_get_page(af,pagenumber,pagebuf,&this_pagesize)){
197 free(pagebuf);
198 return -1;
199 }
200 /* Add to parity buf if we are making a parity page*/
201 if(compute_parity){
202 for(u_int i=0;i<this_pagesize;i++){
203 parity_buf[i] ^= pagebuf[i];
204 }
205 }
206 aff_bom::make_hash(seghash,0,segname,pagebuf,this_pagesize);
207 sigmode = AF_SIGNATURE_MODE1;
208 }
209 else{
210 /* Non-Page segments can be run in SIGNATURE_MODE0 - the actual data in the file */
211 size_t seglen=0;
212 if(af_get_seg(af,segname,0,0,&seglen)){
213 err(1,"Cannot read length of segment '%s' on input file %s", segname,af_filename(af));
214 }
215 unsigned char *segbuf = (unsigned char *)malloc(seglen);
216 if(!segbuf){
217 err(1,"Cannot allocated %d bytes for segment '%s' in %s",
218 (int)seglen,segname,af_filename(af));
219 }
220 /* Now get the raw source segment */
221 unsigned long arg=0;
222 if(af_get_seg(af,segname,&arg,segbuf,&seglen)){
223 err(1,"Cannot read segment '%s' in %s. Deleteing output file", segname,af_filename(af));
224 }
225 aff_bom::make_hash(seghash,arg,segname,segbuf,seglen);
226 sigmode = AF_SIGNATURE_MODE0;
227 free(segbuf);
228 }
229 bom.add(segname,sigmode,seghash,seghash_len); // add to the BOM
230 }
231
232 /* If we have been making the parity buf:
233 * 1 - Write it out; add it to the BOM
234 * 2 - Write out the signature segment for the parity buf; add it to the bom
235 */
236 if(compute_parity){
237 if(af_update_seg(af,AF_PARITY0,0,parity_buf,af_page_size(af))) err(1,"Can't write %s",AF_PARITY0);
238
239 /* Add the parity page that we made to the BOM */
240 u_char seghash[32]; /* resultant message digest; could be any size */
241 unsigned int seghash_len = sizeof(seghash); /* big enough to hold SHA256 */
242
243 aff_bom::make_hash(seghash,0,AF_PARITY0,parity_buf,af_page_size(af));
244 bom.add(AF_PARITY0,AF_SIGNATURE_MODE0,seghash,seghash_len);
245
246
247 /* If we are signing segments for the first time, we need to sign the parity page
248 * and then add the parity page's signature segment to the BOM as well.
249 */
250 if(signed_unsigned_segments){
251 af_sign_seg(af,AF_PARITY0); // sign the parity segment if we signed the other segments
252 bom.add(af,AF_PARITY0_SIG);
253
254 u_char buf[1024];
255 size_t buflen = sizeof(buf);
256
257 const char *segname = AF_PARITY0_SIG;
258 if(af_get_seg(af,segname,0,buf,&buflen)==0){ // Get the signature
259 aff_bom::make_hash(seghash,0,segname,buf,buflen); // and add it to the BOM
260 bom.add(segname,AF_SIGNATURE_MODE0,seghash,seghash_len);
261 }
262 }
263 }
264
265 if(isatty(fileno(stdout))){
266 printf(" \r\n");
267 fflush(stdout);
268 }
269
270 bom.close();
271 bom.write(af,segments);
272 af_close(af);
273 return 0;
274 }
275
276 int remove_signatures(const char *fn)
277 {
278 AFFILE *af = af_open(fn,O_RDWR,0);
279 if(!af) af_err(1,"%s",fn);
280
281 aff::seglist sl(af);
282 for(aff::seglist::const_iterator i = sl.begin();
283 i!= sl.end();
284 i++){
285 if(af_is_signature_segment(i->name.c_str()) || i->name==AF_SIGN256_CERT){
286 cout << "Deleting " << i->name << "\n";
287 af_del_seg(af,i->name.c_str());
288 }
289 }
290 af_close(af);
291 return 0;
292 }
293
294 int main(int argc,char **argv)
295 {
296 int bflag, ch;
297 int opt_zap = 0;
298
299 bflag = 0;
300 while ((ch = getopt(argc, argv, "nk:c:h?vZ")) != -1) {
301 switch (ch) {
302 case 'n': opt_note = 1;break;
303 case 'k':
304 if(access(optarg,R_OK)) err(1,"%s",optarg);
305 opt_sign_key_file = optarg;
306 break;
307 case 'c':
308 if(access(optarg,R_OK)) err(1,"%s",optarg);
309 opt_sign_cert_file = optarg;
310 break;
311 case 'v':
312 printf("%s version %s\n",progname,PACKAGE_VERSION);
313 exit(0);
314 case 'Z':
315 opt_zap = 1;
316 break;
317 case 'h':
318 case '?':
319 default:
320 usage();
321 break;
322 }
323 }
324 argc -= optind;
325 argv += optind;
326
327 if(opt_sign_cert_file==0) opt_sign_cert_file=opt_sign_key_file; // if not set, make same as key file
328
329
330 if(argc!=1){
331 usage();
332 }
333
334 if(opt_zap) return remove_signatures(argv[0]);
335
336 /* We either need both a key file and a cert file, or neither */
337 if((opt_sign_key_file==0) || (opt_sign_cert_file==0)){
338 errx(1,"Both a private key and a certificate must be specified.");
339 }
340
341
342 return afsign(argv[0]);
343 }
344 #else
345 int main(int argc,char **argv)
346 {
347 fprintf(stderr,"afflib compiled without USE_AFFSIGS. afsign cannot run.\n");
348 exit(-1);
349 }
350
351 #endif
352
0 /*
1 * afstats.cpp:
2 *
3 * print specific statistics about one or more AFF files.
4 * Ideally, we can get the stats from the metadata, but this program will
5 * calculate it if necessary.
6 */
7
8 /*
9 * Copyright (c) 2005
10 * Simson L. Garfinkel and Basis Technology, Inc.
11 * All rights reserved.
12 *
13 * This code is derrived from software contributed by
14 * Simson L. Garfinkel
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. All advertising materials mentioning features or use of this software
25 * must display the following acknowledgement:
26 * This product includes software developed by Simson L. Garfinkel
27 * and Basis Technology Corp.
28 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
29 * contributors to this program may be used to endorse or promote
30 * products derived from this software without specific prior written
31 * permission.
32 *
33 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
34 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
35 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
36 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
38 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
39 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
41 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
42 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
43 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
44 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 */
47
48
49 #include "affconfig.h"
50 #include "afflib.h"
51 #include "afflib_i.h"
52
53 #include <openssl/md5.h>
54 #include <openssl/sha.h>
55 #include <zlib.h>
56 #include <assert.h>
57
58 #ifdef HAVE_ERR_H
59 #include <err.h>
60 #endif
61
62 #ifdef HAVE_UNISTD_H
63 #include <unistd.h>
64 #endif
65
66 #ifdef HAVE_UNISTD_H
67 #include <unistd.h>
68 #endif
69
70 #ifdef HAVE_TERM_H
71 #include <term.h>
72 #endif
73
74 #ifdef HAVE_NCURSES_TERM_H
75 #include <ncurses/term.h>
76 #endif
77
78 #ifdef HAVE_NCURSES_H
79 #include <ncurses.h>
80 #endif
81
82 #ifdef WIN32
83 #include "unix4win32.h"
84 #include <malloc.h>
85 #endif
86
87 const char *progname = "afstats";
88 int opt_m = 0;
89
90 void usage()
91 {
92 printf("%s version %s\n\n",progname,PACKAGE_VERSION);
93 printf("usage: %s [options] infile(s)\n",progname);
94 printf(" -m = print all output in megabytes\n");
95 printf(" -v = Just print the version number and exit.\n");
96 exit(0);
97 }
98
99
100 void title()
101 {
102 printf("fname\tbytes\tcompressed\n");
103 }
104
105 void print_size(uint64_t s)
106 {
107 if(opt_m){
108 printf("%u",(unsigned int)(s/(1024*1024)));
109 return;
110 }
111 printf("%"I64u,s);
112 }
113
114 void afstats_title()
115 {
116 printf("Name\tAF_IMAGESIZE\tCompressed\tUncompressed\tBlank\tBad\n");
117 }
118
119 void afstats(const char *fname)
120 {
121 AFFILE *af = af_open(fname,O_RDONLY,0);
122 if(!af) af_err(1,"af_open(%s)",fname);
123
124 printf("%s\t",fname);
125
126 long unsigned int segsize=0;
127
128 int64_t imagesize=0;
129 int64_t blanksectors=0;
130 int64_t badsectors=0;
131 af_get_segq(af,AF_IMAGESIZE,&imagesize);
132 if(af_get_seg(af,AF_PAGESIZE,&segsize,0,0)){
133 af_get_seg(af,AF_SEGSIZE_D,&segsize,0,0); // check for oldstype
134 }
135 af_get_segq(af,AF_BADSECTORS,&badsectors);
136 af_get_segq(af,AF_BLANKSECTORS,&blanksectors);
137
138 print_size(imagesize);
139 printf("\t");
140 fflush(stdout);
141
142 int64_t compressed_bytes = 0;
143 int64_t uncompressed_bytes = 0;
144
145 /* Now read through all of the segments and count the number of
146 * data segments. We know the uncompressed size...
147 */
148 af_rewind_seg(af);
149 char segname[AF_MAX_NAME_LEN+1];
150 size_t datalen;
151 while(af_get_next_seg(af,segname,sizeof(segname),0,0,&datalen)==0){
152 int64_t page_num = af_segname_page_number(segname);
153 if(page_num>=0){
154 compressed_bytes += datalen;
155 uncompressed_bytes += segsize;
156 }
157 }
158 if(uncompressed_bytes > imagesize) uncompressed_bytes = imagesize;
159
160 print_size(compressed_bytes);
161 printf("\t");
162 print_size(uncompressed_bytes);
163 printf(" %"I64d" %"I64d,blanksectors,badsectors);
164 putchar('\n');
165
166
167 }
168
169
170
171
172 int main(int argc,char **argv)
173 {
174 int ch;
175 while ((ch = getopt(argc, argv, "mh?V")) != -1) {
176 switch (ch) {
177 case 'm':
178 opt_m = 1;
179 break;
180 case 'h':
181 case '?':
182 default:
183 usage();
184 break;
185 case 'V':
186 printf("%s version %s\n",progname,PACKAGE_VERSION);
187 exit(0);
188 }
189 }
190 argc -= optind;
191 argv += optind;
192
193 if(argc<1){
194 usage();
195 }
196
197 /* Each argument is now a file. Process each one */
198 afstats_title();
199 while(*argv){
200 afstats(*argv++);
201 argc--;
202 }
203 exit(0);
204 }
205
206
0 /*
1 * afverify.cpp:
2 *
3 * Verify the digital signature on a signed file
4 */
5
6 #include "affconfig.h"
7 #include "afflib.h"
8 #include "afflib_i.h"
9
10 #include "utils.h"
11 #include "base64.h"
12 #include "aff_bom.h"
13 #include "aftimer.h"
14
15 #include <stdio.h>
16 #include <algorithm>
17 #include <vector>
18 #include <iostream>
19 #include <openssl/pem.h>
20 #include <openssl/x509.h>
21
22 using namespace std;
23 using namespace aff;
24
25 const char *progname = "afcrypto";
26 int opt_change = 0;
27 int opt_verbose = 0;
28 int opt_all = 0;
29
30 void usage()
31 {
32 printf("afverify version %s\n",PACKAGE_VERSION);
33 printf("usage: afverify [options] filename.aff\n");
34 printf("Verifies the digital signatures on a file\n");
35 printf("options:\n");
36 printf(" -a --- print all segments\n");
37 printf(" -V --- Just print the version number and exit.\n");
38 printf(" -v --- verbose\n");
39
40 OpenSSL_add_all_digests();
41 const EVP_MD *sha256 = EVP_get_digestbyname("sha256");
42 if(sha256){
43 printf(" SHA256 is operational\n");
44 } else {
45 printf("Warning: EVP_get_digestbyname(\"sha256\") fails\n");
46 }
47 exit(0);
48 }
49
50 void print_x509_info(X509 *cert)
51 {
52 printf("SIGNING CERTIFICATE :\n");
53 printf(" Subject: "); X509_NAME_print_ex_fp(stdout,X509_get_subject_name(cert),0,XN_FLAG_SEP_CPLUS_SPC);
54 printf("\n");
55 printf(" Issuer: "); X509_NAME_print_ex_fp(stdout,X509_get_issuer_name(cert),0,XN_FLAG_SEP_CPLUS_SPC);
56 printf("\n");
57 ASN1_INTEGER *sn = X509_get_serialNumber(cert);
58 if(sn){
59 long num = ASN1_INTEGER_get(sn);
60 if(num>0) printf(" Certificate serial number: %ld\n",num);
61 }
62 printf("\n");
63 }
64
65 #ifdef USE_AFFSIGS
66 #include "expat.h"
67 void startElement(void *userData, const char *name, const char **atts);
68 void endElement(void *userData, const char *name);
69 void cHandler(void *userData,const XML_Char *s,int len);
70
71 class segmenthash {
72 public:
73 segmenthash():total_validated(0),total_invalid(0),sigmode(0),in_cert(false),
74 in_seghash(false),get_cdata(false),arg(0),seglen(0),
75 get_cdata_segment(0),af(0),cert(0),pubkey(0) {
76
77 parser = XML_ParserCreate(NULL);
78 XML_SetUserData(parser, this);
79 XML_SetElementHandler(parser, ::startElement, ::endElement);
80 XML_SetCharacterDataHandler(parser,cHandler);
81 };
82 int parse(const char *buf,int len) { return XML_Parse(parser, buf, len, 1);}
83 XML_Parser parser;
84 int total_validated;
85 int total_invalid;
86 int sigmode;
87 bool in_cert;
88 bool in_seghash;
89 bool get_cdata;
90 string segname;
91 string alg;
92 string cdata;
93 int arg;
94 int seglen;
95 const char *get_cdata_segment; // just get this segment
96 AFFILE *af; // if set, we are parsing crypto
97 X509 *cert; // public key used to sign
98 EVP_PKEY *pubkey;
99 void clear(){
100 segname="";
101 cdata="";
102 sigmode=0;
103 alg="";
104 seglen=0;
105 }
106 ~segmenthash(){
107 if(cert) X509_free(cert);
108 if(parser) XML_ParserFree(parser);
109 }
110 void startElement(const char *name,const char **atts);
111 void endElement(const char *name);
112 };
113
114 int count=0;
115 void startElement(void *userData, const char *name, const char **atts)
116 {
117 segmenthash *sh = (segmenthash *)userData;
118 sh->startElement(name,atts);
119 }
120
121 void segmenthash::startElement(const char *name,const char **atts)
122 {
123 clear();
124 if(strcmp(name,AF_XML_SEGMENT_HASH)==0){
125 for(int i=0;atts[i];i+=2){
126 const char *name = atts[i];
127 const char *value = atts[i+1];
128 if(!strcmp(name,"segname")) segname = value;
129 if(!strcmp(name,"sigmode")) sigmode = atoi(value);
130 if(!strcmp(name,"alg")) alg = value;
131 if(!strcmp(name,"seglen")) seglen = atoi(value);
132 }
133 in_seghash = true;
134 get_cdata = true;
135 return;
136 }
137 if(strcmp(name,"signingcertificate")==0){
138 in_cert = true;
139 get_cdata = true;
140 return;
141 }
142 if(get_cdata_segment && strcmp(name,get_cdata_segment)==0){
143 get_cdata = true;
144 return;
145 }
146 }
147
148 void cHandler(void *userData,const XML_Char *s,int len)
149 {
150 segmenthash *sh = (segmenthash *)userData;
151 if(sh->get_cdata==false) return; // don't want cdata
152 sh->cdata.append(s,len);
153 }
154
155 void endElement(void *userData, const char *name)
156 {
157 segmenthash *sh = (segmenthash *)userData;
158 sh->endElement(name);
159 }
160
161
162 void segmenthash::endElement(const char *name)
163 {
164 if(get_cdata_segment && strcmp(name,get_cdata_segment)==0){
165 get_cdata = false;
166 XML_StopParser(parser,0);
167 return;
168 }
169 if(in_seghash && af){
170 if(segname.size()==0) return; // don't have a segment name
171 /* Try to validate this one */
172 size_t hashbuf_len = cdata.size() + 2;
173 u_char *hashbuf = (u_char *)malloc(hashbuf_len);
174 hashbuf_len = b64_pton_slg((char *)cdata.c_str(),cdata.size(),hashbuf,hashbuf_len);
175 if(alg=="sha256"){
176 /* TODO: Don't re-validate something that's already validated */
177 int r = af_hash_verify_seg2(af,segname.c_str(),hashbuf,hashbuf_len,sigmode);
178 if(r==AF_HASH_VERIFIES){
179 total_validated++;
180 }
181 else total_invalid++;
182 }
183 free(hashbuf);
184 in_seghash = false;
185 }
186 if(in_cert && af){
187 BIO *cert_bio = BIO_new_mem_buf((char *)cdata.c_str(),cdata.size());
188 PEM_read_bio_X509(cert_bio,&cert,0,0);
189 BIO_free(cert_bio);
190 pubkey = X509_get_pubkey(cert);
191 in_cert = false;
192 }
193 cdata = ""; // erase it
194 }
195
196 string get_xml_field(const char *buf,const char *field)
197 {
198 segmenthash sh;
199 sh.get_cdata_segment = field;
200 sh.parse(buf,strlen(buf));
201 return sh.cdata;
202 }
203
204 /* verify the chain signature; return 0 if successful, -1 if failed.
205 * The signature is a block of XML with a base64 encoded at the end.
206 */
207 int verify_bom_signature(AFFILE *af,const char *buf)
208 {
209 OpenSSL_add_all_digests();
210 const EVP_MD *sha256 = EVP_get_digestbyname("sha256");
211
212 if(!sha256){
213 fprintf(stderr,"OpenSSL does not have SHA256; signatures cannot be verified.\n");
214 return -1;
215 }
216
217 const char *cce = "</" AF_XML_AFFBOM ">\n";
218 const char *chain_end = strstr(buf,cce);
219 if(!chain_end){
220 warn("end of chain XML can't be found\n");
221 return -1; // can't find it
222 }
223 const char *sig_start = chain_end + strlen(cce);
224
225 BIO *seg = BIO_new_mem_buf((void *)buf,strlen(buf));
226 if(BIO_seek(seg,0)!=0){
227 printf("Cannot seek to beginning of BIO mem?");
228 return -1;
229 }
230 X509 *cert = 0;
231 PEM_read_bio_X509(seg,&cert,0,0); // get the contained x509 cert
232 BIO_free(seg);
233
234 /* Now get the binary signature */
235 u_char sigbuf[1024];
236 int sigbuf_len = b64_pton_slg(sig_start,strlen(sig_start),sigbuf,sizeof(sigbuf));
237 if(sigbuf_len<80){
238 warn("BOM is not signed");
239 return -1;
240 }
241
242 /* Try to verify it */
243 EVP_MD_CTX md;
244 EVP_VerifyInit(&md,sha256);
245 EVP_VerifyUpdate(&md,buf,sig_start-buf);
246 int r = EVP_VerifyFinal(&md,sigbuf,sigbuf_len,X509_get_pubkey(cert));
247 if(r!=1){
248 printf("BAD SIGNATURE ON BOM\n");
249 return -1;
250 }
251
252 print_x509_info(cert);
253 printf("Date: %s\n",get_xml_field(buf,"date").c_str());
254 printf("Notes: \n%s\n",get_xml_field(buf,"notes").c_str());
255
256 /* Now extract the XML block, terminating at the beginning of the XML signature */
257 char *buffer_without_signature = strdup(buf);
258 char *sigend = strstr(buffer_without_signature,cce);
259 if(sigend){
260 sigend[strlen(cce)] = 0;/* terminate the XML to remove the signature */
261 }
262
263 segmenthash sh;
264 sh.af = af;
265 if (!sh.parse(buffer_without_signature, strlen(buffer_without_signature))){
266 fprintf(stderr, "expat error: %s at line %d\n",
267 XML_ErrorString(XML_GetErrorCode(sh.parser)),
268 (int)XML_GetCurrentLineNumber(sh.parser));
269 fprintf(stderr,"buffer without signature:\n%s\n",buffer_without_signature);
270 return 1;
271 }
272 free(buffer_without_signature);
273 return 0;
274 }
275 #endif
276
277 int crypto_verify(AFFILE *af,u_char *certbuf,size_t certbuf_len)
278 {
279
280 seglist segments(af);
281 seglist no_sigs;
282 seglist bad_sigs;
283 seglist good_sigs;
284 seglist unknown_errors;
285
286 for(seglist::const_iterator seg = segments.begin();
287 seg != segments.end();
288 seg++){
289
290 if(parse_chain(seg->name)>=0) continue; // chain of custody segments don't need signatures
291
292 const char *segname = seg->name.c_str();
293 int i =af_sig_verify_seg(af,segname);
294 if(opt_verbose){
295 printf("af_sig_verify_seg(af,%s)=%d\n",segname,i);
296 }
297 switch(i){
298 case AF_ERROR_SIG_NO_CERT:
299 err(1,"%s: no public key in AFF file\n",af_filename(af));
300 case AF_ERROR_SIG_BAD:
301 bad_sigs.push_back(*seg);
302 break;
303 case AF_ERROR_SIG_READ_ERROR:
304 no_sigs.push_back(*seg);
305 break;
306 case AF_SIG_GOOD:
307 good_sigs.push_back(*seg);
308 break;
309 case AF_ERROR_SIG_SIG_SEG:
310 break; // can't verify the sig on a sig seg
311 case AF_ERROR_SIG_NOT_COMPILED:
312 errx(1,"AFFLIB was compiled without signature support. Cannot continue.\n");
313 default:
314 unknown_errors.push_back(*seg);
315 break;
316 }
317 }
318 const char *prn = "";
319 /* Tell us something about the certificate */
320 BIO *cert_bio = BIO_new_mem_buf(certbuf,certbuf_len);
321 X509 *cert = 0;
322 PEM_read_bio_X509(cert_bio,&cert,0,0);
323 if(!cert) errx(1,"Cannot decode certificate");
324 printf("\n");
325 printf("Filename: %s\n",af_filename(af));
326 printf("# Segments signed and Verified: %d\n",(int)good_sigs.size());
327 printf("# Segments unsigned: %d\n",(int)no_sigs.size());
328 printf("# Segments with corrupted signatures: %d\n",(int)bad_sigs.size());
329 printf("\n");
330 print_x509_info(cert);
331
332 int compromised = 0;
333 for(seglist::const_iterator seg = good_sigs.begin(); seg != good_sigs.end() && opt_all;
334 seg++){
335 if(*seg==good_sigs.front()) printf("%sSegments with valid signatures:\n",prn);
336 printf("\t%s\n",seg->name.c_str());
337 prn = "\n";
338 }
339 for(seglist::const_iterator seg = no_sigs.begin();
340 seg != no_sigs.end();
341 seg++){
342 if(*seg==no_sigs.front()) printf("%sUnsigned segments:\n",prn);
343 printf("\t%s\n",seg->name.c_str());
344 prn = "\n";
345
346 /* Only unsigned data segments are a problem */
347 if(af_segname_page_number(seg->name.c_str())>=0){
348 compromised++;
349 }
350 }
351 for(seglist::const_iterator seg = bad_sigs.begin();
352 seg != bad_sigs.end();
353 seg++){
354 if(*seg==bad_sigs.front()) printf("%sBad signature segments:\n",prn);
355 printf("\t%s\n",seg->name.c_str());
356 prn = "\n";
357 compromised++;
358 }
359 for(seglist::const_iterator seg = unknown_errors.begin();
360 seg != unknown_errors.end();
361 seg++){
362 if(*seg==unknown_errors.front()) printf("%sUnknown error segments:\n",prn);
363 printf("\t%s\n",seg->name.c_str());
364 prn = "\n";
365 compromised++;
366 }
367
368 int highest = highest_chain(segments);
369 printf("\nNumber of custody chains: %d\n",highest+1);
370 for(int i=0;i<=highest;i++){
371 /* Now print each one */
372 printf("---------------------\n");
373 printf("Signed Bill of Material #%d:\n\n",i+1);
374
375 /* Get the segment and verify */
376 size_t chainbuf_len = 0;
377 char segname[AF_MAX_NAME_LEN];
378 snprintf(segname,sizeof(segname),AF_BOM_SEG,i);
379 if(af_get_seg(af,segname,0,0,&chainbuf_len)){
380 printf("*** BOM MISSING ***\n");
381 compromised++;
382 }
383 char *chainbuf = (char *)malloc(chainbuf_len+1);
384 if(af_get_seg(af,segname,0,(u_char *)chainbuf,&chainbuf_len)){
385 printf("*** CANNOT READ BOM ***\n");
386 compromised++;
387 }
388
389 chainbuf[chainbuf_len]=0; // terminate
390 #ifdef USE_AFFSIGS
391 if(verify_bom_signature(af,chainbuf)){
392 printf("*** BOM SIGNATURE INVALID ***\n");
393 compromised++;
394 }
395 #else
396 printf("BOM signature cannot be verified beause libxpat is not available.\n");
397 #endif
398 }
399 printf("---------------------\n");
400 af_close(af);
401 #ifdef USE_AFFSIGS
402 if(compromised){
403 printf("\nEVIDENCE FILE DOES NOT VERIFY.\n");
404 printf("ERRORS DETECTED: %d\n",compromised);
405 printf("EVIDENTUARY VALUE MAY BE COMPROMISED.\n");
406 return -1;
407 }
408 printf("\nEVIDENCE FILE VERIFIES.\n");
409 return 0;
410 #endif
411 printf("\n");
412 return -1;
413 }
414
415 int hash_verify(AFFILE *af)
416 {
417 /* See if there is a SHA1 segment */
418 unsigned char sha1_buf[20];
419 unsigned char md5_buf[16];
420 char hexbuf[256];
421 size_t sha1_len = sizeof(sha1_buf);
422 size_t md5_len =sizeof(md5_buf);
423 const EVP_MD *md5_evp = 0;
424 const EVP_MD *sha1_evp = 0;
425 EVP_MD_CTX md5,sha1;
426 if(af_get_seg(af,AF_SHA1,0,sha1_buf,&sha1_len)==0){
427 printf("SHA1 stored in file: %s\n",af_hexbuf(hexbuf,sizeof(hexbuf),sha1_buf,sha1_len,0));
428 sha1_evp = EVP_get_digestbyname("sha1");
429 EVP_DigestInit(&sha1,sha1_evp);
430 }
431 if(af_get_seg(af,AF_MD5,0,md5_buf,&md5_len)==0){
432 printf("MD5 stored in file: %s\n",af_hexbuf(hexbuf,sizeof(hexbuf),md5_buf,md5_len,0));
433 md5_evp = EVP_get_digestbyname("md5");
434 EVP_DigestInit(&md5,md5_evp);
435 }
436 /* Might as well read this puppy */
437 u_char *buf = (u_char *)malloc(af_get_pagesize(af));
438 ssize_t readsize = 0;
439 ssize_t total_read = 0;
440 af_seek(af,0L,0);
441 aftimer t;
442 t.start();
443 printf("\n");
444 do {
445 char tbuf[64];
446 double frac = (double)total_read / af_get_imagesize(af);
447 printf(" Read %14zd/%14"PRId64" bytes; done in %s\n",
448 total_read,af_get_imagesize(af),t.eta_text(tbuf,frac));
449 readsize = af_read(af,buf,af_get_pagesize(af));
450 if(readsize<1) break;
451 if(md5_evp) EVP_DigestUpdate(&md5,buf,readsize);
452 if(sha1_evp) EVP_DigestUpdate(&sha1,buf,readsize);
453 total_read += readsize;
454 } while(total_read < af_get_imagesize(af));
455
456 printf("\n");
457
458 if(sha1_evp){
459 unsigned char sha1_calc[32];
460 unsigned int sha1_calc_len = sizeof(sha1_calc);
461
462 EVP_DigestFinal(&sha1,sha1_calc,(unsigned int *)&sha1_calc_len);
463 printf("Calculated SHA1: %s ",af_hexbuf(hexbuf,sizeof(hexbuf),sha1_calc,sha1_calc_len,0));
464 if(memcmp(sha1_buf,sha1_calc,sha1_len)==0){
465 printf("VERIFIES\n");
466 } else {
467 printf("INVALID\n");
468 }
469 }
470
471 if(md5_evp){
472 unsigned char md5_calc[32];
473 unsigned int md5_calc_len = sizeof(md5_calc);
474
475 EVP_DigestFinal(&md5,md5_calc,(unsigned int *)&md5_calc_len);
476 printf("Calculated MD5: %s ",af_hexbuf(hexbuf,sizeof(hexbuf),md5_calc,md5_calc_len,0));
477 if(memcmp(md5_buf,md5_calc,md5_len)==0){
478 printf("VERIFIES\n");
479 } else {
480 printf("INVALID\n");
481 }
482 }
483
484 af_close(af);
485 return 0;
486 }
487
488 int process(const char *fn)
489 {
490 AFFILE *af = af_open(fn,O_RDONLY,0666);
491 if(!af) af_err(1,fn);
492
493 /* Get the public key */
494 unsigned char certbuf[65536];
495 size_t certbuf_len = sizeof(certbuf);
496 if(af_get_seg(af,AF_SIGN256_CERT,0,certbuf,&certbuf_len)){
497 /* See if it is present, but encrypted */
498 if(af_get_seg(af,AF_SIGN256_CERT AF_AES256_SUFFIX,0,0,0)==0){
499 errx(1,"%s: signed file is encrypted; present decryption key to verify signature",fn);
500 }
501 printf("%s: no signing certificate present. \n\n",fn);
502 return hash_verify(af);
503 }
504 return crypto_verify(af,certbuf,certbuf_len);
505 }
506
507
508 int main(int argc,char **argv)
509 {
510 int bflag, ch;
511
512 bflag = 0;
513 while ((ch = getopt(argc, argv, "ach?vV")) != -1) {
514 switch (ch) {
515 case 'a': opt_all = 1; break;
516 case 'c': opt_change = 1; break;
517 case 'v': opt_verbose++; break;
518 case 'h':
519 case '?':
520 default:
521 usage();
522 break;
523 case 'V':
524 printf("%s version %s\n",progname,PACKAGE_VERSION);
525 exit(0);
526 }
527 }
528 argc -= optind;
529 argv += optind;
530
531 if(argc!=1){
532 usage();
533 }
534
535 OpenSSL_add_all_digests();
536 return process(argv[0]);
537 }
0 /*
1 * afxml.cpp:
2 *
3 * print AFF information as an XML
4 */
5
6 /*
7 * Copyright (c) 2005
8 * Simson L. Garfinkel and Basis Technology, Inc.
9 * All rights reserved.
10 *
11 * This code is derrived from software contributed by
12 * Simson L. Garfinkel
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by Simson L. Garfinkel
25 * and Basis Technology Corp.
26 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
27 * contributors to this program may be used to endorse or promote
28 * products derived from this software without specific prior written
29 * permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
32 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
34 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
36 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 */
45
46
47 #include "affconfig.h"
48 #include "afflib.h"
49 #include "afflib_i.h"
50 #include "base64.h"
51
52 #ifdef WIN32
53 #include "unix4win32.h"
54 #endif
55
56 #include <vector>
57 #include <string>
58
59 #ifdef HAVE_CSTRING
60 #include <cstring>
61 #endif
62
63 using namespace std;
64
65 #if HAVE_CTYPE_H
66 #include <ctype.h>
67 #endif
68
69 #if !defined(HAVE_ISALPHANUM) && defined(HAVE_ISALNUM)
70 #define isalphanum(c) isalnum(c)
71 #endif
72
73 #if !defined(HAVE_ISALPHANUM) && !defined(HAVE_ISALNUM)
74 #define isalphanum(c) (isalpha(c)||isdigit(c))
75 #endif
76
77 const char *progname = "afxml";
78
79 int opt_x = 0;
80 char **opt_j = 0;
81 int opt_j_count = 0;
82 int opt_stats = 0;
83
84 struct page_stat_block {
85 unsigned long long zsectors; // number of sectors that are all blank
86 unsigned long long badsectors; // number of bad sectors
87 unsigned long long zpages; // number of pages that are all blank
88 unsigned long long pages; // total number of pages
89 unsigned long long sectors; // total number of sectors
90 };
91
92
93 void usage()
94 {
95 printf("%s version %s\n",progname,PACKAGE_VERSION);
96 printf("usage: %s [options] infile... \n",progname);
97 printf(" -V = Just print the version number and exit\n");
98 printf(" -x = Don't include the infile filename in output.\n");
99 printf(" -j segname = Just print information about segname \n");
100 printf(" (may be repeated)\n");
101 printf(" -s = output 'stats' for the file data (may a long time)\n");
102 exit(0);
103 }
104
105
106
107 /* Return true if segname is in the optj list */
108 bool in_opt_j_list(char *segname)
109 {
110 for(int i=0;i<opt_j_count;i++){
111 if(strcmp(segname,opt_j[i])==0) return true;
112 }
113 return false;
114 }
115
116 /* It's okay to print if there are no funky characters in it...
117 * (avoids problems with invalid UTF-8
118 */
119 bool okay_to_print(const char *data,int datalen)
120 {
121 for(const char *cc=data;cc<data+datalen;cc++){
122 if (*cc <= 0) return false;
123 if (*cc == 10 || *cc==13) continue;
124 if (*cc<32) return false;
125 if (*cc>=127) return false;
126 }
127 return true;
128 }
129
130 bool is_blank(const u_char *buf,size_t len)
131 {
132 for(size_t i=0;i<len;i++){
133 if(buf[i]) return false;
134 }
135 return true;
136 }
137
138 void print_xml64(const char *name,int64_t val)
139 {
140 printf(" <%s coding='base10'>%"I64d"</%s>\n\n",name,val,name);
141 }
142
143 int xml_info(const char *infile)
144 {
145 AFFILE *af = af_open(infile,O_RDONLY,0);
146 if(!af){
147 warn("%s",infile);
148 return -1;
149 }
150
151 struct page_stat_block psb;
152 memset(&psb,0,sizeof(psb));
153
154 printf("<!-- XML generated by afxml version %s -->\n",PACKAGE_VERSION);
155 printf("<affinfo");
156 if(!opt_x) printf(" image_filename='%s'",infile);
157 printf(">\n");
158
159 af_rewind_seg(af); // start at the beginning
160
161 char segname[AF_MAX_NAME_LEN];
162 int pages = 0;
163 vector<string> seglist; // list of segments we will get
164 vector<int64_t> pagelist; // list of segments we will get
165
166 while(af_get_next_seg(af,segname,sizeof(segname),0,0,0)==0){
167 if(segname[0]==0) continue; // segment to ignore
168 if(strcmp(segname,AF_DIRECTORY)==0) continue; // don't output the directories
169 if(strstr(segname,AF_AES256_SUFFIX)) continue; // don't output encrypted segments that won't decrypt
170
171 /* check optj */
172 if(opt_j_count > 0 && in_opt_j_list(segname)==false){
173 continue;
174 }
175
176 int64_t page_num = af_segname_page_number(segname);
177 if(page_num>=0){
178 pages += 1;
179 pagelist.push_back(page_num);
180 }
181 else {
182 seglist.push_back(segname);
183 }
184 }
185
186 printf(" <pages coding='base10'>%d</pages>\n",pages); // tell how many pages we have
187
188 /* If we have been asked to create stats, create the states */
189 if(opt_stats){
190 unsigned char *data= (unsigned char *)malloc(af_page_size(af));
191 if(!data) err(1,"Can't allocate page with %d bytes.",af_page_size(af));
192 for(vector<int64_t>::const_iterator it = pagelist.begin(); it != pagelist.end(); it++){
193 size_t pagesize = af_page_size(af);
194 size_t sectorsize = af_get_sectorsize(af);
195 if(af_get_page(af,*it,data,&pagesize)){
196 err(1,"Can't read page %"PRId64,*it);
197 }
198 psb.pages++;
199 bool allblank = true;
200 for(const unsigned char *s = data; s < data+pagesize; s+=sectorsize){
201 psb.sectors ++;
202 if(is_blank(s,sectorsize)){
203 psb.zsectors++;
204 continue;
205 }
206 allblank = false;
207 if(af_is_badsector(af,s)){
208 psb.badsectors++;
209 continue;
210 }
211 }
212 if(allblank) psb.zpages++;
213 }
214 free(data);
215 printf(" <calculated>\n");
216 print_xml64("pages",psb.pages);
217 print_xml64("zpages",psb.zpages);
218 print_xml64("sectors",psb.sectors);
219 print_xml64("zsectors",psb.zsectors);
220 print_xml64("badsectors",psb.badsectors);
221 printf(" </calculated>\n");
222 }
223
224 /* Now that we have a list of segments, print them */
225 for(vector<string>::const_iterator it = seglist.begin();
226 it != seglist.end();
227 it++){
228
229 /* See how long the data is */
230 size_t datalen = 0;
231 unsigned long arg=0;
232
233 strcpy(segname,it->c_str());
234
235 if(af_get_seg(af,segname,&arg,0,&datalen)){
236 err(1,"Can't read info for segment '%s'",segname);
237 }
238
239 unsigned char *data= (unsigned char *)malloc(datalen);
240 if(data==0) err(1,"Can't allocate %zd bytes for data",datalen);
241 if(af_get_seg(af,segname,&arg,data,&datalen)!=0){
242 err(1,"Can't read data for segment '%s'",segname);
243 }
244
245 /* Change non-XML characters in segname to _ */
246 for(char *cc=segname;*cc;cc++){
247 if(!isalphanum(*cc)) *cc = '_';
248 }
249
250 if(datalen==8 && (arg & AF_SEG_QUADWORD || af_display_as_quad(segname))){
251 /* Print it as a 64-bit value.
252 * The strcmp is there because early AF_IMAGESIZE segs didn't set
253 * AF_SEG_QUADWORD...
254 */
255 printf(" <%s coding='base10'>%"I64d"</%s>\n",segname,af_decode_q(data),segname);
256 free(data);
257 continue;
258 }
259
260 /* If datalen==0, just print the arg as an unsigned number */
261 if(datalen==0){
262 printf(" <%s coding='base10'>%ld</%s>\n",segname,arg,segname);
263 free(data);
264 continue;
265 }
266
267 /* Just handle it as binhex ... */
268 printf(" <%s",segname);
269 if(datalen==0){
270 printf(" arg='%lu' />\n",arg);
271 free(data);
272 continue;
273 }
274
275 /* If segname ends 'md5', code in hex */
276 if(strlen(segname)>=3 && strcmp(segname+strlen(segname)-3,"md5")==0){
277 char hex_buf[40];
278 printf(" coding='base16'>%s</%s>\n",
279 af_hexbuf(hex_buf,sizeof(hex_buf),data,datalen,0),
280 segname);
281 free(data);
282 continue;
283 }
284
285 /* If all segment contents are printable ascii with no CRs, LFs, or brackets,
286 * just print as-is...
287 */
288 if(okay_to_print((const char *)data,datalen)){
289 putchar('>');
290 for(const char *cc=(const char *)data;cc<(const char *)data+datalen;cc++){
291 switch(*cc){
292 case '>': fputs("&lt;",stdout);break;
293 case '<': fputs("&gt;",stdout);break;
294 case '&': fputs("&amp;",stdout);break;
295 case '\'': fputs("&apos;",stdout);break;
296 case '"': fputs("&quot;",stdout);break;
297 default: putchar(*cc);
298 }
299 }
300 printf("</%s>\n",segname);
301 free(data);
302 continue;
303 }
304
305 /* Default coding: base64 */
306 int b64size = datalen*2+2;
307 char *b64buf = (char *)calloc(b64size,1);
308 int b64size_real = b64_ntop(data,datalen,b64buf,b64size);
309 data[b64size_real] = 0; // be sure it is null terminated
310
311 printf(" coding='base64'>");
312 fputs(b64buf,stdout);
313 printf("</%s>\n",segname);
314 free(b64buf);
315 free(data);
316 }
317 af_close(af);
318
319 printf("</affinfo>\n");
320 return 0;
321 }
322
323
324 int main(int argc,char **argv)
325 {
326 int bflag, ch;
327 const char *infile;
328
329 /* Figure out how many cols the screen has... */
330
331 bflag = 0;
332 while ((ch = getopt(argc, argv, "xj:h?Vs")) != -1) {
333 switch (ch) {
334 case 'j':
335 if(opt_j==0) opt_j = (char **)malloc(0);
336 opt_j_count++;
337 opt_j = (char **)realloc(opt_j,sizeof(char *)*opt_j_count);
338 opt_j[opt_j_count-1] = strdup(optarg); // make a copy
339 case 'x': opt_x++; break;
340 case 's': opt_stats++; break;
341 case 'h':
342 case '?':
343 default:
344 usage();
345 break;
346 case 'V':
347 printf("%s version %s\n",progname,PACKAGE_VERSION);
348 exit(0);
349 }
350 }
351 argc -= optind;
352 argv += optind;
353
354 if(argc<1){
355 usage();
356 }
357
358
359 /* Loop through all of the files */
360 printf("<?xml version='1.0' encoding='UTF-8'?>\n");
361 printf("<affobjects>\n");
362 while(*argv){
363 infile = *argv++; // get the file
364 argc--; // decrement argument counter
365 xml_info(infile);
366 }
367 printf("</affobjects>\n");
368 exit(0);
369 }
370
371
+0
-866
tools/afinfo.cpp less more
0 /*
1 * afinfo.cpp:
2 *
3 * print information about an aff file
4 */
5
6 /*
7 * Copyright (c) 2005--2008
8 * Simson L. Garfinkel and Basis Technology, Inc.
9 * All rights reserved.
10 *
11 * This code is derrived from software contributed by
12 * Simson L. Garfinkel
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by Simson L. Garfinkel
25 * and Basis Technology Corp.
26 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
27 * contributors to this program may be used to endorse or promote
28 * products derived from this software without specific prior written
29 * permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
32 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
34 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
36 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 */
45
46
47 #include "affconfig.h"
48 #include "afflib.h"
49 #include "utils.h"
50 #include "afflib_i.h"
51
52 #ifdef USE_S3
53 #include "s3_glue.h"
54 #endif
55
56 #include <ctype.h>
57 #include <zlib.h>
58 #include <openssl/md5.h>
59 #include <openssl/sha.h>
60 #include <assert.h>
61
62 #include <algorithm>
63 #include <cstdlib>
64 #include <vector>
65 #include <string>
66
67 #ifdef HAVE_CSTRING
68 #include <cstring>
69 #endif
70
71 using namespace std;
72
73 #ifdef HAVE_CURSES_H
74 #include <curses.h>
75 #endif
76
77 #ifdef HAVE_TERM_H
78 #include <term.h>
79 #endif
80
81 #ifdef HAVE_NCURSES_TERM_H
82 #include <ncurses/term.h>
83 #endif
84
85 #ifdef WIN32
86 #include "unix4win32.h"
87 #endif
88
89 const char *progname = "afinfo";
90
91 #define VALIDATE_MD5 0x01
92 #define VALIDATE_SHA1 0x02
93
94 int opt_validate = 0;
95 int opt_info = 1;
96 int opt_all = 0;
97 int opt_wide = 0;
98 int opt_l = 0;
99 unsigned int cols = 80; // default
100 int opt_x = 0;
101 int opt_b = 0;
102 int opt_identify = 1;
103 int opt_verbose = 0;
104 int opt_y = 0;
105 int opt_hexbuf = AF_HEXBUF_SPACE4 | AF_HEXBUF_UPPERCASE;
106 int opt_page_validate = 0;
107 int opt_no_preview = 0;
108 int opt_preview_md5 = 0;
109 int opt_debug = 0;
110 int opt_figure_media = 0;
111 const char *opt_passphrase = 0;
112
113 vector<string> opt_seglist; // just info these segments
114 bool something_was_decrypted = false;
115 const char *term = 0;
116
117
118 /**
119 * select bold on or off
120 */
121 void bold(int on)
122 {
123 if(!term) return;
124 #if defined(HAVE_LIBNCURSES)
125 #ifdef HAVE_ISATTY
126 if(!isatty(fileno(stdout))) return;
127 #endif
128 if(on) tputs(enter_bold_mode,1,putchar);
129 else tputs(exit_attribute_mode,0,putchar);
130 #endif
131 }
132
133 /**
134 * select a color.
135 * @param num - 0 is black; 1 red; 2 green; 3 yellow; 4 blue; 5 magenta; 6 cyan; 7 white;
136 */
137
138 #define RED 1
139 #define WHITE 7
140
141 void color(int num)
142 {
143 #ifdef HAVE_ISATTY
144 if(!isatty(fileno(stdout))) return;
145 #endif
146 #ifdef HAVE_CURSES_H
147 char *setf = tigetstr((char *)"setf");
148 if(!setf) setf = tigetstr((char *)"setaf");
149 if(setf){
150 putp(tparm(setf,num));
151 }
152 #endif
153 }
154
155
156 void usage()
157 {
158 printf("%s version %s\n",progname,PACKAGE_VERSION);
159 printf("usage: %s [options] infile\n",progname);
160 printf(" -a = print ALL segments (normally data segments are suppressed)\n");
161 printf(" -b = print how many bad blocks in each segment (implies -a)\n");
162 printf(" -i = identify the files, don't do info on them.\n");
163 printf(" -w = wide output; print more than 1 line if necessary.\n");
164 printf(" -s segment = Just print information about 'segment'.\n");
165 printf(" (may be repeated)\n");
166 printf(" -m = validate MD5 hash of entire image\n");
167 printf(" -S = validate SHA1 hash of entire image\n");
168 printf(" -v = validate the hash of each page (if present)\n");
169 printf(" -y = don't print segments of lengths 16 and 20 as hex)\n");
170 printf(" -p<passphrase> = Specify <passphrase> to decrypt file\n");
171 printf(" -l = Just print the segment names and exit\n");
172 printf(" -V = Just print the version number and exit.\n");
173
174 printf("\nPreview Options:\n");
175 printf(" -X = no data preview; just print the segment names\n");
176 printf(" -x = print binary values in hex (default is ASCII)\n");
177 printf("\nMisc:\n");
178 printf(" -d = debug\n");
179 printf(" -A = if infile is a device, print the number of sectors\n");
180 printf(" and sector size to stdout in XML. Otherwise error\n");
181 printf("\nCompilation:\n");
182 printf(" LZMA compression: Enabled\n");
183 #ifdef USE_LIBEWF
184 printf(" LIBEWF enabled\n");
185 #endif
186 #ifdef USE_QEMU
187 printf(" QEMU enabled\n");
188 #endif
189 #ifdef USE_FUSE
190 printf(" FUSE enabled\n");
191 #endif
192 #ifdef USE_S3
193 printf(" Amazon S3 enabled\n");
194 #endif
195 #ifdef HAVE_LIBEXPAT
196 printf(" HAVE_LIBEXPAT ");
197 #endif
198 printf("\n");
199
200 if(opt_debug){
201 for(int i=0;i<9;i++){
202 color(i);printf("Color %d\n",i);color(7);
203 }
204 }
205
206 exit(0);
207 }
208
209
210 AFFILE *af=0;
211
212 void sig_info(int arg)
213 {
214 if(af==0) return;
215 printf("Validating %"I64d" of %"I64d"\n", af->pos,af->image_size);
216 }
217
218
219
220
221 void validate(const char *infile)
222 {
223 af = af_open(infile,O_RDONLY,0);
224 if(!af) af_err(1,infile);
225 switch(af_identify(af)){
226 case AF_IDENTIFY_AFF:
227 case AF_IDENTIFY_AFM:
228 case AF_IDENTIFY_AFD:
229 break;
230 default:
231 printf("%s is not an AFF file\n",infile);
232 af_close(af);
233 return;
234 }
235
236 printf("\nValidating ");
237 if(opt_validate & VALIDATE_MD5) printf("MD5 ");
238 if(opt_validate == (VALIDATE_MD5|VALIDATE_SHA1)) printf("and ");
239 if(opt_validate & VALIDATE_SHA1) printf("SHA1 ");
240 printf("hash codes.\n");
241
242
243 #ifdef SIGINFO
244 signal(SIGINFO,sig_info);
245 #endif
246
247 /* Get a list of all the segments to see if there is a space */
248 af_rewind_seg(af);
249 char segname[AF_MAX_NAME_LEN];
250 vector <int> pages;
251 memset(segname,0,sizeof(segname));
252 while(af_get_next_seg(af,segname,sizeof(segname),0,0,0)==0){
253 int64_t page_num = af_segname_page_number(segname);
254 if(page_num>=0) pages.push_back(page_num);
255 }
256
257 if(pages.size()==0){
258 printf("No pages to validate.\n");
259 af_close(af);
260 }
261
262 sort(pages.begin(),pages.end());
263 vector<int>::iterator i = pages.begin();
264 int last = *i;
265 i++;
266 for(; i!= pages.end();i++){
267 if(last+1 != *i){
268 printf("gap in pages (%d!=%d); %s can't be validated.\n",last+1,*i,infile);
269 af_close(af);
270 return;
271 }
272 last = *i;
273 }
274
275 /* Set up the hash machinery */
276 MD5_CTX md5;
277 MD5_Init(&md5);
278
279 SHA_CTX sha;
280 SHA1_Init(&sha);
281
282 uint64_t total_bytes = 0;
283 while(!af_eof(af)){
284 unsigned char buf[65536]; // a decent size
285 size_t bytes = af_read(af,buf,sizeof(buf));
286 if(bytes==0) break; // reached sparse region of file
287 total_bytes += bytes;
288 if(opt_validate & VALIDATE_MD5) MD5_Update(&md5,buf,bytes);
289 if(opt_validate & VALIDATE_SHA1) SHA1_Update(&sha,buf,bytes);
290 }
291
292 /* Finish the hash calculations and write to the db */
293
294 if(opt_validate & VALIDATE_MD5){
295 unsigned char md5_stored[16];
296 size_t md5len = sizeof(md5_stored);
297 unsigned char md5_computed[16];
298 char buf[256];
299
300 MD5_Final(md5_computed,&md5);
301 printf("computed md5: %s\n",
302 af_hexbuf(buf,sizeof(buf),md5_computed,16,opt_hexbuf));
303 if(af_get_seg(af,AF_MD5,0,md5_stored,&md5len)==0){
304 printf(" stored md5: %s ",
305 af_hexbuf(buf,sizeof(buf),md5_stored,16,opt_hexbuf));
306 if(md5len==16 && !memcmp((const char *)md5_stored,
307 (const char *)md5_computed,16)){
308 printf(" MATCH\n");
309 }
310 else {
311 printf(" NO MATCH!\n");
312 }
313 }
314 else {
315 printf("(no MD5 in AFF file)\n");
316 }
317 }
318
319
320 if(opt_validate & VALIDATE_SHA1){
321 unsigned char sha1_stored[20];
322 size_t sha1len = sizeof(sha1_stored);
323 unsigned char sha1_computed[20];
324 char buf[256];
325
326 SHA1_Final(sha1_computed,&sha);
327 printf("computed sha1: %s \n",af_hexbuf(buf,sizeof(buf),sha1_computed,20,opt_hexbuf));
328 if(af_get_seg(af,AF_SHA1,0,sha1_stored,&sha1len)==0){
329 printf(" stored sha1: %s ",af_hexbuf(buf,sizeof(buf),sha1_stored,20,opt_hexbuf));
330 if(sha1len==20 && !memcmp((const char *)sha1_stored,
331 (const char *)sha1_computed,20)){
332 printf(" MATCH\n");
333 }
334 else {
335 printf(" NO MATCH!\n");
336 }
337 }
338 else {
339 printf("(no SHA1 in AFF file)\n");
340 }
341 }
342
343 af_close(af);
344 }
345
346 #define OUTLINE_LEN 65536
347
348
349 bool display_as_time(const char *segname)
350 {
351 if(strcmp(segname,AF_ACQUISITION_SECONDS)==0) return true;
352 return false;
353 }
354
355 bool display_as_hex(const char *segname,int data_len)
356 {
357 if(af_display_as_hex(segname)) return true;
358 if(data_len==16 && strstr(segname,"md5")) return true;
359 if(data_len==20 && strstr(segname,"sha1")) return true;
360 if(opt_x) return true;
361 if(opt_preview_md5) return true;
362 return false;
363 }
364
365 void badscan(AFFILE *af,int page_number,size_t data_len)
366 {
367 size_t page_size = af->image_pagesize;
368 unsigned char *buf = (unsigned char *)malloc(page_size);
369 if(af_get_page(af,page_number,buf,&page_size)){
370 err(1,"Could not read page %d",page_number);
371 }
372 printf("page_size = %d\n",(int)page_size);
373 int sectors = 0;
374 int bad_sectors = 0;
375 int funny_sectors = 0;
376 for(unsigned int offset=0;offset<page_size;offset+=af->image_sectorsize){
377 sectors++;
378 if(af_is_badsector(af,buf+offset)){
379 bad_sectors ++;
380 continue;
381 }
382 #ifdef __FreeBSD__
383 /* Look for the part of the bad flag that we know and love */
384 if(strnstr((char *)buf+offset,"BAD SECTOR",af->image_sectorsize)){
385 funny_sectors++;
386 continue;
387 }
388 #endif
389 }
390 printf(" sectors scanned: %d bad: %d ", sectors,bad_sectors);
391 if(funny_sectors){
392 printf("suspicious: %d ",funny_sectors);
393 }
394 printf("\n");
395 free(buf);
396 }
397
398
399 /* print_info:
400 * Print the info on a given segment name
401 */
402 void print_info(AFFILE *af,const char *segname)
403 {
404 unsigned long arg;
405 unsigned char *data = 0;
406 int dots = 0;
407 u_int display_len = 0;
408 char *cc = 0;
409
410 /* Check to see if this is a null page. */
411 if(segname[0]==0 && opt_all==0){
412 return;
413 }
414 if(segname[0]=='[' && opt_all){
415 puts(segname);
416 return;
417 }
418
419 /* Check to see if this is a data page */
420 int64_t page_num = af_segname_page_number(segname);
421
422 size_t data_len = 0;
423 /* First find out how big the segment is, then get the data */
424 if(af_get_seg(af,segname,&arg,0,&data_len)){
425 printf("%-25s SEGMENT NOT FOUND\n",segname);
426 return;
427 }
428
429 /* is this an encrypted segment that I have decrypted?
430 * Turn off automatic decryption and see if I can get it again...
431 * If we can get it again, then it wasn't decrypted.
432 */
433 int prev = af_set_option(af,AF_OPTION_AUTO_DECRYPT,0);
434 bool was_decrypted = ( af_get_seg(af,segname,0,0,0)!=0) ;
435 af_set_option(af,AF_OPTION_AUTO_DECRYPT,prev);
436
437 if(was_decrypted){
438 bold(1);
439 something_was_decrypted = true; // print key at bottom
440 }
441
442 /* Start the output line */
443 char output_line[OUTLINE_LEN];
444 memset(output_line,0,sizeof(output_line));
445
446 /* Now append the arg and the data len */
447 sprintf(output_line,"%-24s %8ld %8zd ",segname,arg,data_len);
448
449 if(opt_no_preview){
450 printf("%s\n",output_line);
451 goto done;
452 }
453
454 data = (unsigned char *)malloc(data_len);
455 if(af_get_seg(af,segname,0,data,&data_len)){
456 warn("af_get_seg_2 failed: segname=%s data_len=%zd",segname,data_len);
457 goto done;
458 }
459
460 /* Special handling of values that should be displayed as time */
461 if(display_as_time(segname)){
462 int hours = arg / 3600;
463 int minutes = (arg / 60) % 60;
464 int seconds = arg % 60;
465 printf("%s= %02d:%02d:%02d (hh:mm:ss)\n",output_line,hours,minutes,seconds);
466 goto done;
467 }
468
469 /* Special handling of quadwords that should be printed as such? */
470 if(((arg == AF_SEG_QUADWORD) && (data_len==8)) || af_display_as_quad(segname)){
471 /* Print it as a 64-bit value.
472 * The strcmp is there because early AF_IMAGESIZE segs didn't set
473 * AF_SEG_QUADWORD...
474 */
475 switch(data_len){
476 case 8:
477 printf("%s= %"I64d" (64-bit value)\n",
478 output_line,af_decode_q(data));
479 break;
480 case 0:
481 printf("%s= 0 (0-length segment)\n",output_line);
482 break;
483 default:
484 printf("%s= CANNOT DECODE %d byte segment\n",output_line,(int)data_len);
485 }
486 goto done;
487 }
488
489
490 /* See if I need to truncate */
491 display_len = data_len;
492 if(opt_wide==0 && data_len>32){ // don't bother showing more than first 32 bytes
493 dots = 1;
494 display_len = 32;
495 }
496
497 cc = output_line + strlen(output_line);
498
499 if(opt_preview_md5){
500 u_char md5[32];
501 MD5(data,data_len,md5);
502 memcpy(data,md5,32);
503 data_len = 32;
504 }
505 if(display_as_hex(segname,display_len)){
506 char buf[80];
507 snprintf(cc,sizeof(output_line)-strlen(output_line),
508 "%s%s",af_hexbuf(buf,sizeof(buf),data,display_len,opt_hexbuf),
509 dots ? "..." : "");
510 /* Special code for SHA1 */
511 if(!opt_wide && strcmp(segname,AF_SHA1)==0){
512 int r = fwrite(output_line,1,82,stdout);
513 if(r!=82) fprintf(stderr,"fwrite(output_line,1,82,stdout) returned %d\n",r);
514 printf("\n%62s\n",output_line+82);
515 goto done;
516 }
517 }
518 else {
519 /* Fill it out with some printable data */
520 unsigned int i;
521 if(display_len > sizeof(output_line)-strlen(output_line)){
522 display_len = sizeof(output_line)-strlen(output_line);
523 }
524 for(i=0;i<display_len;i++){
525 *cc = data[i];
526 if(isprint(*cc)==0) *cc='.';
527 if(*cc=='\n' || *cc=='\r') *cc=' ';
528 cc++;
529 }
530 *cc = 0;
531 }
532
533 /* Now print the results... */
534 if(!opt_wide){
535 if(strlen(output_line)>cols){
536 output_line[cols-4] = '.';
537 output_line[cols-3] = '.';
538 output_line[cols-2] = '.';
539 output_line[cols-1] = '\000';
540 }
541 }
542 fputs(output_line,stdout);
543 if(page_num>=0 && opt_b){
544 badscan(af,page_num,data_len);
545 }
546 if(opt_page_validate && page_num>=0){
547 /* Get the page again; this may involve decompression */
548 unsigned char *page_data = (unsigned char *)malloc(af->image_pagesize);
549 size_t page_data_len = af->image_pagesize;
550 if(af_get_page(af,page_num,page_data,&page_data_len)){
551 printf("** COULD NOT READ UNCOMPRESSED PAGE ");
552 goto skip1;
553 }
554
555 char hash_segname[32];
556 unsigned char hash_buf[16];
557 unsigned char hash_calc[16];
558 size_t hash_len = sizeof(hash_buf);
559 snprintf(hash_segname,sizeof(hash_segname),AF_PAGE_MD5,page_num);
560 printf(" ");
561 if(af_get_seg(af,hash_segname,0,hash_buf,&hash_len)){
562 printf("** NO SEGMENT %s ** ",hash_segname);
563 goto skip1;
564 }
565
566 MD5(page_data,page_data_len,hash_calc);
567 if(memcmp(hash_buf,hash_calc,sizeof(hash_buf))!=0){
568 char hb[32];
569 printf("** HASH INVALID **\n%30s Calculated %s\n","",
570 af_hexbuf(hb,sizeof(hb),hash_calc,16,opt_hexbuf));
571 printf("%30s Wanted %s ","",af_hexbuf(hb,sizeof(hb),hash_buf,16,opt_hexbuf));
572 printf("data_len=%d\n",(int)data_len);
573 } else{
574 printf("HASH OK ");
575 }
576 free(page_data);
577 }
578 skip1:;
579 putchar('\n');
580 done:
581 if(data) free(data);
582 bold(0); // make sure bold is off
583
584 //color(WHITE); // make sure we are back to normal color
585 }
586
587
588 /* Print the information on a specific file. */
589 int info_file(const char *infile)
590 {
591 unsigned long total_segs = 0;
592 unsigned long total_pages = 0;
593 unsigned long total_hashes = 0;
594 unsigned long total_signatures =0;
595 unsigned long total_nulls = 0;
596 struct af_vnode_info vni;
597
598 AFFILE *af = af_open(infile,O_RDONLY,0);
599 if(!af) af_err(1,"Cannot open %s",infile);
600 if(af_vstat(af,&vni)) err(1,"%s: af_vstat failed",infile);
601
602 if(opt_l){
603 /* Just list the segments and exit */
604 aff::seglist sl;
605 sl.get_seglist(af);
606 for(aff::seglist::const_iterator i = sl.begin(); i!=sl.end(); i++){
607 printf("%s\n",(*i).name.c_str());
608 }
609 af_close(af);
610 return 0;
611 }
612
613 if(vni.segment_count_encrypted>0 || vni.segment_count_signed>0){
614 printf("%s: has %s%s%ssegments\n",infile,
615 (vni.segment_count_encrypted ? "encrypted " : ""),
616 ((vni.segment_count_encrypted && vni.segment_count_signed) ? "and ": ""),
617 (vni.segment_count_signed ? "signed " : ""));
618 }
619
620
621 if(opt_passphrase){
622 if(af_use_aes_passphrase(af,opt_passphrase)){
623 errx(1,"%s: cannot use passphrase",opt_passphrase);
624 }
625 }
626
627 printf("\n%s\n",af_filename(af));
628 const char *v1 = "data";
629 const char *v2 = "====";
630
631 if(opt_all==0) printf("[skipping data segments]\n");
632 if(opt_all==0 && vni.segment_count_encrypted) printf("[skipping encrypted segments]\n");
633 if(opt_no_preview){
634 v1 = "";
635 v2 = "";
636 }
637 if(opt_preview_md5){
638 v1 = "md5";
639 }
640
641 printf(" data \n");
642 printf("Segment arg length %s\n",v1);
643 printf("======= ========= ======== %s\n",v2);
644
645 /* If a list of segments was specified by the user, just use that list */
646 if(opt_seglist.size()>0){
647 for(vector<string>::iterator i = opt_seglist.begin();
648 i != opt_seglist.end();
649 i++){
650 const char *segname = i->c_str();
651 print_info(af,segname);
652 }
653 af_close(af);
654 return 0;
655 }
656
657 /* Go through the whole file, get all of the segments, put them in a list */
658 vector <string> segments;
659 char segname[AF_MAX_NAME_LEN];
660 af_rewind_seg(af); // start at the beginning
661 int64_t total_datalen = 0;
662 size_t total_segname_len = 0;
663 size_t datalen = 0;
664 int aes_segs=0;
665 while(af_get_next_seg(af,segname,sizeof(segname),0,0,&datalen)==0){
666 total_segs ++;
667 total_datalen += datalen;
668 total_segname_len += strlen(segname);
669 if(segname[0]==0) total_nulls++;
670
671 /* Check to see if this is a regular page or a hash page */
672 char hash[64];
673 int64_t page_num = af_segname_page_number(segname);
674 int64_t hash_num = af_segname_hash_page_number(segname,hash,sizeof(hash));
675 if(page_num>=0) total_pages++;
676 if(hash_num>=0) total_hashes++;
677 if(strstr(segname,AF_SIG256_SUFFIX)) total_signatures++;
678 if(strstr(segname,AF_AES256_SUFFIX)) aes_segs++;
679 if(opt_all==0 && (page_num>=0||hash_num>=0)) continue; // skip
680 if(opt_all==0 && af_is_encrypted_segment(segname)) continue; // skip
681
682 if(segname[0]==0 && datalen>0 && opt_all){
683 snprintf(segname,sizeof(segname),"[null %zd bytes]",datalen);
684 }
685 segments.push_back(segname);
686 }
687
688 /* Now process the segments */
689 for(vector<string>::const_iterator i = segments.begin();
690 i != segments.end(); i++){
691 print_info(af,i->c_str());
692 }
693
694 /* Print the key */
695 if(something_was_decrypted){
696 bold(1);
697 printf("Bold indicates segments that were decrypted.\n");
698 bold(0);
699 }
700
701
702 printf("\n");
703 printf("Total segments: %8lu (%lu real)\n", total_segs,total_segs-total_nulls);
704 if(aes_segs){
705 printf(" Encrypted segments: %8u\n",aes_segs);
706 }
707 printf(" Page segments: %8lu\n",total_pages);
708 printf(" Hash segments: %8lu\n",total_hashes);
709 printf(" Signature segments: %8lu\n",total_signatures);
710 printf(" Null segments: %8lu\n",total_nulls);
711 if(opt_all){
712 printf(" Empty segments: %8lu\n",total_nulls);
713 printf("\n");
714 printf("Total data bytes in segments: %"I64d"\n",total_datalen);
715
716 printf("Total space in file dedicated to segment names: %zd\n",
717 total_segname_len);
718 printf("Total overhead for %lu segments: %zd bytes (%lu*(%zd+%zd))\n",
719 total_segs,
720 (size_t) total_segs*(sizeof(struct af_segment_head) +sizeof(struct af_segment_tail)),
721 total_segs,
722 sizeof(struct af_segment_head),
723 sizeof(struct af_segment_tail));
724 printf("Overhead for AFF file header: %zd bytes\n",sizeof(struct af_head));
725 }
726
727 int64_t device_sectors = 0;
728 af_get_segq(af,AF_DEVICE_SECTORS,&device_sectors);
729 if(device_sectors==0){
730 /* See if we can fake it */
731 unsigned long cylinders=0;
732 unsigned long heads=0;
733 unsigned long sectors_per_track=0;
734 af_get_seg(af,AF_CYLINDERS,&cylinders,0,0);
735 af_get_seg(af,AF_HEADS,&heads,0,0);
736 af_get_seg(af,AF_SECTORS_PER_TRACK,&sectors_per_track,0,0);
737 device_sectors = cylinders * heads * sectors_per_track;
738 }
739 //printf("device_sectors=%"I64d"\n",device_sectors);
740
741
742 int some_missing_pages = 1;
743 if(af->image_pagesize && af->image_sectorsize && device_sectors){
744 int64_t device_bytes = (int64_t)device_sectors * af->image_sectorsize;
745 int64_t device_pages = (device_bytes+af->image_pagesize-1) / af->image_pagesize;
746 int64_t missing_pages = device_pages - total_pages;
747 //printf("device_bytes=%"I64d"\n",device_bytes);
748 //printf("device_pages=%"I64d"\n",device_pages);
749 if(missing_pages!=0){
750 printf("Missing page segments: %8"I64u"\n",missing_pages);
751 }
752 else {
753 some_missing_pages=0;
754 }
755 }
756 if (some_missing_pages){
757 if(((total_pages-1) * af->image_pagesize <= af->image_size) &&
758 ((total_pages) * af->image_pagesize >= af->image_size)){
759 some_missing_pages = 0;
760 }
761 }
762
763 if(some_missing_pages && opt_debug){
764 printf("Cannot calculate missing pages\n");
765 printf(" device_sectors=%"I64d" image_pagesize=%lu sectorsize=%lu\n",
766 device_sectors,af->image_pagesize,af->image_sectorsize);
767 }
768 af_close(af);
769 return 0;
770
771 }
772
773
774 void figure_media(const char *fn)
775 {
776 int fd = open(fn,O_RDONLY,0);
777 if(fd<0) err(1,"open(%s)",fn);
778 struct af_figure_media_buf afb;
779 if(af_figure_media(fd,&afb)){
780 err(1,"af_figure_media(%s)",fn);
781 }
782 printf("<?xml version='1.0' encoding='UTF-8'?>\n");
783 printf("<!DOCTYPE Server >\n");
784 printf("<device name='%s'>\n",fn);
785 printf(" <sector_size>%d</sector_size>\n",afb.sector_size);
786 printf(" <total_sectors>%"PRId64"</total_sectors>\n",afb.total_sectors);
787 printf(" <max_read_blocks>%"PRIu64"</max_read_blocks>\n",afb.max_read_blocks);
788 printf("</device>\n");
789 close(fd);
790 }
791
792 int main(int argc,char **argv)
793 {
794 int ch;
795 const char *infile;
796
797 /* Figure out how many cols the screen has... */
798 #ifdef HAVE_LIBNCURSES
799 term = getenv("TERM");
800 if(term){
801 setupterm((char *)0,1,(int *)0);
802 start_color();
803 cols = tgetnum((char *)"co");
804 }
805 #endif
806
807 while ((ch = getopt(argc, argv, "abh?s:SmiIwj:p:xvVX5dAl")) != -1) {
808 switch (ch) {
809 case 'a': opt_all++; break;
810 case 'b': opt_all ++; opt_b ++; break;
811 case 'i': opt_info=0; opt_identify = 1; break;
812 case 'w': opt_wide++; break;
813 case 'X': opt_no_preview++;break;
814 case 'x': opt_x++; break;
815 case 'y': opt_y++; break;
816 case 'l': opt_l++;break;
817 case 'm': opt_validate |= VALIDATE_MD5; break;
818 case 'S': opt_validate |= VALIDATE_SHA1; break;
819 case 'v': opt_page_validate = 1;break;
820 case 'p': opt_passphrase = optarg; break;
821 case '5': opt_preview_md5 = 1;break;
822 case 'd': opt_debug = 1;break;
823 case 'A': opt_figure_media = 1 ; break;
824
825 case 'h':
826 case '?':
827 default:
828 usage();
829 break;
830 case 's':
831 opt_seglist.push_back(optarg); // add to the list of segments to info
832 break;
833 case 'V':
834 printf("%s version %s\n",progname,PACKAGE_VERSION);
835 exit(0);
836 }
837 }
838 argc -= optind;
839 argv += optind;
840
841 if(argc<1){
842 usage();
843 }
844
845
846 /* Loop through all of the files */
847 while(*argv){
848 infile = *argv++; // get the file
849 argc--; // decrement argument counter
850
851 const char *name = af_identify_file_name(infile,1);
852 if(!name) err(1,"%s",infile);
853
854 if(opt_figure_media){ figure_media(infile);continue;}
855 if(opt_identify) printf("%s is a %s file\n",infile,name);
856 if(opt_info) info_file(infile);
857 if(opt_validate) validate(infile);
858 }
859 #ifdef USE_S3
860 s3_audit(0);
861 #endif
862 return(0);
863 }
864
865
+0
-206
tools/afrecover.cpp less more
0 /*
1 * afrecover.cpp
2 *
3 * Recover broken pages of an AFF file using the party bits
4 */
5
6 /*
7 * Copyright (c) 2005
8 * Simson L. Garfinkel and Basis Technology, Inc.
9 * All rights reserved.
10 *
11 * This code is derrived from software contributed by
12 * Simson L. Garfinkel
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by Simson L. Garfinkel
25 * and Basis Technology Corp.
26 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
27 * contributors to this program may be used to endorse or promote
28 * products derived from this software without specific prior written
29 * permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
32 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
34 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
36 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 */
45
46
47 #include "affconfig.h"
48 #include "afflib.h"
49 #include "afflib_i.h"
50 #include "utils.h"
51
52 #include <ctype.h>
53
54 #include <zlib.h>
55 #include <openssl/md5.h>
56 #include <openssl/sha.h>
57 #include <assert.h>
58
59 #ifdef HAVE_UNISTD_H
60 #include <unistd.h>
61 #endif
62
63 #ifdef HAVE_TERM_H
64 #include <term.h>
65 #endif
66
67 #ifdef HAVE_NCURSES_TERM_H
68 #include <ncurses/term.h>
69 #endif
70
71 #ifdef WIN32
72 #include "unix4win32.h"
73 #include <malloc.h>
74 #endif
75
76 using namespace std;
77 using namespace aff;
78
79 const char *progname = "affix";
80
81
82 int opt_b = 0;
83
84
85 void usage()
86 {
87 printf("usage: %s filename\n",progname);
88 exit(0);
89 }
90
91
92
93 int recover(const char *fname)
94 {
95 AFFILE *af = af_open(fname,O_RDWR,0);
96 if(!af) af_err(1,fname);
97
98 /* Get the parity page */
99 size_t pagesize = af_page_size(af);
100 u_char *pagebuf = (unsigned char *)calloc(pagesize,1);
101 u_char *parity_buf = (unsigned char *)calloc(pagesize,1);
102 u_char *my_parity_buf = (unsigned char *)calloc(pagesize,1);
103
104
105 if(af_get_seg(af,AF_PARITY0,0,parity_buf,&pagesize)){
106 err(1,"Cannot read %s segment; cannot continue",AF_PARITY0);
107 }
108
109 /* Now, for every page:
110 * 1. Read the page & the signature
111 * 2. If the signature is good, add it into the parity buffer.
112 * - If not, put it on the list of bad segments.
113 */
114 seglist segments(af);
115 seglist bad_sigs;
116 seglist good_sigs;
117 for(seglist::const_iterator seg = segments.begin();
118 seg != segments.end();
119 seg++){
120
121 if (seg->pagenumber()<0) continue; // only look for pages
122 switch(af_sig_verify_seg(af,seg->name.c_str())){
123 case AF_ERROR_SIG_NO_CERT:
124 errx(1,"%s: no public key in AFF file\n",af_filename(af));
125 case AF_ERROR_SIG_READ_ERROR:
126 errx(1,"no signature for segment '%s' --- recovery cannot continue",seg->name.c_str());
127 case AF_ERROR_SIG_BAD:
128 printf("%s has a bad signature\n",af_filename(af));
129 bad_sigs.push_back(*seg);
130 break;
131 case AF_SIG_GOOD:
132 good_sigs.push_back(*seg);
133 /* While the page is in the cache, make our parity buf */
134 pagesize = af_page_size(af);
135 if(af_get_page(af,seg->pagenumber(),pagebuf,&pagesize)){
136 err(1,"cannot read %s\n",seg->name.c_str());
137 }
138 for(u_int i=0;i<pagesize;i++){
139 my_parity_buf[i] ^= pagebuf[i];
140 }
141 break;
142 default:
143 break;
144 }
145 }
146 u_char *new_pagebuf = (unsigned char *)calloc(pagesize,1);
147
148 if(bad_sigs.size()>1) errx(1,"This program can only repair 1 bad page at the moment.");
149 if(bad_sigs.size()==0) errx(1,"There are no bad pages for this program to repair.");
150 printf("Attempting to repair %s\n",bad_sigs[0].name.c_str());
151
152 /* Calculate the page buf */
153 for(u_int i=0;i<pagesize;i++){
154 new_pagebuf[i] = parity_buf[i] ^ my_parity_buf[i];
155 }
156
157 /* Write the page back */
158 if(af_update_page(af,bad_sigs[0].pagenumber(),new_pagebuf,pagesize)){
159 err(1,"Cannot put page back");
160 }
161
162 /* Now verify the signature */
163 int r = af_sig_verify_seg(af,bad_sigs[0].name.c_str());
164 if(r==AF_SIG_GOOD){
165 printf("Page %s successfully repaired\n",bad_sigs[0].name.c_str());
166 }
167 else{
168 printf("Page %s could not be repaired; signature error code=%d\n",bad_sigs[0].name.c_str(),r);
169 exit(1);
170 }
171 af_close(af);
172 return 0;
173 }
174
175
176
177 int main(int argc,char **argv)
178 {
179 setvbuf(stdout,0,_IONBF,0); // turn off buffering
180 int ch;
181 while ((ch = getopt(argc, argv, "bh?v")) != -1) {
182 switch (ch) {
183 case 'h':
184 case '?':
185 default:
186 usage();
187 break;
188 case 'v':
189 printf("%s version %s\n",progname,PACKAGE_VERSION);
190 exit(0);
191
192 }
193 }
194 argc -= optind;
195 argv += optind;
196
197 if(argc<1){
198 usage();
199 }
200
201 recover(argv[0]);
202 exit(0);
203 }
204
205
+0
-332
tools/afsegment.cpp less more
0 /*
1 * afsegment.cpp
2 *
3 * segment manipulation tool
4 */
5
6 /*
7 * Copyright (c) 2006
8 * Simson L. Garfinkel and Basis Technology, Inc.
9 * All rights reserved.
10 *
11 * This code is derrived from software contributed by
12 * Simson L. Garfinkel
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by Simson L. Garfinkel
25 * and Basis Technology Corp.
26 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
27 * contributors to this program may be used to endorse or promote
28 * products derived from this software without specific prior written
29 * permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
32 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
34 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
36 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 */
45
46
47 #include "affconfig.h"
48 #include "afflib.h"
49 #include "afflib_i.h"
50
51 #include <limits.h>
52
53 #ifdef HAVE_REGEX_H
54 #include <regex.h>
55 #endif
56
57 #include <algorithm>
58 #include <cstdlib>
59 #include <vector>
60 #include <string>
61
62 #ifdef HAVE_CSTRING
63 #include <cstring>
64 #endif
65
66 using namespace std;
67
68
69 const char *progname = "afsegment";
70
71 int opt_create = 0;
72 int opt_quad = 0;
73 int opt_arg = 0;
74 int opt_verbose = 0;
75 int filecount = 0;
76 int opt_debug = 0;
77 int opt_x = 0;
78
79 void usage()
80 {
81 printf("afsegment version %s\n",PACKAGE_VERSION);
82 #ifdef REG_EXTENDED
83 printf("usage: afsegment [options] file1.aff [file2.aff ...]\n");
84 printf("options:\n");
85 printf(" -c Create AFF files if they do not exist\n");
86 printf(" -ssegval Sets the value of a segment; may be repeated\n");
87 printf(" -psegname Prints the contents of the segment name for each file\n");
88 printf(" -V Just print the version number and exit.\n");
89 printf(" -dname Delete segment 'name'\n");
90 printf(" -h, -? Print this message\n");
91 printf(" -Q interpert 8-byte segments as a 64-bit value\n");
92 printf(" -A Print the 32-bit arg, not the segment value\n");
93 printf(" -x Print the segment as a hex string\n");
94 printf("\n");
95 printf("Values for segval:\n");
96 printf("\n");
97 printf("Setting the segment values:\n");
98 printf(" -sname=- Take the new value of segment 'name' from stdin\n");
99 printf(" -sname=val Sets segment 'name' to be 'val' \n");
100 printf(" -sname=<val Sets segment 'name' to be contents of file 'val'\n");
101 printf("\n");
102 printf("Setting the segment args:\n");
103 printf(" -sname/arg Sets segment 'name' arg to be 'arg' (may be repeated)\n");
104 printf("\n");
105 printf("Setting both the segment value and the arg:\n");
106 printf(" -sname/arg=val Sets both arg and val for segment 'name'\n");
107 printf(" -sname/arg=<file Sets the arg and take contents from file 'file'\n");
108 printf(" -sname/arg=- Sets the arg of segment 'name' and take the contents from stdin\n");
109 printf("\n");
110 printf("Note: All deletions are done first, then all updates. Don't specify the\n");
111 printf("same segment twice on one command line.\n");
112 #else
113 printf("afsegment requires a functioning regex package to be installed\n");
114 #endif
115 exit(0);
116 }
117
118 #ifdef REG_EXTENDED
119 int get_segment_from_file(AFFILE *af,const char *segname,unsigned long arg,FILE *in)
120 {
121 u_char *value = (u_char *)malloc(0);
122 int value_len = 0;
123
124 while(!feof(in)){
125 char buf[4096];
126 int count;
127 count = fread(buf,1,sizeof(buf),in);
128 if(count>0){
129 value = (u_char *)realloc(value,value_len+count);
130 memcpy(value+value_len,buf,count);
131 value_len += count;
132 }
133 }
134 int r = af_update_seg(af,segname,arg,value,value_len);
135 free(value);
136 return r;
137 }
138
139
140 void update_segment(AFFILE *af,const char *segname,
141 const char *argstr,const char *segval)
142 {
143 unsigned long arg = 0;
144
145 if(strlen(argstr)>1) arg = atoi(argstr+1);
146
147 if(!strcmp(segval,"=-")){
148 get_segment_from_file(af,segname,arg,stdin);
149 return;
150 }
151 if(!strncmp(segval,"=<",2)){
152 FILE *f = fopen(segval+2,"rb");
153 if(!f) err(1,"fopen(%s)",segval+2);
154 get_segment_from_file(af,segname,arg,f);
155 fclose(f);
156 return;
157 }
158 segval++; // skip past the "="
159 int r = af_update_seg(af,segname,arg,(const u_char *)segval,strlen(segval));
160 if(r) warn("af_update(%s,%s) ",af_filename(af),segname);
161 }
162
163
164 char *make_re_string(const char *buf,regmatch_t *match,int num)
165 {
166 int len = match[num].rm_eo - match[num].rm_so;
167 char *ret = (char *)malloc(len+1);
168 memcpy(ret,buf+match[num].rm_so,len);
169 ret[len] = '\000';
170 return ret;
171 }
172
173
174 vector<string>del_segs;
175 vector<string>new_segs;
176 vector<string>print_segs;
177 int flags=O_RDONLY;
178 int openmode = 0666;
179 regex_t re;
180
181 void process(const char *fn)
182 {
183 AFFILE *af = af_open(fn,flags,openmode);
184 if(af){
185 vector<string>::iterator i;
186
187 for(i=del_segs.begin();i!=del_segs.end();i++){
188 if(af_del_seg(af,i->c_str())){
189 warnx("af_del_seg(%s): cannot delete segment '%s' ",fn,i->c_str());
190 }
191 else {
192 printf("%s: '%s' deleted\n",fn,i->c_str());
193 }
194 }
195 for(i=new_segs.begin();i!=new_segs.end();i++){
196 regmatch_t match[10];
197 memset(match,0,sizeof(match));
198 if(regexec(&re,i->c_str(),10,match,0)==0){
199 char *segname = make_re_string(i->c_str(),match,1);
200 char *argstr = make_re_string(i->c_str(),match,2);
201 char *segval = make_re_string(i->c_str(),match,3);
202 update_segment(af,segname,argstr,segval);
203 free(segname);
204 free(argstr);
205 free(segval);
206 }
207 }
208 for(i=print_segs.begin();i!=print_segs.end();i++){
209 size_t len = 0;
210 const char *segname = i->c_str();
211 if(opt_debug) fprintf(stderr," %s: \n",segname);
212 unsigned char *buf=0;
213 if(af_get_seg(af,segname,0,0,&len)){
214 #if HAVE_ISATTY
215 if(isatty(fileno(stdout))){
216 fprintf(stderr,"%s: segment %s not found\n",fn,segname);
217 continue;
218 }
219 #endif
220 if(opt_debug) fprintf(stderr," <<not found>>\n");
221 continue;
222 }
223
224 buf = (u_char *)malloc(len+1);
225 if(!buf) err(1,"malloc");
226 unsigned long arg = 0;
227 buf[len] = 0;
228 if(af_get_seg(af,segname,&arg,buf,&len)){
229 af_err(1,"af_get_seg"); // this shoudln't fail here
230 free(buf);
231 continue;
232 }
233 if(opt_debug) fprintf(stderr," arg=%lu len=%zd\n",arg,len);
234 int p = 1;
235
236 if(filecount>1) printf("%s:",fn);
237 if(print_segs.size()>1) printf("%s=",segname);
238 if(opt_quad && len==8){
239 uint64_t quad = af_decode_q(buf);
240 printf("%"I64u"\n",quad);
241 p = 0;
242 }
243
244 if(opt_arg){
245 printf("%lu\n",arg);
246 p = 0;
247 }
248
249 if(p){
250 for(u_int i=0;i<len;i++){
251 putchar(buf[i]);
252 }
253 }
254 if(filecount>1) printf("\n");
255 fflush(stdout);
256 if(buf) free(buf);
257 }
258 af_close(af);
259 if(opt_x) printf("\n");
260 }
261 else {
262 af_err(1,"af_open(%s) failed:",fn);
263 }
264 }
265
266 int main(int argc,char **argv)
267 {
268
269 int ch;
270 while ((ch = getopt(argc, argv, "cd:Vp:s::h?QADx")) != -1) {
271 switch (ch) {
272 case 'c':
273 flags |= O_CREAT;
274 openmode = 0666;
275 break;
276 case 'Q': opt_quad=1;break;
277 case 'A': opt_arg=1;break;
278 case 'd':
279 if(optarg==0) usage();
280 del_segs.push_back(optarg); flags |= O_RDWR;break;
281 case 'D':
282 opt_debug=1;
283 break;
284 case 'p':
285 if(optarg==0) usage();
286 print_segs.push_back(optarg); break;
287 case 's':
288 if(optarg==0) usage();
289 if(strlen(optarg)==0) usage();
290 new_segs.push_back(optarg); flags |= O_RDWR;break;
291 case 'x':
292 opt_x++;
293 break;
294 case 'h':
295 case '?':
296 default:
297 usage();
298 exit(0);
299 case 'V':
300 printf("%s version %s\n",progname,PACKAGE_VERSION);
301 exit(0);
302 }
303 }
304 argc -= optind;
305 argv += optind;
306
307 if(argc<1){
308 usage();
309 }
310
311 if(regcomp(&re,"([^/=]*)(/[0-9]+)?(=.*)?",REG_EXTENDED|REG_ICASE)){
312 err(1,"regcomp");
313 }
314
315 filecount = argc;
316 while(*argv){
317 fflush(stdout);
318 if(opt_debug) fprintf(stderr,"%s:\n",*argv);
319 process(*argv);
320 argv++;
321 argc--;
322 }
323 exit(0);
324 }
325 #else
326 int main(int argc,char **argv)
327 {
328 usage();
329 exit(1);
330 }
331 #endif
+0
-353
tools/afsign.cpp less more
0 /*
1 * afsign.cpp:
2 *
3 * Sign an existing AFF file.
4 */
5
6 /*
7 * Copyright (c) 2007
8 * Simson L. Garfinkel and Basis Technology, Inc.
9 * All rights reserved.
10 *
11 * This code is derrived from software contributed by
12 * Simson L. Garfinkel
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by Simson L. Garfinkel
25 * and Basis Technology Corp.
26 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
27 * contributors to this program may be used to endorse or promote
28 * products derived from this software without specific prior written
29 * permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
32 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
34 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
36 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 */
45
46 #include "affconfig.h"
47 #include "afflib.h"
48 #include "afflib_i.h"
49
50 #ifdef USE_AFFSIGS
51
52 #include "utils.h"
53 #include "base64.h"
54
55 #include <stdio.h>
56 #include <algorithm>
57 #include <vector>
58 #include <iostream>
59 #include <openssl/pem.h>
60 #include <openssl/x509.h>
61
62
63 #include "aff_bom.h"
64
65 int opt_note = 0;
66 const char *opt_sign_key_file = 0;
67 const char *opt_sign_cert_file = 0;
68
69 using namespace std;
70 using namespace aff;
71
72 const char *progname = "afsign";
73
74 void usage()
75 {
76 printf("%s version %s\n",progname,PACKAGE_VERSION);
77 printf("usage: %s [options] filename.aff\n",progname);
78 printf("This program will:\n");
79 printf(" * Sign each segment if there are no segment signatures.\n");
80 printf(" * Write signed chain-of-custody Bill of Materials segment.\n");
81 printf("\nSignature Options:\n");
82 printf(" -k filename.key = specify private key for signing\n");
83 printf(" -c filename.cer = specify a X.509 certificate that matches the private key\n");
84 printf(" (by default, the file is assumed to be the same one\n");
85 printf(" provided with the -k option.)\n");
86 printf(" -Z = ZAP (remove) all signature segments.\n");
87 printf("options:\n");
88 printf(" -n --- ask for a chain-of-custody note.\n");
89 printf(" -v --- Just print the version number and exit.\n");
90 exit(0);
91 }
92
93
94 int afsign(const char *fn)
95 {
96 AFFILE *af = af_open(fn,O_RDWR,0);
97 if(!af) af_err(1,"%s",fn);
98
99 struct af_vnode_info vni;
100 if(af_vstat(af,&vni)) err(1,"af_vstat");
101
102 if(vni.supports_metadata==0){
103 /* If it is a raw file, we can create an AFM file to sign */
104 if(vni.is_raw==0) errx(1,"%s: file does not support metadata. Cannot sign\n",fn);
105 af_close(af); // afm will open it
106 char afmfile[MAXPATHLEN+1];
107 char file000[MAXPATHLEN+1];
108 char extension[MAXPATHLEN+1];
109 strcpy(afmfile,fn);
110 char *period = strrchr(afmfile,'.');
111 if(!period) errx(1,"%s: file does not support metadata and lacks a file extension,\n"
112 "which is needed to create an AFM file '%s\n",afmfile,fn);
113 strcpy(extension,period+1); // get the extension
114
115 /* If the file being opened is not a .000 file, and a .000 file exists, do not proceed */
116 strcpy(period,".000");
117 strcpy(file000,afmfile); // make the 000 file
118 strcpy(period,".afm");
119
120 if(strcmp(extension,"000")!=0){
121 if(access(file000,F_OK)==0){
122 errx(1,"Can't create .afm file because %s exists.\n",file000);
123 }
124 }
125
126 strcpy(period,".afm"); // we are now going to make an afm file
127 af = af_open(afmfile,O_RDWR|O_CREAT,0600);
128 if(!af) af_err(1,"%s: file does not support metadata and cannot create AFM file '%s\n",fn,afmfile);
129 if(strcmp(extension,"000")!=0){
130 af_update_seg(af,AF_RAW_IMAGE_FILE_EXTENSION,0,(const u_char *)extension,strlen(extension));
131 af_close(af);
132 unlink(file000); // get rid of that .000 file
133 af = af_open(afmfile,O_RDWR,0600);
134 if(!af) af_err(1,"%s: Created AFM file but cannot re-open it\n",fn);
135 /* Read the first byte to force a call to afm_split_raw_setup().
136 * The results of the read don't matter, but we better be able to read.
137 */
138 u_char buf[1];
139 if(af_read(af,buf,1)!=1){
140 err(1,"Cannot read first byte of %s",fn);
141 }
142 af_seek(af,0L,0);
143 }
144 }
145
146 seglist segments(af);
147
148 if(isatty(fileno(stdout))){
149 printf("Signing segments...\n");
150 fflush(stdout);
151 }
152
153 bool signed_unsigned_segments = false;
154 if(segments.has_signed_segments()==false){
155 if(af_set_sign_files(af,opt_sign_key_file,opt_sign_cert_file)){
156 errx(1,"key file '%s' or certificate file '%s' is invalid",
157 opt_sign_key_file,opt_sign_cert_file);
158 }
159 int r = af_sign_all_unsigned_segments(af);
160 if(r<0) af_err(1,"%s: all unsigned segments cannot be signed.",fn);
161 if(r>0) signed_unsigned_segments = true;
162 }
163
164 aff_bom bom(opt_note);
165 if(bom.read_files(opt_sign_cert_file,opt_sign_key_file)) err(1,"Can't read signature files???");
166
167 u_char *pagebuf = (unsigned char *)calloc(af_page_size(af),1);
168 u_char *parity_buf = (unsigned char *)calloc(af_page_size(af),1);
169 bool compute_parity = true; // do we need to compute the parity?
170
171 /* Create the parity buffer if it doesn't exist. If the parity buffer exists, we'll just trust it.
172 * We could do a two-pass here, one for creating the parity buffer, another for creating the BOM.
173 * But that would require reading the data twice; hence this extra layer of complexity.
174 */
175 size_t parity_buf_len = af_page_size(af);
176 if(af_get_seg(af,AF_PARITY0,0,parity_buf,&parity_buf_len)==0){
177 compute_parity = false; // no need to compute it; we read it
178 }
179
180 for(seglist::const_iterator seg = segments.begin(); seg!= segments.end();seg++){
181 const char *segname = seg->name.c_str();
182
183 if(isatty(fileno(stdout))){
184 printf("\rCalculating BOM for segment %s... ",segname);
185 printf("\n");
186 fflush(stdout);
187 }
188
189 u_char seghash[32]; /* resultant message digest; could be any size */
190 unsigned int seghash_len = sizeof(seghash); /* big enough to hold SHA256 */
191 int sigmode = 0;
192 int64_t pagenumber = af_segname_page_number(segname);
193 if(pagenumber>=0){
194 /* Page segments must run in SIGNATURE_MODE1 - the actual data in the page */
195 size_t this_pagesize = af_page_size(af);
196 if(af_get_page(af,pagenumber,pagebuf,&this_pagesize)){
197 free(pagebuf);
198 return -1;
199 }
200 /* Add to parity buf if we are making a parity page*/
201 if(compute_parity){
202 for(u_int i=0;i<this_pagesize;i++){
203 parity_buf[i] ^= pagebuf[i];
204 }
205 }
206 aff_bom::make_hash(seghash,0,segname,pagebuf,this_pagesize);
207 sigmode = AF_SIGNATURE_MODE1;
208 }
209 else{
210 /* Non-Page segments can be run in SIGNATURE_MODE0 - the actual data in the file */
211 size_t seglen=0;
212 if(af_get_seg(af,segname,0,0,&seglen)){
213 err(1,"Cannot read length of segment '%s' on input file %s", segname,af_filename(af));
214 }
215 unsigned char *segbuf = (unsigned char *)malloc(seglen);
216 if(!segbuf){
217 err(1,"Cannot allocated %d bytes for segment '%s' in %s",
218 (int)seglen,segname,af_filename(af));
219 }
220 /* Now get the raw source segment */
221 unsigned long arg=0;
222 if(af_get_seg(af,segname,&arg,segbuf,&seglen)){
223 err(1,"Cannot read segment '%s' in %s. Deleteing output file", segname,af_filename(af));
224 }
225 aff_bom::make_hash(seghash,arg,segname,segbuf,seglen);
226 sigmode = AF_SIGNATURE_MODE0;
227 free(segbuf);
228 }
229 bom.add(segname,sigmode,seghash,seghash_len); // add to the BOM
230 }
231
232 /* If we have been making the parity buf:
233 * 1 - Write it out; add it to the BOM
234 * 2 - Write out the signature segment for the parity buf; add it to the bom
235 */
236 if(compute_parity){
237 if(af_update_seg(af,AF_PARITY0,0,parity_buf,af_page_size(af))) err(1,"Can't write %s",AF_PARITY0);
238
239 /* Add the parity page that we made to the BOM */
240 u_char seghash[32]; /* resultant message digest; could be any size */
241 unsigned int seghash_len = sizeof(seghash); /* big enough to hold SHA256 */
242
243 aff_bom::make_hash(seghash,0,AF_PARITY0,parity_buf,af_page_size(af));
244 bom.add(AF_PARITY0,AF_SIGNATURE_MODE0,seghash,seghash_len);
245
246
247 /* If we are signing segments for the first time, we need to sign the parity page
248 * and then add the parity page's signature segment to the BOM as well.
249 */
250 if(signed_unsigned_segments){
251 af_sign_seg(af,AF_PARITY0); // sign the parity segment if we signed the other segments
252 bom.add(af,AF_PARITY0_SIG);
253
254 u_char buf[1024];
255 size_t buflen = sizeof(buf);
256
257 const char *segname = AF_PARITY0_SIG;
258 if(af_get_seg(af,segname,0,buf,&buflen)==0){ // Get the signature
259 aff_bom::make_hash(seghash,0,segname,buf,buflen); // and add it to the BOM
260 bom.add(segname,AF_SIGNATURE_MODE0,seghash,seghash_len);
261 }
262 }
263 }
264
265 if(isatty(fileno(stdout))){
266 printf(" \r\n");
267 fflush(stdout);
268 }
269
270 bom.close();
271 bom.write(af,segments);
272 af_close(af);
273 return 0;
274 }
275
276 int remove_signatures(const char *fn)
277 {
278 AFFILE *af = af_open(fn,O_RDWR,0);
279 if(!af) af_err(1,"%s",fn);
280
281 aff::seglist sl(af);
282 for(aff::seglist::const_iterator i = sl.begin();
283 i!= sl.end();
284 i++){
285 if(af_is_signature_segment(i->name.c_str()) || i->name==AF_SIGN256_CERT){
286 cout << "Deleting " << i->name << "\n";
287 af_del_seg(af,i->name.c_str());
288 }
289 }
290 af_close(af);
291 return 0;
292 }
293
294 int main(int argc,char **argv)
295 {
296 int bflag, ch;
297 int opt_zap = 0;
298
299 bflag = 0;
300 while ((ch = getopt(argc, argv, "nk:c:h?vZ")) != -1) {
301 switch (ch) {
302 case 'n': opt_note = 1;break;
303 case 'k':
304 if(access(optarg,R_OK)) err(1,"%s",optarg);
305 opt_sign_key_file = optarg;
306 break;
307 case 'c':
308 if(access(optarg,R_OK)) err(1,"%s",optarg);
309 opt_sign_cert_file = optarg;
310 break;
311 case 'v':
312 printf("%s version %s\n",progname,PACKAGE_VERSION);
313 exit(0);
314 case 'Z':
315 opt_zap = 1;
316 break;
317 case 'h':
318 case '?':
319 default:
320 usage();
321 break;
322 }
323 }
324 argc -= optind;
325 argv += optind;
326
327 if(opt_sign_cert_file==0) opt_sign_cert_file=opt_sign_key_file; // if not set, make same as key file
328
329
330 if(argc!=1){
331 usage();
332 }
333
334 if(opt_zap) return remove_signatures(argv[0]);
335
336 /* We either need both a key file and a cert file, or neither */
337 if((opt_sign_key_file==0) || (opt_sign_cert_file==0)){
338 errx(1,"Both a private key and a certificate must be specified.");
339 }
340
341
342 return afsign(argv[0]);
343 }
344 #else
345 int main(int argc,char **argv)
346 {
347 fprintf(stderr,"afflib compiled without USE_AFFSIGS. afsign cannot run.\n");
348 exit(-1);
349 }
350
351 #endif
352
+0
-207
tools/afstats.cpp less more
0 /*
1 * afstats.cpp:
2 *
3 * print specific statistics about one or more AFF files.
4 * Ideally, we can get the stats from the metadata, but this program will
5 * calculate it if necessary.
6 */
7
8 /*
9 * Copyright (c) 2005
10 * Simson L. Garfinkel and Basis Technology, Inc.
11 * All rights reserved.
12 *
13 * This code is derrived from software contributed by
14 * Simson L. Garfinkel
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. All advertising materials mentioning features or use of this software
25 * must display the following acknowledgement:
26 * This product includes software developed by Simson L. Garfinkel
27 * and Basis Technology Corp.
28 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
29 * contributors to this program may be used to endorse or promote
30 * products derived from this software without specific prior written
31 * permission.
32 *
33 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
34 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
35 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
36 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
38 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
39 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
41 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
42 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
43 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
44 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 */
47
48
49 #include "affconfig.h"
50 #include "afflib.h"
51 #include "afflib_i.h"
52
53 #include <openssl/md5.h>
54 #include <openssl/sha.h>
55 #include <zlib.h>
56 #include <assert.h>
57
58 #ifdef HAVE_ERR_H
59 #include <err.h>
60 #endif
61
62 #ifdef HAVE_UNISTD_H
63 #include <unistd.h>
64 #endif
65
66 #ifdef HAVE_UNISTD_H
67 #include <unistd.h>
68 #endif
69
70 #ifdef HAVE_TERM_H
71 #include <term.h>
72 #endif
73
74 #ifdef HAVE_NCURSES_TERM_H
75 #include <ncurses/term.h>
76 #endif
77
78 #ifdef HAVE_NCURSES_H
79 #include <ncurses.h>
80 #endif
81
82 #ifdef WIN32
83 #include "unix4win32.h"
84 #include <malloc.h>
85 #endif
86
87 const char *progname = "afstats";
88 int opt_m = 0;
89
90 void usage()
91 {
92 printf("%s version %s\n\n",progname,PACKAGE_VERSION);
93 printf("usage: %s [options] infile(s)\n",progname);
94 printf(" -m = print all output in megabytes\n");
95 printf(" -v = Just print the version number and exit.\n");
96 exit(0);
97 }
98
99
100 void title()
101 {
102 printf("fname\tbytes\tcompressed\n");
103 }
104
105 void print_size(uint64_t s)
106 {
107 if(opt_m){
108 printf("%u",(unsigned int)(s/(1024*1024)));
109 return;
110 }
111 printf("%"I64u,s);
112 }
113
114 void afstats_title()
115 {
116 printf("Name\tAF_IMAGESIZE\tCompressed\tUncompressed\tBlank\tBad\n");
117 }
118
119 void afstats(const char *fname)
120 {
121 AFFILE *af = af_open(fname,O_RDONLY,0);
122 if(!af) af_err(1,"af_open(%s)",fname);
123
124 printf("%s\t",fname);
125
126 long unsigned int segsize=0;
127
128 int64_t imagesize=0;
129 int64_t blanksectors=0;
130 int64_t badsectors=0;
131 af_get_segq(af,AF_IMAGESIZE,&imagesize);
132 if(af_get_seg(af,AF_PAGESIZE,&segsize,0,0)){
133 af_get_seg(af,AF_SEGSIZE_D,&segsize,0,0); // check for oldstype
134 }
135 af_get_segq(af,AF_BADSECTORS,&badsectors);
136 af_get_segq(af,AF_BLANKSECTORS,&blanksectors);
137
138 print_size(imagesize);
139 printf("\t");
140 fflush(stdout);
141
142 int64_t compressed_bytes = 0;
143 int64_t uncompressed_bytes = 0;
144
145 /* Now read through all of the segments and count the number of
146 * data segments. We know the uncompressed size...
147 */
148 af_rewind_seg(af);
149 char segname[AF_MAX_NAME_LEN+1];
150 size_t datalen;
151 while(af_get_next_seg(af,segname,sizeof(segname),0,0,&datalen)==0){
152 int64_t page_num = af_segname_page_number(segname);
153 if(page_num>=0){
154 compressed_bytes += datalen;
155 uncompressed_bytes += segsize;
156 }
157 }
158 if(uncompressed_bytes > imagesize) uncompressed_bytes = imagesize;
159
160 print_size(compressed_bytes);
161 printf("\t");
162 print_size(uncompressed_bytes);
163 printf(" %"I64d" %"I64d,blanksectors,badsectors);
164 putchar('\n');
165
166
167 }
168
169
170
171
172 int main(int argc,char **argv)
173 {
174 int ch;
175 while ((ch = getopt(argc, argv, "mh?V")) != -1) {
176 switch (ch) {
177 case 'm':
178 opt_m = 1;
179 break;
180 case 'h':
181 case '?':
182 default:
183 usage();
184 break;
185 case 'V':
186 printf("%s version %s\n",progname,PACKAGE_VERSION);
187 exit(0);
188 }
189 }
190 argc -= optind;
191 argv += optind;
192
193 if(argc<1){
194 usage();
195 }
196
197 /* Each argument is now a file. Process each one */
198 afstats_title();
199 while(*argv){
200 afstats(*argv++);
201 argc--;
202 }
203 exit(0);
204 }
205
206
+0
-499
tools/afverify.cpp less more
0 /*
1 * afverify.cpp:
2 *
3 * Verify the digital signature on a signed file
4 */
5
6 /*
7 * Copyright (c) 2007
8 * Simson L. Garfinkel and Basis Technology, Inc.
9 * All rights reserved.
10 *
11 * This code is derrived from software contributed by
12 * Simson L. Garfinkel
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by Simson L. Garfinkel
25 * and Basis Technology Corp.
26 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
27 * contributors to this program may be used to endorse or promote
28 * products derived from this software without specific prior written
29 * permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
32 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
34 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
36 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 */
45
46 #include "affconfig.h"
47 #include "afflib.h"
48 #include "afflib_i.h"
49
50 #include "utils.h"
51 #include "base64.h"
52
53 #include "aff_bom.h"
54
55 #include <stdio.h>
56 #include <algorithm>
57 #include <vector>
58 #include <iostream>
59 #include <openssl/pem.h>
60 #include <openssl/x509.h>
61
62 using namespace std;
63 using namespace aff;
64
65 const char *progname = "afcrypto";
66 int opt_change = 0;
67 int opt_verbose = 0;
68 int opt_all = 0;
69
70 void usage()
71 {
72 printf("afverify version %s\n",PACKAGE_VERSION);
73 printf("usage: afverify [options] filename.aff\n");
74 printf("Verifies the digital signatures on a file\n");
75 printf("options:\n");
76 printf(" -a --- print all segments\n");
77 printf(" -V --- Just print the version number and exit.\n");
78 printf(" -v --- verbose\n");
79
80 OpenSSL_add_all_digests();
81 const EVP_MD *sha256 = EVP_get_digestbyname("sha256");
82 if(sha256){
83 printf(" SHA256 is operational\n");
84 } else {
85 printf("Warning: EVP_get_digestbyname(\"sha256\") fails\n");
86 }
87 exit(0);
88 }
89
90 void print_x509_info(X509 *cert)
91 {
92 printf("SIGNING CERTIFICATE :\n");
93 printf(" Subject: "); X509_NAME_print_ex_fp(stdout,X509_get_subject_name(cert),0,XN_FLAG_SEP_CPLUS_SPC);
94 printf("\n");
95 printf(" Issuer: "); X509_NAME_print_ex_fp(stdout,X509_get_issuer_name(cert),0,XN_FLAG_SEP_CPLUS_SPC);
96 printf("\n");
97 ASN1_INTEGER *sn = X509_get_serialNumber(cert);
98 if(sn){
99 long num = ASN1_INTEGER_get(sn);
100 if(num>0) printf(" Certificate serial number: %ld\n",num);
101 }
102 printf("\n");
103 }
104
105 #ifdef USE_AFFSIGS
106 #include "expat.h"
107 void startElement(void *userData, const char *name, const char **atts);
108 void endElement(void *userData, const char *name);
109 void cHandler(void *userData,const XML_Char *s,int len);
110
111 class segmenthash {
112 public:
113 segmenthash():total_validated(0),total_invalid(0),sigmode(0),in_cert(false),
114 in_seghash(false),get_cdata(false),arg(0),seglen(0),
115 get_cdata_segment(0),af(0),cert(0),pubkey(0) {
116
117 parser = XML_ParserCreate(NULL);
118 XML_SetUserData(parser, this);
119 XML_SetElementHandler(parser, ::startElement, ::endElement);
120 XML_SetCharacterDataHandler(parser,cHandler);
121 };
122 int parse(const char *buf,int len) { return XML_Parse(parser, buf, len, 1);}
123 XML_Parser parser;
124 int total_validated;
125 int total_invalid;
126 int sigmode;
127 bool in_cert;
128 bool in_seghash;
129 bool get_cdata;
130 string segname;
131 string alg;
132 string cdata;
133 int arg;
134 int seglen;
135 const char *get_cdata_segment; // just get this segment
136 AFFILE *af; // if set, we are parsing crypto
137 X509 *cert; // public key used to sign
138 EVP_PKEY *pubkey;
139 void clear(){
140 segname="";
141 cdata="";
142 sigmode=0;
143 alg="";
144 seglen=0;
145 }
146 ~segmenthash(){
147 if(cert) X509_free(cert);
148 if(parser) XML_ParserFree(parser);
149 }
150 void startElement(const char *name,const char **atts);
151 void endElement(const char *name);
152 };
153
154 int count=0;
155 void startElement(void *userData, const char *name, const char **atts)
156 {
157 segmenthash *sh = (segmenthash *)userData;
158 sh->startElement(name,atts);
159 }
160
161 void segmenthash::startElement(const char *name,const char **atts)
162 {
163 clear();
164 if(strcmp(name,AF_XML_SEGMENT_HASH)==0){
165 for(int i=0;atts[i];i+=2){
166 const char *name = atts[i];
167 const char *value = atts[i+1];
168 if(!strcmp(name,"segname")) segname = value;
169 if(!strcmp(name,"sigmode")) sigmode = atoi(value);
170 if(!strcmp(name,"alg")) alg = value;
171 if(!strcmp(name,"seglen")) seglen = atoi(value);
172 }
173 in_seghash = true;
174 get_cdata = true;
175 return;
176 }
177 if(strcmp(name,"signingcertificate")==0){
178 in_cert = true;
179 get_cdata = true;
180 return;
181 }
182 if(get_cdata_segment && strcmp(name,get_cdata_segment)==0){
183 get_cdata = true;
184 return;
185 }
186 }
187
188 void cHandler(void *userData,const XML_Char *s,int len)
189 {
190 segmenthash *sh = (segmenthash *)userData;
191 if(sh->get_cdata==false) return; // don't want cdata
192 sh->cdata.append(s,len);
193 }
194
195 void endElement(void *userData, const char *name)
196 {
197 segmenthash *sh = (segmenthash *)userData;
198 sh->endElement(name);
199 }
200
201
202 void segmenthash::endElement(const char *name)
203 {
204 if(get_cdata_segment && strcmp(name,get_cdata_segment)==0){
205 get_cdata = false;
206 XML_StopParser(parser,0);
207 return;
208 }
209 if(in_seghash && af){
210 if(segname.size()==0) return; // don't have a segment name
211 /* Try to validate this one */
212 size_t hashbuf_len = cdata.size() + 2;
213 u_char *hashbuf = (u_char *)malloc(hashbuf_len);
214 hashbuf_len = b64_pton_slg((char *)cdata.c_str(),cdata.size(),hashbuf,hashbuf_len);
215 if(alg=="sha256"){
216 /* TODO: Don't re-validate something that's already validated */
217 int r = af_hash_verify_seg2(af,segname.c_str(),hashbuf,hashbuf_len,sigmode);
218 if(r==AF_HASH_VERIFIES){
219 total_validated++;
220 }
221 else total_invalid++;
222 }
223 free(hashbuf);
224 in_seghash = false;
225 }
226 if(in_cert && af){
227 BIO *cert_bio = BIO_new_mem_buf((char *)cdata.c_str(),cdata.size());
228 PEM_read_bio_X509(cert_bio,&cert,0,0);
229 BIO_free(cert_bio);
230 pubkey = X509_get_pubkey(cert);
231 in_cert = false;
232 }
233 cdata = ""; // erase it
234 }
235
236 string get_xml_field(const char *buf,const char *field)
237 {
238 segmenthash sh;
239 sh.get_cdata_segment = field;
240 sh.parse(buf,strlen(buf));
241 return sh.cdata;
242 }
243
244 /* verify the chain signature; return 0 if successful, -1 if failed.
245 * The signature is a block of XML with a base64 encoded at the end.
246 */
247 int verify_bom_signature(AFFILE *af,const char *buf)
248 {
249 OpenSSL_add_all_digests();
250 const EVP_MD *sha256 = EVP_get_digestbyname("sha256");
251
252 if(!sha256){
253 fprintf(stderr,"OpenSSL does not have SHA256; signatures cannot be verified.\n");
254 return -1;
255 }
256
257 const char *cce = "</" AF_XML_AFFBOM ">\n";
258 const char *chain_end = strstr(buf,cce);
259 if(!chain_end){
260 warn("end of chain XML can't be found\n");
261 return -1; // can't find it
262 }
263 const char *sig_start = chain_end + strlen(cce);
264
265 BIO *seg = BIO_new_mem_buf((void *)buf,strlen(buf));
266 if(BIO_seek(seg,0)!=0){
267 printf("Cannot seek to beginning of BIO mem?");
268 return -1;
269 }
270 X509 *cert = 0;
271 PEM_read_bio_X509(seg,&cert,0,0); // get the contained x509 cert
272 BIO_free(seg);
273
274 /* Now get the binary signature */
275 u_char sigbuf[1024];
276 int sigbuf_len = b64_pton_slg(sig_start,strlen(sig_start),sigbuf,sizeof(sigbuf));
277 if(sigbuf_len<80){
278 warn("BOM is not signed");
279 return -1;
280 }
281
282 /* Try to verify it */
283 EVP_MD_CTX md;
284 EVP_VerifyInit(&md,sha256);
285 EVP_VerifyUpdate(&md,buf,sig_start-buf);
286 int r = EVP_VerifyFinal(&md,sigbuf,sigbuf_len,X509_get_pubkey(cert));
287 if(r!=1){
288 printf("BAD SIGNATURE ON BOM\n");
289 return -1;
290 }
291
292 print_x509_info(cert);
293 printf("Date: %s\n",get_xml_field(buf,"date").c_str());
294 printf("Notes: \n%s\n",get_xml_field(buf,"notes").c_str());
295
296 /* Now extract the XML block, terminating at the beginning of the XML signature */
297 char *buffer_without_signature = strdup(buf);
298 char *sigend = strstr(buffer_without_signature,cce);
299 if(sigend){
300 sigend[strlen(cce)] = 0;/* terminate the XML to remove the signature */
301 }
302
303 segmenthash sh;
304 sh.af = af;
305 if (!sh.parse(buffer_without_signature, strlen(buffer_without_signature))){
306 fprintf(stderr, "expat error: %s at line %d\n",
307 XML_ErrorString(XML_GetErrorCode(sh.parser)),
308 (int)XML_GetCurrentLineNumber(sh.parser));
309 fprintf(stderr,"buffer without signature:\n%s\n",buffer_without_signature);
310 return 1;
311 }
312 free(buffer_without_signature);
313 return 0;
314 }
315 #endif
316
317 int process(const char *fn)
318 {
319 AFFILE *af = af_open(fn,O_RDONLY,0666);
320 if(!af) af_err(1,fn);
321
322 /* Get the public key */
323 unsigned char certbuf[65536];
324 size_t certbuf_len = sizeof(certbuf);
325 if(af_get_seg(af,AF_SIGN256_CERT,0,certbuf,&certbuf_len)){
326 /* See if it is present, but encrypted */
327 if(af_get_seg(af,AF_SIGN256_CERT AF_AES256_SUFFIX,0,0,0)==0){
328 errx(1,"%s: signed file is encrypted; present decryption key to verify signature",fn);
329 }
330 errx(1,"%s: no signing certificate present. Cannot continue.",fn);
331 }
332
333 seglist segments(af);
334 seglist no_sigs;
335 seglist bad_sigs;
336 seglist good_sigs;
337 seglist unknown_errors;
338
339 for(seglist::const_iterator seg = segments.begin();
340 seg != segments.end();
341 seg++){
342
343 if(parse_chain(seg->name)>=0) continue; // chain of custody segments don't need signatures
344
345 const char *segname = seg->name.c_str();
346 int i =af_sig_verify_seg(af,segname);
347 if(opt_verbose){
348 printf("af_sig_verify_seg(af,%s)=%d\n",segname,i);
349 }
350 switch(i){
351 case AF_ERROR_SIG_NO_CERT:
352 err(1,"%s: no public key in AFF file\n",af_filename(af));
353 case AF_ERROR_SIG_BAD:
354 bad_sigs.push_back(*seg);
355 break;
356 case AF_ERROR_SIG_READ_ERROR:
357 no_sigs.push_back(*seg);
358 break;
359 case AF_SIG_GOOD:
360 good_sigs.push_back(*seg);
361 break;
362 case AF_ERROR_SIG_SIG_SEG:
363 break; // can't verify the sig on a sig seg
364 case AF_ERROR_SIG_NOT_COMPILED:
365 errx(1,"AFFLIB was compiled without signature support. Cannot continue.\n");
366 default:
367 unknown_errors.push_back(*seg);
368 break;
369 }
370 }
371 const char *prn = "";
372 /* Tell us something about the certificate */
373 BIO *cert_bio = BIO_new_mem_buf(certbuf,certbuf_len);
374 X509 *cert = 0;
375 PEM_read_bio_X509(cert_bio,&cert,0,0);
376 if(!cert) errx(1,"Cannot decode certificate");
377 printf("\n");
378 printf("Filename: %s\n",fn);
379 printf("# Segments signed and Verified: %d\n",(int)good_sigs.size());
380 printf("# Segments unsigned: %d\n",(int)no_sigs.size());
381 printf("# Segments with corrupted signatures: %d\n",(int)bad_sigs.size());
382 printf("\n");
383 print_x509_info(cert);
384
385 int compromised = 0;
386 for(seglist::const_iterator seg = good_sigs.begin(); seg != good_sigs.end() && opt_all;
387 seg++){
388 if(*seg==good_sigs.front()) printf("%sSegments with valid signatures:\n",prn);
389 printf("\t%s\n",seg->name.c_str());
390 prn = "\n";
391 }
392 for(seglist::const_iterator seg = no_sigs.begin();
393 seg != no_sigs.end();
394 seg++){
395 if(*seg==no_sigs.front()) printf("%sUnsigned segments:\n",prn);
396 printf("\t%s\n",seg->name.c_str());
397 prn = "\n";
398
399 /* Only unsigned data segments are a problem */
400 if(af_segname_page_number(seg->name.c_str())>=0){
401 compromised++;
402 }
403 }
404 for(seglist::const_iterator seg = bad_sigs.begin();
405 seg != bad_sigs.end();
406 seg++){
407 if(*seg==bad_sigs.front()) printf("%sBad signature segments:\n",prn);
408 printf("\t%s\n",seg->name.c_str());
409 prn = "\n";
410 compromised++;
411 }
412 for(seglist::const_iterator seg = unknown_errors.begin();
413 seg != unknown_errors.end();
414 seg++){
415 if(*seg==unknown_errors.front()) printf("%sUnknown error segments:\n",prn);
416 printf("\t%s\n",seg->name.c_str());
417 prn = "\n";
418 compromised++;
419 }
420
421 int highest = highest_chain(segments);
422 printf("\nNumber of custody chains: %d\n",highest+1);
423 for(int i=0;i<=highest;i++){
424 /* Now print each one */
425 printf("---------------------\n");
426 printf("Signed Bill of Material #%d:\n\n",i+1);
427
428 /* Get the segment and verify */
429 size_t chainbuf_len = 0;
430 char segname[AF_MAX_NAME_LEN];
431 snprintf(segname,sizeof(segname),AF_BOM_SEG,i);
432 if(af_get_seg(af,segname,0,0,&chainbuf_len)){
433 printf("*** BOM MISSING ***\n");
434 compromised++;
435 }
436 char *chainbuf = (char *)malloc(chainbuf_len+1);
437 if(af_get_seg(af,segname,0,(u_char *)chainbuf,&chainbuf_len)){
438 printf("*** CANNOT READ BOM ***\n");
439 compromised++;
440 }
441
442 chainbuf[chainbuf_len]=0; // terminate
443 #ifdef USE_AFFSIGS
444 if(verify_bom_signature(af,chainbuf)){
445 printf("*** BOM SIGNATURE INVALID ***\n");
446 compromised++;
447 }
448 #else
449 printf("BOM signature cannot be verified beause libxpat is not available.\n");
450 #endif
451 }
452 printf("---------------------\n");
453 af_close(af);
454 #ifdef USE_AFFSIGS
455 if(compromised){
456 printf("\nEVIDENCE FILE DOES NOT VERIFY.\n");
457 printf("ERRORS DETECTED: %d\n",compromised);
458 printf("EVIDENTUARY VALUE MAY BE COMPROMISED.\n");
459 return -1;
460 }
461 printf("\nEVIDENCE FILE VERIFIES.\n");
462 return 0;
463 #endif
464 printf("\n");
465 return -1;
466 }
467
468
469 int main(int argc,char **argv)
470 {
471 int bflag, ch;
472
473 bflag = 0;
474 while ((ch = getopt(argc, argv, "ach?vV")) != -1) {
475 switch (ch) {
476 case 'a': opt_all = 1; break;
477 case 'c': opt_change = 1; break;
478 case 'v': opt_verbose++; break;
479 case 'h':
480 case '?':
481 default:
482 usage();
483 break;
484 case 'V':
485 printf("%s version %s\n",progname,PACKAGE_VERSION);
486 exit(0);
487 }
488 }
489 argc -= optind;
490 argv += optind;
491
492 if(argc!=1){
493 usage();
494 }
495
496 OpenSSL_add_all_digests();
497 return process(argv[0]);
498 }
+0
-372
tools/afxml.cpp less more
0 /*
1 * afxml.cpp:
2 *
3 * print AFF information as an XML
4 */
5
6 /*
7 * Copyright (c) 2005
8 * Simson L. Garfinkel and Basis Technology, Inc.
9 * All rights reserved.
10 *
11 * This code is derrived from software contributed by
12 * Simson L. Garfinkel
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by Simson L. Garfinkel
25 * and Basis Technology Corp.
26 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
27 * contributors to this program may be used to endorse or promote
28 * products derived from this software without specific prior written
29 * permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
32 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
34 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
36 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 */
45
46
47 #include "affconfig.h"
48 #include "afflib.h"
49 #include "afflib_i.h"
50 #include "base64.h"
51
52 #ifdef WIN32
53 #include "unix4win32.h"
54 #endif
55
56 #include <vector>
57 #include <string>
58
59 #ifdef HAVE_CSTRING
60 #include <cstring>
61 #endif
62
63 using namespace std;
64
65 #if HAVE_CTYPE_H
66 #include <ctype.h>
67 #endif
68
69 #if !defined(HAVE_ISALPHANUM) && defined(HAVE_ISALNUM)
70 #define isalphanum(c) isalnum(c)
71 #endif
72
73 #if !defined(HAVE_ISALPHANUM) && !defined(HAVE_ISALNUM)
74 #define isalphanum(c) (isalpha(c)||isdigit(c))
75 #endif
76
77 const char *progname = "afxml";
78
79 int opt_x = 0;
80 char **opt_j = 0;
81 int opt_j_count = 0;
82 int opt_stats = 0;
83
84 struct page_stat_block {
85 unsigned long long zsectors; // number of sectors that are all blank
86 unsigned long long badsectors; // number of bad sectors
87 unsigned long long zpages; // number of pages that are all blank
88 unsigned long long pages; // total number of pages
89 unsigned long long sectors; // total number of sectors
90 };
91
92
93 void usage()
94 {
95 printf("%s version %s\n",progname,PACKAGE_VERSION);
96 printf("usage: %s [options] infile... \n",progname);
97 printf(" -V = Just print the version number and exit\n");
98 printf(" -x = Don't include the infile filename in output.\n");
99 printf(" -j segname = Just print information about segname \n");
100 printf(" (may be repeated)\n");
101 printf(" -s = output 'stats' for the file data (may a long time)\n");
102 exit(0);
103 }
104
105
106
107 /* Return true if segname is in the optj list */
108 bool in_opt_j_list(char *segname)
109 {
110 for(int i=0;i<opt_j_count;i++){
111 if(strcmp(segname,opt_j[i])==0) return true;
112 }
113 return false;
114 }
115
116 /* It's okay to print if there are no funky characters in it...
117 * (avoids problems with invalid UTF-8
118 */
119 bool okay_to_print(const char *data,int datalen)
120 {
121 for(const char *cc=data;cc<data+datalen;cc++){
122 if (*cc <= 0) return false;
123 if (*cc == 10 || *cc==13) continue;
124 if (*cc<32) return false;
125 if (*cc>=127) return false;
126 }
127 return true;
128 }
129
130 bool is_blank(const u_char *buf,size_t len)
131 {
132 for(size_t i=0;i<len;i++){
133 if(buf[i]) return false;
134 }
135 return true;
136 }
137
138 void print_xml64(const char *name,int64_t val)
139 {
140 printf(" <%s coding='base10'>%"I64d"</%s>\n\n",name,val,name);
141 }
142
143 int xml_info(const char *infile)
144 {
145 AFFILE *af = af_open(infile,O_RDONLY,0);
146 if(!af){
147 warn("%s",infile);
148 return -1;
149 }
150
151 struct page_stat_block psb;
152 memset(&psb,0,sizeof(psb));
153
154 printf("<!-- XML generated by afxml version %s -->\n",PACKAGE_VERSION);
155 printf("<affinfo");
156 if(!opt_x) printf(" image_filename='%s'",infile);
157 printf(">\n");
158
159 af_rewind_seg(af); // start at the beginning
160
161 char segname[AF_MAX_NAME_LEN];
162 int pages = 0;
163 vector<string> seglist; // list of segments we will get
164 vector<int64_t> pagelist; // list of segments we will get
165
166 while(af_get_next_seg(af,segname,sizeof(segname),0,0,0)==0){
167 if(segname[0]==0) continue; // segment to ignore
168 if(strcmp(segname,AF_DIRECTORY)==0) continue; // don't output the directories
169 if(strstr(segname,AF_AES256_SUFFIX)) continue; // don't output encrypted segments that won't decrypt
170
171 /* check optj */
172 if(opt_j_count > 0 && in_opt_j_list(segname)==false){
173 continue;
174 }
175
176 int64_t page_num = af_segname_page_number(segname);
177 if(page_num>=0){
178 pages += 1;
179 pagelist.push_back(page_num);
180 }
181 else {
182 seglist.push_back(segname);
183 }
184 }
185
186 printf(" <pages coding='base10'>%d</pages>\n",pages); // tell how many pages we have
187
188 /* If we have been asked to create stats, create the states */
189 if(opt_stats){
190 unsigned char *data= (unsigned char *)malloc(af_page_size(af));
191 if(!data) err(1,"Can't allocate page with %d bytes.",af_page_size(af));
192 for(vector<int64_t>::const_iterator it = pagelist.begin(); it != pagelist.end(); it++){
193 size_t pagesize = af_page_size(af);
194 size_t sectorsize = af_get_sectorsize(af);
195 if(af_get_page(af,*it,data,&pagesize)){
196 err(1,"Can't read page %"PRId64,*it);
197 }
198 psb.pages++;
199 bool allblank = true;
200 for(const unsigned char *s = data; s < data+pagesize; s+=sectorsize){
201 psb.sectors ++;
202 if(is_blank(s,sectorsize)){
203 psb.zsectors++;
204 continue;
205 }
206 allblank = false;
207 if(af_is_badsector(af,s)){
208 psb.badsectors++;
209 continue;
210 }
211 }
212 if(allblank) psb.zpages++;
213 }
214 free(data);
215 printf(" <calculated>\n");
216 print_xml64("pages",psb.pages);
217 print_xml64("zpages",psb.zpages);
218 print_xml64("sectors",psb.sectors);
219 print_xml64("zsectors",psb.zsectors);
220 print_xml64("badsectors",psb.badsectors);
221 printf(" </calculated>\n");
222 }
223
224 /* Now that we have a list of segments, print them */
225 for(vector<string>::const_iterator it = seglist.begin();
226 it != seglist.end();
227 it++){
228
229 /* See how long the data is */
230 size_t datalen = 0;
231 unsigned long arg=0;
232
233 strcpy(segname,it->c_str());
234
235 if(af_get_seg(af,segname,&arg,0,&datalen)){
236 err(1,"Can't read info for segment '%s'",segname);
237 }
238
239 unsigned char *data= (unsigned char *)malloc(datalen);
240 if(data==0) err(1,"Can't allocate %zd bytes for data",datalen);
241 if(af_get_seg(af,segname,&arg,data,&datalen)!=0){
242 err(1,"Can't read data for segment '%s'",segname);
243 }
244
245 /* Change non-XML characters in segname to _ */
246 for(char *cc=segname;*cc;cc++){
247 if(!isalphanum(*cc)) *cc = '_';
248 }
249
250 if(datalen==8 && (arg & AF_SEG_QUADWORD || af_display_as_quad(segname))){
251 /* Print it as a 64-bit value.
252 * The strcmp is there because early AF_IMAGESIZE segs didn't set
253 * AF_SEG_QUADWORD...
254 */
255 printf(" <%s coding='base10'>%"I64d"</%s>\n",segname,af_decode_q(data),segname);
256 free(data);
257 continue;
258 }
259
260 /* If datalen==0, just print the arg as an unsigned number */
261 if(datalen==0){
262 printf(" <%s coding='base10'>%ld</%s>\n",segname,arg,segname);
263 free(data);
264 continue;
265 }
266
267 /* Just handle it as binhex ... */
268 printf(" <%s",segname);
269 if(datalen==0){
270 printf(" arg='%lu' />\n",arg);
271 free(data);
272 continue;
273 }
274
275 /* If segname ends 'md5', code in hex */
276 if(strlen(segname)>=3 && strcmp(segname+strlen(segname)-3,"md5")==0){
277 char hex_buf[40];
278 printf(" coding='base16'>%s</%s>\n",
279 af_hexbuf(hex_buf,sizeof(hex_buf),data,datalen,0),
280 segname);
281 free(data);
282 continue;
283 }
284
285 /* If all segment contents are printable ascii with no CRs, LFs, or brackets,
286 * just print as-is...
287 */
288 if(okay_to_print((const char *)data,datalen)){
289 putchar('>');
290 for(const char *cc=(const char *)data;cc<(const char *)data+datalen;cc++){
291 switch(*cc){
292 case '>': fputs("&lt;",stdout);break;
293 case '<': fputs("&gt;",stdout);break;
294 case '&': fputs("&amp;",stdout);break;
295 case '\'': fputs("&apos;",stdout);break;
296 case '"': fputs("&quot;",stdout);break;
297 default: putchar(*cc);
298 }
299 }
300 printf("</%s>\n",segname);
301 free(data);
302 continue;
303 }
304
305 /* Default coding: base64 */
306 int b64size = datalen*2+2;
307 char *b64buf = (char *)calloc(b64size,1);
308 int b64size_real = b64_ntop(data,datalen,b64buf,b64size);
309 data[b64size_real] = 0; // be sure it is null terminated
310
311 printf(" coding='base64'>");
312 fputs(b64buf,stdout);
313 printf("</%s>\n",segname);
314 free(b64buf);
315 free(data);
316 }
317 af_close(af);
318
319 printf("</affinfo>\n");
320 return 0;
321 }
322
323
324 int main(int argc,char **argv)
325 {
326 int bflag, ch;
327 const char *infile;
328
329 /* Figure out how many cols the screen has... */
330
331 bflag = 0;
332 while ((ch = getopt(argc, argv, "xj:h?Vs")) != -1) {
333 switch (ch) {
334 case 'j':
335 if(opt_j==0) opt_j = (char **)malloc(0);
336 opt_j_count++;
337 opt_j = (char **)realloc(opt_j,sizeof(char *)*opt_j_count);
338 opt_j[opt_j_count-1] = strdup(optarg); // make a copy
339 case 'x': opt_x++; break;
340 case 's': opt_stats++; break;
341 case 'h':
342 case '?':
343 default:
344 usage();
345 break;
346 case 'V':
347 printf("%s version %s\n",progname,PACKAGE_VERSION);
348 exit(0);
349 }
350 }
351 argc -= optind;
352 argv += optind;
353
354 if(argc<1){
355 usage();
356 }
357
358
359 /* Loop through all of the files */
360 printf("<?xml version='1.0' encoding='UTF-8'?>\n");
361 printf("<affobjects>\n");
362 while(*argv){
363 infile = *argv++; // get the file
364 argc--; // decrement argument counter
365 xml_info(infile);
366 }
367 printf("</affobjects>\n");
368 exit(0);
369 }
370
371
88 echo === Putting a new metadata segment into blank.aff ===
99
1010 /bin/rm -f $BLANK_AFF
11 afcopy /dev/null $BLANK_AFF
12 afsegment -ssegname=testseg1 $BLANK_AFF
13 if [ x"testseg1" = x`afsegment -p segname $BLANK_AFF` ] ; then
14 echo afsegment worked!
11 affcopy /dev/null $BLANK_AFF
12 affsegment -ssegname=testseg1 $BLANK_AFF
13 if [ x"testseg1" = x`affsegment -p segname $BLANK_AFF` ] ; then
14 echo affsegment worked!
1515 else
16 echo afsegment does not work properly
16 echo affsegment does not work properly
1717 exit 1
1818 fi
1919 /bin/rm -f $BLANK_AFF
88
99 BASE=`mktemp -t encryptedXXXXXX`
1010 ENCRYPTED_AFF=$BASE.aff
11 ENCRYPTED_ISO=$BASE.iso
11 ENCRYPTED_AFD=$BASE.afd
12 PLAINTEXT_ISO=$BASE.iso
13
14 echo Making encrypted AFF from stored value
1215
1316 openssl base64 -d > $ENCRYPTED_AFF <<EOF
1417 QUZGMTANCgBBRkYAAAAABwAAAgAAAAAAYmFkZmxhZ0JBRCBTRUNUT1IAQwRKkA4whVoweN599xo5
2932 uydwNotCzenReTJdzn7fdMlBVFQAAAAARA==
3033 EOF
3134
32 openssl base64 -d > $ENCRYPTED_ISO <<EOF
35 echo Making encrypted AFD
36 mkdir $ENCRYPTED_AFD
37 cp $ENCRYPTED_AFF $ENCRYPTED_AFD/file_000.aff
38
39 echo Making plaintext ISO
40 openssl base64 -d > $PLAINTEXT_ISO <<EOF
3341 QUZGIGRlY3J5cHRpb24gYXBwZWFycyB0byB3b3JrLgo=
3442 EOF
3543
44 echo TESTING WITH PASSPHRASE IN ENVIRONMENT VARIABLE
45 export AFFLIB_PASSPHRASE=password
46 if ! affcompare $ENCRYPTED_AFF $PLAINTEXT_ISO ;
47 then
48 echo $ENCRYPTED_AFF does not decrypt properly.
49 exit 1
50 fi
51
52 if ! affcompare $ENCRYPTED_AFD $PLAINTEXT_ISO ;
53 then
54 echo $ENCRYPTED_AFD does not decrypt properly.
55 exit 1
56 fi
57
58 echo TESTING DECRYPTION WITH URL
59 unset AFFLIB_PASSPHRASE
60
61 if ! affcompare file://:password@/$ENCRYPTED_AFF $PLAINTEXT_ISO ;
62 then
63 echo $ENCRYPTED_AFF does not decrypt properly.
64 exit 1
65 fi
66
67 if ! affcompare file://:password@/$ENCRYPTED_AFD $PLAINTEXT_ISO ;
68 then
69 echo $ENCRYPTED_AFF does not decrypt properly.
70 exit 1
71 fi
72
73
3674 # file://:password@/$ENCRYPTED_AFF
37 echo afcompare $ENCRYPTED_ISO $ENCRYPTED_ISO
38 if ! afcompare $ENCRYPTED_ISO $ENCRYPTED_ISO ; then
39 echo $ENCRYPTED_ISO does not decrypt properly.
40 exit 1
41 fi
42 /bin/rm -f $ENCRYPTED_ISO $ENCRYPTED_AFF
75
76 # /bin/rm -f $PLAINTEXT_ISO $ENCRYPTED_AFF
4377 exit 0
33
44 export PATH=$srcdir:../tools:../../tools:.:$PATH
55
6 echo === testing `afcrypto -V` ===
6 echo === testing `affcrypto -V` ===
77 echo === MAKING THE TEST FILES ==
88 unset AFFLIB_PASSPHRASE
99
2222 exit 0
2323 fi
2424
25 afconvert -o $BLANK_AFF $BLANK_ISO || exit 1
26 afconvert -o file://:passphrase@/$BLANK_ENCRYPTED_AFF $BLANK_ISO || exit 1
25 affconvert -o $BLANK_AFF $BLANK_ISO || exit 1
26 affconvert -o file://:passphrase@/$BLANK_ENCRYPTED_AFF $BLANK_ISO || exit 1
2727
2828 if [ ! -r $BLANK_ENCRYPTED_AFF ]; then
2929 echo CANNOT CREATE $BLANK_ENCRYPTED_AFF
3232 fi
3333
3434
35 # Make sure afcrypto reports properly for with and with no encrypted segments
36 if (afcrypto $BLANK_AFF | grep " 0 encrypted" > /dev/null ) ; then
35 # Make sure affcrypto reports properly for with and with no encrypted segments
36 if (affcrypto $BLANK_AFF | grep " 0 encrypted" > /dev/null ) ; then
3737 echo $BLANK_ENCRYPTED_AFF properly created
3838 else
3939 echo ENCRYPTED SEGMENTS IN $BLANK_ENCRYPTED_AFF --- STOP
4040 exit 1
4141 fi
4242
43 # Now test afcrypto
44 echo Encrypted segment count: `afcrypto -j $BLANK_ENCRYPTED_AFF`
45 if [ `afcrypto -j $BLANK_ENCRYPTED_AFF` = "0" ]; then
43 # Now test affcrypto
44 echo Encrypted segment count: `affcrypto -j $BLANK_ENCRYPTED_AFF`
45 if [ `affcrypto -j $BLANK_ENCRYPTED_AFF` = "0" ]; then
4646 echo NO ENCRYPTED SEGMENTS IN $BLANK_ENCRYPTED_AFF --- STOP
4747 exit 1
4848 else
5454 echo "doc" >> $WORDS
5555 echo "passphrase" >> $WORDS
5656 echo "foobar" >> $WORDS
57 if [ "`afcrypto -k -f $WORDS $BLANK_ENCRYPTED_AFF|grep correct|grep passphrase`"x = x ] ; then
58 echo afcrypto did not find the right passphrase
57 if [ "`affcrypto -k -f $WORDS $BLANK_ENCRYPTED_AFF|grep correct|grep passphrase`"x = x ] ; then
58 echo affcrypto did not find the right passphrase
5959 exit 1
6060 else
61 echo afcrypto found the correct pasphrase
61 echo affcrypto found the correct pasphrase
6262 fi
6363
6464 rm $BLANK_ISO $BLANK_AFF $BLANK_ENCRYPTED_AFF $WORDS
3535 cp $RECOVERY_ISO $RECOVERY_BAK
3636 echo ===========
3737 echo Step 1: SIGNING $RECOVERY_ISO
38 if ! afsign -k $RECOVERY_PEM $RECOVERY_ISO ; then exit 1 ; fi
38 if ! affsign -k $RECOVERY_PEM $RECOVERY_ISO ; then exit 1 ; fi
3939 ls -l $RECOVERY_ISO $RECOVERY_AFM
4040 echo ===========
4141 echo Step 2: VERIFYING SIGNATURE
42 if ! afverify $RECOVERY_AFM ; then exit 1 ; fi
42 if ! affverify $RECOVERY_AFM ; then exit 1 ; fi
4343 echo ===========
4444 echo Step 3: CORRUPTING FILE recovery.iso
4545 dd if=/dev/random of=$RECOVERY_ISO count=1 skip=1 conv=notrunc
4646 echo ===========
4747 echo Step 4: ATTEMPTING RECOVERY
48 if ! afrecover $RECOVERY_AFM ; then exit 1 ; fi
48 if ! affrecover $RECOVERY_AFM ; then exit 1 ; fi
4949 echo ==========
5050 echo Step 5: MAKING SURE THAT THE MD5 HAS NOT CHANGED
5151 if ! cmp $RECOVERY_BAK $RECOVERY_ISO ; then echo file changed ; exit 1 ; fi
5252 echo MD5 has not changed
5353 echo ==========
5454 echo Step 6: See if Digital Signature is still good
55 if ! afverify $RECOVERY_AFM ; then echo signature no longer good ; exit 1 ; fi
55 if ! affverify $RECOVERY_AFM ; then echo signature no longer good ; exit 1 ; fi
5656 echo Signature still good
5757 echo ALL TESTS PASS
5858 /bin/rm -f $RECOVERY_KEY $RECOVERY_BAK $RECOVERY_ISO $RECOVERY_AFM $RECOVERY_PEM
1313
1414 /bin/rm -f $AGENT_PEM $ANALYST_PEM $ARCHIVES_PEM $EVIDENCE $EVIDENCE2 $EVIDENCE3
1515
16 echo TEST $0
1617 echo === MAKING THE TEST FILES ===
1718
1819 export PATH=$srcdir:../tools:../../tools:.:$PATH
2930
3031 echo Making an AFF file to sign
3132 rm -f $EVIDENCE evidence?.aff
32 afconvert -o $EVIDENCE rawevidence.iso
33 affconvert -o $EVIDENCE rawevidence.iso
3334 echo Initial AFF file
34 if ! afinfo -a $EVIDENCE ; then exit 1 ; fi
35 if ! affinfo -a $EVIDENCE ; then exit 1 ; fi
3536
3637 echo Signing AFF file...
37 echo afsign -k $AGENT_PEM $EVIDENCE
38 if ! afsign -k $AGENT_PEM $EVIDENCE ; then echo afsign failed ; exit 1 ; fi
38 echo affsign -k $AGENT_PEM $EVIDENCE
39 if ! affsign -k $AGENT_PEM $EVIDENCE ; then echo affsign failed ; exit 1 ; fi
3940
4041 echo Verifying Signature...
41 echo afverify $EVIDENCE
42 if ! afverify $EVIDENCE ; then echo afverify failed ; exit 1 ; fi ;
42 echo affverify $EVIDENCE
43 if ! affverify $EVIDENCE ; then echo affverify failed ; exit 1 ; fi ;
4344
4445 echo Signature test 1 passed
4546
4647 echo Testing chain-of-custody signatures
4748 echo Copying original raw file to evidence1.aff
4849
49 if ! afcopy -z -k $AGENT_PEM rawevidence.iso evidence1.aff ; then exit 1; fi
50 if ! afinfo -a evidence1.aff ; then exit 1 ; fi
51 if ! afcompare rawevidence.iso evidence1.aff ; then exit 1 ; fi
52 if ! afverify evidence1.aff ; then exit 1 ; fi
50 if ! affcopy -z -k $AGENT_PEM rawevidence.iso evidence1.aff ; then exit 1; fi
51 if ! affinfo -a evidence1.aff ; then exit 1 ; fi
52 if ! affcompare rawevidence.iso evidence1.aff ; then exit 1 ; fi
53 if ! affverify evidence1.aff ; then exit 1 ; fi
5354
5455 echo
5556 echo Making the second generation copy
56 echo "This copy was made by the analyst" | afcopy -z -k $ANALYST_PEM -n evidence1.aff $EVIDENCE2
57 if ! afinfo -a $EVIDENCE2 ; then exit 1 ; fi
58 if ! afcompare rawevidence.iso $EVIDENCE2 ; then exit 1 ; fi
59 if ! afverify $EVIDENCE2 ; then exit 1 ; fi
57 echo "This copy was made by the analyst" | affcopy -z -k $ANALYST_PEM -n evidence1.aff $EVIDENCE2
58 if ! affinfo -a $EVIDENCE2 ; then exit 1 ; fi
59 if ! affcompare rawevidence.iso $EVIDENCE2 ; then exit 1 ; fi
60 if ! affverify $EVIDENCE2 ; then exit 1 ; fi
6061 echo
6162 echo Making the third generation copy
62 echo "This copy was made by the archives" | afcopy -z -k $ARCHIVES_PEM -n $EVIDENCE2 $EVIDENCE3
63 if ! afinfo -a $EVIDENCE3 ; then exit 1 ; fi
64 if ! afcompare rawevidence.iso $EVIDENCE3 ; then exit 1 ; fi
65 if ! afverify $EVIDENCE3 ; then exit 1 ; fi
63 echo "This copy was made by the archives" | affcopy -z -k $ARCHIVES_PEM -n $EVIDENCE2 $EVIDENCE3
64 if ! affinfo -a $EVIDENCE3 ; then exit 1 ; fi
65 if ! affcompare rawevidence.iso $EVIDENCE3 ; then exit 1 ; fi
66 if ! affverify $EVIDENCE3 ; then exit 1 ; fi
6667
6768
6869 echo All tests passed successfully
+0
-373
win32/Makefile.am.old less more
0 #
1 # Make sure that these files get included in our distribution
2
3 TARGETS = afcompare.exe afconvert.exe afcopy.exe afdiskprint.exe affix.exe afinfo.exe afstats.exe afxml.exe
4
5 EXTRA_DIST = \
6 README.txt \
7 affconfig.h \
8 afflib.mak \
9 getopt.c \
10 getopt.h \
11 make.bat \
12 libeay32.dll \
13 openssl/Win32OpenSSL-0_9_8k.exe \
14 openssl/Win32OpenSSL_Light-0_9_8k.exe \
15 libewf-20080501/aclocal.m4 \
16 libewf-20080501/AUTHORS \
17 libewf-20080501/ChangeLog \
18 libewf-20080501/common/character_string.c \
19 libewf-20080501/common/character_string.h \
20 libewf-20080501/common/common.h \
21 libewf-20080501/common/config.h \
22 libewf-20080501/common/config.h.in \
23 libewf-20080501/common/config_windows.h \
24 libewf-20080501/common/date_time.c \
25 libewf-20080501/common/date_time.h \
26 libewf-20080501/common/endian.h \
27 libewf-20080501/common/error_string.c \
28 libewf-20080501/common/error_string.h \
29 libewf-20080501/common/file_io.c \
30 libewf-20080501/common/file_io.h \
31 libewf-20080501/common/Makefile.am \
32 libewf-20080501/common/Makefile.in \
33 libewf-20080501/common/memory.h \
34 libewf-20080501/common/notify.c \
35 libewf-20080501/common/notify.h \
36 libewf-20080501/common/string_conversion.c \
37 libewf-20080501/common/string_conversion.h \
38 libewf-20080501/common/system_string.c \
39 libewf-20080501/common/system_string.h \
40 libewf-20080501/common/types.h \
41 libewf-20080501/config.guess \
42 libewf-20080501/config.sub \
43 libewf-20080501/configure \
44 libewf-20080501/configure.ac \
45 libewf-20080501/COPYING \
46 libewf-20080501/debian/changelog \
47 libewf-20080501/debian/changelog.in \
48 libewf-20080501/debian/compat \
49 libewf-20080501/debian/control \
50 libewf-20080501/debian/copyright \
51 libewf-20080501/debian/cron.d.ex \
52 libewf-20080501/debian/emacsen-install.ex \
53 libewf-20080501/debian/emacsen-remove.ex \
54 libewf-20080501/debian/emacsen-startup.ex \
55 libewf-20080501/debian/init.d.ex \
56 libewf-20080501/debian/libewf-default.ex \
57 libewf-20080501/debian/libewf-dev.dirs \
58 libewf-20080501/debian/libewf-dev.docs \
59 libewf-20080501/debian/libewf-dev.install \
60 libewf-20080501/debian/libewf-tools.dirs \
61 libewf-20080501/debian/libewf-tools.docs \
62 libewf-20080501/debian/libewf-tools.install \
63 libewf-20080501/debian/libewf.dirs \
64 libewf-20080501/debian/libewf.doc-base.EX \
65 libewf-20080501/debian/libewf.docs \
66 libewf-20080501/debian/libewf.install \
67 libewf-20080501/debian/libewf.postinst.debhelper \
68 libewf-20080501/debian/libewf.postrm.debhelper \
69 libewf-20080501/debian/manpage.1.ex \
70 libewf-20080501/debian/manpage.sgml.ex \
71 libewf-20080501/debian/manpage.xml.ex \
72 libewf-20080501/debian/menu.ex \
73 libewf-20080501/debian/postinst.ex \
74 libewf-20080501/debian/postrm.ex \
75 libewf-20080501/debian/preinst.ex \
76 libewf-20080501/debian/prerm.ex \
77 libewf-20080501/debian/rules \
78 libewf-20080501/debian/shlibs.local.ex \
79 libewf-20080501/debian/shlibs.local.ex.in \
80 libewf-20080501/debian/watch.ex \
81 libewf-20080501/depcomp \
82 libewf-20080501/doc/header.txt \
83 libewf-20080501/doc/header2.txt \
84 libewf-20080501/doc/tests.txt \
85 libewf-20080501/ewftools/ewfacquire.c \
86 libewf-20080501/ewftools/ewfacquirestream.c \
87 libewf-20080501/ewftools/ewfalter.c \
88 libewf-20080501/ewftools/ewfbyte_size_string.c \
89 libewf-20080501/ewftools/ewfbyte_size_string.h \
90 libewf-20080501/ewftools/ewfcommon.c \
91 libewf-20080501/ewftools/ewfcommon.h \
92 libewf-20080501/ewftools/ewfdigest_context.c \
93 libewf-20080501/ewftools/ewfdigest_context.h \
94 libewf-20080501/ewftools/ewfdigest_hash.c \
95 libewf-20080501/ewftools/ewfdigest_hash.h \
96 libewf-20080501/ewftools/ewfexport.c \
97 libewf-20080501/ewftools/ewfgetopt.c \
98 libewf-20080501/ewftools/ewfgetopt.h \
99 libewf-20080501/ewftools/ewfglob.c \
100 libewf-20080501/ewftools/ewfglob.h \
101 libewf-20080501/ewftools/ewfinfo.c \
102 libewf-20080501/ewftools/ewfinput.c \
103 libewf-20080501/ewftools/ewfinput.h \
104 libewf-20080501/ewftools/ewfmd5.h \
105 libewf-20080501/ewftools/ewfoutput.c \
106 libewf-20080501/ewftools/ewfoutput.h \
107 libewf-20080501/ewftools/ewfsha1.h \
108 libewf-20080501/ewftools/ewfsignal.c \
109 libewf-20080501/ewftools/ewfsignal.h \
110 libewf-20080501/ewftools/ewfstring.c \
111 libewf-20080501/ewftools/ewfstring.h \
112 libewf-20080501/ewftools/ewfverify.c \
113 libewf-20080501/ewftools/Makefile.am \
114 libewf-20080501/ewftools/Makefile.in \
115 libewf-20080501/include/libewf/definitions.h \
116 libewf-20080501/include/libewf/definitions.h.in \
117 libewf-20080501/include/libewf/extern.h \
118 libewf-20080501/include/libewf/handle.h \
119 libewf-20080501/include/libewf/types.h \
120 libewf-20080501/include/libewf/types.h.in \
121 libewf-20080501/include/libewf.h \
122 libewf-20080501/include/libewf.h.in \
123 libewf-20080501/INSTALL \
124 libewf-20080501/install-sh \
125 libewf-20080501/libewf/ewf_char.h \
126 libewf-20080501/libewf/ewf_crc.h \
127 libewf-20080501/libewf/ewf_data.h \
128 libewf-20080501/libewf/ewf_definitions.h \
129 libewf-20080501/libewf/ewf_digest_hash.h \
130 libewf-20080501/libewf/ewf_error2.h \
131 libewf-20080501/libewf/ewf_file_header.h \
132 libewf-20080501/libewf/ewf_hash.h \
133 libewf-20080501/libewf/ewf_ltree.h \
134 libewf-20080501/libewf/ewf_section.h \
135 libewf-20080501/libewf/ewf_session.h \
136 libewf-20080501/libewf/ewf_string.h \
137 libewf-20080501/libewf/ewf_table.h \
138 libewf-20080501/libewf/ewf_volume.h \
139 libewf-20080501/libewf/ewf_volume_smart.h \
140 libewf-20080501/libewf/ewfx_delta_chunk.h \
141 libewf-20080501/libewf/libewf.c \
142 libewf-20080501/libewf/libewf_chunk_cache.c \
143 libewf-20080501/libewf/libewf_chunk_cache.h \
144 libewf-20080501/libewf/libewf_chunk_offset.h \
145 libewf-20080501/libewf/libewf_compression.c \
146 libewf-20080501/libewf/libewf_compression.h \
147 libewf-20080501/libewf/libewf_debug.c \
148 libewf-20080501/libewf/libewf_debug.h \
149 libewf-20080501/libewf/libewf_file.c \
150 libewf-20080501/libewf/libewf_file.h \
151 libewf-20080501/libewf/libewf_filename.c \
152 libewf-20080501/libewf/libewf_filename.h \
153 libewf-20080501/libewf/libewf_handle.c \
154 libewf-20080501/libewf/libewf_handle.h \
155 libewf-20080501/libewf/libewf_hash_sections.c \
156 libewf-20080501/libewf/libewf_hash_sections.h \
157 libewf-20080501/libewf/libewf_hash_values.c \
158 libewf-20080501/libewf/libewf_hash_values.h \
159 libewf-20080501/libewf/libewf_header_sections.c \
160 libewf-20080501/libewf/libewf_header_sections.h \
161 libewf-20080501/libewf/libewf_header_values.c \
162 libewf-20080501/libewf/libewf_header_values.h \
163 libewf-20080501/libewf/libewf_interface.c \
164 libewf-20080501/libewf/libewf_interface.h \
165 libewf-20080501/libewf/libewf_media_values.c \
166 libewf-20080501/libewf/libewf_media_values.h \
167 libewf-20080501/libewf/libewf_offset_table.c \
168 libewf-20080501/libewf/libewf_offset_table.h \
169 libewf-20080501/libewf/libewf_read.c \
170 libewf-20080501/libewf/libewf_read.h \
171 libewf-20080501/libewf/libewf_section.c \
172 libewf-20080501/libewf/libewf_section.h \
173 libewf-20080501/libewf/libewf_section_list.c \
174 libewf-20080501/libewf/libewf_section_list.h \
175 libewf-20080501/libewf/libewf_sector_table.c \
176 libewf-20080501/libewf/libewf_sector_table.h \
177 libewf-20080501/libewf/libewf_segment_file.c \
178 libewf-20080501/libewf/libewf_segment_file.h \
179 libewf-20080501/libewf/libewf_segment_file_handle.c \
180 libewf-20080501/libewf/libewf_segment_file_handle.h \
181 libewf-20080501/libewf/libewf_segment_table.c \
182 libewf-20080501/libewf/libewf_segment_table.h \
183 libewf-20080501/libewf/libewf_string.c \
184 libewf-20080501/libewf/libewf_string.h \
185 libewf-20080501/libewf/libewf_support.c \
186 libewf-20080501/libewf/libewf_support.h \
187 libewf-20080501/libewf/libewf_values_table.c \
188 libewf-20080501/libewf/libewf_values_table.h \
189 libewf-20080501/libewf/libewf_write.c \
190 libewf-20080501/libewf/libewf_write.h \
191 libewf-20080501/libewf/Makefile.am \
192 libewf-20080501/libewf/Makefile.in \
193 libewf-20080501/libewf.pc \
194 libewf-20080501/libewf.pc.in \
195 libewf-20080501/libewf.spec \
196 libewf-20080501/libewf.spec.in \
197 libewf-20080501/ltmain.sh \
198 libewf-20080501/macosx/Introduction.rtf \
199 libewf-20080501/macosx/Introduction.rtf.in \
200 libewf-20080501/macosx/libewf.pmproj \
201 libewf-20080501/macosx/License.rtf \
202 libewf-20080501/macosx/Readme.rtf \
203 libewf-20080501/Makefile.am \
204 libewf-20080501/Makefile.in \
205 libewf-20080501/manuals/ewfacquire.1 \
206 libewf-20080501/manuals/ewfacquirestream.1 \
207 libewf-20080501/manuals/ewfexport.1 \
208 libewf-20080501/manuals/ewfinfo.1 \
209 libewf-20080501/manuals/ewfverify.1 \
210 libewf-20080501/manuals/libewf.3 \
211 libewf-20080501/manuals/Makefile.am \
212 libewf-20080501/manuals/Makefile.in \
213 libewf-20080501/missing \
214 libewf-20080501/msvscpp/ewfacquire/ewfacquire.vcproj \
215 libewf-20080501/msvscpp/ewfacquirestream/ewfacquirestream.vcproj \
216 libewf-20080501/msvscpp/ewfalter/ewfalter.vcproj \
217 libewf-20080501/msvscpp/ewfexport/ewfexport.vcproj \
218 libewf-20080501/msvscpp/ewfinfo/ewfinfo.vcproj \
219 libewf-20080501/msvscpp/ewfverify/ewfverify.vcproj \
220 libewf-20080501/msvscpp/libewf.sln \
221 libewf-20080501/msvscpp/libewf_dll/libewf_dll.vcproj \
222 libewf-20080501/NEWS \
223 libewf-20080501/README \
224 zlib-1.2.3/adler32.c \
225 zlib-1.2.3/algorithm.txt \
226 zlib-1.2.3/as400/bndsrc \
227 zlib-1.2.3/as400/compile.clp \
228 zlib-1.2.3/as400/readme.txt \
229 zlib-1.2.3/as400/zlib.inc \
230 zlib-1.2.3/ChangeLog \
231 zlib-1.2.3/compress.c \
232 zlib-1.2.3/configure \
233 zlib-1.2.3/crc32.c \
234 zlib-1.2.3/crc32.h \
235 zlib-1.2.3/deflate.c \
236 zlib-1.2.3/deflate.h \
237 zlib-1.2.3/example-res.rc \
238 zlib-1.2.3/example-static-res.rc \
239 zlib-1.2.3/example.c \
240 zlib-1.2.3/examples/fitblk.c \
241 zlib-1.2.3/examples/gun.c \
242 zlib-1.2.3/examples/gzappend.c \
243 zlib-1.2.3/examples/gzjoin.c \
244 zlib-1.2.3/examples/gzlog.c \
245 zlib-1.2.3/examples/gzlog.h \
246 zlib-1.2.3/examples/README.examples \
247 zlib-1.2.3/examples/zlib_how.html \
248 zlib-1.2.3/examples/zpipe.c \
249 zlib-1.2.3/examples/zran.c \
250 zlib-1.2.3/FAQ \
251 zlib-1.2.3/gzio.c \
252 zlib-1.2.3/INDEX \
253 zlib-1.2.3/infback.c \
254 zlib-1.2.3/inffast.c \
255 zlib-1.2.3/inffast.h \
256 zlib-1.2.3/inffixed.h \
257 zlib-1.2.3/inflate.c \
258 zlib-1.2.3/inflate.h \
259 zlib-1.2.3/inftrees.c \
260 zlib-1.2.3/inftrees.h \
261 zlib-1.2.3/make_vms.com \
262 zlib-1.2.3/Makefile \
263 zlib-1.2.3/Makefile.in \
264 zlib-1.2.3/minigzip-res.rc \
265 zlib-1.2.3/minigzip-static-res.rc \
266 zlib-1.2.3/minigzip.c \
267 zlib-1.2.3/patches/foo.gz \
268 zlib-1.2.3/patches/zlib-1.2.2.diff \
269 zlib-1.2.3/patches/zlib-1.2.3.diff \
270 zlib-1.2.3/patches/zlib-dllversion.c \
271 zlib-1.2.3/patches/zlib-ltversion \
272 zlib-1.2.3/patches/zlib.ico \
273 zlib-1.2.3/projects/README.projects \
274 zlib-1.2.3/projects/visualc6/example.dsp \
275 zlib-1.2.3/projects/visualc6/minigzip.dsp \
276 zlib-1.2.3/projects/visualc6/README.txt \
277 zlib-1.2.3/projects/visualc6/zlib.dsp \
278 zlib-1.2.3/projects/visualc6/zlib.dsw \
279 zlib-1.2.3/qnx/package.qpg \
280 zlib-1.2.3/README \
281 zlib-1.2.3/trees.c \
282 zlib-1.2.3/trees.h \
283 zlib-1.2.3/uncompr.c \
284 zlib-1.2.3/win32/DLL_FAQ.txt \
285 zlib-1.2.3/win32/Makefile.bor \
286 zlib-1.2.3/win32/Makefile.emx \
287 zlib-1.2.3/win32/Makefile.gcc \
288 zlib-1.2.3/win32/Makefile.msc \
289 zlib-1.2.3/win32/VisualC.txt \
290 zlib-1.2.3/win32/zlib.def \
291 zlib-1.2.3/win32/zlib1.rc \
292 zlib-1.2.3/zconf.h \
293 zlib-1.2.3/zconf.in.h \
294 zlib-1.2.3/zlib-dll-res.rc \
295 zlib-1.2.3/zlib-dllversion.c \
296 zlib-1.2.3/zlib-ltversion \
297 zlib-1.2.3/zlib.3 \
298 zlib-1.2.3/zlib.h \
299 zlib-1.2.3/zlib.ico \
300 zlib-1.2.3/zutil.c \
301 zlib-1.2.3/zutil.h \
302 expat-2.0.1/lib/amigaconfig.h \
303 expat-2.0.1/lib/ascii.h \
304 expat-2.0.1/lib/asciitab.h \
305 expat-2.0.1/lib/expat.h \
306 expat-2.0.1/lib/expat_external.h \
307 expat-2.0.1/lib/iasciitab.h \
308 expat-2.0.1/lib/internal.h \
309 expat-2.0.1/lib/latin1tab.h \
310 expat-2.0.1/lib/macconfig.h \
311 expat-2.0.1/lib/nametab.h \
312 expat-2.0.1/lib/utf8tab.h \
313 expat-2.0.1/lib/winconfig.h \
314 expat-2.0.1/lib/xmlrole.h \
315 expat-2.0.1/lib/xmltok.h \
316 expat-2.0.1/lib/xmltok_impl.h \
317 expat-2.0.1/lib/xmlparse.c \
318 expat-2.0.1/lib/xmlrole.c \
319 expat-2.0.1/lib/xmltok.c \
320 expat-2.0.1/lib/xmltok_impl.c \
321 expat-2.0.1/lib/xmltok_ns.c
322
323
324 BE_DIR = ../../bulk_extractor/java/
325 $(BE_DIR)/bulk_extractor.jar:
326 (cd $(BE_DIR) ; make bulk_extractor.jar)
327 cp $(BE_DIR)/*.jar .
328 cp $(BE_DIR)/*.bat .
329
330 RELEASE_USER = simsong@
331 RELEASE_HOST = www.afflib.org
332 RELEASE_DIR = afflib.org/
333
334 RELEASE_LOC = $(RELEASE_DIR)/downloads/
335 CHANGES_LOC = $(RELEASE_DIR)/ChangeLog.txt
336 RELEASE_FN = $(PACKAGE)_winversion.txt
337 RELEASE_PATH = $(RELEASE_LOC)/$(RELEASE_FN)
338 RELEASE_SSH = $(RELEASE_USER)$(RELEASE_HOST):$(RELEASE_LOC)
339 RELEASE = $(PACKAGE)-$(VERSION)
340
341 release:
342 make the_release
343 make distribute_release
344
345 the_release: afflib.lib $(TARGETS)
346 echo "This distribution should be made after the EXEs are created in Windows"
347 cp ../lib/afflib.h .
348 cp $(BE_DIR)/bulk_extractor.jar .
349 zip $(RELEASE)-win.zip $(TARGETS) afflib.lib afflib.h bulk_extractor.jar libeay32.dll
350 rm afflib.h bulk_extractor.jar
351 gpg --detach-sign $(RELEASE).zip
352
353 distribute_release:
354 scp $(RELEASE)-win.zip{,.sig} $(RELEASE_SSH)
355 ssh $(RELEASE_HOST) 'cd $(RELEASE_LOC);/bin/rm $(PACKAGE)-win.zip;ln -s $(RELEASE)-win.zip $(PACKAGE)-win.zip'
356 ssh $(RELEASE_HOST) 'echo $(RELEASE).zip > $(RELEASE_PATH)'
357
358 afflib.lib:
359 echo To make afflib.lib, fire up Windows and type make.bat
360
361 extra_dist:
362 cp /dev/null extra-dist.txt
363 echo README.txt >> extra-dist.txt
364 echo affconfig.h >> extra-dist.txt
365 echo afflib.mak >> extra-dist.txt
366 echo getopt.c >> extra-dist.txt
367 echo getopt.h >> extra-dist.txt
368 echo make.bat >> extra-dist.txt
369 find openssl -type f -print | grep -v .svn >> extra-dist.txt
370 find libewf-20080501 -type f -print | grep -v .svn >> extra-dist.txt
371 find zlib-1.2.3 -type f | grep -v .svn >> extra-dist.txt
372
130130
131131 % make afcat.exe
132132
133 5. To open a multi-file EnCase file, just specify the first .E01 file; the AFFLIB
133 5. To make the library alone:
134
135 * Open a VS2008 command prompt (run vcvars32.bat).
136 * Make sure you have OpenSSL and zlib installed.
137 * Add OpenSSL and zlib include paths to your INCLUDE path.
138 * Run "make.bat afflib.lib" (inside the win32 directory).
139 * Rename afflib.lib to afflibMT.lib
140
141 Repeat 3 more times with different COMPILER_MODE to produce 3 more
142 libs:
143 ========================================================================
144 * Run "make.bat clean" before each build, just to be safe.
145 * COMPILER_MODE /MD /O2 /D NDEBUG => rename to afflibMD.lib
146 * COMPILER_MODE /MTd => rename to afflibMTd.lib
147 * COMPILER_MODE /MDd => rename to afflibMDd.lib
148 * Put libs in world/3rdparty/afflib/VER/lib/vs20XX/win32
149
150 Repeat 4 more times to build 64-bit libraries with same names:
151 ==============================================================
152 * Run vcvars64.bat instead of vcvars32.bat to set up environment.
153 * May want to reset INCLUDE path for OpenSSL and zlib, just to be
154 safe.
155 * Don't forget to use /O2 /D NDEBUG when building release (MT and MD).
156 * Note: No need to specify /MACHINE:X64 linker option in afflib.mak
157 because
158 we're only building a static library, not linking to create any
159 EXEs/DLLs.
160 * Run "make.bat clean" before each build, just to be safe.
161 * Put libs in world/3rdparty/afflib/VER/lib/vs20XX/x64
162
163
164 Once it is compiled:
165
166 1. To open a multi-file EnCase file, just specify the first .E01 file; the AFFLIB
134167 implementation will automatically look for all of the other EnCase files.
135168
136 6. Right now you should really use this library for READING AFF & E01
169 2. Right now you should really use this library for READING AFF & E01
137170 files, rather than WRITING them. Writing should work, but it's not
138171 very well tested on Windows. S3 is currently not supported on Windows.
139172
140 7. If you want to change the compile switches, feel free. They're in afflib.mak
173 3. If you want to change the compile switches, feel free. They're in afflib.mak
174
175
141176
142177
143178 ================================================================
0 #include "../affconfig.h"
0 /* This file is for compiling afflib using Microsoft Visual C++ */
1
12 #undef C_ALLOCA
23 #undef DISABLE_QEMU
34 #undef HAVE_ALLOCA_H
5051 #undef HAVE_FLOCK
5152 #undef HAVE_INTTYPES_H
5253
54 #ifdef USE_EWF
5355 #define HAVE_LIBEWF 1
5456 /* Define to 1 if you have the libewf_get_bytes_per_sector function. */
5557 #define HAVE_LIBEWF_GET_BYTES_PER_SECTOR 1
6567 #define HAVE_LIBEWF_GET_MEDIA_SIZE_ARGUMENT_VALUE 1
6668 /* Define to 1 if you have the <libewf.h> header file. */
6769 #define HAVE_LIBEWF_H 1
70 #endif
71
72 /* The following lines added per AccessData */
73 #include <windows.h>
74 #undef USE_LIBEWF
75 #define DISABLE_QEMU
76 #define HAVE_ALLOCA 1
77 #define HAVE_ASSERT_H 1
78 #define HAVE_CSTRING 1
79 #define HAVE_CTYPE_H 1
80 #define HAVE_EVP_MD_SIZE 1
81 #define HAVE_EVP_READ_PW_STRING 1
82 #define HAVE_ERRNO_H 1
83 #define HAVE_FCNTL_H 1
84 #define HAVE_ISLNUM 1
85 #define HAVE_ISDIGIT 1
86 #define HAVE_MEMORY_H 1
87 #define HAVE_LIBSSL 1
88 #define HAVE_LIBZ 1
89 #define HAVE_MALLOC_H 1
90 #define HAVE_MD5 1
91 #define HAVE_MEMORY_H 1
92 #define HAVE_MEMSET 1
93 #define HAVE_MKDIR 1
94 #define HAVE_SHA1 1
95 #define HAVE_AES_ENCRYPT 1
96 #define HAVE_OPENSSL_AES_H 1
97 #define HAVE_OPENSSL_BIO_H 1
98 #define HAVE_OPENSSL_EVP_H 1
99 #define HAVE_OPENSSL_HMAC_H 1
100 #define HAVE_OPENSSL_MD5_H 1
101 #define HAVE_OPENSSL_PEM_H 1
102 #define HAVE_OPENSSL_RAND_H 1
103 #define HAVE_OPENSSL_RSA_H 1
104 #define HAVE_OPENSSL_SHA_H 1
105 #define HAVE_OPENSSL_X509_H 1
106 #define HAVE_PEM_READ_BIO_RSA_PUBKEY 1
107 #define HAVE_PUTENV 1
108 #define HAVE_RAND_PSEUDO_BYTES 1
109 #define HAVE_STDIO_H 1
110 #define HAVE_STDLIB_H 1
111 #define HAVE_STRCHR 1
112 #define HAVE_STRDUP 1
113 #define HAVE_STRERROR 1
114 #define HAVE_STRING_H 1
115 #define HAVE_STRRCHR 1
116 #define HAVE_SYS_STAT_H 1
117 #define HAVE_SYS_TYPES_H 1
118 #define HAVE_ZLIB_H 1
119 #define PACKAGE_VERSION "3.6.2"
120 typedef SSIZE_T ssize_t;
22 #
33
44 # What to make:
5 TARGETS = afcompare.exe afconvert.exe afcopy.exe afdiskprint.exe affix.exe afinfo.exe afstats.exe afxml.exe
5 TARGETS = affcompare.exe affconvert.exe affcopy.exe affdiskprint.exe affix.exe affinfo.exe affstats.exe affxml.exe
66
77 # These are things you may need to change:
88 #
1313
1414 # COMPILER_MODE specifies how you want the libaries compiled:
1515
16 COMPILE_MODE = /MT
16 COMPILER_MODE = /MT /O2 /D NDEBUG
1717
18 LIBEWF = libewf-20070512
19 LIBEWF = libewf-20080501
20 LIBEWFDIR = $(LIBEWF)\libewf
2118 EXPATDIR = expat-2.0.1\lib
2219
2320 all: $(TARGETS)
3027 /I..\lib \
3128 /I..\lzma443\C \
3229 /I..\lzma443\C\7zip\Compress\LZMA_Alone \
33 /I$(LIBEWF)\include /I$(LIBEWF)\common \
3430 /I$(EXPATDIR) \
3531 /I$(SDK_DIR)/Include /I$(OPENSSL_DIR)/Include
3632
37 EWF_DEFS = /DHAVE_CONFIG_WINDOWS_H /DHAVE_LIBCRYPTO /DHAVE_OPENSSL_EVP_H /DHAVE_WINDOWS_API
38 DEFS = /DWIN32 /DWIN32_NT /DUSE_LIBEWF /DMSC /D_CRT_SECURE_NO_DEPRECATE $(EWF_DEFS) /DHAVE_MEMMOVE
33 DEFS = /DWIN32 /DWIN32_NT /DMSC /D_CRT_SECURE_NO_DEPRECATE /DHAVE_CONFIG_WINDOWS_H /DHAVE_LIBCRYPTO /DHAVE_OPENSSL_EVP_H /DHAVE_WINDOWS_API/DHAVE_MEMMOVE
3934
4035
4136 CC=cl
112107 ..\lib\vnode_aff.obj \
113108 ..\lib\vnode_afd.obj \
114109 ..\lib\vnode_afm.obj \
115 ..\lib\vnode_ewf.obj \
116110 ..\lib\vnode_raw.obj \
117111 ..\lib\vnode_s3.obj \
118112 ..\lib\vnode_split_raw.obj \
119113 ..\lib\utils.obj \
120114 ..\lib\display.obj
121115
122
123 EWF2007_OBJS = \
124 $(LIBEWFDIR)\ewf_compress.obj \
125 $(LIBEWFDIR)\ewf_crc.obj \
126 $(LIBEWFDIR)\ewf_data.obj \
127 $(LIBEWFDIR)\ewf_error2.obj \
128 $(LIBEWFDIR)\ewf_file_header.obj \
129 $(LIBEWFDIR)\ewf_hash.obj \
130 $(LIBEWFDIR)\ewf_ltree.obj \
131 $(LIBEWFDIR)\ewf_section.obj \
132 $(LIBEWFDIR)\ewf_string.obj \
133 $(LIBEWFDIR)\ewf_table.obj \
134 $(LIBEWFDIR)\ewf_volume.obj \
135 $(LIBEWFDIR)\ewf_volume_smart.obj \
136 $(LIBEWFDIR)\libewf_chunk_cache.obj \
137 $(LIBEWFDIR)\libewf_common.obj \
138 $(LIBEWFDIR)\libewf_debug.obj \
139 $(LIBEWFDIR)\libewf_digest_context.obj \
140 $(LIBEWFDIR)\libewf_endian.obj \
141 $(LIBEWFDIR)\libewf_file.obj \
142 $(LIBEWFDIR)\libewf_hash_values.obj \
143 $(LIBEWFDIR)\libewf_header_values.obj \
144 $(LIBEWFDIR)\libewf_internal_handle.obj \
145 $(LIBEWFDIR)\libewf_notify.obj \
146 $(LIBEWFDIR)\libewf_offset_table.obj \
147 $(LIBEWFDIR)\libewf_read.obj \
148 $(LIBEWFDIR)\libewf_section.obj \
149 $(LIBEWFDIR)\libewf_section_list.obj \
150 $(LIBEWFDIR)\libewf_segment_table.obj \
151 $(LIBEWFDIR)\libewf_string.obj \
152 $(LIBEWFDIR)\libewf_write.obj
153
154 EWF_OBJS = \
155 $(LIBEWFDIR)\libewf.obj\
156 $(LIBEWFDIR)\libewf_chunk_cache.obj \
157 $(LIBEWFDIR)\libewf_compression.obj \
158 $(LIBEWFDIR)\libewf_debug.obj \
159 $(LIBEWFDIR)\libewf_file.obj \
160 $(LIBEWFDIR)\libewf_filename.obj \
161 $(LIBEWFDIR)\libewf_handle.obj \
162 $(LIBEWFDIR)\libewf_hash_sections.obj \
163 $(LIBEWFDIR)\libewf_hash_values.obj \
164 $(LIBEWFDIR)\libewf_header_sections.obj \
165 $(LIBEWFDIR)\libewf_header_values.obj \
166 $(LIBEWFDIR)\libewf_interface.obj \
167 $(LIBEWFDIR)\libewf_media_values.obj \
168 $(LIBEWFDIR)\libewf_offset_table.obj \
169 $(LIBEWFDIR)\libewf_read.obj \
170 $(LIBEWFDIR)\libewf_section.obj \
171 $(LIBEWFDIR)\libewf_section_list.obj \
172 $(LIBEWFDIR)\libewf_sector_table.obj \
173 $(LIBEWFDIR)\libewf_segment_file.obj \
174 $(LIBEWFDIR)\libewf_segment_file_handle.obj \
175 $(LIBEWFDIR)\libewf_segment_table.obj \
176 $(LIBEWFDIR)\libewf_string.obj \
177 $(LIBEWFDIR)\libewf_support.obj \
178 $(LIBEWFDIR)\libewf_values_table.obj \
179 $(LIBEWFDIR)\libewf_write.obj \
180 $(LIBEWFDIR)\..\common\character_string.obj \
181 $(LIBEWFDIR)\..\common\date_time.obj \
182 $(LIBEWFDIR)\..\common\error_string.obj \
183 $(LIBEWFDIR)\..\common\file_io.obj \
184 $(LIBEWFDIR)\..\common\notify.obj \
185 $(LIBEWFDIR)\..\common\string_conversion.obj \
186 $(LIBEWFDIR)\..\common\system_string.obj
187116
188117 ZLIB_OBJS = zlib-1.2.3\adler32.obj \
189118 zlib-1.2.3\compress.obj \
213142
214143 # LIB_OBJS are all of the objects that we'll put in the library
215144
216 LIB_OBJS = $(EWF_OBJS) $(AFF_OBJS) $(LZMA_OBJS) $(WIN32_OBJS) $(ZLIB_OBJS)
145 LIB_OBJS = $(AFF_OBJS) $(LZMA_OBJS) $(WIN32_OBJS) $(ZLIB_OBJS)
217146
218147 afflib.lib: $(LIB_OBJS)
219148 lib -out:afflib.lib $(LIB_OBJS)
229158
230159 LINK_OPTS = /libpath:$(SDK_DIR)/Lib /nodefaultlib:libc $(WIN32LIBS)
231160
232 aftest.exe: ..\lib\aftest.obj afflib.lib
233 link -out:aftest.exe ..\lib\aftest.obj afflib.lib $(LINK_OPTS)
161 afftest.exe: ..\lib\aftest.obj afflib.lib
162 link -out:afftest.exe ..\lib\afftest.obj afflib.lib $(LINK_OPTS)
234163
235 afcat.exe: ..\tools\afcat.obj afflib.lib
236 link -out:afcat.exe ..\tools\afcat.obj afflib.lib $(LINK_OPTS)
164 affcat.exe: ..\tools\affcat.obj afflib.lib
165 link -out:affcat.exe ..\tools\affcat.obj afflib.lib $(LINK_OPTS)
237166
238 afcopy.exe: ..\tools\afcopy.obj ..\tools\aff_bom.obj afflib.lib
239 link -out:afcopy.exe ..\tools\afcopy.obj ..\tools\aff_bom.obj afflib.lib $(LINK_OPTS)
167 affcopy.exe: ..\tools\affcopy.obj ..\tools\aff_bom.obj afflib.lib
168 link -out:affcopy.exe ..\tools\affcopy.obj ..\tools\aff_bom.obj afflib.lib $(LINK_OPTS)
240169
241 afcompare.exe: ..\tools\afcompare.obj afflib.lib
242 link -out:afcompare.exe ..\tools\afcompare.obj afflib.lib $(LINK_OPTS)
170 affcompare.exe: ..\tools\affcompare.obj afflib.lib
171 link -out:affcompare.exe ..\tools\affcompare.obj afflib.lib $(LINK_OPTS)
243172
244 afconvert.exe: ..\tools\afconvert.obj afflib.lib
245 link -out:afconvert.exe ..\tools\afconvert.obj afflib.lib $(LINK_OPTS)
173 affconvert.exe: ..\tools\affconvert.obj afflib.lib
174 link -out:affconvert.exe ..\tools\affconvert.obj afflib.lib $(LINK_OPTS)
246175
247 afdiskprint.exe: ..\tools\afdiskprint.obj afflib.lib $(EXPAT_OBJS)
248 link -out:afdiskprint.exe ..\tools\afdiskprint.obj ..\tools\aff_bom.obj afflib.lib $(EXPAT_OBJS) $(LINK_OPTS)
176 affdiskprint.exe: ..\tools\affdiskprint.obj afflib.lib $(EXPAT_OBJS)
177 link -out:affdiskprint.exe ..\tools\affdiskprint.obj ..\tools\aff_bom.obj afflib.lib $(EXPAT_OBJS) $(LINK_OPTS)
249178
250179 affix.exe: ..\tools\affix.obj afflib.lib
251180 link -out:affix.exe ..\tools\affix.obj afflib.lib $(LINK_OPTS)
252181
253 afinfo.exe: ..\tools\afinfo.obj afflib.lib
254 link -out:afinfo.exe ..\tools\afinfo.obj afflib.lib $(LINK_OPTS)
182 affinfo.exe: ..\tools\affinfo.obj afflib.lib
183 link -out:affinfo.exe ..\tools\affinfo.obj afflib.lib $(LINK_OPTS)
255184
256 afsegment.exe: ..\tools\afsegment.obj afflib.lib
257 link -out:afsegment.exe ..\tools\afsegment.obj afflib.lib $(LINK_OPTS)
185 affsegment.exe: ..\tools\affsegment.obj afflib.lib
186 link -out:affsegment.exe ..\tools\affsegment.obj afflib.lib $(LINK_OPTS)
258187
259 afstats.exe: ..\tools\afstats.obj afflib.lib
260 link -out:afstats.exe ..\tools\afstats.obj afflib.lib $(LINK_OPTS)
188 affstats.exe: ..\tools\affstats.obj afflib.lib
189 link -out:affstats.exe ..\tools\affstats.obj afflib.lib $(LINK_OPTS)
261190
262 afxml.exe: ..\tools\afxml.obj afflib.lib
263 link -out:afxml.exe ..\tools\afxml.obj afflib.lib $(LINK_OPTS)
191 affxml.exe: ..\tools\affxml.obj afflib.lib
192 link -out:affxml.exe ..\tools\affxml.obj afflib.lib $(LINK_OPTS)
264193