1 |
davidg |
1758 |
# |
2 |
|
|
# @(#)$Id$ |
3 |
|
|
# |
4 |
|
|
# |
5 |
|
|
package OSSL; |
6 |
|
|
use strict; |
7 |
|
|
use POSIX; |
8 |
|
|
use File::Temp qw/ tempfile /; |
9 |
|
|
use IPC::Open3; |
10 |
|
|
use IO::Select; |
11 |
|
|
use Time::Local; |
12 |
|
|
use vars qw/ $log $cnf $opensslversion /; |
13 |
|
|
|
14 |
|
|
# Syntax: |
15 |
|
|
# OSSL->new( [path] ); |
16 |
|
|
# OSSL->setName( name); |
17 |
|
|
|
18 |
|
|
# |
19 |
|
|
sub new { |
20 |
|
|
my $obref = {}; bless $obref; |
21 |
|
|
my $self = shift; |
22 |
|
|
$self = $obref; |
23 |
|
|
my $openssl = shift; |
24 |
|
|
$self->{"openssl"} = "openssl"; |
25 |
|
|
$self->{"openssl"} = $::cnf->{_}->{"openssl"} if $::cnf->{_}->{"openssl"}; |
26 |
|
|
$self->setOpenSSL($openssl) if $openssl; |
27 |
|
|
$self->{"version"} = undef; |
28 |
|
|
return $self; |
29 |
|
|
} |
30 |
|
|
|
31 |
|
|
sub setOpenSSL($$) { |
32 |
|
|
my $self = shift or die "Invalid invocation of CRL::setOpenSSL\n"; |
33 |
|
|
my $openssl = shift; |
34 |
|
|
return 0 unless $openssl; |
35 |
|
|
|
36 |
|
|
$openssl =~ /\// and ! -x "$openssl" or |
37 |
|
|
$::log->err("OpenSSL binary $openssl is not executable or does not exist") |
38 |
|
|
and return 0; |
39 |
|
|
|
40 |
|
|
$::log->verb(4,"Using OpenSSL at $openssl"); |
41 |
|
|
$self->{"openssl"} = $openssl; |
42 |
|
|
$self->{"version"} = undef; |
43 |
|
|
|
44 |
|
|
return 1; |
45 |
|
|
} |
46 |
|
|
|
47 |
|
|
sub getVersion($) { |
48 |
|
|
my $self = shift or die "Invalid invocation of CRL::getVersion\n"; |
49 |
|
|
#$self->{"version"} and return $self->{"version"}; |
50 |
|
|
$opensslversion and return $opensslversion; |
51 |
|
|
|
52 |
|
|
my ($data,$errors) = $self->Exec3(undef,qw/version/); |
53 |
|
|
if ( defined $data ) { |
54 |
|
|
$data =~ /^OpenSSL\s+([\d\.]+\w)/ or |
55 |
|
|
$::log->err("Cannot get OpenSSL version from command: invalid format in $data".($errors?" ($errors)":"")) and |
56 |
|
|
return undef; |
57 |
|
|
|
58 |
|
|
$self->{"version"} = $1; |
59 |
|
|
$opensslversion = $self->{"version"}; |
60 |
|
|
return $1; |
61 |
|
|
} else { |
62 |
|
|
$::log->err("Cannot get OpenSSL version from command: $errors"); |
63 |
|
|
return undef; |
64 |
|
|
} |
65 |
|
|
} |
66 |
|
|
|
67 |
|
|
sub Exec3select($$@) { |
68 |
|
|
my $self = shift or die "Invalid invocation of CRL::OpenSSL\n"; |
69 |
|
|
my $datain = shift; |
70 |
|
|
my ($dataout, $dataerr) = ("",undef); |
71 |
|
|
my $rc = 0; |
72 |
|
|
local(*CMD_IN, *CMD_OUT, *CMD_ERR); |
73 |
|
|
|
74 |
|
|
$::log->verb(6,"Executing openssl",@_); |
75 |
|
|
my $pid = open3(*CMD_IN, *CMD_OUT, *CMD_ERR, $self->{"openssl"}, @_ ); |
76 |
|
|
|
77 |
|
|
$SIG{CHLD} = sub { |
78 |
|
|
$rc = $? >> 8 if waitpid($pid, 0) > 0 |
79 |
|
|
}; |
80 |
|
|
$datain and print CMD_IN $datain; |
81 |
|
|
close(CMD_IN); |
82 |
|
|
print STDERR "Printed " . length($datain). " bytes of data\n"; |
83 |
|
|
|
84 |
|
|
my $selector = IO::Select->new(); |
85 |
|
|
$selector->add(*CMD_ERR); |
86 |
|
|
$selector->add(*CMD_OUT); |
87 |
|
|
|
88 |
|
|
my ($char,$cnt); |
89 |
|
|
while ($selector->count) { |
90 |
|
|
my @ready = $selector->can_read(1); |
91 |
|
|
#my @ready = IO::Select->select($selector,undef,undef,1); |
92 |
|
|
foreach my $fh (@ready) { |
93 |
|
|
if (fileno($fh) == fileno(CMD_ERR)) { |
94 |
|
|
$cnt = sysread CMD_ERR, $char, 1; |
95 |
|
|
if ( $cnt ) { $dataerr .= $char; } |
96 |
|
|
else { $selector->remove($fh); $dataerr and print STDERR "$dataerr\n";} |
97 |
|
|
} else { |
98 |
|
|
$cnt = sysread CMD_OUT, $char, 1; |
99 |
|
|
if ( $cnt ) { $dataout .= $char; } |
100 |
|
|
else { $selector->remove($fh); $dataout and print STDERR "$dataout\n"; } |
101 |
|
|
} |
102 |
|
|
$selector->remove($fh) if eof($fh); |
103 |
|
|
} |
104 |
|
|
} |
105 |
|
|
close(CMD_OUT); |
106 |
|
|
close(CMD_ERR); |
107 |
|
|
|
108 |
|
|
if ( $rc >> 8 ) { |
109 |
|
|
$::log->warn("Execute openssl " . $ARGV[0] . " failed: $rc"); |
110 |
|
|
(my $errmsg = $dataerr) =~ s/\n.*//sgm; |
111 |
|
|
$::log->verb(6,"STDERR:",$errmsg); |
112 |
|
|
return undef unless wantarray; |
113 |
|
|
return (undef,$dataerr); |
114 |
|
|
} |
115 |
|
|
return $dataout unless wantarray; |
116 |
|
|
return ($dataout,$dataerr); |
117 |
|
|
} |
118 |
|
|
|
119 |
|
|
sub Exec3pipe($$@) { |
120 |
|
|
my $self = shift or die "Invalid invocation of CRL::OpenSSL\n"; |
121 |
|
|
my $datain = shift; |
122 |
|
|
my ($dataout, $dataerr) = ("",undef); |
123 |
|
|
my $rc = 0; |
124 |
|
|
local(*CMD_IN, *CMD_OUT, *CMD_ERR); |
125 |
|
|
|
126 |
|
|
$::log->verb(6,"Executing openssl",@_); |
127 |
|
|
|
128 |
|
|
my ($tmpfh,$tmpname); |
129 |
|
|
$datain and do { |
130 |
davidg |
1777 |
($tmpfh,$tmpname) = tempfile("fetchcrl3.XXXXXX", DIR=>'/tmp'); |
131 |
davidg |
1758 |
$|=1; |
132 |
|
|
print $tmpfh $datain; |
133 |
|
|
close $tmpfh; |
134 |
|
|
push @_, "-in", $tmpname; |
135 |
|
|
select undef,undef,undef,0.01; |
136 |
|
|
}; |
137 |
|
|
|
138 |
|
|
$|=1; |
139 |
|
|
|
140 |
|
|
my $pid = open3( *CMD_IN, *CMD_OUT, *CMD_ERR, $self->{"openssl"}, @_ ); |
141 |
|
|
|
142 |
|
|
# allow delay for child to startup - but will hang on many older platforms |
143 |
|
|
select undef,undef,undef,0.15; |
144 |
|
|
|
145 |
|
|
$SIG{CHLD} = sub { |
146 |
|
|
$rc = $? >> 8 if waitpid($pid, 0) > 0 |
147 |
|
|
}; |
148 |
|
|
|
149 |
|
|
#close(CMD_IN); |
150 |
|
|
CMD_OUT->autoflush; |
151 |
|
|
CMD_ERR->autoflush; |
152 |
|
|
|
153 |
|
|
my $selector = IO::Select->new(); |
154 |
|
|
$selector->add(*CMD_ERR, *CMD_OUT); |
155 |
|
|
|
156 |
|
|
while (my @ready = $selector->can_read(0.01)) { |
157 |
|
|
foreach my $fh (@ready) { |
158 |
|
|
if (fileno($fh) == fileno(CMD_ERR)) {$dataerr .= scalar <CMD_ERR>} |
159 |
|
|
else {$dataout .= scalar <CMD_OUT>} |
160 |
|
|
$selector->remove($fh) if eof($fh); |
161 |
|
|
} |
162 |
|
|
} |
163 |
|
|
close(CMD_OUT); |
164 |
|
|
close(CMD_ERR); |
165 |
|
|
$tmpname and unlink $tmpname; |
166 |
|
|
|
167 |
|
|
if ( $rc >> 8 ) { |
168 |
|
|
$::log->warn("Execute openssl " . $ARGV[0] . " failed: $rc"); |
169 |
|
|
(my $errmsg = $dataerr) =~ s/\n.*//sgm; |
170 |
|
|
$::log->verb(6,"STDERR:",$errmsg); |
171 |
|
|
return undef unless wantarray; |
172 |
|
|
return (undef,$dataerr); |
173 |
|
|
} |
174 |
|
|
return $dataout unless wantarray; |
175 |
|
|
return ($dataout,$dataerr); |
176 |
|
|
} |
177 |
|
|
|
178 |
|
|
|
179 |
|
|
sub Exec3file($$@) { |
180 |
|
|
my $self = shift or die "Invalid invocation of CRL::OpenSSL\n"; |
181 |
|
|
my $datain = shift; |
182 |
|
|
my ($dataout, $dataerr) = ("",undef); |
183 |
|
|
my $rc = 0; |
184 |
|
|
local(*CMD_IN, *CMD_OUT, *CMD_ERR); |
185 |
|
|
|
186 |
|
|
$::log->verb(6,"Executing openssl",@_); |
187 |
|
|
|
188 |
|
|
my ($tmpin,$tmpinname); |
189 |
|
|
my ($tmpout,$tmpoutname); |
190 |
|
|
my ($tmperr,$tmperrname); |
191 |
|
|
|
192 |
|
|
my $tmpdir = $::cnf->{_}->{exec3tmpdir} || $ENV{"TMPDIR"} || '/tmp'; |
193 |
|
|
|
194 |
|
|
$|=1; |
195 |
|
|
$datain and do { |
196 |
|
|
($tmpin,$tmpinname) = tempfile("fetchcrl3in.XXXXXX", |
197 |
davidg |
1777 |
DIR=>$tmpdir); |
198 |
davidg |
1758 |
print $tmpin $datain; |
199 |
|
|
close $tmpin; |
200 |
|
|
}; |
201 |
|
|
($tmpout,$tmpoutname) = tempfile("fetchcrl3out.XXXXXX", |
202 |
davidg |
1777 |
DIR=>$tmpdir); |
203 |
davidg |
1758 |
($tmperr,$tmperrname) = tempfile("fetchcrl3out.XXXXXX", |
204 |
davidg |
1777 |
DIR=>$tmpdir); |
205 |
davidg |
1758 |
|
206 |
|
|
my $pid = fork(); |
207 |
|
|
|
208 |
|
|
defined $pid or |
209 |
|
|
$::log->warn("Internal error, fork for openssl failed: $!") and |
210 |
|
|
return undef; |
211 |
|
|
|
212 |
|
|
if ( $pid == 0 ) { # I'm a kid |
213 |
|
|
close STDIN; |
214 |
|
|
if ( $tmpinname ) { |
215 |
|
|
open STDIN, "<", $tmpinname or |
216 |
|
|
die "Cannot open tempfile $tmpinname again $!\n"; |
217 |
|
|
} else { |
218 |
|
|
open STDIN, "<", "/dev/null" or |
219 |
|
|
die "Cannot open /dev/null ??? $!\n"; |
220 |
|
|
} |
221 |
|
|
close STDOUT; |
222 |
|
|
if ( $tmpoutname ) { |
223 |
|
|
open STDOUT, ">", $tmpoutname or |
224 |
|
|
die "Cannot open tempfile $tmpoutname again $!\n"; |
225 |
|
|
} else { |
226 |
|
|
open STDOUT, ">", "/dev/null" or |
227 |
|
|
die "Cannot open /dev/null ??? $!\n"; |
228 |
|
|
} |
229 |
|
|
close STDERR; |
230 |
|
|
if ( $tmpoutname ) { |
231 |
|
|
open STDERR, ">", $tmperrname or |
232 |
|
|
die "Cannot open tempfile $tmperrname again $!\n"; |
233 |
|
|
} else { |
234 |
|
|
open STDERR, ">", "/dev/null" or |
235 |
|
|
die "Cannot open /dev/null ??? $!\n"; |
236 |
|
|
} |
237 |
|
|
exec $self->{"openssl"}, @_; |
238 |
|
|
} |
239 |
|
|
$rc = $? >> 8 if waitpid($pid, 0) > 0; |
240 |
|
|
|
241 |
|
|
{ local $/; $dataout = <$tmpout>; }; |
242 |
|
|
{ local $/; $dataerr = <$tmperr>; }; |
243 |
|
|
|
244 |
|
|
$tmpinname and unlink $tmpinname; |
245 |
|
|
$tmpoutname and unlink $tmpoutname; |
246 |
|
|
$tmperrname and unlink $tmperrname; |
247 |
|
|
|
248 |
|
|
if ( $rc >> 8 ) { |
249 |
|
|
$::log->warn("Execute openssl " . $ARGV[0] . " failed: $rc"); |
250 |
|
|
(my $errmsg = $dataerr) =~ s/\n.*//sgm; |
251 |
|
|
$::log->verb(6,"STDERR:",$errmsg); |
252 |
|
|
return undef unless wantarray; |
253 |
|
|
return (undef,$dataerr); |
254 |
|
|
} |
255 |
|
|
return $dataout unless wantarray; |
256 |
|
|
return ($dataout,$dataerr); |
257 |
|
|
} |
258 |
|
|
|
259 |
|
|
sub Exec3($@) { |
260 |
|
|
my $self = shift; |
261 |
|
|
|
262 |
|
|
grep /^pipe$/, $::cnf->{_}->{exec3mode}||"" and return $self->Exec3pipe(@_); |
263 |
|
|
grep /^select$/, $::cnf->{_}->{exec3mode}||"" and return $self->Exec3select(@_); |
264 |
|
|
return $self->Exec3file(@_); # default |
265 |
|
|
} |
266 |
|
|
|
267 |
|
|
sub gms2t($$) { |
268 |
|
|
my $self = shift; |
269 |
|
|
my ( $month, $mday, $htm, $year, $tz ) = split(/\s+/,$_[0]); |
270 |
|
|
die "OSSL::gms2t: cannot hangle non GMT output from OpenSSL\n" |
271 |
|
|
unless $tz eq "GMT"; |
272 |
|
|
|
273 |
|
|
my %mon=("Jan"=>0,"Feb"=>1,"Mar"=>2,"Apr"=>3,"May"=>4,"Jun"=>5, |
274 |
|
|
"Jul"=>6,"Aug"=>7,"Sep"=>8,"Oct"=>9,"Nov"=>10,"Dec"=>11); |
275 |
|
|
|
276 |
|
|
my ( $hrs,$min,$sec ) = split(/:/,$htm); |
277 |
|
|
my $gmt = timegm($sec,$min,$hrs,$mday,$mon{$month},$year); |
278 |
|
|
|
279 |
|
|
#print STDERR ">>> converted $_[0] to $gmt\n"; |
280 |
|
|
return $gmt; |
281 |
|
|
} |
282 |
|
|
|
283 |
|
|
|
284 |
|
|
1; |