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 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 335 2009-02-13 04:48:54Z 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
$|) {
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 return &print_errors
("[-] Encrypted hidden file");
421 sub obf_skipped_hidden_files_dirs
() {
422 @data_dir_files = ();
423 find
(\
&find_files
, $data_dir);
424 for my $file (@data_dir_files) {
425 if ($file =~ m
|^\
.| or $file =~ m
|/\
.|) {
426 ### check for any .gpg or .asc extensions except
427 ### for the gpgdir_map_file
428 if ($file !~ m
|gpgdir_map_file
| and ($file =~ m
|\
.gpg
$|
429 or $file =~ m
|\
.asc
$|)) {
430 return &print_errors
("[-] Encrypted hidden file");
439 my $file = $File::Find
::name
;
440 push @data_dir_files, $file;
444 sub collect_md5sums
() {
445 @data_dir_files = ();
446 find
(\
&find_files
, $data_dir);
447 for my $file (@data_dir_files) {
449 $md5sums{$file} = md5_base64
($file);
455 sub md5sum_validation
() {
456 @data_dir_files = ();
457 find
(\
&find_files
, $data_dir);
458 for my $file (@data_dir_files) {
460 if (not defined $md5sums{$file}
461 or $md5sums{$file} ne md5_base64
($file)) {
462 return &print_errors
("[-] MD5 sum mis-match for $file");
470 if (&run_cmd
("$gpgdirCmd $default_args --test", $NO_APPEND)) {
472 open F
, "< $current_test_file"
473 or die "[*] Could not open $current_test_file: $!";
475 if (/Decrypted\s+content\s+matches\s+original/i) {
483 return &print_errors
("[-] Encrypt/decrypt basic --test mode");
486 sub perl_compilation
() {
487 unless (&run_cmd
("perl -c $gpgdirCmd", $NO_APPEND)) {
488 return &print_errors
("[-] $gpgdirCmd does not compile");
494 if (&run_cmd
("$gpgdirCmd --no-such-argument", $NO_APPEND)) {
495 return &print_errors
("[-] $gpgdirCmd " .
496 "allowed --no-such-argument on the command line");
505 for (my $i=length($msg); $i < $PRINT_LEN; $i++) {
514 &logr
("fail ($test_num)\n$msg\n");
515 if (-e
$current_test_file) {
516 &logr
(" STDOUT and STDERR available in: " .
517 "$current_test_file file.\n");
518 open F
, ">> $current_test_file"
519 or die "[*] Could not open $current_test_file: $!";
520 print F
"MSG: $msg\n";
527 my ($cmd, $append) = @_;
529 if ($append == $APPEND) {
530 open F
, ">> $current_test_file"
531 or die "[*] Could not open $current_test_file: $!";
532 print F
"CMD: $cmd\n";
535 open F
, "> $current_test_file"
536 or die "[*] Could not open $current_test_file: $!";
537 print F
"CMD: $cmd\n";
540 my $rv = ((system "$cmd >> $current_test_file 2>&1") >> 8);
547 sub prepare_results
() {
549 die "[*] $output_dir does not exist" unless -d
$output_dir;
550 die "[*] $logfile does not exist, has gpgdir_test.pl been executed?"
553 unlink $tarfile or die "[*] Could not unlink $tarfile: $!";
557 system "tar cvfz $tarfile $logfile $output_dir";
558 print "[+] Test results file: $tarfile\n";
567 $|++; ### turn off buffering
569 die "[*] $conf_dir directory does not exist." unless -d
$conf_dir;
570 unless (-d
$output_dir) {
571 mkdir $output_dir or die "[*] Could not mkdir $output_dir: $!";
574 die "[*] Password file $pw_file does not exist" unless -f
$pw_file;
575 die "[*] Broken password file $broken_pw_file does not exist"
576 unless -f
$broken_pw_file;
577 die "[*] $data_dir/multi-line-ascii file does not exist"
578 unless -f
"$data_dir/multi-line-ascii";
580 for my $file (glob("$output_dir/cmd*")) {
581 unlink $file or die "[*] Could not unlink($file)";
584 for my $file (glob("$output_dir/*.test")) {
585 unlink $file or die "[*] Could not unlink($file)";
588 for my $file (glob("$output_dir/*.warn")) {
589 unlink $file or die "[*] Could not unlink($file)";
592 for my $file (glob("$output_dir/*.die")) {
593 unlink $file or die "[*] Could not unlink($file)";
596 die "[*] $gpgdirCmd does not exist" unless -e
$gpgdirCmd;
597 die "[*] $gpgdirCmd not executable" unless -x
$gpgdirCmd;
600 unlink $logfile or die $!;
606 &logr
("pass ($test_num)\n");
615 open F
, ">> $logfile" or die $!;