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