code restructure to put encryption/decryption code in dedicated functions, bug fix...
authorMichael Rash <mbr@cipherdyne.org>
Tue, 30 Mar 2010 03:50:13 +0000 (03:50 +0000)
committerMichael Rash <mbr@cipherdyne.org>
Tue, 30 Mar 2010 03:50:13 +0000 (03:50 +0000)
git-svn-id: file:///home/mbr/svn/gpgdir_repos/gpgdir/trunk@355 958e171a-1414-0410-8e2f-9d295d3c0db0

gpgdir

diff --git a/gpgdir b/gpgdir
index bd6a553..66c5fcd 100755 (executable)
--- a/gpgdir
+++ b/gpgdir
@@ -729,195 +729,225 @@ sub gpg_operation() {
 
         if ($encrypt_mode) {
 
-            my $encrypt_filename = "$filename.gpg";
+            &do_encrypt($dir, $file, $filename, $mtime, $atime);
 
-            if ($obfuscate_mode) {
+        } else {
 
-                unless (defined $obfuscate_ctrs{$dir}) {
+            &do_decrypt($dir, $file, $filename, $mtime, $atime);
+        }
+    }
 
-                    ### create a new gpgdir mapping file for obfuscated file
-                    ### names, but preserve any previously encrypted file
-                    ### name mappings
-                    &handle_old_obfuscated_map_file();
+    print "\n" unless $quiet;
+    chdir $initial_dir or &cleanup("[*] Could not chdir: $initial_dir\n");
+    return;
+}
 
-                    ### make obfuscated file names start at 1 for each
-                    ### directory
-                    $obfuscate_ctrs{$dir} = 1;
-                }
+sub do_encrypt() {
+    my ($dir, $file, $filename, $mtime, $atime) = @_;
 
-                $encrypt_filename = 'gpgdir_' . $obfuscate_ctrs{$dir} . '.gpg';
-            }
+    my $encrypt_filename = "$filename.gpg";
 
-            if ($ascii_armor_mode or $signing_mode) {
-                $encrypt_filename = "$filename.asc";
-            }
+    if ($obfuscate_mode) {
 
-            if (-e $encrypt_filename and not $overwrite_encrypted) {
-                my $str = 'Encrypted';
-                $str = 'Signed' if $signing_mode;
-                print "[-] $str file $dir/$encrypt_filename already ",
-                    "exists, skipping.\n" unless $quiet;
-                next FILE;
-            }
+        unless (defined $obfuscate_ctrs{$dir}) {
 
-            if ($interactive_mode) {
-                my $str = 'Encrypt';
-                $str = 'Sign' if $signing_mode;
-                next FILE unless (&query_yes_no(
-                    "    $str: $file ([y]/n)?  ", $ACCEPT_YES_DEFAULT));
+            ### create a new gpgdir mapping file for obfuscated file
+            ### names, but preserve any previously encrypted file
+            ### name mappings, and ensure no conflicts if a new file
+            ### with the same name as an old one is created in a
+            ### previously encrypted directory
+            my $previous_obf_files = &handle_old_obfuscated_map_file();
+
+            if (defined $previous_obf_files->{$filename}) {
+                print "[-] Previous file $filename exists, skipping.\n"
+                    unless $quiet;
+                return;
             }
 
-            my $str = 'Encrypting';
-            $str = 'Signing' if $signing_mode;
-            print "[+] $str:  $file\n" unless $quiet;
+            ### make obfuscated file names start at 1 for each
+            ### directory
+            $obfuscate_ctrs{$dir} = 1;
+        }
 
-            unless ($trial_run) {
+        $encrypt_filename = 'gpgdir_' . $obfuscate_ctrs{$dir} . '.gpg';
 
-                my $rv = &encrypt_or_sign_file($filename, $encrypt_filename,
-                        $NO_DEL_SOURCE_FILE);
+        ### if a file has been added to a previously encrypted directory
+        ### (encrypted with -O), then find the next 'gpgdir_<num>' file
+        while (-e $encrypt_filename) {
+            print "here\n";
+            $obfuscate_ctrs{$dir}++;
+            $encrypt_filename = 'gpgdir_' . $obfuscate_ctrs{$dir} . '.gpg';
+        }
+    }
 
-                if (-e $encrypt_filename and -s $encrypt_filename != 0) {
-                    ### set the atime and mtime to be the same as the
-                    ### original file.
-                    unless ($no_fs_times) {
-                        if (defined $mtime and $mtime and
-                                defined $atime and $atime) {
-                            utime $atime, $mtime, $encrypt_filename;
-                        }
-                    }
+    if ($ascii_armor_mode or $signing_mode) {
+        $encrypt_filename = "$filename.asc";
+    }
 
-                    unless ($signing_mode) {
-                        ### only delete the original file if
-                        ### the encrypted one exists
-                        if ($wipe_mode and not $quiet) {
-                            print "    Securely deleting file: $file\n";
-                        }
-                        &delete_file($filename);
+    if (-e $encrypt_filename and not $overwrite_encrypted) {
+        my $str = 'Encrypted';
+        $str = 'Signed' if $signing_mode;
+        print "[-] $str file $dir/$encrypt_filename already ",
+              "exists, skipping.\n" unless $quiet;
+        return;
+    }
 
-                        if ($obfuscate_mode) {
+    if ($interactive_mode) {
+        my $str = 'Encrypt';
+        $str = 'Sign' if $signing_mode;
+        return unless (&query_yes_no(
+                    "    $str: $file ([y]/n)?  ", $ACCEPT_YES_DEFAULT));
+    }
 
-                            ### record the original file name mapping
-                            &append_obfuscated_mapping($filename,
-                                $encrypt_filename);
+    my $str = 'Encrypting';
+    $str = 'Signing' if $signing_mode;
+    print "[+] $str:  $file\n" unless $quiet;
 
-                            $obfuscate_ctrs{$dir}++;
-                        }
-                    }
+    unless ($trial_run) {
 
-                    $total_encrypted++;
+        my $rv = &encrypt_or_sign_file($filename, $encrypt_filename,
+                $NO_DEL_SOURCE_FILE);
 
-                } else {
-                    my $str = 'encrypt';
-                    $str = 'sign' if $signing_mode;
-                    print "[-] Could not $str file: $file\n" unless $quiet;
-                    next FILE;
+        if (-e $encrypt_filename and -s $encrypt_filename != 0) {
+            ### set the atime and mtime to be the same as the
+            ### original file.
+            unless ($no_fs_times) {
+                if (defined $mtime and $mtime and
+                        defined $atime and $atime) {
+                    utime $atime, $mtime, $encrypt_filename;
                 }
             }
 
-        } else {
+            unless ($signing_mode) {
+                ### only delete the original file if
+                ### the encrypted one exists
+                if ($wipe_mode and not $quiet) {
+                    print "    Securely deleting file: $file\n";
+                }
+                &delete_file($filename);
+
+                if ($obfuscate_mode) {
 
-            ### allow filenames with spaces
-            my $decrypt_filename = '';
-            if ($filename =~ /^(.+)\.gpg$/) {
-                $decrypt_filename = $1;
-            } elsif ($filename =~ /^(.+)\.asc$/) {
-                $decrypt_filename = $1;
-            } elsif ($filename =~ /^(.+)\.pgp$/) {
-                $decrypt_filename = $1;
+                    ### record the original file name mapping
+                    &append_obfuscated_mapping($filename,
+                            $encrypt_filename);
+
+                    $obfuscate_ctrs{$dir}++;
+                }
             }
 
-            if ($obfuscate_mode) {
+            $total_encrypted++;
 
-                &import_obfuscated_file_map($dir)
-                    unless defined $obfuscated_dirs{$dir};
+        } else {
+            my $str = 'encrypt';
+            $str = 'sign' if $signing_mode;
+            print "[-] Could not $str file: $file\n" unless $quiet;
+            return;
+        }
+    }
+    return;
+}
 
-                if (defined $obfuscated_dirs{$dir}{$filename}) {
-                    $decrypt_filename = $obfuscated_dirs{$dir}{$filename};
-                } else {
-                    ###
-                    print "[-] Obfuscated file map does not exist for ",
-                        "$filename in\n    $obfuscate_map_file, ",
-                        "skipping.\n" unless $quiet;
-                    next FILE;
-                }
+sub do_decrypt() {
+    my ($dir, $file, $filename, $mtime, $atime) = @_;
+
+    ### allow filenames with spaces
+    my $decrypt_filename = '';
+    if ($filename =~ /^(.+)\.gpg$/) {
+        $decrypt_filename = $1;
+    } elsif ($filename =~ /^(.+)\.asc$/) {
+        $decrypt_filename = $1;
+    } elsif ($filename =~ /^(.+)\.pgp$/) {
+        $decrypt_filename = $1;
+    }
 
-            } else {
-                if (not $force_mode and ($file =~ /gpgdir_\d+_\d+\.gpg/
-                        or $file =~ /gpgdir_\d+\.gpg/)) {
-                    ### be careful not to decrypt obfuscated file unless we
-                    ### are running in -O mode.  This ensures that the
-                    ### original file names will be acquired from the
-                    ### /some/dir/.gpgdir_map_file
-                    $have_obfuscated_file = 1;
-                    next FILE;
-                }
-            }
+    if ($obfuscate_mode) {
 
-            ### length() allows files named "0"
-            next FILE unless length($decrypt_filename) > 0;
+        &import_obfuscated_file_map($dir)
+            unless defined $obfuscated_dirs{$dir};
 
-            if ($verify_mode) {
-                unless (-e $decrypt_filename) {
-                    print "[-] Original file $decrypt_filename ",
-                        "does not exist, skipping.\n";
-                    next FILE;
-                }
-            } else {
-                ### don't decrypt a file on top of a normal file of
-                ### the same name
-                if (-e $decrypt_filename and not $overwrite_decrypted) {
-                    print "[-] Decrypted file $dir/$decrypt_filename ",
-                        "already exists. Skipping.\n" unless $quiet;
-                    next FILE;
-                }
-            }
+        if (defined $obfuscated_dirs{$dir}{$filename}) {
+            $decrypt_filename = $obfuscated_dirs{$dir}{$filename};
+        } else {
+            print "[-] Obfuscated file map does not exist for ",
+                  "$filename in\n    $obfuscate_map_file, ",
+                  "skipping.\n" unless $quiet;
+            return;
+        }
 
-            if ($interactive_mode) {
-                my $str = 'Decrypt';
-                $str = 'Verify' if $verify_mode;
-                next FILE unless (&query_yes_no(
-                    "    $str: $file ([y]/n)?  ", $ACCEPT_YES_DEFAULT));
-            }
+    } else {
+        if (not $force_mode and ($file =~ /gpgdir_\d+_\d+\.gpg/
+                    or $file =~ /gpgdir_\d+\.gpg/)) {
+            ### be careful not to decrypt obfuscated file unless we
+            ### are running in -O mode.  This ensures that the
+            ### original file names will be acquired from the
+            ### /some/dir/.gpgdir_map_file
+            $have_obfuscated_file = 1;
+            return;
+        }
+    }
 
-            unless ($trial_run) {
-                my $str = 'Decrypting';
-                $str = 'Verifying' if $verify_mode;
-                print "[+] $str:  $dir/$filename\n" unless $quiet;
-                my $rv = &decrypt_or_verify_file($filename, $decrypt_filename,
-                        $NO_DEL_SOURCE_FILE);
-
-                if ($verify_mode) {
-                    $total_decrypted++ if $rv;
-                } else {
-                    if (-e $decrypt_filename and -s $decrypt_filename != 0) {
-                        ### set the atime and mtime to be the same as the
-                        ### original file.
-                        unless ($no_fs_times) {
-                            if (defined $mtime and $mtime and
-                                    defined $atime and $atime) {
-                                utime $atime, $mtime, $decrypt_filename;
-                            }
-                        }
-                        if ($wipe_mode and not $quiet) {
-                            print "    Securely deleting file: $file\n";
-                        }
-                        ### only delete the original encrypted
-                        ### file if the decrypted one exists
-                        &delete_file($filename);
+    ### length() allows files named "0"
+    return unless length($decrypt_filename) > 0;
+
+    if ($verify_mode) {
+        unless (-e $decrypt_filename) {
+            print "[-] Original file $decrypt_filename ",
+                  "does not exist, skipping.\n";
+            return;
+        }
+    } else {
+        ### don't decrypt a file on top of a normal file of
+        ### the same name
+        if (-e $decrypt_filename and not $overwrite_decrypted) {
+            print "[-] Decrypted file $dir/$decrypt_filename ",
+                  "already exists. Skipping.\n" unless $quiet;
+            return;
+        }
+    }
 
-                        $total_decrypted++;
+    if ($interactive_mode) {
+        my $str = 'Decrypt';
+        $str = 'Verify' if $verify_mode;
+        return unless (&query_yes_no(
+                    "    $str: $file ([y]/n)?  ", $ACCEPT_YES_DEFAULT));
+    }
 
-                    } else {
-                        print "[-] Could not decrypt file: $file\n"
-                            unless $quiet;
-                        next FILE;
+    unless ($trial_run) {
+        my $str = 'Decrypting';
+        $str = 'Verifying' if $verify_mode;
+        print "[+] $str:  $dir/$filename\n" unless $quiet;
+        my $rv = &decrypt_or_verify_file($filename, $decrypt_filename,
+                $NO_DEL_SOURCE_FILE);
+
+        if ($verify_mode) {
+            $total_decrypted++ if $rv;
+        } else {
+            if (-e $decrypt_filename and -s $decrypt_filename != 0) {
+                ### set the atime and mtime to be the same as the
+                ### original file.
+                unless ($no_fs_times) {
+                    if (defined $mtime and $mtime and
+                            defined $atime and $atime) {
+                        utime $atime, $mtime, $decrypt_filename;
                     }
                 }
+                if ($wipe_mode and not $quiet) {
+                    print "    Securely deleting file: $file\n";
+                }
+                ### only delete the original encrypted
+                ### file if the decrypted one exists
+                &delete_file($filename);
+
+                $total_decrypted++;
+
+            } else {
+                print "[-] Could not decrypt file: $file\n"
+                    unless $quiet;
+                return;
             }
         }
     }
-    print "\n" unless $quiet;
-    chdir $initial_dir or &cleanup("[*] Could not chdir: $initial_dir\n");
     return;
 }
 
@@ -982,6 +1012,8 @@ sub obfuscated_mapping_directories() {
 
     OUTER_LOOP: while($continue) {
 
+        $continue = 0 unless keys %$dirs_hr;
+
         DIR: for my $dir (keys %$dirs_hr) {
 
             next DIR unless -d $dir;
@@ -1108,8 +1140,10 @@ sub obfuscated_mapping_files() {
             next DIR unless -e $obfuscate_map_file;
             ### encrypt the map file now that we have encrypted
             ### the directory
+
             print "[+] Encrypting mapping file:  ",
                 "$dir/$obfuscate_map_file\n" unless $quiet;
+
             unless ($trial_run) {
                 &encrypt_or_sign_file($obfuscate_map_file,
                     "$obfuscate_map_file.gpg", $NO_DEL_SOURCE_FILE);
@@ -1147,17 +1181,20 @@ sub handle_old_obfuscated_map_file() {
     unlink "$obfuscate_map_file.gpg";
 
     my @existing_obfuscated_files = ();
+    my %previous_obfuscated_files = ();
 
     open F, "< $obfuscate_map_file" or &cleanup("[*] Could not open ",
         "$obfuscate_map_file: $!");
     while (<F>) {
-        if (/^\s*.*\s+(gpgdir_\d+_\d+\.gpg)/) {
-            if (-e $1) {
+        if (/^\s*(.*)\s+(gpgdir_\d+_\d+\.gpg)/) {
+            if (-e $2) {
                 push @existing_obfuscated_files, $_;
+                $previous_obfuscated_files{$1} = '';
             }
-        } elsif (/^\s*.*\s+(gpgdir_\d+\.gpg)/) {
-            if (-e $1) {
+        } elsif (/^\s*(.*)\s+(gpgdir_\d+\.gpg)/) {
+            if (-e $2) {
                 push @existing_obfuscated_files, $_;
+                $previous_obfuscated_files{$1} = '';
             }
         }
     }
@@ -1171,7 +1208,7 @@ sub handle_old_obfuscated_map_file() {
         print G for @existing_obfuscated_files;
         close G;
     }
-    return;
+    return \%previous_obfuscated_files;
 }
 
 sub append_obfuscated_dir() {