xref: /trunk/main/postprocess/signing/signing.pl (revision c966c2767fb7824758cc9ea4cc4af5e395cd580d)
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 $success = GetOptions('h' => \$opt_help,
86         'd=s' => \$opt_dir, 'e=s'=>\$opt_exclude, 'f=s'=>\$opt_pfxfile, 'l=s'=>\$opt_log,
87         'p=s'=>\$opt_pass,'v'=>\$opt_verbose, 't=s'=>\$opt_timestamp_url);
88    if ( !$success || $opt_help ) {
89        usage();
90        exit(1);
91    }
92    if ( !$opt_exclude || !$opt_pfxfile || !$opt_pass || !$opt_timestamp_url) {
93        print "ERROR: Parameter missing!\n!";
94        usage();
95        exit(1);
96    }
97    return @ARGV;
98}   ##parse_options
99
100############################################################################
101sub get_exclude_files       #09.07.2007 10:12
102############################################################################
103{
104    if ( -e $opt_exclude ) {
105            # get data from cache file
106            open( IN, "<$opt_exclude") || die "Can't open exclude file $opt_exclude\n";
107            while ( my $line = <IN> ) {
108            chomp($line);
109            $exclude_files{$line} = 1;          # fill hash
110            print "$line - $exclude_files{$line}\n" if ($debug);
111            }
112        } else
113        {
114            print_error("Can't open $opt_exclude file!\n");
115        }
116}   ##get_exclude_files
117
118############################################################################
119sub get_files       #10.07.2007 10:19
120############################################################################
121 {
122    use File::Basename;
123    my $target = shift;
124    my $file_pattern;
125    my $file;
126    my @files = ();
127    print "\n";
128    foreach $file_pattern ( @$target )
129    {
130        print "Files: $file_pattern\n";
131        foreach $file ( glob( $file_pattern ) )
132        {
133            my $lib = File::Basename::basename $file;
134            if ( ! $exclude_files{$lib} ) {
135                push @files,$file;
136            }
137            else
138            {
139                print "exclude=$lib\n" if ($opt_verbose);
140            }
141        }
142    }
143    print "\n";
144    return @files;
145}   ##get_files
146
147############################################################################
148sub sign_files      #09.07.2007 10:36
149############################################################################
150{
151    my $files_to_sign = shift;
152    my $commandline_base = ""; # contains whole stuff without the file name
153    my $file = "";
154    my $result = "";
155
156    print_error("Can't open PFX file: $opt_pfxfile\n") if ( ! -e $opt_pfxfile );
157    print_error("Password is empty\n") if ( !$opt_pass );
158    if ( $opt_pass =~ /\.exe$/ ) {
159        # get password by tool
160        open(PIPE, "$opt_pass 2>&1 |") || die "Can't open PIPE!\n";
161        my $pass = <PIPE>;
162        close PIPE;
163        print_error("Can't get password!\n") if ( !$pass ); # exit here
164        $opt_pass = $pass;
165    }
166    $signtool .= " -v" if ($opt_verbose);
167    $commandline_base = $signtool . " " . "-f $opt_pfxfile -p $opt_pass -t $opt_timestamp_url";
168
169    # Here switch between:
170    # one command line for muliple files (all doesn't work, too much) / for each file one command line
171    if ( $max_files > 1 ) {
172        exec_multi_sign($files_to_sign, $commandline_base);
173    } else
174    {
175        exec_single_sign($files_to_sign, $commandline_base);
176    }
177}   ##sign_files
178
179############################################################################
180sub exec_single_sign        #11.07.2007 09:05
181############################################################################
182{
183    my $files_to_sign    = shift;
184    my $commandline_base = shift;                 # contains whole stuff without the file name
185    my $file = "";
186    my $commandline = "";
187
188    foreach $file (@$files_to_sign)
189    {
190        $commandline = $commandline_base . " $file";
191        print "$commandline\n" if ($debug);
192        execute($commandline);
193    } #foreach
194}   ##exec_single_sign
195
196############################################################################
197sub exec_multi_sign     #11.07.2007 08:56
198############################################################################
199 {
200    # sign multiple file with one command line
201    my $files_to_sign    = shift;
202    my $commandline_base = shift;                 # contains whole stuff without the file name
203    my $commandline = $commandline_base;          # contains stuff which will be executed
204    my $file = "";
205    my $counter = 0;
206
207    foreach $file (@$files_to_sign)
208    {
209        $commandline .= " $file";
210        ++$counter;
211        if ( $counter >= $max_files ) {
212            execute($commandline);
213            $counter = 0;                        # reset counter
214            $commandline = $commandline_base;    # reset command line
215        }
216    }
217    execute($commandline) if ($counter > 0);
218}   ##exec_multi_sign
219
220############################################################################
221sub execute     #11.07.2007 10:02
222############################################################################
223{
224    my $commandline = shift;
225    my $result = "";
226
227    print "$commandline\n" if ($debug);
228    open(PIPE, "$commandline 2>&1 |") || die "Error: Cant open pipe!\n";
229    while ( $result = <PIPE> ) {
230        print LOG "$result" if ($opt_log);        # logging
231        if ( $result =~ /SignTool Error\:/ ) {
232            close PIPE;
233            print_error( "$result\n" );
234        } # if error
235    } # while
236    close PIPE;
237}   ##execute
238
239############################################################################
240sub print_error     #09.07.2007 11:21
241############################################################################
242 {
243    my $text = shift;
244    print "ERROR: $text\n";
245    print LOG "ERROR: $text\n" if ($opt_log);        # logging
246    close LOG if ($opt_log);                         # logging
247    exit(1);
248}   ##print_error
249
250############################################################################
251sub usage       #09.07.2007 08:39
252############################################################################
253 {
254    print "Usage:\t $myname <-e filename> <-f filename> <-p password> <-t timestamp> [-l filename] [-v] <file[list]> \n";
255    print "Options:\n";
256    print "\t -e filename\t\t\tFile which contains a list of files which don't have to be signed.\n";
257    print                            "Mandatory.\n";
258    print "\t -f pfx_filename\t\t\"Personal Information Exchange\" file. ";
259    print                            "Mandatory.\n";
260    print "\t -p password\t\t\tPassword for \"Personal Information Exchange\" file. Mandatory.\n";
261    print "\t -t timestamp\t\t\tTimestamp URL e.g. \"http://timestamp.verisign.com/scripts/timstamp.dll\"\n";
262    print "\t\t\t\t\tMandatory.\n";
263    print "\t -l log_filename\t\tFile for logging.\n";
264    print "\t -v\t\t\t\tVerbose.\n";
265}   ##usage
266
267
268
269
270