3 #############################################################################
7 # Purpose: This program provides a testing infrastructure for the gpgdir
8 # Single Packet Authorization client and server.
10 # Author: Michael Rash (mbr@cipherdyne.org)
14 # Copyright (C) 2008-2009 Michael Rash (mbr@cipherdyne.org)
16 # License (GNU Public License):
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
28 #############################################################################
30 # $Id: gpgdir_test.pl 341 2009-08-26 02:43:51Z mbr $
33 use Digest
::MD5
'md5_base64';
39 #=================== config defaults ==============
40 my $gpgdirCmd = '../gpgdir';
42 my $conf_dir = 'conf';
43 my $output_dir = 'output';
44 my $logfile = 'test.log';
45 my $tarfile = 'gpgdir_test.tar.gz';
46 my $data_dir = 'data-dir';
48 my $gpg_dir = "$conf_dir/test-gpg";
49 my $pw_file = "$conf_dir/test.pw";
50 my $broken_pw_file = "$conf_dir/broken.pw";
51 my $key_id = '375D7DB9';
52 #==================== end config ==================
60 my $prepare_results = 0;
61 my $successful_tests = 0;
62 my $current_test_file = "$output_dir/$test_num.test";
63 my $previous_test_file = '';
64 my @data_dir_files = ();
67 my $default_args = "--gnupg-dir $gpg_dir " .
68 "--Key-id $key_id --pw-file $pw_file";
70 die "[*] Use --help" unless GetOptions
(
71 'Prepare-results' => \
$prepare_results,
75 exit &prepare_results
() if $prepare_results;
81 &logr
("\n[+] ==> Running gpgdir test suite <==\n\n");
84 &test_driver
('(Setup) gpgdir program compilation', \
&perl_compilation
);
85 &test_driver
('(Setup) Command line argument processing', \
&getopt_test
);
86 &test_driver
('(Test mode) gpgdir basic test mode', \
&test_mode
);
89 &test_driver
('(Encrypt dir) gpgdir directory encryption', \
&encrypt
);
90 &test_driver
('(Encrypt dir) Files recursively encrypted',
91 \
&recursively_encrypted
);
92 &test_driver
('(Encrypt dir) Exclude hidden files/dirs',
93 \
&skipped_hidden_files_dirs
);
94 &test_driver
('(Decrypt dir) gpgdir directory decryption', \
&decrypt
);
95 &test_driver
('(Decrypt dir) Files recursively decrypted',
96 \
&recursively_decrypted
);
97 &test_driver
('(MD5 digest) match across encrypt/decrypt cycle',
100 ### ascii encrypt/decrypt
101 &test_driver
('(Ascii-armor dir) gpgdir directory encryption',
103 &test_driver
('(Ascii-armor dir) Files recursively encrypted',
104 \
&ascii_recursively_encrypted
);
105 &test_driver
('(Ascii-armor dir) Exclude hidden files/dirs',
106 \
&skipped_hidden_files_dirs
);
107 &test_driver
('(Decrypt dir) gpgdir directory decryption', \
&decrypt
);
108 &test_driver
('(Decrypt dir) Files recursively decrypted',
109 \
&ascii_recursively_decrypted
);
110 &test_driver
('(MD5 digest) match across encrypt/decrypt cycle',
111 \
&md5sum_validation
);
113 ### obfuscate filenames encrypt/decrypt cycle
114 &test_driver
('(Obfuscate filenames) gpgdir directory encryption',
116 &test_driver
('(Obfuscate filenames) Files recursively encrypted',
117 \
&obf_recursively_encrypted
);
118 &test_driver
('(Obfuscate filenames) Exclude hidden files/dirs',
119 \
&obf_skipped_hidden_files_dirs
);
120 &test_driver
('(Decrypt dir) gpgdir directory decryption',
122 &test_driver
('(Decrypt dir) Files recursively decrypted',
123 \
&obf_recursively_decrypted
); ### same as ascii_recursively_decrypted()
124 &test_driver
('(MD5 digest) match across encrypt/decrypt cycle',
125 \
&md5sum_validation
);
127 ### sign/verify cycle
128 &test_driver
('(Sign/verify dir) gpgdir directory signing', \
&sign
);
129 &test_driver
('(Sign/verify dir) Files recursively signed',
130 \
&recursively_signed
);
131 &test_driver
('(Sign/verify dir) Exclude hidden files/dirs',
132 \
&skipped_hidden_files_dirs
);
133 &test_driver
('(Sign/verify dir) Broken signature detection',
134 \
&broken_sig_detection
);
135 &test_driver
('(Sign/verify dir) gpgdir directory verification', \
&verify
);
136 &test_driver
('(Sign/verify dir) Files recursively verified',
137 \
&recursively_verified
);
139 ### bad password detection
140 &test_driver
('(Bad passphrase) detect broken passphrase',
141 \
&broken_passphrase
);
144 if ($successful_tests) {
145 &logr
("[+] ==> Passed $successful_tests/$test_num tests " .
146 "against gpgdir. <==\n");
149 &logr
("[+] ==> Failed $failed_tests/$test_num tests " .
150 "against gpgdir. <==\n");
152 &logr
("[+] This console output has been stored in: $logfile\n\n");
155 #======================== end main =========================
158 my ($msg, $func_ref) = @_;
160 my $test_status = 'pass';
165 $test_status = 'fail';
169 open C
, ">> $current_test_file"
170 or die "[*] Could not open $current_test_file: $!";
171 print C
"\nTEST: $msg, STATUS: $test_status\n";
174 $previous_test_file = $current_test_file;
176 $current_test_file = "$output_dir/$test_num.test";
180 sub broken_passphrase
() {
181 if (not &run_cmd
("$gpgdirCmd --gnupg-dir $gpg_dir " .
182 " --pw-file $broken_pw_file --Key-id $key_id -e $data_dir",
184 my $found_bad_pass = 0;
185 open F
, "< $current_test_file" or die $!;
192 if ($found_bad_pass) {
196 return &print_errors
("[-] Accepted broken passphrase");
200 if (&run_cmd
("$gpgdirCmd $default_args -e $data_dir", $NO_APPEND)) {
203 return &print_errors
("[-] Directory encryption");
206 sub ascii_encrypt
() {
207 if (&run_cmd
("$gpgdirCmd $default_args --Plain-ascii -e $data_dir",
211 return &print_errors
("[-] Directory encryption");
215 if (&run_cmd
("$gpgdirCmd $default_args -O -e $data_dir",
219 return &print_errors
("[-] Directory encryption");
223 if (&run_cmd
("$gpgdirCmd $default_args --sign $data_dir",
227 return &print_errors
("[-] Directory signing");
231 if (&run_cmd
("$gpgdirCmd $default_args -d $data_dir",
235 return &print_errors
("[-] Directory decryption");
239 if (&run_cmd
("$gpgdirCmd $default_args -O -d $data_dir",
243 return &print_errors
("[-] Directory decryption");
247 if (&run_cmd
("$gpgdirCmd $default_args --verify $data_dir",
251 return &print_errors
("[-] Directory verification");
254 sub recursively_encrypted
() {
255 @data_dir_files = ();
256 find
(\
&find_files
, $data_dir);
257 for my $file (@data_dir_files) {
258 if (-f
$file and not ($file =~ m
|^\
.| or $file =~ m
|/\
.|)) {
259 unless ($file =~ m
|\
.gpg
$|) {
260 return &print_errors
("[-] File $file not encrypted");
267 sub recursively_signed
() {
268 @data_dir_files = ();
269 find
(\
&find_files
, $data_dir);
270 for my $file (@data_dir_files) {
271 if (-f
$file and not ($file =~ m
|^\
.| or $file =~ m
|/\
.|)) {
272 if ($file !~ m
|\
.asc
$|) {
273 unless (-e
"$file.asc") {
274 return &print_errors
("[-] File $file not signed");
282 sub recursively_decrypted
() {
283 @data_dir_files = ();
284 find
(\
&find_files
, $data_dir);
285 for my $file (@data_dir_files) {
286 if (-f
$file and not ($file =~ m
|^\
.| or $file =~ m
|/\
.|)) {
287 if ($file =~ m
|\
.gpg
$| or $file =~ m
|\
.pgp
$|) {
288 return &print_errors
("[-] File $file not encrypted");
295 sub broken_sig_detection
() {
296 move
"$data_dir/multi-line-ascii", "$data_dir/multi-line-ascii.orig"
298 open F
, "> $data_dir/multi-line-ascii" or die $!;
299 print F
"bogus data\n";
302 &run_cmd
("$gpgdirCmd $default_args --verify $data_dir",
305 my $found_bad_sig = 0;
306 open F
, "< $current_test_file" or die $!;
314 if ($found_bad_sig) {
315 unlink "$data_dir/multi-line-ascii";
316 move
"$data_dir/multi-line-ascii.orig", "$data_dir/multi-line-ascii"
320 return &print_errors
("[-] Could not find bad signature");
323 sub recursively_verified
() {
325 ### search for signature verification errors here
326 my $found_bad_sig = 0;
327 open F
, "< $previous_test_file" or die $!;
335 if ($found_bad_sig) {
336 return &print_errors
("[-] Bad signature generated");
339 ### now remove signature files
340 @data_dir_files = ();
341 find
(\
&find_files
, $data_dir);
342 for my $file (@data_dir_files) {
343 if (-f
$file and not ($file =~ m
|^\
.| or $file =~ m
|/\
.|)) {
344 if ($file =~ m
|\
.asc
$|) {
352 sub ascii_recursively_encrypted
() {
353 @data_dir_files = ();
354 find
(\
&find_files
, $data_dir);
355 for my $file (@data_dir_files) {
356 if (-f
$file and not ($file =~ m
|^\
.| or $file =~ m
|/\
.|)) {
357 unless ($file =~ m
|\
.asc
$|) {
358 return &print_errors
("[-] File $file not encrypted");
365 sub obf_recursively_encrypted
() {
366 @data_dir_files = ();
367 find
(\
&find_files
, $data_dir);
368 for my $file (@data_dir_files) {
369 if (-f
$file and not ($file =~ m
|^\
.| or $file =~ m
|/\
.|)) {
371 unless ($file =~ m
|gpgdir_\d
+\
.gpg
$|) {
372 return &print_errors
("[-] File $file not " .
373 "encrypted and obfuscated");
380 sub ascii_recursively_decrypted
() {
381 @data_dir_files = ();
382 find
(\
&find_files
, $data_dir);
383 for my $file (@data_dir_files) {
384 if (-f
$file and not ($file =~ m
|^\
.| or $file =~ m
|/\
.|)) {
385 if ($file =~ m
|\
.asc
$|) {
386 return &print_errors
("[-] File $file not encrypted");
393 sub obf_recursively_decrypted
() {
394 @data_dir_files = ();
395 find
(\
&find_files
, $data_dir);
396 for my $file (@data_dir_files) {
397 if (-f
$file and not ($file =~ m
|^\
.| or $file =~ m
|/\
.|)) {
398 if ($file =~ m
|\
.asc
$|) {
399 return &print_errors
("[-] File $file not encrypted");
406 sub skipped_hidden_files_dirs
() {
407 @data_dir_files = ();
408 find
(\
&find_files
, $data_dir);
409 for my $file (@data_dir_files) {
410 if ($file =~ m
|^\
.| or $file =~ m
|/\
.|) {
411 ### check for any .gpg or .asc extensions except
412 ### for the gpgdir_map_file
413 if ($file =~ m
|\
.gpg
$| or $file =~ m
|\
.asc
$|
414 or $file =~ m
|\
.pgp
$|) {
415 return &print_errors
("[-] Encrypted hidden file");
422 sub obf_skipped_hidden_files_dirs
() {
423 @data_dir_files = ();
424 find
(\
&find_files
, $data_dir);
425 for my $file (@data_dir_files) {
426 if ($file =~ m
|^\
.| or $file =~ m
|/\
.|) {
427 ### check for any .gpg or .asc extensions except
428 ### for the gpgdir_map_file
429 if ($file !~ m
|gpgdir_map_file
| and ($file =~ m
|\
.gpg
$|
430 or $file =~ m
|\
.asc
$| or $file =~ m
|\
.pgp
$|)) {
431 return &print_errors
("[-] Encrypted hidden file");
440 my $file = $File::Find
::name
;
441 push @data_dir_files, $file;
445 sub collect_md5sums
() {
446 @data_dir_files = ();
447 find
(\
&find_files
, $data_dir);
448 for my $file (@data_dir_files) {
450 $md5sums{$file} = md5_base64
($file);
456 sub md5sum_validation
() {
457 @data_dir_files = ();
458 find
(\
&find_files
, $data_dir);
459 for my $file (@data_dir_files) {
461 if (not defined $md5sums{$file}
462 or $md5sums{$file} ne md5_base64
($file)) {
463 return &print_errors
("[-] MD5 sum mis-match for $file");
471 if (&run_cmd
("$gpgdirCmd $default_args --test", $NO_APPEND)) {
473 open F
, "< $current_test_file"
474 or die "[*] Could not open $current_test_file: $!";
476 if (/Decrypted\s+content\s+matches\s+original/i) {
484 return &print_errors
("[-] Encrypt/decrypt basic --test mode");
487 sub perl_compilation
() {
488 unless (&run_cmd
("perl -c $gpgdirCmd", $NO_APPEND)) {
489 return &print_errors
("[-] $gpgdirCmd does not compile");
495 if (&run_cmd
("$gpgdirCmd --no-such-argument", $NO_APPEND)) {
496 return &print_errors
("[-] $gpgdirCmd " .
497 "allowed --no-such-argument on the command line");
506 for (my $i=length($msg); $i < $PRINT_LEN; $i++) {
515 &logr
("fail ($test_num)\n$msg\n");
516 if (-e
$current_test_file) {
517 &logr
(" STDOUT and STDERR available in: " .
518 "$current_test_file file.\n");
519 open F
, ">> $current_test_file"
520 or die "[*] Could not open $current_test_file: $!";
521 print F
"MSG: $msg\n";
528 my ($cmd, $append) = @_;
530 if ($append == $APPEND) {
531 open F
, ">> $current_test_file"
532 or die "[*] Could not open $current_test_file: $!";
533 print F
"CMD: $cmd\n";
536 open F
, "> $current_test_file"
537 or die "[*] Could not open $current_test_file: $!";
538 print F
"CMD: $cmd\n";
541 my $rv = ((system "$cmd >> $current_test_file 2>&1") >> 8);
548 sub prepare_results
() {
550 die "[*] $output_dir does not exist" unless -d
$output_dir;
551 die "[*] $logfile does not exist, has gpgdir_test.pl been executed?"
554 unlink $tarfile or die "[*] Could not unlink $tarfile: $!";
558 system "tar cvfz $tarfile $logfile $output_dir";
559 print "[+] Test results file: $tarfile\n";
568 $|++; ### turn off buffering
570 die "[*] $conf_dir directory does not exist." unless -d
$conf_dir;
571 unless (-d
$output_dir) {
572 mkdir $output_dir or die "[*] Could not mkdir $output_dir: $!";
575 die "[*] Password file $pw_file does not exist" unless -f
$pw_file;
576 die "[*] Broken password file $broken_pw_file does not exist"
577 unless -f
$broken_pw_file;
578 die "[*] $data_dir/multi-line-ascii file does not exist"
579 unless -f
"$data_dir/multi-line-ascii";
581 for my $file (glob("$output_dir/cmd*")) {
582 unlink $file or die "[*] Could not unlink($file)";
585 for my $file (glob("$output_dir/*.test")) {
586 unlink $file or die "[*] Could not unlink($file)";
589 for my $file (glob("$output_dir/*.warn")) {
590 unlink $file or die "[*] Could not unlink($file)";
593 for my $file (glob("$output_dir/*.die")) {
594 unlink $file or die "[*] Could not unlink($file)";
597 die "[*] $gpgdirCmd does not exist" unless -e
$gpgdirCmd;
598 die "[*] $gpgdirCmd not executable" unless -x
$gpgdirCmd;
601 unlink $logfile or die $!;
607 &logr
("pass ($test_num)\n");
616 open F
, ">> $logfile" or die $!;