1*b1cdbd2cSJim Jagielski: 2*b1cdbd2cSJim Jagielskieval 'exec perl -wS $0 ${1+"$@"}' 3*b1cdbd2cSJim Jagielski if 0; 4*b1cdbd2cSJim Jagielski#************************************************************** 5*b1cdbd2cSJim Jagielski# 6*b1cdbd2cSJim Jagielski# Licensed to the Apache Software Foundation (ASF) under one 7*b1cdbd2cSJim Jagielski# or more contributor license agreements. See the NOTICE file 8*b1cdbd2cSJim Jagielski# distributed with this work for additional information 9*b1cdbd2cSJim Jagielski# regarding copyright ownership. The ASF licenses this file 10*b1cdbd2cSJim Jagielski# to you under the Apache License, Version 2.0 (the 11*b1cdbd2cSJim Jagielski# "License"); you may not use this file except in compliance 12*b1cdbd2cSJim Jagielski# with the License. You may obtain a copy of the License at 13*b1cdbd2cSJim Jagielski# 14*b1cdbd2cSJim Jagielski# http://www.apache.org/licenses/LICENSE-2.0 15*b1cdbd2cSJim Jagielski# 16*b1cdbd2cSJim Jagielski# Unless required by applicable law or agreed to in writing, 17*b1cdbd2cSJim Jagielski# software distributed under the License is distributed on an 18*b1cdbd2cSJim Jagielski# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19*b1cdbd2cSJim Jagielski# KIND, either express or implied. See the License for the 20*b1cdbd2cSJim Jagielski# specific language governing permissions and limitations 21*b1cdbd2cSJim Jagielski# under the License. 22*b1cdbd2cSJim Jagielski# 23*b1cdbd2cSJim Jagielski#************************************************************** 24*b1cdbd2cSJim Jagielski 25*b1cdbd2cSJim Jagielski 26*b1cdbd2cSJim Jagielski 27*b1cdbd2cSJim Jagielskiuse strict; 28*b1cdbd2cSJim Jagielskiuse Getopt::Long; 29*b1cdbd2cSJim Jagielski 30*b1cdbd2cSJim Jagielskimy $debug = 0; 31*b1cdbd2cSJim Jagielskimy $max_files = 20; # sign $max_files with one command line 32*b1cdbd2cSJim Jagielski 33*b1cdbd2cSJim Jagielski#### globals ##### 34*b1cdbd2cSJim Jagielskimy $myname = ""; 35*b1cdbd2cSJim Jagielskimy $opt_dir = ""; 36*b1cdbd2cSJim Jagielskimy $opt_exclude = ""; # file with a list of not signable dll and exe files 37*b1cdbd2cSJim Jagielskimy $opt_verbose = 0; 38*b1cdbd2cSJim Jagielskimy $opt_help = 0; 39*b1cdbd2cSJim Jagielskimy $opt_log = ""; # for logging 40*b1cdbd2cSJim Jagielskimy $opt_pass = ""; # password for signing 41*b1cdbd2cSJim Jagielskimy $opt_pfxfile = ""; # Personal Information Exchange file 42*b1cdbd2cSJim Jagielskimy $opt_timestamp_url = ""; # timestamp url 43*b1cdbd2cSJim Jagielskimy %exclude_files = (); # list of not signable dll and exe files 44*b1cdbd2cSJim Jagielskimy $signtool = "signtool.exe sign"; 45*b1cdbd2cSJim Jagielskimy @args = (); 46*b1cdbd2cSJim Jagielskimy @files_to_sign = (); 47*b1cdbd2cSJim Jagielski 48*b1cdbd2cSJim Jagielski#### main ##### 49*b1cdbd2cSJim Jagielski$myname = script_id(); 50*b1cdbd2cSJim Jagielskiif ( $#ARGV < 2 ) { 51*b1cdbd2cSJim Jagielski usage(); 52*b1cdbd2cSJim Jagielski exit(1); 53*b1cdbd2cSJim Jagielski} 54*b1cdbd2cSJim Jagielski@args = parse_options(); 55*b1cdbd2cSJim Jagielskiget_exclude_files(); 56*b1cdbd2cSJim Jagielski@files_to_sign = get_files(\@args); 57*b1cdbd2cSJim Jagielskiif ( $opt_log ) { # logging 58*b1cdbd2cSJim Jagielski open(LOG,">$opt_log") || die "Can't open log file $opt_log\n"; 59*b1cdbd2cSJim Jagielski} 60*b1cdbd2cSJim Jagielskisign_files(\@files_to_sign); 61*b1cdbd2cSJim Jagielskiclose LOG if ($opt_log); # logging 62*b1cdbd2cSJim Jagielskiexit 0; 63*b1cdbd2cSJim Jagielski 64*b1cdbd2cSJim Jagielski 65*b1cdbd2cSJim Jagielski#### subroutines #### 66*b1cdbd2cSJim Jagielski 67*b1cdbd2cSJim Jagielskisub script_id 68*b1cdbd2cSJim Jagielski{ 69*b1cdbd2cSJim Jagielski ( my $script_name = $0 ) =~ s/^.*[\\\/]([\w\.]+)$/$1/; 70*b1cdbd2cSJim Jagielski 71*b1cdbd2cSJim Jagielski my $script_rev; 72*b1cdbd2cSJim Jagielski my $id_str = ' $Revision$ '; 73*b1cdbd2cSJim Jagielski $id_str =~ /Revision:\s+(\S+)\s+\$/ 74*b1cdbd2cSJim Jagielski ? ($script_rev = $1) : ($script_rev = "-"); 75*b1cdbd2cSJim Jagielski# print "\n$script_name -- version: $script_rev\n"; 76*b1cdbd2cSJim Jagielski return $script_name; 77*b1cdbd2cSJim Jagielski} 78*b1cdbd2cSJim Jagielski 79*b1cdbd2cSJim Jagielski############################################################################ 80*b1cdbd2cSJim Jagielskisub parse_options #09.07.2007 08:13 81*b1cdbd2cSJim Jagielski############################################################################ 82*b1cdbd2cSJim Jagielski{ 83*b1cdbd2cSJim Jagielski # e exclude list file 84*b1cdbd2cSJim Jagielski # v verbose 85*b1cdbd2cSJim Jagielski my $filelist_filename = undef; 86*b1cdbd2cSJim Jagielski my $success = GetOptions('h' => \$opt_help, 87*b1cdbd2cSJim Jagielski 'd=s' => \$opt_dir, 'e=s'=>\$opt_exclude, 'f=s'=>\$opt_pfxfile, 'l=s'=>\$opt_log, 88*b1cdbd2cSJim Jagielski 'p=s'=>\$opt_pass,'v'=>\$opt_verbose, 't=s'=>\$opt_timestamp_url, 'i=s'=>\$filelist_filename); 89*b1cdbd2cSJim Jagielski if ( !$success || $opt_help ) { 90*b1cdbd2cSJim Jagielski usage(); 91*b1cdbd2cSJim Jagielski exit(1); 92*b1cdbd2cSJim Jagielski } 93*b1cdbd2cSJim Jagielski if ( !$opt_exclude || !$opt_pfxfile || !$opt_pass || !$opt_timestamp_url) { 94*b1cdbd2cSJim Jagielski print "ERROR: Parameter missing!\n!"; 95*b1cdbd2cSJim Jagielski usage(); 96*b1cdbd2cSJim Jagielski exit(1); 97*b1cdbd2cSJim Jagielski } 98*b1cdbd2cSJim Jagielski 99*b1cdbd2cSJim Jagielski # Read the names of files to sign from the given file. 100*b1cdbd2cSJim Jagielski die "no list of files given" unless defined $filelist_filename; 101*b1cdbd2cSJim Jagielski open my $in, $filelist_filename; 102*b1cdbd2cSJim Jagielski my @filelist = (); 103*b1cdbd2cSJim Jagielski while (<$in>) 104*b1cdbd2cSJim Jagielski { 105*b1cdbd2cSJim Jagielski chomp($_); 106*b1cdbd2cSJim Jagielski push @filelist, $_; 107*b1cdbd2cSJim Jagielski } 108*b1cdbd2cSJim Jagielski return @filelist; 109*b1cdbd2cSJim Jagielski} ##parse_options 110*b1cdbd2cSJim Jagielski 111*b1cdbd2cSJim Jagielski############################################################################ 112*b1cdbd2cSJim Jagielskisub get_exclude_files #09.07.2007 10:12 113*b1cdbd2cSJim Jagielski############################################################################ 114*b1cdbd2cSJim Jagielski{ 115*b1cdbd2cSJim Jagielski if ( -e $opt_exclude ) { 116*b1cdbd2cSJim Jagielski # get data from cache file 117*b1cdbd2cSJim Jagielski open( IN, "<$opt_exclude") || die "Can't open exclude file $opt_exclude\n"; 118*b1cdbd2cSJim Jagielski while ( my $line = <IN> ) { 119*b1cdbd2cSJim Jagielski chomp($line); 120*b1cdbd2cSJim Jagielski $exclude_files{$line} = 1; # fill hash 121*b1cdbd2cSJim Jagielski print "$line - $exclude_files{$line}\n" if ($debug); 122*b1cdbd2cSJim Jagielski } 123*b1cdbd2cSJim Jagielski } else 124*b1cdbd2cSJim Jagielski { 125*b1cdbd2cSJim Jagielski print_error("Can't open $opt_exclude file!\n"); 126*b1cdbd2cSJim Jagielski } 127*b1cdbd2cSJim Jagielski} ##get_exclude_files 128*b1cdbd2cSJim Jagielski 129*b1cdbd2cSJim Jagielski############################################################################ 130*b1cdbd2cSJim Jagielskisub get_files #10.07.2007 10:19 131*b1cdbd2cSJim Jagielski############################################################################ 132*b1cdbd2cSJim Jagielski { 133*b1cdbd2cSJim Jagielski use File::Basename; 134*b1cdbd2cSJim Jagielski my $target = shift; 135*b1cdbd2cSJim Jagielski my $file_pattern; 136*b1cdbd2cSJim Jagielski my $file; 137*b1cdbd2cSJim Jagielski my @files = (); 138*b1cdbd2cSJim Jagielski print "\n"; 139*b1cdbd2cSJim Jagielski foreach $file_pattern ( @$target ) 140*b1cdbd2cSJim Jagielski { 141*b1cdbd2cSJim Jagielski print "Files: $file_pattern\n"; 142*b1cdbd2cSJim Jagielski foreach $file ( glob( $file_pattern ) ) 143*b1cdbd2cSJim Jagielski { 144*b1cdbd2cSJim Jagielski my $lib = File::Basename::basename $file; 145*b1cdbd2cSJim Jagielski if ( ! $exclude_files{$lib} ) { 146*b1cdbd2cSJim Jagielski push @files,$file; 147*b1cdbd2cSJim Jagielski } 148*b1cdbd2cSJim Jagielski else 149*b1cdbd2cSJim Jagielski { 150*b1cdbd2cSJim Jagielski print "exclude=$lib\n" if ($opt_verbose); 151*b1cdbd2cSJim Jagielski } 152*b1cdbd2cSJim Jagielski } 153*b1cdbd2cSJim Jagielski } 154*b1cdbd2cSJim Jagielski print "\n"; 155*b1cdbd2cSJim Jagielski return @files; 156*b1cdbd2cSJim Jagielski} ##get_files 157*b1cdbd2cSJim Jagielski 158*b1cdbd2cSJim Jagielski############################################################################ 159*b1cdbd2cSJim Jagielskisub sign_files #09.07.2007 10:36 160*b1cdbd2cSJim Jagielski############################################################################ 161*b1cdbd2cSJim Jagielski{ 162*b1cdbd2cSJim Jagielski my $files_to_sign = shift; 163*b1cdbd2cSJim Jagielski my $commandline_base = ""; # contains whole stuff without the file name 164*b1cdbd2cSJim Jagielski my $file = ""; 165*b1cdbd2cSJim Jagielski my $result = ""; 166*b1cdbd2cSJim Jagielski 167*b1cdbd2cSJim Jagielski print_error("Can't open PFX file: $opt_pfxfile\n") if ( ! -e $opt_pfxfile ); 168*b1cdbd2cSJim Jagielski print_error("Password is empty\n") if ( !$opt_pass ); 169*b1cdbd2cSJim Jagielski if ( $opt_pass =~ /\.exe$/ ) { 170*b1cdbd2cSJim Jagielski # get password by tool 171*b1cdbd2cSJim Jagielski open(PIPE, "$opt_pass 2>&1 |") || die "Can't open PIPE!\n"; 172*b1cdbd2cSJim Jagielski my $pass = <PIPE>; 173*b1cdbd2cSJim Jagielski close PIPE; 174*b1cdbd2cSJim Jagielski print_error("Can't get password!\n") if ( !$pass ); # exit here 175*b1cdbd2cSJim Jagielski $opt_pass = $pass; 176*b1cdbd2cSJim Jagielski } 177*b1cdbd2cSJim Jagielski $signtool .= " -v" if ($opt_verbose); 178*b1cdbd2cSJim Jagielski $commandline_base = $signtool . " " . "-f $opt_pfxfile -p $opt_pass -t $opt_timestamp_url"; 179*b1cdbd2cSJim Jagielski 180*b1cdbd2cSJim Jagielski # Here switch between: 181*b1cdbd2cSJim Jagielski # one command line for muliple files (all doesn't work, too much) / for each file one command line 182*b1cdbd2cSJim Jagielski if ( $max_files > 1 ) { 183*b1cdbd2cSJim Jagielski exec_multi_sign($files_to_sign, $commandline_base); 184*b1cdbd2cSJim Jagielski } else 185*b1cdbd2cSJim Jagielski { 186*b1cdbd2cSJim Jagielski exec_single_sign($files_to_sign, $commandline_base); 187*b1cdbd2cSJim Jagielski } 188*b1cdbd2cSJim Jagielski} ##sign_files 189*b1cdbd2cSJim Jagielski 190*b1cdbd2cSJim Jagielski############################################################################ 191*b1cdbd2cSJim Jagielskisub exec_single_sign #11.07.2007 09:05 192*b1cdbd2cSJim Jagielski############################################################################ 193*b1cdbd2cSJim Jagielski{ 194*b1cdbd2cSJim Jagielski my $files_to_sign = shift; 195*b1cdbd2cSJim Jagielski my $commandline_base = shift; # contains whole stuff without the file name 196*b1cdbd2cSJim Jagielski my $file = ""; 197*b1cdbd2cSJim Jagielski my $commandline = ""; 198*b1cdbd2cSJim Jagielski 199*b1cdbd2cSJim Jagielski foreach $file (@$files_to_sign) 200*b1cdbd2cSJim Jagielski { 201*b1cdbd2cSJim Jagielski $commandline = $commandline_base . " $file"; 202*b1cdbd2cSJim Jagielski print "$commandline\n" if ($debug); 203*b1cdbd2cSJim Jagielski execute($commandline); 204*b1cdbd2cSJim Jagielski } #foreach 205*b1cdbd2cSJim Jagielski} ##exec_single_sign 206*b1cdbd2cSJim Jagielski 207*b1cdbd2cSJim Jagielski############################################################################ 208*b1cdbd2cSJim Jagielskisub exec_multi_sign #11.07.2007 08:56 209*b1cdbd2cSJim Jagielski############################################################################ 210*b1cdbd2cSJim Jagielski { 211*b1cdbd2cSJim Jagielski # sign multiple file with one command line 212*b1cdbd2cSJim Jagielski my $files_to_sign = shift; 213*b1cdbd2cSJim Jagielski my $commandline_base = shift; # contains whole stuff without the file name 214*b1cdbd2cSJim Jagielski my $commandline = $commandline_base; # contains stuff which will be executed 215*b1cdbd2cSJim Jagielski my $file = ""; 216*b1cdbd2cSJim Jagielski my $counter = 0; 217*b1cdbd2cSJim Jagielski 218*b1cdbd2cSJim Jagielski foreach $file (@$files_to_sign) 219*b1cdbd2cSJim Jagielski { 220*b1cdbd2cSJim Jagielski $commandline .= " $file"; 221*b1cdbd2cSJim Jagielski ++$counter; 222*b1cdbd2cSJim Jagielski if ( $counter >= $max_files ) { 223*b1cdbd2cSJim Jagielski execute($commandline); 224*b1cdbd2cSJim Jagielski $counter = 0; # reset counter 225*b1cdbd2cSJim Jagielski $commandline = $commandline_base; # reset command line 226*b1cdbd2cSJim Jagielski } 227*b1cdbd2cSJim Jagielski } 228*b1cdbd2cSJim Jagielski execute($commandline) if ($counter > 0); 229*b1cdbd2cSJim Jagielski} ##exec_multi_sign 230*b1cdbd2cSJim Jagielski 231*b1cdbd2cSJim Jagielski############################################################################ 232*b1cdbd2cSJim Jagielskisub execute #11.07.2007 10:02 233*b1cdbd2cSJim Jagielski############################################################################ 234*b1cdbd2cSJim Jagielski{ 235*b1cdbd2cSJim Jagielski my $commandline = shift; 236*b1cdbd2cSJim Jagielski my $result = ""; 237*b1cdbd2cSJim Jagielski 238*b1cdbd2cSJim Jagielski print "$commandline\n" if ($debug); 239*b1cdbd2cSJim Jagielski open(PIPE, "$commandline 2>&1 |") || die "Error: Cant open pipe!\n"; 240*b1cdbd2cSJim Jagielski while ( $result = <PIPE> ) { 241*b1cdbd2cSJim Jagielski print LOG "$result" if ($opt_log); # logging 242*b1cdbd2cSJim Jagielski if ( $result =~ /SignTool Error\:/ ) { 243*b1cdbd2cSJim Jagielski close PIPE; 244*b1cdbd2cSJim Jagielski print_error( "$result\n" ); 245*b1cdbd2cSJim Jagielski } # if error 246*b1cdbd2cSJim Jagielski } # while 247*b1cdbd2cSJim Jagielski close PIPE; 248*b1cdbd2cSJim Jagielski} ##execute 249*b1cdbd2cSJim Jagielski 250*b1cdbd2cSJim Jagielski############################################################################ 251*b1cdbd2cSJim Jagielskisub print_error #09.07.2007 11:21 252*b1cdbd2cSJim Jagielski############################################################################ 253*b1cdbd2cSJim Jagielski { 254*b1cdbd2cSJim Jagielski my $text = shift; 255*b1cdbd2cSJim Jagielski print "ERROR: $text\n"; 256*b1cdbd2cSJim Jagielski print LOG "ERROR: $text\n" if ($opt_log); # logging 257*b1cdbd2cSJim Jagielski close LOG if ($opt_log); # logging 258*b1cdbd2cSJim Jagielski exit(1); 259*b1cdbd2cSJim Jagielski} ##print_error 260*b1cdbd2cSJim Jagielski 261*b1cdbd2cSJim Jagielski############################################################################ 262*b1cdbd2cSJim Jagielskisub usage #09.07.2007 08:39 263*b1cdbd2cSJim Jagielski############################################################################ 264*b1cdbd2cSJim Jagielski { 265*b1cdbd2cSJim Jagielski print "Usage:\t $myname <-e filename> <-f filename> <-p password> <-t timestamp> <-i filename> [-l filename] [-v]\n"; 266*b1cdbd2cSJim Jagielski print "Options:\n"; 267*b1cdbd2cSJim Jagielski print "\t -e filename\t\t\tFile which contains a list of files which don't have to be signed.\n"; 268*b1cdbd2cSJim Jagielski print "Mandatory.\n"; 269*b1cdbd2cSJim Jagielski print "\t -f pfx_filename\t\t\"Personal Information Exchange\" file. "; 270*b1cdbd2cSJim Jagielski print "Mandatory.\n"; 271*b1cdbd2cSJim Jagielski print "\t -p password\t\t\tPassword for \"Personal Information Exchange\" file. Mandatory.\n"; 272*b1cdbd2cSJim Jagielski print "\t -t timestamp\t\t\tTimestamp URL e.g. \"http://timestamp.verisign.com/scripts/timstamp.dll\"\n"; 273*b1cdbd2cSJim Jagielski print "\t -i filename\t\t\tName of the file that contains the names of files to sign.\"\n"; 274*b1cdbd2cSJim Jagielski print "\t\t\t\t\tMandatory.\n"; 275*b1cdbd2cSJim Jagielski print "\t -l log_filename\t\tFile for logging.\n"; 276*b1cdbd2cSJim Jagielski print "\t -v\t\t\t\tVerbose.\n"; 277*b1cdbd2cSJim Jagielski} ##usage 278