# # $Date: 2005/03/15 21:15:49 $ # # Functions to check and get the arguments from URL # # ver 2.00+ # Brian Carrier [carrier@sleuthkit.org] # Copyright (c) 2003-2004 by Brian Carrier. All rights reserved # # This file is part of the Autopsy Forensic Browser (Autopsy) # # Autopsy is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Autopsy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Autopsy; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE. # IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS OR # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package Args; # Parse the argument string into the args hash sub parse_args { my $lcl_args = shift; foreach my $nam_val (split(/&/, $lcl_args)) { my ($name, $value) = split(/=/, $nam_val); if (defined $value) { my $dec_name = url_decode($name); $Args::enc_args{$dec_name} = $value; $Args::args{$dec_name} = url_decode($value); } } } sub url_encode { my $text = shift; $text =~ s/([^a-z0-9_.!~*'() -])/sprintf "%%%02X", ord($1)/eig; $text =~ tr/ /+/; return $text; } sub url_decode { my $text = shift; $text =~ tr/\+/ /; $text =~ s/%([a-f0-9][a-f0-9])/chr( hex( $1 ) )/eig; return $text; } # This assumes that the checking of the types has been done and this just # makes a string of the key values if they exist # # case # host # img # Must add & after sub make_baseargs { $Args::baseargs = ""; # The standard case, host, and investigator $Args::baseargs .= "case=$Args::enc_args{'case'}&" if ((exists $Args::enc_args{'case'}) && ($Args::enc_args{'case'} ne "")); $Args::baseargs .= "host=$Args::enc_args{'host'}&" if ((exists $Args::enc_args{'host'}) && ($Args::enc_args{'host'} ne "")); $Args::baseargs .= "inv=$Args::enc_args{'inv'}&" if ((exists $Args::enc_args{'inv'}) && ($Args::enc_args{'inv'} ne "")); $Args::baseargs_novol = $Args::baseargs; # Add the image, file system type, and mount point $Args::baseargs .= "vol=$Args::enc_args{'vol'}&" if ((exists $Args::enc_args{'vol'}) && ($Args::enc_args{'vol'} ne "")); # remove the final '&' $Args::baseargs_novol = $1 if ($Args::baseargs_novol =~ /^(.*?)&$/); $Args::baseargs = $1 if ($Args::baseargs =~ /^(.*?)&$/); return; } # Does not do mnt or img sub make_hidden { my $str = ""; $str .= "\n" if ((exists $Args::args{'host'}) && ($Args::args{'host'} ne "")); $str .= "\n" if ((exists $Args::args{'case'}) && ($Args::args{'case'} ne "")); $str .= "\n" if ((exists $Args::args{'inv'}) && ($Args::args{'inv'} ne "")); return $str; } ############################### # block ############################### sub check_block { if ((!exists $Args::args{'block'}) || ($Args::args{'block'} !~ /^\d+$/)) { Print::print_check_err( "Invalid block argument (positive numbers only)"); } return 0; } sub get_block { if ($Args::args{'block'} =~ /^(\d+)$/) { return $1; } Print::print_err("Invalid Block"); } ############################### # body ############################### sub check_body { unless (exists $Args::args{'body'}) { Print::print_check_err("Missing body argument"); } unless ($Args::args{'body'} =~ /^$::REG_VNAME$/o) { Print::print_check_err( "Invalid body value (only letters, " . "numbers,-,., and _)"); } return 0; } sub get_body { if ($Args::args{'body'} =~ /^($::REG_VNAME)$/o) { return $1; } Print::print_err("Invalid Body"); } ################################ # Case name ################################ sub check_case { unless (exists $Args::args{'case'}) { Print::print_check_err("Missing case argument"); } unless ($Args::args{'case'} =~ /^$::REG_CASE$/o) { Print::print_check_err( "Invalid case value (letters, num, and symbols only"); } return 0; } sub get_case { if ($Args::args{'case'} =~ /^($::REG_CASE)$/o) { return $1; } Print::print_err("Invalid Case Name"); } ############################### # cell_mode ############################### sub check_cell_mode { if ( (!exists $Args::args{'cell_mode'}) || ($Args::args{'cell_mode'} !~ /^\d$/o)) { Print::print_check_err( "Invalid cell_mode argument (numbers >= 0 only)"); } return 0; } ################################ # dir ################################ sub check_dir { if ( (!exists $Args::args{'dir'}) || ($Args::args{'dir'} =~ /\/\.\.\//) || ($Args::args{'dir'} =~ /\;/)) { Print::print_check_err("Invalid dir argument (valid file path only)"); } return 0; } sub get_dir { if ($Args::args{'dir'} =~ /([^;]*)/o) { my $d = $1; # Remove double slashes $d =~ s/\/\//\//g; return $d; } Print::print_err("Invalid Directory"); } ############################### # dirmode ############################### sub check_dirmode { if ((!exists $Args::args{'dirmode'}) || ($Args::args{'dirmode'} !~ /^\d+$/)) { Print::print_check_err( "Invalid dirmode argument (positive numbers only)"); } return 0; } sub get_dirmode { if ($Args::args{'dirmode'} =~ /^(\d+)$/) { return $1; } Print::print_err("Invalid dirmode"); } ################################ # do_md5 ################################ sub check_do_md5 { if ((!exists $Args::args{'do_md5'}) || ($Args::args{'do_md5'} !~ /^\d+$/)) { Print::print_check_err("Missing do_md5 argument"); } return 0; } sub get_do_md5 { if ($Args::args{'do_md5'} =~ /^\s*(\d+)$/) { return $1; } Print::print_err("Invalid MD5 Flag"); } ################################ # fname ################################ sub check_fname { unless (exists $Args::args{'fname'}) { Print::print_check_err("Missing fname argument"); } unless ($Args::args{'fname'} =~ /^$::REG_FNAME$/o) { Print::print_check_err( "Invalid fname value (only letters, " . "numbers,-,., and _)"); } return 0; } sub get_fname { if ($Args::args{'fname'} =~ /^($::REG_FNAME)$/o) { return "$::host_dir" . "$::DATADIR/$1"; } Print::print_err("Invalid File Name"); } ################################ # fname_mode ################################ sub check_fname_mode { if (!exists $Args::args{'fname_mode'}) { Print::print_check_err("Missing fname_mode argument"); } unless ($Args::args{'fname_mode'} =~ /^\d+$/) { Print::print_check_err("invalid mode: numbers only"); } return 0; } ################################ # fname_rel # Return the relative fname ################################ sub get_fname_rel { if ($Args::args{'fname'} =~ /^($::REG_FNAME)$/o) { return "$::DATADIR/$1"; } Print::print_err("Invalid Relative File Name"); } ############################### # force ############################### sub get_force { if ($Args::args{'force'} =~ /^(\d+)$/) { return $1; } Print::print_err("Invalid Force Flag"); } ################################ # ftype ################################ sub get_ftype_blah { if (exists $Args::args{'ftype'}) { if ($Args::args{'ftype'} =~ /^($::REG_FTYPE)$/o) { return $1; } } if ( (exists $Args::args{'img'}) && (exists $Caseman::vol2ftype{$Args::args{'img'}})) { return $Caseman::vol2ftype{$Args::args{'img'}}; } Print::print_err("Missing ftype value"); } sub check_ftype_blah { unless ( ( (exists $Args::args{'img'}) && (exists $Caseman::vol2ftype{$Args::args{'img'}}) && ($Caseman::vol2ftype{$Args::args{'img'}} =~ /^$::REG_FTYPE$/o) ) || ( (exists $Args::args{'ftype'}) && ($Args::args{'ftype'} =~ /^$::REG_FTYPE$/o)) ) { Print::print_check_err("Missing or invalid ftype value"); } return 0; } ################################ # host # Host for the case ################################ sub check_host { unless (exists $Args::args{'host'}) { Print::print_check_err("Missing host argument"); } unless ($Args::args{'host'} =~ /^$::REG_HOST$/o) { Print::print_check_err("Invalid host value: $Args::args{'host'}"); } return 0; } sub get_host { if ($Args::args{'host'} =~ /^($::REG_HOST)$/o) { return $1; } Print::print_err("Invalid Host"); } ################################ # htype ################################ sub check_htype { if ((!exists $Args::args{'htype'}) || ($Args::args{'htype'} !~ /^\d+$/)) { Print::print_check_err( "Invalid htype argument (positive numbers only)"); } return 0; } sub get_htype { if ($Args::args{'htype'} =~ /^(\d+)$/) { return $1; } Print::print_err("Invalid htype"); } ############################### # ifind # ifind is optional and by default is 0 if not given ############################### sub get_ifind { if (!exists $Args::args{'ifind'}) { return 0; } elsif ($Args::args{'ifind'} =~ /^(\d+)$/) { return $1; } Print::print_err("Invalid ifind flag"); } ############################### # img_path is used when adding images - it is the full path to the # non-evidence locker copy of the image ############################### sub check_img_path { if (!exists $Args::args{'img_path'}) { Print::print_check_err("Missing image (img_path) argument"); } elsif ($Args::args{'img_path'} =~ /^$::REG_IMG_PATH$/o) { # Check for its actual existence Print::print_check_err("Image not found at $Args::args{'img_path'}") unless ( (-e "$Args::args{'img_path'}") || ( (-l "$Args::args{'img_path'}") && (-e readlink "$::host_dir" . "$Args::args{$img}")) ); } else { Print::print_check_err("Invalid image path (only letters, " . "numbers,-,.,_/ and start with /) [$Args::args{'img_path'}]"); } return 0; } sub get_img_path { if ($Args::args{'img_path'} =~ /^($::REG_IMG_PATH)$/o) { return "$1"; } Print::print_err("Invalid Image Path"); } sub check_img_path_wild { if (!exists $Args::args{'img_path'}) { Print::print_check_err("Missing wild image (img_path) argument"); } elsif ($Args::args{'img_path'} !~ /^$::REG_IMG_PATH_WILD$/o) { # IF there is extra white space then remove it and move on if ($Args::args{'img_path'} =~ /^\s*($::REG_IMG_PATH_WILD)\s*$/o) { $Args::args{'img_path'} = $1; return 0; } else { Print::print_check_err("Invalid wild image (img_path) argument"); } } return 0; } sub get_img_path_wild { if ($Args::args{'img_path'} =~ /^($::REG_IMG_PATH_WILD)$/o) { return "$1"; } Print::print_err("Invalid Image Path"); } ############################### # meta ############################### sub check_meta { my $meta = shift; if ( (!exists $Args::args{$meta}) || ($Args::args{$meta} !~ /^$::REG_META$/o)) { Print::print_check_err( "Invalid meta address ($meta) argument (numbers >= 0 only)"); } return 0; } sub get_meta { my $meta = shift; if ($Args::args{$meta} =~ /^($::REG_META)$/o) { return $1; } Print::print_err("Invalid Meta Address"); } ################################ # inv # Investigator ################################ sub check_inv { unless (exists $Args::args{'inv'}) { Print::print_check_err("Missing inv argument"); } unless ($Args::args{'inv'} =~ /^$::REG_INVESTIG$/o) { Print::print_check_err( "Invalid inv value (letters, num, and symbols only"); } return 0; } sub get_inv { if ($Args::args{'inv'} =~ /^($::REG_INVESTIG)$/o) { return $1; } Print::print_err("Invalid Investigator"); } ############################### # len ############################### sub check_len { if ( (!exists $Args::args{'len'}) || ($Args::args{'len'} !~ /^\d+$/) || ($Args::args{'len'} == 0)) { Print::print_check_err("Invalid len argument (positive numbers only)"); } return 0; } sub get_len { if ((exists $Args::args{'len'}) && ($Args::args{'len'} =~ /^(\d+)$/)) { return $1; } # return the default len of 1 if it is not defined return 1; } ############################### # min ############################### sub get_min { if ($Args::args{'min'} =~ /^(\d+)$/) { return $1; } Print::print_err("Invalid Minute"); } ################################ # module ################################ sub check_mod { if ((!exists $Args::args{'mod'}) || ($Args::args{'mod'} !~ /^\d+$/)) { Print::print_check_err( "Invalid Module argument (positive numbers only)"); } return 0; } sub get_mod { if ($Args::args{'mod'} =~ /^(\d+)$/) { return $1; } Print::print_err("Invalid Module"); } ################################ # mnt ############################### sub check_mnt { my $ftype = Args::get_ftype(); if (($ftype eq "dls") || ($ftype eq "swap") || ($ftype eq "raw")) { $Args::args{'mnt'} = $ftype; $Args::enc_args{'mnt'} = $ftype; } elsif (!exists $Args::args{'mnt'}) { # Look it up if it is not found if (exists $Args::args{'img'}) { unless (exists $Caseman::vol2mnt{$Args::args{'img'}}) { Print::print_check_err( "Mounting point not found: $Args::args{'img'}"); } my $mnt = $Caseman::vol2mnt{$Args::args{'img'}}; $Args::args{'mnt'} = $mnt; $Args::enc_args{'mnt'} = Args::url_encode($mnt); } else { Print::print_check_err("Mounting point not found"); } } if ($Args::args{'mnt'} =~ /\/\.\.\//) { Print::print_check_err( "Invalid mount point argument (valid file path only)"); } unless ($Args::args{'mnt'} =~ /^$::REG_MNT$/o) { Print::print_check_err( "Invalid mount point argument (valid file path only)"); } return 0; } sub get_mnt { if ((exists $Args::args{'mnt'}) && ($Args::args{'mnt'} =~ /($::REG_MNT)/o)) { return $1; } Print::print_err("Invalid Mounting Point"); } ################################ # note ################################ sub check_note { if (!exists $Args::args{'note'}) { Print::print_check_err("Missing note argument"); } return 0; } ################# # num_img - adding disk images sub check_num_img { if ((!exists $Args::args{'num_img'}) || ($Args::args{'num_img'} !~ /^\d+$/)) { Print::print_check_err( "Invalid num_img argument (positive numbers only)"); } return 0; } sub get_num_img { if ($Args::args{'num_img'} =~ /^(\d+)$/) { return $1; } Print::print_err("Invalid num_img"); } ############################### # recmode ############################### sub check_recmode { if ((!exists $Args::args{'recmode'}) || ($Args::args{'recmode'} !~ /^\d+$/)) { Print::print_check_err( "Invalid recmode argument (positive numbers only)"); } return 0; } sub get_recmode { if ($Args::args{'recmode'} =~ /^(\d+)$/) { return $1; } Print::print_err("Invalid recmode"); } ################################ # srchidx # # Index for previous keyword search ############################### sub check_srchidx { if ((!exists $Args::args{'srchidx'}) || ($Args::args{'srchidx'} !~ /^\d+$/)) { Print::print_check_err( "Invalid srchidx argument (positive numbers only)"); } return 0; } ############################### # sort ############################### sub check_sort { if ((!exists $Args::args{'sort'}) || ($Args::args{'sort'} !~ /^\d+$/)) { Print::print_check_err("Invalid sort argument (positive numbers only)"); } return 0; } sub get_sort { if ($Args::args{'sort'} =~ /^(\d+)$/) { return $1; } Print::print_err("Invalid sort flag"); } ################################ # st_mon ################################ sub check_st_mon { if ( (exists $Args::args{'st_mon'}) && ($Args::args{'st_mon'} =~ /^(\d\d?)$/)) { if (($1 < 1) || ($1 > 12)) { print("Invalid start month\n"); return 1; } } else { print("Invalid start month\n"); return 1; } } sub get_st_mon { if ($Args::args{'st_mon'} =~ /^(\d\d?)$/) { return $1; } Print::print_err("Invalid Month"); } ################################ # st_year ################################ sub check_st_year { if ( (exists $Args::args{'st_year'}) && ($Args::args{'st_year'} =~ /^(\d\d\d\d?)$/)) { if (($1 < 1970) || ($1 > 2020)) { print("Invalid start year\n"); return 1; } } else { print("Invalid start year\n"); return 1; } } sub get_st_year { if ($Args::args{'st_year'} =~ /^(\d\d\d\d)$/) { return $1; } Print::print_err("Invalid Year"); } ################################ # str # search string ################################ # This should be made more flexible sub check_str { if (!exists $Args::args{'str'}) { Print::print_check_err("Missing string argument"); } return 0; } sub get_str { if ($Args::args{'str'} =~ /^\s*(.*)$/) { return $1; } Print::print_err("Invalid String"); } ############################### # submod # Used by the tab module to identify the actual module ############################### sub check_submod { if ((!exists $Args::args{'submod'}) || ($Args::args{'submod'} !~ /^\d+$/)) { Print::print_check_err( "Invalid sub-mode argument (positive numbers only)"); } return 0; } sub get_submod { if ($Args::args{'submod'} =~ /^(\d+)$/) { return $1; } Print::print_err("Invalid sub-mode"); } ################################ # tl ############################### sub check_tl { if ((!exists $Args::args{'tl'}) || ($Args::args{'tl'} !~ /^$::REG_VNAME$/)) { Print::print_check_err( "Invalid timeline argument (positive numbers only)"); } return 0; } sub get_tl { if ($Args::args{'tl'} =~ /^($::REG_VNAME)$/o) { return $1; } Print::print_err("Invalid Timeline"); } ################################ # ts # time skew ################################ sub check_ts { if ((!exists $Args::args{'ts'}) || ($Args::args{'ts'} !~ /^$::REG_SKEW$/o)) { Print::print_check_err("Missing time skew argument"); } return 0; } sub get_ts { if ($Args::args{'ts'} =~ /^\s*($::REG_SKEW)$/o) { return $1; } Print::print_err("Invalid Time Skew"); } ################################ # tz # timezone ################################ sub check_tz { if ( (!exists $Args::args{'tz'}) || ($Args::args{'tz'} !~ /^$::REG_ZONE_ARGS$/o)) { Print::print_check_err("Missing time zone argument"); } return 0; } sub get_tz { if ($Args::args{'tz'} =~ /^($::REG_ZONE_ARGS)$/o) { return $1; } Print::print_err("Invalid Timezone"); } ################################ # unitsize ################################ sub get_unitsize { my $vol = Args::get_vol('vol'); my $ftype = $Caseman::vol2ftype{$vol}; my $dcat_out; if ($ftype eq 'dls') { if (exists $Caseman::mod2vol{$vol}) { my $orig = $Caseman::mod2vol{$vol}; my $img = $Caseman::vol2path{$orig}; my $offset = $Caseman::vol2start{$orig}; my $imgtype = $Caseman::vol2itype{$orig}; local *OUT; Exec::exec_pipe(*OUT, "'$::TSKDIR/dcat' -f $Caseman::vol2ftype{$orig} -s -o $offset -i $imgtype $img" ); $dcat_out = ; close(OUT); } # We don't have the original image, so just set the size to 512 else { return 512; } } elsif ($ftype eq 'swap') { return 4096; } elsif ($ftype eq 'raw') { return 512; } elsif ($Caseman::vol2cat{$vol} eq 'disk') { return 512; } else { my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; local *OUT; Exec::exec_pipe(*OUT, "'$::TSKDIR/dcat' -f $ftype -s -o $offset -i $imgtype $img"); $dcat_out = ; close(OUT); } $dcat_out = "Error getting unit size" if ((!defined $dcat_out) || ($dcat_out eq "")); if ($dcat_out =~ /(\d+): Size of Addressable Unit/) { return $1; } else { Print::print_err("Error identifying block size (dcat -s output)
\n" . "$dcat_out
\n"); } } ################################ # View - subset of module ################################ sub check_view { if ((!exists $Args::args{'view'}) || ($Args::args{'view'} !~ /^\d+$/)) { Print::print_check_err("Invalid View argument (positive numbers only)"); } return 0; } sub get_view { if ($Args::args{'view'} =~ /^(\d+)$/) { return $1; } Print::print_err("Invalid View"); } ############################### # We don't allow much for the volume because this is an argument to # the TSK programs. We keep these files only in one # directory and for easy/simple security only allow basic names # Symbolic links are allowed if these simple names are not desired # # Allowed values are A-Za-z0-9_-. # # The argument is the name of the image ############################### sub check_vol { my $vol = shift; if ((!exists $Args::args{$vol}) || ($Args::args{$vol} !~ /^$::REG_VNAME$/)) { Print::print_check_err( "Invalid volume ($vol) argument (name and number only)"); } return 0; } sub get_vol { my $vol = shift; if ($Args::args{$vol} =~ /^($::REG_VNAME)$/) { return $1; } Print::print_err("Invalid volume ($vol)"); } 1;