8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / tools / codesign / signit.pl
bloba3fe4f1fe7b3bdcf18964fa70fa3f4ef32948bf2
1 #!/usr/perl5/bin/perl
3 # CDDL HEADER START
5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License (the "License").
7 # You may not use this file except in compliance with the License.
9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 # or http://www.opensolaris.org/os/licensing.
11 # See the License for the specific language governing permissions
12 # and limitations under the License.
14 # When distributing Covered Code, include this CDDL HEADER in each
15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 # If applicable, add the following below this CDDL HEADER, with the
17 # fields enclosed by brackets "[]" replaced with your own identifying
18 # information: Portions Copyright [yyyy] [name of copyright owner]
20 # CDDL HEADER END
23 # ident "%Z%%M% %I% %E% SMI"
25 # Copyright 2007 Sun Microsystems, Inc. All rights reserved.
26 # Use is subject to license terms.
29 # signit [-q] [-i dir][-o dir] [-l user]
31 # Client program for use with code signing server.
32 # Reads a list of signing credential names and file pathnames
33 # from standard input. Each file is read from the input directory,
34 # sent to the signing server, signed with the specified credential,
35 # and written to the output directory.
37 # Options:
38 # -q quiet operation: avoid printing files successfully signed
39 # -i dir input directory (defaults to current dir)
40 # -o dir output directory (defautls to input dir)
41 # -l user user account on signing server (defaults to current user)
43 # The CODESIGN_SERVER environment variable can be used to
44 # specify the hostname or IP address of the signing server
45 # (defaults to quill.sfbay).
47 use strict;
48 use Cwd;
49 use File::Temp 'tempdir';
50 use Getopt::Std;
51 use IPC::Open2;
54 # Global variables
56 my ($Indir, $Outdir); # Input and output directories (may be the same)
57 my $Server; # Signing server hostname
58 my $Quiet; # Suppress printing each file successfully signed
59 my ($pid); # Process id for ssh client
60 my @cred_rules; # Array of path prefixes and credentials to use
61 my $Tmpdir = tempdir(CLEANUP => 1); # Temporary directory
62 my $Warnings = 0; # Count of warnings returned
66 # Main program
69 $Server = $ENV{CODESIGN_SERVER} || "quill.sfbay";
71 # Get command-line arguments
72 our($opt_c, $opt_i, $opt_o, $opt_l, $opt_q);
73 if (!getopts("i:o:c:l:q")) {
74 die "Usage: $0 [-i dir] [-o dir] [-l user]\n";
76 $Quiet = $opt_q;
78 # Get input/output directories
79 $Indir = $opt_i || getcwd(); # default to current dir
80 $Outdir = $opt_o || $Indir; # default to input dir
81 $Indir = getcwd() . "/$Indir" if (substr($Indir, 0, 1) ne "/");
82 $Outdir = getcwd() . "/$Outdir" if (substr($Outdir, 0, 1) ne "/");
84 # Ignore SIGPIPE to allow proper error messages
85 $SIG{PIPE} = 'IGNORE';
87 # Create ssh connection to server
88 my(@args);
89 if (defined($opt_l)) {
90 push @args, "-l", $opt_l;
92 push @args, "-s", $Server, "codesign";
93 $pid = open2(*SRV_OUT, *SRV_IN, "/usr/bin/ssh", @args) or
94 die "ERROR Connection to server $Server failed\n";
95 select(SRV_IN); $| = 1; select(STDOUT); # unbuffered writes
97 # Sign each file with the specified credential
98 chdir($Indir);
99 while (<>) {
100 my ($cred, $path) = split;
102 sign_file($cred, $path);
104 exit($Warnings > 0);
107 # END()
109 # Clean up after normal or abnormal exit.
111 sub END {
112 my $old_status = $?;
114 $? = 0;
115 close(SRV_IN);
116 close(SRV_OUT);
117 waitpid($pid, 0) if ($pid);
118 if ($?) {
119 print STDERR "ERROR Connection to server $Server failed\n";
120 $? = 1;
122 $? = $old_status if ($? == 0);
126 # debug(msg)
128 # Print debug message to standard error.
130 sub debug {
131 print STDERR "### @_";
135 # check_response(str)
137 # Validate response from server. Print messages for warnings or errors,
138 # and exit in the case of an error. If the response indicates a successful
139 # signing operation, return the size of the output data.
141 sub check_response {
142 my ($str) = @_;
144 if ($str =~ /^OK SIGN (\d+)/) {
145 return ($1);
147 elsif ($str =~ /^OK/) {
148 return (0);
150 elsif ($str =~ /^WARNING/) {
151 print STDERR $str;
152 $Warnings++;
153 return (-1);
155 elsif ($str =~ /^ERROR/) {
156 print STDERR $str;
157 exit(1);
159 else {
160 printf STDERR "ERROR Protocol failure (%d)\n", length($str);
161 exit(1);
166 # sign_file(credential, filename)
168 # Send the file to the server for signing. Package the file into a
169 # ZIP archive, send to the server, and extract the ZIP archive that
170 # is returned. The input ZIP archive always contains a single file,
171 # but the returned archive may contain one or more files.
173 sub sign_file {
174 my ($cred, $path) = @_;
175 my ($res, $size);
177 $path =~ s:^\./::g; # remove leading "./"
178 unlink("$Tmpdir/in.zip");
179 system("cd $Indir; /usr/bin/zip -q $Tmpdir/in.zip $path");
181 sendfile("$Tmpdir/in.zip", "$cred $path") || return;
183 $res = <SRV_OUT>;
184 $size = check_response($res);
185 if ($size > 0) {
186 recvfile("$Tmpdir/out.zip", $size) || return;
188 if (system("cd $Outdir; /usr/bin/unzip -qo $Tmpdir/out.zip")) {
189 $Warnings++;
190 } else {
191 print "$cred\t$path\n" unless $Quiet;
197 # sendfile(file, args)
199 # Send a ZIP archive file to the signing server. This involves
200 # sending a SIGN command with the given arguments, followed by
201 # the contents of the archive itself.
203 sub sendfile {
204 my ($file, $args) = @_;
205 my ($size, $bytes);
207 $size = -s $file;
208 print SRV_IN "SIGN $size $args\n";
209 if (!open(F, "<$file")) {
210 print STDERR "$file: $!\n";
211 return (0);
213 read(F, $bytes, $size);
214 close(F);
215 if (!syswrite(SRV_IN, $bytes, $size)) {
216 print STDERR "Can't send to server: $!\n";
217 return (0);
219 return (1);
223 # recvfile(file, size)
225 # Receive a ZIP archive from the signing server. The caller
226 # provides the size argument previously obtained from the
227 # server response.
229 sub recvfile {
230 my ($file, $size) = @_;
231 my $bytes;
233 if (!read(SRV_OUT, $bytes, $size)) {
234 print STDERR "Can't read from server: $!\n";
235 return (0);
237 if (!open(F, ">$file")) {
238 print STDERR "$file: $!\n";
239 return (0);
241 syswrite(F, $bytes, $size);
242 close(F);
243 return (1);