File Coverage

blib/lib/OpenCA/OpenSSL.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             ## OpenCA::OpenSSL
2             ##
3             ## Copyright (C) 1998-2001 Massimiliano Pala (madwolf@openca.org)
4             ## All rights reserved.
5             ##
6             ## This library is free for commercial and non-commercial use as long as
7             ## the following conditions are aheared to. The following conditions
8             ## apply to all code found in this distribution, be it the RC4, RSA,
9             ## lhash, DES, etc., code; not just the SSL code. The documentation
10             ## included with this distribution is covered by the same copyright terms
11             ##
12             ## Copyright remains Massimiliano Pala's, and as such any Copyright notices
13             ## in the code are not to be removed.
14             ## If this package is used in a product, Massimiliano Pala should be given
15             ## attribution as the author of the parts of the library used.
16             ## This can be in the form of a textual message at program startup or
17             ## in documentation (online or textual) provided with the package.
18             ##
19             ## Redistribution and use in source and binary forms, with or without
20             ## modification, are permitted provided that the following conditions
21             ## are met:
22             ## 1. Redistributions of source code must retain the copyright
23             ## notice, this list of conditions and the following disclaimer.
24             ## 2. Redistributions in binary form must reproduce the above copyright
25             ## notice, this list of conditions and the following disclaimer in the
26             ## documentation and/or other materials provided with the distribution.
27             ## 3. All advertising materials mentioning features or use of this software
28             ## must display the following acknowledgement:
29             ## // "This product includes OpenCA software written by Massimiliano Pala
30             ## // (madwolf@openca.org) and the OpenCA Group (www.openca.org)"
31             ## 4. If you include any Windows specific code (or a derivative thereof) from
32             ## some directory (application code) you must include an acknowledgement:
33             ## "This product includes OpenCA software (www.openca.org)"
34             ##
35             ## THIS SOFTWARE IS PROVIDED BY OPENCA DEVELOPERS ``AS IS'' AND
36             ## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37             ## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38             ## ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
39             ## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40             ## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41             ## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42             ## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43             ## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44             ## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45             ## SUCH DAMAGE.
46             ##
47             ## The licence and distribution terms for any publically available version or
48             ## derivative of this code cannot be changed. i.e. this code cannot simply be
49             ## copied and put under another distribution licence
50             ## [including the GNU Public Licence.]
51             ##
52             ## Contributions by:
53             ## Martin Leung
54             ## Uwe Gansert
55              
56             ##
57             ## General Errorcodes:
58             ##
59             ## The errorcodes consists of seven numbers:
60             ## 1234567
61             ## 12: module
62             ## 34: function
63             ## 567: errorcode
64             ##
65             ## The modules errorcode is 77.
66             ##
67             ## The functions use the following errorcodes:
68             ##
69             ## new 00
70             ## setParams 01
71             ## errno 02
72             ## errval 03
73             ## genKey 11
74             ## genReq 12
75             ## genCert 13
76             ## crl2pkcs7 21
77             ## dataConvert 22
78             ## issueCert 31
79             ## revoke 32
80             ## issueCrl 33
81             ## SPKAC 41
82             ## getDigest 51
83             ## verify 42
84             ## sign 43
85             ## decrypt 46
86             ## encrypt 47
87             ## getCertAttribute 61
88             ## getReqAttribute 62
89             ## getCRLAttribute 63
90             ## pkcs7Certs 44
91             ## updateDB 71
92             ## getSMIME 52
93             ## getPIN 53
94             ## getOpenSSLDate 54
95             ## getNumericDate 55
96             ## getNumericDateDays 56
97            
98              
99 5     5   39890 use strict;
  5         10  
  5         335  
100              
101             package OpenCA::OpenSSL;
102              
103             our ($errno, $errval);
104              
105 5     5   11188 use X500::DN;
  5         880681  
  5         428  
106 5     5   66 use Carp;
  5         19  
  5         439  
107 5     5   4927 use OpenCA::OpenSSL::SMIME;
  0            
  0            
108              
109             ## i18n stuff needs this
110             use Locale::Messages qw (:locale_h :libintl_h);
111             use POSIX qw (setlocale);
112              
113             ($OpenCA::OpenSSL::VERSION = '$Revision: 1.29 $' )=~ s/(?:^.*: (\d+))|(?:\s+\$$)/defined $1?"2\.0":""/eg;
114              
115             ## Global Variables Go HERE
116             my %params = (
117             shell => undef,
118             cnf => undef,
119             tmpDir => undef,
120             baseDir => undef,
121             verify => undef,
122             sign => undef,
123             decrypt => undef,
124             encrypt => undef,
125             errno => undef,
126             errval => undef,
127             OPENSSL => undef,
128             CALLBACK_HANDLER => undef,
129             PIN_CALLBACK => undef,
130             STDERR_CALLBACK => undef,
131             STDOUT_CALLBACK => undef
132             );
133              
134             ## Create an instance of the Class
135             sub new {
136             my $that = shift;
137             my $class = ref($that) || $that;
138              
139             my $self = {
140             %params,
141             };
142              
143             bless $self, $class;
144              
145             my $keys = { @_ };
146              
147             $self->setParams( @_ );
148              
149             if( not $self->{binDir} ) {
150             $self->{binDir} = "/usr/bin";
151             };
152              
153             if( not $self->{shell} ) {
154             $self->{shell} = "$self->{binDir}/openssl";
155             };
156              
157             if( not $self->{openca_sv} ) {
158             $self->{openca_sv} = "$self->{binDir}/openca-sv";
159             }
160              
161             if( not $self->{verify} ) {
162             $self->{verify} = "$self->{binDir}/openca-sv verify";
163             };
164              
165             if( not $self->{sign} ) {
166             $self->{sign} = "$self->{binDir}/openca-sv sign";
167             };
168              
169             if( not $self->{decrypt} ) {
170             $self->{decrypt} = "$self->{binDir}/openca-sv decrypt";
171             };
172              
173             if( not $self->{encrypt} ) {
174             $self->{encrypt} = "$self->{binDir}/openca-sv encrypt";
175             };
176              
177             if( not $self->{tmpDir} ) {
178             $self->{tmpDir} = '/tmp';
179             };
180              
181             if( not $self->{gettext} ) {
182             $self->setError (7700110, "There is no translation function specified.");
183             return undef;
184             };
185              
186             if( not -e $self->{openssl} ) {
187             $self->setError (7700120,
188             $self->{gettext} ("There is no path to OpenSSL specified."));
189             return undef;
190             };
191              
192             $self->setError (0, "");
193              
194             return $self;
195             }
196              
197              
198             sub setParams {
199              
200             my $self = shift;
201             my $params = { @_ };
202             my $key;
203             my $rebuild_engine = 0;
204              
205             ## activate debugging
206             # $self->{DEBUG} = $params->{DEBUG} if (exists $params->{DEBUG});
207             $self->{DEBUG} = 0;
208              
209             foreach $key ( keys %{$params} ) {
210              
211             $self->_debug ("setParams: key: $key");
212             $self->_debug ("setParams: value: $params->{$key}");
213              
214             $self->{cnf} = $params->{$key} if ( $key =~ /CONFIG/ );
215             $self->{gettext} = $params->{$key} if ( $key =~ /GETTEXT/ );
216              
217             $self->{openssl} = $params->{$key} if ( $key =~ /SHELL/ );
218             $self->{wrapper} = $params->{$key} if ( $key =~ /WRAPPER/ );
219             $self->{ENGINE} = $params->{$key} if ( $key =~ /^ENGINE/ );
220             $self->{PRE_ENGINE} = $params->{$key} if ( $key =~ /PRE_ENGINE/ );
221             $self->{POST_ENGINE} = $params->{$key} if ( $key =~ /POST_ENGINE/ );
222             $self->{DYNAMIC_ENGINE} = $params->{$key} if ( $key =~ /DYNAMIC_ENGINE/ );
223             $self->{CALLBACK_HANDLER} = $params->{$key} if ( $key =~ /CALLBACK_HANDLER/);
224             $self->{GET_PIN_CALLBACK} = $params->{$key} if ( $key =~ /GET_PIN_CALLBACK/);
225             $self->{PIN_CALLBACK} = $params->{$key} if ( $key =~ /^PIN_CALLBACK/);
226             $self->{STDERR_CALLBACK} = $params->{$key} if ( $key =~ /STDERR_CALLBACK/);
227             $self->{STDOUT_CALLBACK} = $params->{$key} if ( $key =~ /STDOUT_CALLBACK/);
228              
229             $self->{KEY} = $params->{$key} if ( $key eq "KEY" );
230             $self->{KEYFORM} = $params->{$key} if ( $key eq "KEYFORM" );
231             $self->{PASSWD} = $params->{$key} if ( $key =~ /PASSWD/ );
232             $self->{PEM_CERT} = $params->{$key} if ( $key =~ /PEM_CERT/ );
233              
234             $self->{tmpDir} = $params->{$key} if ( $key =~ /TMPDIR/ );
235             $self->{binDir} = $params->{$key} if ( $key =~ /BINDIR/ );
236             if ( $key =~ /OPENCA_SV/ )
237             {
238             $self->{openca_sv} = $params->{$key};
239             $self->{verify} = $self->{openca_sv}." verify";
240             $self->{sign} = $self->{openca_sv}." sign";
241             $self->{decrypt} = $self->{openca_sv}." decrypt";
242             $self->{encrypt} = $self->{openca_sv}." encrypt";
243             $rebuild_engine = 1;
244             }
245             $ENV{RANDFILE} = $params->{$key} if ( $key =~ /RANDFILE/ );
246             $self->{DEBUG} = $params->{$key} if ( $key =~ /DEBUG/ );
247             open STDERR, $params->{$key} if ( $key =~ /STDERR/ );
248             }
249              
250             $self->{shell} = $self->{openssl};
251              
252             # add wrapper to commands that make use of private keys
253             if ((exists $self->{wrapper}) and $self->{wrapper})
254             {
255             foreach (qw(shell sign decrypt))
256             {
257             if (exists $self->{$_})
258             {
259             $self->{$_} = $self->{wrapper} . " " . $self->{$_};
260             }
261             }
262             }
263              
264             # set keyform if engine is in use
265             if ($self->{ENGINE} and not $self->{KEYFORM})
266             {
267             $self->{KEYFORM} = "e";
268             }
269              
270             return 1;
271             }
272              
273             sub errno {
274             my $self = shift;
275              
276             return $errno;
277             }
278              
279             sub errval {
280             my $self = shift;
281              
282             return $errval;
283             }
284              
285             sub setError {
286             my $self = shift;
287              
288             if (scalar (@_) == 4) {
289             my $keys = { @_ };
290             $errval = $keys->{ERRVAL};
291             $errno = $keys->{ERRNO};
292             } else {
293             $errno = $_[0];
294             $errval = $_[1];
295             }
296              
297             $self->_debug ("setError: errno: $errno");
298             $self->_debug ("setError: errval: $errval");
299              
300             ## support for: return $self->setError (1234, "Something fails.") if (not $xyz);
301             return undef;
302             }
303              
304             sub getRandomBytes {
305             my $self = shift;
306             my $bytes = shift;
307             my $ret = undef;
308              
309             if ( $bytes <= 0 ) {
310             return undef;
311             }
312              
313             $ret = OpenCA::OpenSSL::Misc::rand_bytes ( $bytes );
314              
315             return $ret;
316             }
317              
318              
319             sub genKey {
320              
321             ## Generate a new key, arguments accepted are, in order
322             ## ( BITS=>$bits, OUTFILE=>$outfile, ALGORITHM=>$alg, PASSWD=>$passwd )
323              
324             my $self = shift;
325             my $keys = { @_ };
326              
327             my $bits = $keys->{BITS};
328             my $outfile = $keys->{OUTFILE};
329             $outfile = $self->{KEY} if (not $outfile);
330             my $alg = $keys->{ALGORITHM};
331             $alg = "aes256" if (not $alg);
332             my $type = lc($keys->{TYPE});
333             my $passwd = $keys->{PASSWD};
334             $passwd = $self->{PASSWD} if (not $passwd);
335             my $engine = $self->{ENGINE};
336             my $rand = $keys->{RAND};
337              
338             ## generate the parameter file if necessary
339              
340             # $self->{DEBUG} = 1;
341              
342             my $param_file = "";
343             if ( lc($type) eq "dsa" ) {
344             use File::Basename;
345             $param_file = $self->{tmpDir};
346             $param_file = dirname ($outfile) if (dirname ($outfile));
347             $param_file .= "/dsa_param.$$";
348              
349             my $command = "dsaparam -out $param_file ";
350             if( $engine ) {
351             $command .= "-engine $engine ";
352             }
353             if ($bits) {
354             $command .= $bits;
355             undef $bits;
356             } else {
357             $command .= "2048";
358             }
359              
360             if (not $self->_execute_command (COMMAND => $command, KEY_USAGE => $engine)) {
361             $self->setError (7711005,
362             $self->{gettext} ("OpenCA::OpenSSL->genKey: Cannot execute command (__ERRNO__). __ERRVAL__",
363             "__ERRVAL__", $self->errval,
364             "__ERRNO__", $self->errno));
365             return undef;
366             }
367             }
368              
369             ## generate the key
370              
371             my $command = "";
372              
373             if ($type) {
374             $self->_debug ( "genKey -> type is $type!");
375             if( $type =~ /^ecdsa$/i ) {
376             $command .= "ecparam -genkey -noout ";
377             } else {
378             $command .= "gen".lc($type)." ";
379             }
380             } else {
381             $command .= "genrsa ";
382             }
383              
384             if( $engine ) {
385             $command .= "-engine $engine ";
386             }
387              
388             if( ($passwd) and (lc($type) ne "ecdsa")) {
389             $command .= "-passout env:pwd ";
390             $alg = "aes256 " if ( not(defined($alg)) or $alg eq "" );
391              
392             if ( defined($alg) && $alg ne "" ) {
393             $command .= "-$alg ";
394             }
395             }
396              
397             if ( defined($outfile) && $outfile ne "" ) {
398             $command .= "-out $outfile ";
399             }
400              
401             if ( defined($rand) && $rand ne "" ) {
402             $command .= "-rand $rand ";
403             } else {
404             $ENV{'RANDFILE'} = $self->{tmpDir}."/.rand_${$}";
405             }
406              
407             if ($param_file) {
408             ## DSA
409             $command .= $param_file;
410             } elsif ( $type =~ /^ecdsa$/i ) {
411             if( defined($bits) ) {
412             if ( $bits <= 112 ) {
413             $command .= " -name secp112r1 ";
414             } elsif ( $bits <= 128 ) {
415             $command .= " -name secp128r1 ";
416             } elsif ( $bits <= 160 ) {
417             $command .= " -name secp160r1 ";
418             } elsif ( $bits <= 192 ) {
419             $command .= " -name prime192v1 ";
420             } elsif ( $bits <= 224 ) {
421             $command .= " -name secp224r1 ";
422             } elsif ( $bits <= 256 ) {
423             $command .= " -name prime256v1 ";
424             } elsif ( $bits <= 384 ) {
425             $command .= " -name secp384r1 ";
426             } elsif ( $bits <= 521 ) {
427             $command .= " -name secp521r1 ";
428             } else {
429             #not supported, let's default to 224
430             $command .= " -name secp224r1 ";
431             $self->setError (7711006,
432             $self->{gettext} ("OpenCA::OpenSSL->genKey: You must specify a key length less or equal to 521 for ECDSA keys."));
433             $self->_debug ( "genKey -> ERROR::type is ECDSA but bits is $bits!");
434             return undef;
435             }
436             } else {
437             $self->setError (7711007,
438             $self->{gettext} ("OpenCA::OpenSSL->genKey: You must specify a key length for ECDSA keys."));
439             $self->_debug ( "genKey -> ERROR::type is ECDSA but bits is not defined ($bits)!");
440             return undef;
441             }
442              
443             } elsif (defined($bits)) {
444             ## RSA
445             $command .= $bits;
446             } else {
447             $self->setError (7711008,
448             $self->{gettext} ("OpenCA::OpenSSL->genKey: You must specify a parameterfile for DSA or a the key length for RSA keys."));
449             return undef;
450             }
451              
452             $self->_debug ( "genKey -> INFO::Command is ($command)");
453              
454             $ENV{'pwd'} = "$passwd" if (defined($passwd));
455             if (not $self->_execute_command (COMMAND => $command, KEY_USAGE => $engine)) {
456             $self->setError (7711011,
457             $self->{gettext} ("OpenCA::OpenSSL->genKey: Cannot execute command (__ERRNO__). __ERRVAL__" . "(__COMMAND__)",
458             "__ERRVAL__", $self->errval,
459             "__ERRNO__", $self->errno),
460             "__COMMAND__", $command );
461             delete ($ENV{'pwd'}) if( defined($passwd));
462             return undef;
463             }
464              
465             if( ($passwd) and (lc($type) eq "ecdsa" )) {
466             my $encCommand = "";
467              
468             $encCommand = "ec ";
469             $encCommand .= "-passout env:pwd ";
470             if( $alg ne "" ) {
471             $encCommand .= "-ecdsa ";
472             };
473              
474             if ( $outfile ne "" ) {
475             $encCommand .= "-in \"$outfile\" -out \"$outfile\"";
476             }
477              
478             $self->_execute_command( COMMAND => $encCommand,
479             KEY_USAGE => $engine );
480             }
481              
482             delete ($ENV{'pwd'}) if( defined($passwd));
483             delete ($ENV{'RANDFILE'}) if (defined($ENV{'RANDFILE'}));
484              
485             if( not defined( $rand )) {
486             unlink( $self->{tmpDir}."/.rand_${$}" );
487             }
488              
489             if( $? != 0 ) {
490             $self->setError (7711021,
491             $self->{gettext} ("OpenCA::OpenSSL->genKey: OpenSSL fails (__ERRNO__).",
492             "__ERRNO__", $?));
493             return undef;
494             }
495              
496             $self->{DEBUG} = 0;
497              
498             return 1;
499             }
500              
501             sub genReq {
502              
503             ## Generate a Request file, parameter accepted are
504             ## ( $outfile, $keyfile, $passwd , [email, cn, ou, o, c ] )
505             ## To utilize null passwd simply pass a "" reference.
506              
507             my $self = shift;
508             my $keys = { @_ };
509              
510             my $engine = $self->{ENGINE};
511              
512             my $outfile = $keys->{OUTFILE};
513             my $outform = $keys->{OUTFORM};
514             my $keyfile = $keys->{KEYFILE};
515             $keyfile = $self->{KEY} if (not $keyfile);
516             my $subject = $keys->{SUBJECT};
517             my $noemaildn = $keys->{NOEMAILDN};
518             my $passwd = $keys->{PASSWD};
519             my $extensions = $keys->{EXTENSIONS};
520             $passwd = $self->{PASSWD} if (not $passwd);
521             my $command = "req -new ";
522             my $tmpfile = $self->{tmpDir} . "/${$}_req.pem";
523             my ( $ret, $tmp );
524              
525             if( not $keyfile ) {
526             $self->setError (7712011,
527             $self->{gettext} ("OpenCA::OpenSSL->genReq: No keyfile specified."));
528             return undef;
529             }
530              
531             ## fix DN-handling of OpenSSL
532             if ($subject) {
533             $subject =~ s/\w+=\s*\,//g;
534             $subject =~ s/\w+=\s*$//;
535             # $self->setError(7712014,"NEW SUBJECT => $subject");
536             # return undef;
537              
538             $self->_debug ("genReq: subject_rfc2253: $subject");
539             my $dn_obj = X500::DN->ParseRFC2253 ($subject);
540             if (not $dn_obj) {
541             $self->setError (7712013,
542             $self->{gettext} ("OpenCA::OpenSSL->genReq: Cannot build X500::DN-object from subject __SUBJECT__",
543             "__SUBJECT__", $subject));
544             return undef;
545             }
546             $subject = $dn_obj->getOpenSSLString ();
547             $self->_debug ("genReq: subject_x500: $subject");
548             } else {
549             $self->_debug ("genReq: the subject of the request is not defined");
550             $self->setError (7712015,
551             $self->{gettext} ("OpenCA::OpenSSL->genReq: The subject of the request is not defined."));
552             return undef;
553             }
554              
555             if ( defined($self->{cnf}) && $self->{cnf} ne "" ) {
556             $command .= "-config " . $self->{cnf} . " ";
557             }
558              
559             if (not $self->{PIN_CALLBACK} and not $self->{GET_PIN_CALLBACK})
560             {
561             $command .= "-passin env:pwd " if ( defined($passwd) && $passwd ne "" );
562             }
563              
564             if( $keys->{NOEMAILDN} ) {
565             $subject =~ s/emailAddress=[^\/\,]+\,*\/*//gi;
566             $subject =~ s/(\,*|\/*)$//;
567             $subject =~ s/^\/\//\//;
568             };
569              
570             $command .= "-subj \"$subject\" ";
571             $command .= "-multivalue-rdn " if ($subject =~ /[^\\](\\\\)*\+/);
572              
573             if( $engine ) {
574             $command .= "-engine $engine -keyform ".$self->{KEYFORM}." ";
575             }
576              
577             if( $extensions ) {
578             $command .= "-reqexts \"$extensions\" ";
579             }
580              
581             if( defined($outform) ) {
582             $outform = uc( $outform );
583              
584             if ( $outform =~ /(PEM|DER)/i ) {
585             $command .= "-outform $outform ";
586             } elsif ( $outform =~ /(TXT)/ ) {
587             $command .= "-text -noout ";
588             }
589             }
590              
591             $command .= "-key $keyfile ";
592              
593             if ( $outfile ne "" ) {
594             $command .= "-out $outfile ";
595             } else {
596             $command .= " -out $tmpfile ";
597             }
598            
599             $ENV{'pwd'} = "$passwd" if( defined($passwd));
600             if (not $self->_execute_command (COMMAND => $command, KEY_USAGE => $engine)) {
601             $self->setError (7712071,
602             $self->{gettext} ("OpenCA::OpenSSL->genReq: Cannot execute command (__ERRNO__). __ERRVAL__",
603             "__ERRVAL__", $self->errval,
604             "__ERRNO__", $self->errno));
605             delete( $ENV{'pwd'} ) if( defined($passwd) );
606             return undef;
607             }
608             delete( $ENV{'pwd'} ) if( defined($passwd) );
609              
610             if( not defined $outfile or $outfile eq "" ) {
611             if (not open( FD, "<$tmpfile" )) {
612             $self->setError (7712081,
613             $self->{gettext} ("OpenCA::OpenSSL->genReq: Cannot open tmpfile __FILENAME__ for reading.",
614             "__FILENAME__", $tmpfile));
615             return undef;
616             }
617             while( $tmp = ) {
618             $ret .= $tmp;
619             }
620             close(FD);
621             unlink( "$tmpfile" );
622              
623             return $ret;
624             }
625              
626            
627             return 1;
628             }
629              
630             sub genCert {
631              
632             ## Generate a new Certificate file, parameter accepted are
633             ## (OUTFILE=>$outfile,KEYFILE=>$keyfile,REQFILE=>$reqfile,
634             ## PASSWD=>$passwd, DN=>[ @list ] )
635              
636             my $self = shift;
637             my $keys = { @_ };
638              
639             my $outfile = $keys->{OUTFILE};
640             my $keyfile = $keys->{KEYFILE};
641             $keyfile = $self->{KEY} if (not $keyfile);
642             my $reqfile = $keys->{REQFILE};
643             my $subject = $keys->{SUBJECT};
644             my $noemail = $keys->{NOEMAILDN};
645             my $passwd = $keys->{PASSWD};
646             $passwd = $self->{PASSWD} if (not $passwd);
647             my $days = $keys->{DAYS};
648             my $tmpfile = $self->{tmpDir} . "/${$}_crt.tmp";
649              
650             my $engine = $self->{ENGINE};
651              
652             my $extfile = $keys->{EXTFILE};
653             my $extensions = $keys->{EXTENSIONS};
654              
655             ## fix DN-handling of OpenSSL
656             if ($subject) {
657             $subject =~ s/\w+=\s*\,//g;
658             $subject =~ s/\w+=\s*$//;
659             # $self->setError(7712014,"NEW SUBJECT => $subject");
660             # return undef;
661              
662             $self->_debug ("genReq: subject_rfc2253: $subject");
663             my $dn_obj = X500::DN->ParseRFC2253 ($subject);
664             if (not $dn_obj) {
665             $self->setError (7713013,
666             $self->{gettext} ("OpenCA::OpenSSL->genCert: Cannot build X500::DN-object from subject __SUBJECT__.",
667             "__SUBJECT__", $subject));
668             return undef;
669             }
670             $subject = $dn_obj->getOpenSSLString ();
671             $self->_debug ("genReq: subject_x500: $subject");
672             }
673              
674             my $command = "ca -batch -selfsign ";
675              
676             my ( $ret, $tmp );
677              
678             if (not $keyfile) {
679             $self->setError (7713015,
680             $self->{gettext} ("OpenCA::OpenSSL->genCert: No keyfile specified."));
681             return undef;
682             }
683             if (not $reqfile) {
684             $self->setError (7713016,
685             $self->{gettext} ("OpenCA::OpenSSL->genCert: No requestfile specified."));
686             return undef;
687             }
688              
689             if( $engine ) {
690             $command .= "-engine $engine -keyform ".$self->{KEYFORM}." ";
691             }
692              
693             if ( defined($subject) && ($subject ne "") ) {
694              
695             # if( $keys->{NOEMAILDN} ) {
696             # $subject =~ s/emailAddress=[^\/\,]+\,*\/*//gi;
697             # $subject =~ s/(\,*|\/*)$//;
698             # $subject =~ s/^\/\//\//;
699             # };
700              
701             $command .= " -subj \"$subject\" ";
702             };
703              
704             $command .= "-multivalue-rdn " if ($subject and $subject =~ /[^\\](\\\\)*\+/);
705              
706             if (not $self->{PIN_CALLBACK} and not $self->{GET_PIN_CALLBACK})
707             {
708             $command .= "-passin env:pwd "
709             if ( defined($passwd) && $passwd ne "" );
710             }
711              
712             $command .= "-config ". $self->{cnf} . " "
713             if ( defined($self->{'cnf'}) && $self->{cnf} ne "" );
714              
715             $command .= "-days $days "
716             if ( defined($days) && $days =~ /\d+/ && $days > 0 );
717              
718             $command .= "-in \"$reqfile\" -keyfile \"$keyfile\" ";
719              
720             $command .= "-extensions \"" . $extensions . "\" " if( $extensions );
721             $command .= qq{ -extfile "$extfile" } if ( $extfile );
722              
723             if( defined($outfile) && $outfile ne "" ) {
724             $command .= "-out \"$outfile\" ";
725             } else {
726             $command .= "-out \"$tmpfile\" ";
727             }
728              
729             $ENV{'pwd'} = "$passwd" if( defined($passwd) );
730              
731             $ret = $self->_execute_command (COMMAND => $command,
732             KEY_USAGE => $engine);
733              
734             delete( $ENV{'pwd'} ) if( defined($passwd) );
735              
736             if( not $ret ) {
737             $self->setError (7713071,
738             $self->{gettext} ("OpenCA::OpenSSL->genCert: OpenSSL failed (__ERRNO__). __ERRVAL__",
739             "__ERRNO__", $self->errno,
740             "__ERRVAL__", $self->errval));
741             return undef;
742             }
743              
744             if( not(defined($outfile)) or $outfile eq "" ) {
745             if (not open( FD, "<$tmpfile" )) {
746             $self->setError (7713081,
747             $self->{gettext} ("OpenCA::OpenSSL->genCert: Cannot open tmpfile __FILENAME__ for reading.",
748             "__FILENAME__", $tmpfile));
749             return undef;
750             }
751             while( $tmp = ) {
752             $ret .= $tmp;
753             }
754             close(FD);
755             unlink( "$tmpfile" );
756             }
757              
758             return "$ret";
759             }
760              
761             sub crl2pkcs7 {
762             my $self = shift;
763             my $keys = { @_ };
764              
765             my $data = $keys->{DATA};
766             my $crlfile = $keys->{CRLFILE};
767             my $inform = $keys->{INFORM};
768             my $outfile = $keys->{OUTFILE};
769             my $outform = $keys->{OUTFORM};
770              
771             my ( $ret, $tmp, $tmpfile, $command, $nocrl );
772             $command = "crl2pkcs7 ";
773              
774             if( (not(defined($data)) or $data eq "") and
775             (not(defined($crlfile)) or $crlfile eq "" )) {
776             $nocrl = 1;
777             $command .= "-nocrl ";
778             } else {
779             $nocrl = 0;
780             }
781              
782             if ( not defined $crlfile or $crlfile eq "" ){
783             $tmpfile = $self->{tmpDir} . "/${$}_incrl.tmp";
784             if (not open( FD, ">$tmpfile" )) {
785             $self->setError (7721011,
786             $self->{gettext} ("OpenCA::OpenSSL->crl2pkcs7: Cannot open tmpfile __FILENAME__ for writing.",
787             "__FILENAME__", $tmpfile));
788             return undef;
789             }
790             print FD "$data";
791             close( FD );
792             } else {
793             $tmpfile = $crlfile;
794             }
795             $command .= "-in $tmpfile " if( $nocrl == 1 );
796              
797             $command .= "-out $outfile "
798             if ( defined($outfile) and $outfile ne "");
799             $command .= "-inform $inform "
800             if ( defined($inform) and $inform ne "");
801             $command .= "-outform $outform "
802             if ( defined($outform) and $outform ne "");
803              
804             if( defined $keys->{CERTSLIST} ) {
805             my @certs = @{ $keys->{CERTSLIST}};
806              
807             for (@certs) {
808             $command .= "-certfile $_ "
809             if( ("$_" ne "") and (-f "$_") );
810             }
811             }
812              
813             $ret = $self->_execute_command (COMMAND => $command);
814             if(not $ret) {
815             $self->setError (7721071,
816             $self->{gettext} ("OpenCA::OpenSSL->crl2pkcs7: OpenSSL fails (__ERRNO__). __ERRVAL__",
817             "__ERRNO__", $self->errno,
818             "__ERRVAL__", $self->errval));
819             $ret = undef;
820             } else {
821             $ret = 1 if( $outfile ne "" );
822             }
823             unlink("$tmpfile") if ( $crlfile eq "" );
824              
825             return $ret;
826             }
827              
828             sub dataConvert {
829              
830             ## You can convert data structures to different formats
831             ## Accepted parameters are:
832             ##
833             ## DATATYPE=> CRL|CERTIFICATE|REQUEST|KEY
834             ## OUTFORM => PEM|DER|NET|TXT|PKCS12|PKCS8
835             ## INFORM => PEM|DER|NET|TXT|PKCS12|PKCS8
836             ## OUTFILE => $outfile
837             ## INFILE => $infile
838             ## DATA => $data
839             ## KEYFILE => $keyfile
840             ## CACERT => $cacert
841              
842             ## PKCS12 encode parameter :
843             ## INFILE or DATA (must be PEM encoded)
844             ## KEYFILE (might be in front of the DATA or in INFILE)
845             ## P12PASSWD = password for pkcs12 file (optional)
846             ## PASSWD = password for KEYFILE (optional)
847             ## INPASSWD = password for KEYFILE (optional)
848             ## OUTPASSWD = password for KEYFILE (optional)
849             ## OUTFILE = optional
850             ## ALGO = optionl, default = des3
851             ## DATATYPE must be 'CERTIFICATE'
852             ## CACERT = add additional cacert to pkcs#12
853              
854             ## PKCS12 decode parameter
855             ## INFILE or DATA (must be PKCS12 encoded)
856             ## P12PASSWD
857             ## PASSWD (PEM password optional)
858             ## OUTFILE = optional
859             ## DATATYPE must be 'CERTIFICATE'
860              
861             ## KEY encode/decode parameter
862             ## PUBOUT = true value - output only the public key?
863             ## PUBIN = true value - input is only the public key?
864              
865             my $self = shift;
866             my $keys = { @_ };
867              
868             my $data = $keys->{DATA};
869             my $type = $keys->{DATATYPE};
870             my $outform = $keys->{OUTFORM};
871             my $encoding= $keys->{ENCODING};
872             my $inform = $keys->{INFORM};
873             my $outfile = $keys->{OUTFILE};
874             my $infile = $keys->{INFILE};
875             my $keyfile = $keys->{KEYFILE};
876             $keyfile = $self->{KEY} if (not $keyfile);
877             my $passwd = $keys->{'PASSWD'};
878             $passwd = $self->{PASSWD} if (not $passwd and
879             not exists $keys->{'OUTPASSWD'} and
880             not exists $keys->{'INPASSWD'});
881             my $p12pass = $keys->{'P12PASSWD'};
882             my $inpwd = $keys->{'INPASSWD'};
883             my $outpwd = $keys->{'OUTPASSWD'};
884             my $algo = $keys->{'ALGO'} || 'des3';
885             my $nokeys = $keys->{'NOKEYS'};
886             my $cacert = $keys->{'CACERT'};
887             $cacert = $self->{PEM_CERT} if (not $cacert);
888             my $pubin = $keys->{'PUBIN'};
889             my $pubout = $keys->{'PUBOUT'};
890              
891             my ( $command, $tmp, $ret, $tmpfile );
892              
893             ## rest errordetection
894             if( $? != 0 ) {
895             $self->_debug ("dataConvert: resetting error from ${?} to 0.");
896             $? = 0;
897             }
898             if( $errno != 0 ) {
899             $self->_debug ("dataConvert: resetting errno from $errno to 0.");
900             $self->setError (0, "");
901             }
902              
903             if ( not $type) {
904             $self->setError (7722011,
905             $self->{gettext} ("OpenCA::OpenSSL->dataConvert: No datatype specified."));
906             return undef;
907             }
908             if ( (not $data) and (not $infile) and ($type =~ /KEY/)) {
909             $infile = $self->{KEY};
910             }
911             if ( (not $data) and (not $infile)) {
912             $self->setError (7722012,
913             $self->{gettext} ("OpenCA::OpenSSL->dataConvert: No input data specified."));
914             return undef;
915             }
916             if ( not $algo =~ /des3|des|idea/ ) {
917             $self->setError (7722013,
918             $self->{gettext} ("OpenCA::OpenSSL->dataConvert: Unsupported algorithm specified."));
919             return undef;
920             }
921             if ( defined($nokeys) and ($outform eq 'PKCS12') ) {
922             $self->setError (7722014,
923             $self->{gettext} ("OpenCA::OpenSSL->dataConvert: No keys available but the output format is PKCS#12."));
924             return undef;
925             }
926              
927             ## Return if $infile does not exists
928             if( $infile and ( not -e $infile )) {
929             $self->setError (7722015,
930             $self->{gettext} ("OpenCA::OpenSSL->dataConvert: The specified inputfile doesn't exist."));
931             return undef;
932             }
933             if (not $infile) {
934             $infile = $self->{tmpDir} . "/${$}_data.tmp";
935             $self->_debug ("dataConvert: create temporary infile $infile");
936             $self->_debug ("dataConvert: the data is like follows");
937             $self->_debug ("dataConvert: $data");
938             if (not open FD, ">".$infile) {
939             $self->_debug ("dataConvert: failed to open temporary infile $infile");
940             $self->setError (7722041,
941             $self->{gettext} ("OpenCA::OpenSSL->dataConvert: Cannot write inputdata to tmpfile __FILENAME__.",
942             "__FILENAME__", $infile));
943             return undef;
944             }
945             print FD $data;
946             close FD;
947             } else {
948             $data = 0;
949             }
950              
951             $outform = "PEM" if( not $outform );
952             $inform = "PEM" if( not $inform );
953              
954             $tmpfile = "$self->{tmpDir}/${$}_cnv.tmp";
955             $command = "";
956              
957             if( $type =~ /CRL/i ) {
958             $command .= "crl ";
959             } elsif ( $type =~ /CERTIFICATE/i ) {
960             if( $outform eq 'PKCS12' or $inform eq 'PKCS12' ) {
961             $command .= 'pkcs12 ';
962             } else {
963             $command .= "x509 -nameopt RFC2253,-esc_msb ";
964             }
965             } elsif ( $type =~ /REQ/i ) {
966             $command .= "req -nameopt RFC2253,-esc_msb ";
967             if ( defined($self->{cnf}) && $self->{cnf} ne "" ) {
968             $command .= "-config " . $self->{cnf} . " ";
969             }
970             } elsif ( $type =~ /KEY/i ) {
971             ## PKCS8 enforces PEM because the OpenSSL command req can
972             ## only handle PEM-encoded PKCS#8 keys
973             if ( ($outform =~ /PKCS8/i) or ($inform =~ /PKCS8/i) ) {
974             $command .= "pkcs8 ";
975             } else {
976             $command .= "rsa ";
977             }
978             if ( $pubout ) {
979             $command .= " -pubout ";
980             }
981             if ( $pubin ) {
982             $command .= " -pubin ";
983             }
984             if (not $inpwd) {
985             $inpwd = $passwd;
986             }
987             if (not $inpwd) {
988             ## unlink ($infile) if ($data);
989             ## $self->setError (7722018,
990             ## "OpenCA::OpenSSL->dataConvert: Cannot convert key without input passphrase.");
991             ## return undef;
992             } else {
993             $command .= ' -passin env:inpwd ';
994             }
995             if (not $outpwd) {
996             $outpwd = $passwd;
997             }
998             if (not $outpwd) {
999             ## unlink ($infile) if ($data);
1000             ## $self->setError (7722019,
1001             ## "OpenCA::OpenSSL->dataConvert: Cannot convert key without output passphrase.");
1002             ## return undef;
1003              
1004             ## I had to comment this one out. In my version of
1005             ## openssl (0.9.7a-1) it is not necessary nor
1006             ## recognized.
1007             #$command .= ' -nocrypt ';
1008             } else {
1009             $command .= ' -passout env:outpwd ';
1010             }
1011             } else {
1012             ## if no known type is given...
1013             $self->setError (7722021,
1014             $self->{gettext} ("OpenCA::OpenSSL->dataConvert: The datatype which should be converted is not known."));
1015             unlink ($infile) if ($data);
1016             return undef;
1017             }
1018              
1019             $outfile = $tmpfile if ( not $outfile );
1020              
1021             $command .= "-out $outfile ";
1022             $command .= "-in $infile ";
1023             $command .= "-inkey $keyfile " if( defined($keyfile) and ($inform eq 'PKCS12' or $outform eq 'PKCS12')); #PKCS12 only
1024              
1025             # outform in PKCS12 is always PEM
1026             if( $outform =~ /TXT/i ) {
1027             ## FIXME: noout was removed because of a bug in OpenSSL 0.9.7
1028             ## FIXME: the crl command returns an error if -noout is in use
1029             ## $command .= "-text -noout ";
1030             $command .= "-text ";
1031             } elsif ( $outform =~ /(PEM|DER|NET)/i ) {
1032             if( $inform eq 'PKCS12' ) {
1033             $command .= '-passout env:pempwd 'if( defined($passwd) );
1034             $command .= '-passin env:p12pwd ' if( defined($p12pass) );
1035             $command .= '-nokeys ' if( defined($nokeys) );
1036             if( defined($passwd) ) {
1037             $command .= "-$algo " if( $algo eq 'des' or
1038             $algo eq 'des3' or
1039             $algo eq 'idea' );
1040             } else {
1041             $command .= '-nodes' if( not defined($passwd) );
1042             }
1043             } else {
1044             $command .= "-outform " . uc($outform) . " ";
1045             }
1046             } elsif ( $outform eq 'PKCS12' ) {
1047             $command .= "-export ";
1048             $command .= '-passout env:p12pwd ';
1049             $command .= '-passin env:pempwd ' if( defined($passwd) );
1050             $command .= "-certfile $cacert " if(defined($cacert));
1051             } elsif ( $outform =~ /PKCS8/i ) {
1052             $command .= " -topk8 ";
1053             $command .= " -nocrypt " if (not $outpwd);
1054             if ($encoding) {
1055             $command .= " -outform ".uc($encoding)." ";
1056             } else {
1057             $command .= " -outform PEM ";
1058             }
1059             } else {
1060             ## no valid format received...
1061             $self->_debug ("dataConvert: failed to determine the output format ($outform)");
1062             unlink ($infile) if ($data);
1063             $self->setError (7722024,
1064             $self->{gettext} ("OpenCA::OpenSSL->dataConvert: The output format is unknown or unsupported."));
1065             return undef;
1066             }
1067              
1068             if( $outform ne 'PKCS12' ) {
1069             if( $inform =~ /(PEM|DER|NET)/i ) {
1070             $command .= "-inform " . uc($inform) ." ";
1071             } elsif( $inform eq 'PKCS12' ) {
1072             # nothing to do here.
1073             } elsif( $inform eq 'PKCS8' ) {
1074             # nothing to do here.
1075             } else {
1076             ## no valid format received ...
1077             $self->_debug ("dataConvert: failed to determine the input format ($inform)");
1078             unlink ($infile) if ($data);
1079             $self->setError (7722026,
1080             $self->{gettext} ("OpenCA::OpenSSL->dataConvert: You don't try to convert to PKCS#12 but the input format is unknown or unsupported."));
1081             return undef;
1082             }
1083             }
1084              
1085             $self->_debug ("dataConvert: p12pass is set") if( defined($p12pass) );
1086             $self->_debug ("dataConvert: passwd is set") if( defined($passwd) );
1087             $self->_debug ("dataConvert: inpwd is set") if( defined($inpwd) );
1088             $self->_debug ("dataConvert: outpwd is set") if( defined($outpwd) );
1089             $self->_debug ("dataConvert: command=$command");
1090              
1091             if( $? != 0 ) {
1092             $self->setError (7722069,
1093             $self->{gettext} ("OpenCA::OpenSSL->dataConvert: Unkown Error detected before OpenSSL starts (__ERRNO__)",
1094             "__ERRNO__", $?));
1095             unlink ($infile) if ($data);
1096             return undef;
1097             }
1098              
1099             $ENV{'p12pwd'} = "$p12pass" if( defined($p12pass) );
1100             $ENV{'pempwd'} = "$passwd" if( defined($passwd) );
1101             $ENV{'inpwd'} = "$inpwd" if( defined($inpwd) );
1102             $ENV{'outpwd'} = "$outpwd" if( defined($outpwd) );
1103              
1104             if( defined($infile) && $infile ne "" ) {
1105             $self->_debug ("dataConvert: using infile");
1106             $ret=$self->_execute_command (COMMAND => $command);
1107             } else {
1108             $self->_debug ("dataConvert: data piping is no longer supported - please use tmp files");
1109             $self->setError (7722071,
1110             $self->{gettext} ("OpenCA::OpenSSL->dataConvert: Data piping is no longer supported."));
1111             return undef;
1112             }
1113             $self->_debug ("dataConvert: openssl itself successful");
1114              
1115             delete($ENV{'pwd'});
1116             delete($ENV{'pempwd'});
1117             delete($ENV{'inpwd'});
1118             delete($ENV{'outpwd'});
1119             $self->_debug ("dataConvert: passphrases deleted");
1120              
1121             if( not $ret ) {
1122             $self->setError (7722073,
1123             $self->{gettext} ("OpenCA::OpenSSL->dataConvert: OpenSSL failed (__ERRNO__). __ERRVAL__",
1124             "__ERRNO__", $self->errno,
1125             "__ERRVAL__", $self->errval));
1126             unlink ($tmpfile) if (not $keys->{OUTFILE});
1127             unlink ($infile) if ($data);
1128             return undef;
1129             }
1130              
1131             unlink ($infile) if ($data);
1132              
1133             if( $keys->{OUTFILE} ) {
1134             $self->_debug ("dataConvert: return 1 and infile deleted if temporary");
1135             return 1;
1136             }
1137              
1138             $ret = "";
1139             if (not open( TMP, "<$outfile" )) {
1140             $self->_debug ("dataConvert: cannot open outfile $outfile for reading");
1141             $self->setError (7722081,
1142             $self->{gettext} ("OpenCA::OpenSSL->dataConvert: Cannot open outfile __FILENAME__ for reading.",
1143             "__FILENAME__", $outfile));
1144             return undef;
1145             }
1146             while( $tmp = ) {
1147             $ret .= $tmp;
1148             }
1149             close( TMP );
1150             unlink ($outfile);
1151              
1152             $self->_debug ("dataConvert: return result like follows");
1153             $self->_debug ("dataConvert: $ret");
1154             return $ret;
1155            
1156             }
1157              
1158             sub issueCert {
1159              
1160             ## Use this function to issue a certificate using the
1161             ## ca utility. Use this if you already own a valid CA
1162             ## certificate. Accepted parameters are:
1163              
1164             ## REQDATA => $data
1165             ## REQFILE => $reqfilename
1166             ## INFORM => PEM|DER|NET|SPKAC ; defaults to PEM
1167             ## PRESERVE_DN => Y/N ; defaults to Y/N
1168             ## CAKEY => $CAkeyfile
1169             ## CACERT => $CAcertfile
1170             ## DAYS => $days
1171             ## PASSWD => $passwd
1172             ## EXTS => $extentions
1173             ## NOEMAILDN => -noemailDN
1174             ## NOUNIQUEDN => -nouniqueDN
1175              
1176             my $self = shift;
1177             my $keys = { @_ };
1178              
1179             my $reqdata = $keys->{REQDATA};
1180             my $reqfile = $keys->{REQFILE};
1181             my $inform = $keys->{INFORM};
1182             my $preserve = ( $keys->{PRESERVE_DN} or "N" );
1183             my $cakey = $keys->{CAKEY};
1184             $cakey = $self->{KEY} if (not $cakey);
1185             my $days = $keys->{DAYS};
1186             my $startDate= $keys->{START_DATE};
1187             my $endDate = $keys->{END_DATE};
1188             my $passwd = $keys->{PASSWD};
1189             $passwd = $self->{PASSWD} if (not $passwd);
1190             my $exts = $keys->{EXTS};
1191             my $extFile = $keys->{EXTFILE};
1192             my $subject = $keys->{SUBJECT};
1193              
1194             my $reqfiles =$keys->{REQFILES};
1195             my $outdir =$keys->{OUTDIR};
1196             my $caName = $keys->{CA_NAME};
1197            
1198             my $engine = $self->{ENGINE};
1199              
1200             my ( $ret, $tmpfile );
1201              
1202             ## fix DN-handling of OpenSSL
1203             if ($subject) {
1204              
1205             ## OpenSSL includes a bug in -nameopt RFC2253
1206             ## = signs are not escaped if they are normal values
1207             my $i = 0;
1208             my $now = "name";
1209             while ($i < length ($subject))
1210             {
1211             if (substr ($subject, $i, 1) =~ /\\/)
1212             {
1213             $i++;
1214             } elsif (substr ($subject, $i, 1) =~ /=/) {
1215             if ($now =~ /value/)
1216             {
1217             ## OpenSSL forgets to escape =
1218             $subject = substr ($subject, 0, $i)."\\".substr ($subject, $i);
1219             $i++;
1220             } else {
1221             $now = "value";
1222             }
1223             } elsif (substr ($subject, $i, 1) =~ /[,+]/) {
1224             $now = "name";
1225             }
1226             $i++;
1227             }
1228              
1229             $subject =~ s/\w+=\s*\,//g;
1230             $subject =~ s/\w+=\s*$//;
1231             # $self->setError(7712014,"NEW SUBJECT => $subject");
1232             # return undef;
1233              
1234             $self->_debug ("issueCert: subject_rfc2253: $subject");
1235             my $dn_obj = X500::DN->ParseRFC2253 ($subject);
1236             $self->_debug ("issueCert: subject parsed by X500::DN");
1237             if (not $dn_obj) {
1238             $self->_debug ("issueCert: cannot create X500::DN-object");
1239             $self->setError (7731001,
1240             $self->{gettext} ("OpenCA::OpenSSL->issueCert: Cannot create X500::DN-object."));
1241             return undef;
1242             }
1243             $subject = $dn_obj->getOpenSSLString ();
1244             $self->_debug ("issueCert: subject_x500: $subject");
1245             }
1246              
1247             #return if( (not $reqdata) and (not $reqfile));
1248             # to make multi certs you need to tell openssl
1249             # what directory to put it.
1250             if( (not $reqdata) and (not $reqfile) and
1251             ((not $reqfiles) or (not $outdir)) ) {
1252             $self->setError (7731011,
1253             $self->{gettext} ("OpenCA::OpenSSL->issueCert: No request specified."));
1254             return undef;
1255             }
1256             if (not $reqfile and not $reqfiles) {
1257             $reqfile = $self->{tmpDir} . "/${$}_req.tmp";
1258             $self->_debug ("issueCert: create temporary reqfile $reqfile");
1259             $self->_debug ("issueCert: the data is like follows");
1260             $self->_debug ("issueCert: $reqdata");
1261             if (not open FD, ">".$reqfile) {
1262             $self->_debug ("issueCertConvert: failed to open temporary reqfile $reqfile");
1263             $self->setError (7731015,
1264             $self->{gettext} ("OpenCA::OpenSSL->issueCert: Cannot write inputdata to tmpfile __FILENAME__.",
1265             "__FILENAME__", $reqfile));
1266             return undef;
1267             }
1268             print FD $reqdata;
1269             close FD;
1270             } else {
1271             $reqdata = 0;
1272             }
1273              
1274             $inform = "PEM" if( not $inform );
1275              
1276             my $command = "ca -batch ";
1277             ## activate this if you have a patched OpenSSL 0.9.8
1278             ## $command .= "-multivalue-rdn ";
1279              
1280             if( $engine ) {
1281             $command .= "-engine $engine -keyform ".$self->{KEYFORM}." ";
1282             }
1283              
1284             $command .= "-config " .$self->{cnf}." " if ( $self->{cnf} );
1285             $command .= "-keyfile $cakey " if( $cakey );
1286             if (not $self->{PIN_CALLBACK} and not $self->{GET_PIN_CALLBACK})
1287             {
1288             $command .= "-passin env:pwd " if ( $passwd ne "" );
1289             }
1290             $command .= "-days $days " if ( $days );
1291             $command .= "-extfile $extFile " if ( $extFile );
1292             $command .= "-extensions $exts " if ( $exts );
1293             $command .= "-preserveDN " if ( $preserve =~ /Y/i );
1294             $command .= "-startdate $startDate " if ( $startDate );
1295             $command .= "-enddate $endDate " if ( $endDate );
1296             $command .= "-name $caName " if ( $caName );
1297             $command .= "-subj \"$subject\" " if ( $subject );
1298             $command .= "-multivalue-rdn " if ($subject and $subject =~ /[^\\](\\\\)*\+/);
1299             $command .= "-noemailDN " if ( $keys->{NOEMAILDN} );
1300             $command .= "-nouniqueDN " if ( $keys->{NOUNIQUEDN} );
1301              
1302             if( $inform =~ /(PEM|DER|NET)/i ) {
1303              
1304             #this has to be the last option
1305             $command .= "-outdir $outdir " if ($outdir);
1306             $command .= "-infiles @$reqfiles" if ($reqfiles);
1307              
1308             $command .= "-in $reqfile " if ( $reqfile );
1309             } elsif ( $inform =~ /SPKAC/ ) {
1310             if ( not $reqfile ) {
1311             $self->setError (7731012,
1312             $self->{gettext} ("OpenCA::OpenSSL->issueCert: You must specify a requestfile if you use SPKAC."));
1313             return undef;
1314             }
1315             $command .= "-spkac $reqfile ";
1316             } else {
1317             ## no valid format received ...
1318             $self->setError (7731013,
1319             $self->{gettext} ("OpenCA::OpenSSL->issueCert: The requests format (__FORMAT__) is not supported.",
1320             "__FORMAT__", $inform));
1321             return undef;
1322             }
1323              
1324             ## running the OpenSSL command
1325             $self->_debug ("issueCert: openssl=$command");
1326             $ENV{'pwd'} = "$passwd";
1327             $ret = $self->_execute_command (COMMAND => $command, KEY_USAGE => $engine);
1328             delete ($ENV{'pwd'});
1329             unlink ($reqfile) if ($reqdata);
1330             if( not $ret ) {
1331             $self->setError (7731075,
1332             $self->{gettext} ("OpenCA::OpenSSL->issueCert: OpenSSL fails (__ERRNO__). __ERRVAL__",
1333             "__ERRNO__", $self->errno,
1334             "__ERRVAL__", $self->errval));
1335             return undef;
1336             }
1337              
1338             $self->_debug ("issueCert: certificate issued successfully");
1339             return 1;
1340             }
1341              
1342             sub revoke {
1343              
1344             ## CAKEY => $CAkeyfile (Optional)
1345             ## CACERT => $CAcertfile (Optional)
1346             ## PASSWD => $passwd (Optional - if not needed)
1347             ## INFILE => $certFile (PEM Formatted certificate file);
1348             ## CRL_REASON => Reason for revocation
1349             ## unspecified
1350             ## keyCompromise
1351             ## CACompromise
1352             ## affiliationChanged
1353             ## superseded
1354             ## cessationOfOperation
1355             ## certificateHold
1356             ## removeFromCRL
1357             ## holdInstruction
1358             ## keyTime
1359             ## CAkeyTime
1360              
1361             my $self = shift;
1362             my $keys = { @_ };
1363              
1364             my $cakey = $keys->{CAKEY};
1365             $cakey = $self->{KEY} if (not $cakey);
1366             my $cacert = $keys->{CACERT};
1367             $cacert = $self->{PEM_CERT} if (not $cacert);
1368             my $passwd = $keys->{PASSWD};
1369             $passwd = $self->{PASSWD} if (not $passwd);
1370             my $certFile = $keys->{INFILE};
1371             my $crlReason= $keys->{CRL_REASON};
1372              
1373             my $engine = $self->{ENGINE};
1374              
1375             my ( $tmp, $ret );
1376             my $command = "ca -revoke $certFile ";
1377              
1378             if (not $certFile) {
1379             $self->setError (7732011,
1380             $self->{gettext} ("OpenCA::OpenSSL->revoke: No inputfile specified."));
1381             return undef;
1382             }
1383              
1384             if( $engine ) {
1385             $command .= "-engine $engine -keyform ".$self->{KEYFORM}." ";
1386             }
1387              
1388             $command .= "-config " . $self->{cnf}. " " if ( defined($self->{'cnf'}) && $self->{cnf} ne "" );
1389             $command .= "-keyfile $cakey " if( defined($cakey) && $cakey ne "" );
1390             if (not $self->{PIN_CALLBACK} and not $self->{GET_PIN_CALLBACK})
1391             {
1392             $command .= "-passin env:pwd " if ( defined($passwd) && $passwd ne "" );
1393             }
1394             $command .= "-cert $cacert " if ( defined($cacert) && $cacert ne "" );
1395             $command .= "-nouniqueDN " if ( $keys->{NOUNIQUEDN} );
1396             $command .= "-crl_reason $crlReason " if ( $keys->{CRL_REASON} );
1397              
1398             $ENV{'pwd'} = "$passwd";
1399             $ret = $self->_execute_command (COMMAND => $command, KEY_USAGE => $engine);
1400             delete ($ENV{'pwd'});
1401             if( not $ret ) {
1402             $self->setError (7732073,
1403             $self->{gettext} ("OpenCA::OpenSSL->revoke: OpenSSL failed (__ERRNO__). __ERRVAL__" . "

(COMMAND=>$command)",
1404             "__ERRNO__", $self->errno,
1405             "__ERRVAL__", $self->errval));
1406             return undef;
1407             } else {
1408             return 1;
1409             }
1410             }
1411              
1412              
1413             sub issueCrl {
1414              
1415             ## CAKEY => $CAkeyfile
1416             ## CACERT => $CAcertfile
1417             ## PASSWD => $passwd
1418             ## DAYS => $days
1419             ## SECONDS => $seconds
1420             ## EXTS => $extentions
1421             ## OUTFILE => $outfile
1422             ## OUTFORM => PEM|DER|NET|TXT
1423              
1424             my $self = shift;
1425             my $keys = { @_ };
1426              
1427             my $cakey = $keys->{CAKEY};
1428             $cakey = $self->{KEY} if (not $cakey);
1429             my $cacert = $keys->{CACERT};
1430             $cacert = $self->{PEM_CERT} if (not $cacert);
1431             my $hours = $keys->{HOURS};
1432             my $days = $keys->{DAYS};
1433             my $passwd = $keys->{PASSWD};
1434             $passwd = $self->{PASSWD} if (not $passwd);
1435             my $outfile = $keys->{OUTFILE};
1436             my $outform = $keys->{OUTFORM};
1437             my $exts = $keys->{EXTS};
1438             my $extfile = $keys->{EXTFILE};
1439              
1440             my $engine = $self->{ENGINE};
1441            
1442             my ( $ret, $tmp, $tmpfile );
1443             my $command = "ca -gencrl ";
1444              
1445             if( $engine ) {
1446             $command .= "-engine $engine -keyform ".$self->{KEYFORM}." ";
1447             }
1448              
1449             if ( not defined $outfile or $outfile eq "" ){
1450             $tmpfile = $self->{tmpDir} . "/${$}_crl.tmp";
1451             } else {
1452             $tmpfile = $outfile;
1453             }
1454             $command .= "-out $tmpfile ";
1455              
1456             $command .= "-config " . $self->{cnf}. " " if ( defined($self->{'cnf'}) && $self->{cnf} ne "" );
1457             $command .= "-keyfile $cakey " if( defined($cakey) && $cakey ne "" );
1458             if (not $self->{PIN_CALLBACK} and not $self->{GET_PIN_CALLBACK})
1459             {
1460             $command .= "-passin env:pwd " if ( defined($passwd) && $passwd ne "" );
1461             }
1462             $command .= "-cert $cacert " if ( defined($cacert) && $cacert ne "" );
1463             $command .= "-crldays $days " if ( defined($days) && $days ne "" );
1464             $command .= "-crlhours $hours " if ( defined($hours) && $hours ne "" );
1465             $command .= "-crlexts $exts " if ( defined($exts) && $exts ne "" );
1466             $command .= "-extfile $extfile " if ( defined($extfile) && $extfile ne "" );
1467             $command .= "-nouniqueDN " if ( $keys->{NOUNIQUEDN} );
1468              
1469             $ENV{'pwd'} = "$passwd";
1470             $ret = $self->_execute_command (COMMAND => $command, KEY_USAGE => $engine);
1471             delete( $ENV{'pwd'} );
1472              
1473             if( not $ret ) {
1474             $self->setError (7733071,
1475             $self->{gettext} ("OpenCA::OpenSSL->issueCrl: OpenSSL failed (__ERRNO__). __ERRVAL__",
1476             "__ERRNO__", $self->errno,
1477             "__ERRVAL__", $self->errval));
1478             return undef;
1479             }
1480              
1481             $ret = $self->dataConvert( INFILE =>$tmpfile,
1482             OUTFORM =>$outform,
1483             DATATYPE=>"CRL" );
1484              
1485             if( not $ret ) {
1486             $self->setError (7733082,
1487             $self->{gettext} ("OpenCA::OpenSSL->issueCrl: data conversion failed (__ERRNO__). __ERRVAL__",
1488             "__ERRNO__", $self->errno(),
1489             "__ERRVAL__", $self->errval()));
1490             return undef;
1491             }
1492              
1493             if( defined($outfile) && $outfile ne "" ) {
1494             if (not open( FD, ">$outfile" )) {
1495             $self->setError (7733084,
1496             $self->{gettext} ("OpenCA::OpenSSL->issueCrl: Cannot open outfile __FILENAME__ for writing.",
1497             "__FILENAME__", $outfile));
1498             return undef;
1499             }
1500             print FD "$ret";
1501             close( FD );
1502             return 1;
1503             }
1504              
1505             unlink( $tmpfile );
1506             return "$ret";
1507             }
1508              
1509             sub SPKAC {
1510              
1511             my $self = shift;
1512             my $keys = { @_ };
1513              
1514             my $infile = $keys->{INFILE};
1515             my $outfile = $keys->{OUTFILE};
1516             my $spkac = $keys->{SPKAC};
1517              
1518             my $command = "spkac -verify ";
1519             my $tmpfile = $self->{tmpDir} . "/${$}_SPKAC.tmp";
1520              
1521             my $engine = $self->{ENGINE};
1522              
1523             my $ret = "";
1524             my $retVal = 0;
1525             my $tmp;
1526              
1527             if( defined($spkac) && $spkac ne "" ) {
1528             $infile = $self->{tmpDir} . "/${$}_in_SPKAC.tmp";
1529             if (not open( FD, ">$infile" )) {;
1530             $self->setError (7741011,
1531             $self->{gettext} ("OpenCA::OpenSSL->SPKAC: Cannot open infile __FILENAME__ for writing.",
1532             "__FILENAME__", $infile));
1533             return undef;
1534             }
1535             print FD "$spkac\n";
1536             close ( FD );
1537             }
1538              
1539             if( $engine ) {
1540             $command .= "-engine $engine ";
1541             }
1542              
1543             $command .= "-in $infile " if( defined($infile) && $infile ne "" );
1544             if( defined($outfile) && $outfile ne "" ) {
1545             $command .= "-out $outfile ";
1546             } else {
1547             $command .= "-out $tmpfile ";
1548             }
1549              
1550             $ret = $self->_execute_command (COMMAND => $command);
1551              
1552             ## Unlink the infile if it was temporary
1553             unlink $infile if( defined($spkac) && $spkac ne "");
1554              
1555             if (not $ret) {
1556             $self->setError (7741073,
1557             $self->{gettext} ("OpenCA::OpenSSL->SPKAC: OpenSSL failed (__ERRNO__). __ERRVAL__",
1558             "__ERRNO__", $self->errno,
1559             "__ERRVAL__", $self->errval));
1560             return undef;
1561             }
1562              
1563             if( defined($outfile) && $outfile ne "" ) {
1564             return 1;
1565             }
1566              
1567             ## Get the output
1568             if (not open( TMP, "$tmpfile" )) {
1569             $self->setError (7741081,
1570             $self->{gettext} ("OpenCA::OpenSSL->SPKAC: Cannot open tmpfile __FILENAME__.",
1571             "__FILENAME__", $tmpfile));
1572             return undef;
1573             }
1574             while ( $tmp = ) {
1575             $ret .= $tmp;
1576             }
1577             close( TMP );
1578             unlink $tmpfile if (not defined $outfile or $outfile eq "");
1579              
1580             if ( $? != 0 ) {
1581             $self->setError (7741083,
1582             $self->{gettext} ("OpenCA::OpenSSL->SPKAC: Cannot read tmpfile __FILENAME__ successfully (__ERRNO__).",
1583             "__FILENAME__", $tmpfile,
1584             "__ERRNO__", $?));
1585             return undef;
1586             }
1587              
1588             return $ret;
1589             }
1590              
1591             sub getFingerprint {
1592             my $self = shift;
1593              
1594             my $keys = { @_ };
1595              
1596             my $alg = lc ( $keys->{ALGORITHM} );
1597             my $cert = $keys->{CERT};
1598              
1599             if ( $alg eq "" ) {
1600             $alg = "sha1";
1601             }
1602              
1603             if ( not $cert or not $cert->getPEM()) {
1604             return undef;
1605             }
1606              
1607             my $cert_dat = OpenCA::OpenSSL::X509::_new_from_pem ($cert->getPEM());
1608              
1609             return OpenCA::OpenSSL::X509::fingerprint ( $cert_dat, $alg );
1610              
1611             # return getDigest ( DATA => $keys->{DATA},
1612             # ALGORITHM => $alg,
1613             # ENGINE => $keys->{ENGINE} );
1614             }
1615              
1616              
1617             sub getDigest {
1618              
1619             ## Returns Digest of the provided message
1620             ## DATA=>$data, ALGORITHM=>$alg
1621              
1622             my $self = shift;
1623             my $keys = { @_ };
1624            
1625             my $data = $keys->{DATA};
1626             my $alg = lc( $keys->{ALGORITHM} );
1627              
1628             my $engine = $self->{ENGINE};
1629              
1630             my ( $command, $ret );
1631              
1632             $alg = "sha256" if( not $alg );
1633              
1634             if (not $data) {
1635             $self->setError (7751011,
1636             $self->{gettext} ("OpenCA::OpenSSL->getDigest: No data specified."));
1637             return undef;
1638             }
1639              
1640             $command = "dgst -$alg ";
1641              
1642             if( defined($engine) and ($engine ne "")) {
1643             $command .= "-engine $engine ";
1644             }
1645              
1646             $ret = $self->_execute_command (COMMAND => $command, INPUT => $data);
1647             $ret =~ s/\n//g;
1648             $ret =~ s/^[^=]+=\s+//;
1649              
1650             if( not $ret ) {
1651             $self->setError (7751071,
1652             $self->{gettext} ("OpenCA::OpenSSL->getDigest: OpenSSL failed (__ERRNO__). __ERRVAL__",
1653             "__ERRNO__", $self->errno,
1654             "__ERRVAL__", $self->errval));
1655             return undef;
1656             } else {
1657             return $ret;
1658             }
1659             }
1660              
1661             # The common invocation mode requires a DATA specification (signed text)
1662             # and a SIGNATURE (detached PKCS#7 signature).
1663             # If OPAQUESIGNATURE is set, DATA and DATA_FILE must not be specified,
1664             # and SIGNATURE or SIGNATURE_FILE must hold a PKCS#7 object containing
1665             # both data and signature.
1666             sub verify {
1667              
1668             ## Verify PKCS7 signatures (new OpenCA::verify command
1669             ## should be used )
1670              
1671             my $self = shift;
1672             my $keys = { @_ };
1673              
1674             my $data = $keys->{DATA};
1675             my $datafile= $keys->{DATA_FILE};
1676             my $sig = $keys->{SIGNATURE};
1677             my $sigfile = $keys->{SIGNATURE_FILE};
1678             my $cacert = $keys->{CA_CERT};
1679             $cacert = $self->{PEM_CERT} if (not $cacert);
1680             my $cadir = $keys->{CA_DIR};
1681             my $verbose = $keys->{VERBOSE};
1682             my $out = $keys->{OUTFILE};
1683             my $noChain = $keys->{NOCHAIN};
1684             my $opaquesig = $keys->{OPAQUESIGNATURE};
1685             my $tmpfile = $self->{tmpDir} . "/${$}_vrfy.tmp";
1686             my $command = $self->{verify} . " ";
1687              
1688             my ( $ret, $tmp );
1689              
1690             if((not $opaquesig) and (not $data) and (not $datafile) ) {
1691             $self->_debug ("verify: cannot open command");
1692             $self->setError (7742011,
1693             $self->{gettext} ("OpenCA::OpenSSL->verify: No input source specified."));
1694             return undef;
1695             }
1696              
1697             if ((not $opaquesig) and (not $datafile)) {
1698             $datafile = $self->{tmpDir} . "/${$}_data.tmp";
1699             if (not open (FD, ">".$datafile)) {
1700             $self->setError (7742023,
1701             $self->{gettext} ("OpenCA::OpenSSL->verify: Cannot open datafile __FILENAME__ for writing.",
1702             "__FILENAME__", $datafile));
1703             return undef;
1704             }
1705             print FD $data;
1706             close FD;
1707             } else {
1708             $data = 0;
1709             }
1710              
1711             if (not $sigfile) {
1712             $sigfile = $self->{tmpDir} . "/${$}_sig.tmp";
1713             if (not open (FD, ">".$sigfile)) {
1714             $self->setError (7742025,
1715             $self->{gettext} ("OpenCA::OpenSSL->verify: Cannot open sigfile __FILENAME__ for writing.",
1716             "__FILENAME__", $sigfile));
1717             unlink $datafile if ($data);
1718             return undef;
1719             }
1720             print FD $sig;
1721             close FD;
1722             $sig = 1;
1723             } else {
1724             $sig = 0;
1725             }
1726              
1727             $command .= "-verbose " if ( $verbose );
1728             $command .= "-cf $cacert " if ( $cacert );
1729             $command .= "-cd $cadir " if ($cadir);
1730             $command .= "-data $datafile " if ($datafile);
1731             ## the user should know what he is doing
1732             ## $command .= "-no_chain " if ( $noChain and not($cacert or $cadir));
1733             $command .= "-no_chain " if ( $noChain );
1734             $command .= "-in $sigfile" if ( $sigfile );
1735             $command .= ">$out " if ( $out );
1736              
1737             if( not $out ) {
1738             $command .= " >$tmpfile";
1739             }
1740              
1741             $command .= " 2>\&1";
1742              
1743             $self->_debug ("verify: command=$command");
1744              
1745             $ret =`$command`;
1746             my $org_err = $?;
1747              
1748             unlink ($datafile ) if ($data);
1749             unlink ($sigfile) if ($sig);
1750              
1751             $ret = "";
1752             if (not open( TMP, "<$tmpfile" )) {
1753             $self->_debug ("verify: Cannot open tmpfile");
1754             $self->setError (7742082,
1755             $self->{gettext} ("OpenCA::OpenSSL->verify: Cannot open tmpfile __FILENAME__ for reading.",
1756             "__FILENAME__", $tmpfile));
1757             return undef;
1758             }
1759             while( not eof ( TMP ) ) {
1760             $ret .= ;
1761             }
1762             close( TMP );
1763              
1764             if ( $? == 256 ) {
1765             $self->_debug ("verify: error detected");
1766             $self->_debug ("verify: original errorcode: ${?}");
1767             $self->_debug ("verify: deleting error");
1768             $? = 0;
1769             } elsif ( $? != 0 ) {
1770             if ($? == -1)
1771             {
1772             $self->setError (7742071,
1773             $self->{gettext} ("OpenCA::OpenSSL->verify: openca-sv failed with errorcode -1. This usually means that the command __COMMAND__ is not present.",
1774             "__COMMAND__", $self->{verify}));
1775             } elsif ($? == 32256)
1776             {
1777             $self->setError (7742074,
1778             $self->{gettext} ("OpenCA::OpenSSL->verify: openca-sv failed with errorcode 32256. This usually means that the file permissions are wrong for the command __COMMAND__.",
1779             "__COMMAND__", $self->{verify}));
1780             } elsif ($? == 32512)
1781             {
1782             $self->setError (7742072,
1783             $self->{gettext} ("OpenCA::OpenSSL->verify: openca-sv failed with errorcode 32512. This usually means that the command openca-sv is malformed or not present (__COMMAND__).",
1784             "__COMMAND__", $self->{verify}));
1785             } else
1786             {
1787             $self->_debug ("verify: error detected");
1788             $self->_debug ("verify: original errorcode: ${?}");
1789             (my $h) =
1790             ( $ret =~ /(Verify Error\s*.*?\s*:\s*.*?)\n/ );
1791             $self->setError (7742073,
1792             $self->{gettext} ("OpenCA::OpenSSL->verify: openca-sv failed (__ERRNO__). __ERRVAL__",
1793             "__ERRNO__", $org_err,
1794             "__ERRVAL__", $h));
1795             $self->_debug ("verify: errorcode: $self->errno");
1796             $self->_debug ("verify: errormsg: $self->errval");
1797             }
1798             unlink( $tmpfile ) if (not $out);
1799             return undef;
1800             }
1801             unlink( $tmpfile ) if (not $out);
1802             if ($ret =~ /\[Error\]/i)
1803             {
1804             $self->setError (7742075,
1805             $self->{gettext} ("OpenCA::OpenSSL->verify: openca-sv failed. __ERRVAL__",
1806             "__ERRVAL__", $ret));
1807             return undef;
1808             }
1809            
1810              
1811             $self->_debug ("verify: returned data:\n$ret");
1812             if( not $out) {
1813             unlink( $tmpfile );
1814             $self->_debug ("verify: finished successfully (return output)");
1815             return $ret;
1816             } else {
1817             $self->_debug ("verify: finished successfully (return 1)");
1818             return 1;
1819             }
1820             }
1821              
1822             sub sign {
1823              
1824             ## Generate a PKCS7 signature.
1825              
1826             my $self = shift;
1827             my $keys = { @_ };
1828              
1829             my $data = $keys->{DATA};
1830             my $datafile= $keys->{DATA_FILE};
1831             my $out = $keys->{OUT_FILE};
1832             my $certfile= $keys->{CERT_FILE};
1833             $certfile = $self->{PEM_CERT} if (not $certfile);
1834             my $cert = $keys->{CERT};
1835             my $keyfile = $keys->{KEY_FILE};
1836             $keyfile = $self->{KEY} if (not $keyfile);
1837             my $key = $keys->{KEY};
1838             my $nonDetach = $keys->{INCLUDE_DATA};
1839             my $pwd = ( $keys->{PWD} or $keys->{PASSWD} );
1840             $pwd = $self->{PASSWD} if (not $pwd);
1841             my $tmpfile = $self->{tmpDir} . "/${$}_sign.tmp";
1842              
1843             my $command = $self->{sign} . " ";
1844             if( $self->{ENGINE} ) {
1845             my $init = $self->_build_engine_params(KEY_USAGE => "1");
1846             $command .= " -engine $self->{ENGINE} -keyform ".$self->{KEYFORM}." $init ";
1847             }
1848              
1849             my ( $ret );
1850              
1851             if( (not $data) and (not $datafile) ) {
1852             $self->setError (7743011,
1853             $self->{gettext} ("OpenCA::OpenSSL->sign: No input source."));
1854             return undef;
1855             }
1856             if( (not $cert) and (not $certfile) ) {
1857             $self->setError (7743012,
1858             $self->{gettext} ("OpenCA::OpenSSL->sign: No certificate specified."));
1859             return undef;
1860             }
1861             if( (not $key) and (not $keyfile) ) {
1862             $self->setError (7743013,
1863             $self->{gettext} ("OpenCA::OpenSSL->sign: No private key specified."));
1864             return undef;
1865             }
1866              
1867             if ( not $datafile ) {
1868             $datafile = $self->{tmpDir} . "/${$}_data.tmp";
1869             if (not open FD, ">".$datafile) {
1870             $self->setError (7743031,
1871             $self->{gettext} ("OpenCA::OpenSSL->sign: Cannot open datafile __FILENAME__ for writing.",
1872             "__FILENAME__", $datafile));
1873             return undef;
1874             }
1875             print FD $data;
1876             close FD;
1877             } else {
1878             $data = 0;
1879             }
1880             if ( not $keyfile ) {
1881             $keyfile = $self->{tmpDir} . "/${$}_key.tmp";
1882             if (not open FD, ">".$keyfile) {
1883             $self->setError (7743033,
1884             $self->{gettext} ("OpenCA::OpenSSL->sign: Cannot open keyfile __FILENAME__ for writing.",
1885             "__FILENAME__", $keyfile));
1886             unlink ($datafile) if ($data);
1887             return undef;
1888             }
1889             print FD $key;
1890             close FD;
1891             } else {
1892             $key = 0;
1893             }
1894             if ( not $certfile ) {
1895             $certfile = $self->{tmpDir} . "/${$}_cert.tmp";
1896             if (not open FD, ">".$certfile) {
1897             $self->setError (7743035,
1898             $self->{gettext} ("OpenCA::OpenSSL->sign: Cannot open certfile __FILENAME__ for writing.",
1899             "__FILENAME__", $certfile));
1900             unlink ($datafile) if ($data);
1901             unlink ($keyfile) if ($key);
1902             return undef;
1903             }
1904             print FD $cert;
1905             close FD;
1906             } else {
1907             $cert = 0;
1908             }
1909              
1910             $command .= "-in $datafile ";
1911             $command .= "-out $out " if ( $out );
1912             if (not $self->{GET_PIN_CALLBACK})
1913             {
1914             $command .= "-passin env:pwd " if ( $pwd );
1915             }
1916             $command .= "-nd " if ( $nonDetach );
1917              
1918             $command .= "-cert $certfile ";
1919             $command .= " -keyfile $keyfile ";
1920              
1921             if( not $out) {
1922             $command .= " >$tmpfile";
1923             };
1924              
1925             $self->_debug ("sign: $command");
1926              
1927             $ENV{pwd} = "$pwd" if ( $pwd );
1928             $ret =`$command`;
1929             delete ($ENV{pwd});
1930              
1931             if ( $? == 256 ) {
1932             $self->_debug ("sign: Error 256 detected");
1933             $self->_debug ("sign: ignoring error");
1934             } elsif ( $? ) {
1935             unlink( $tmpfile ) if (not $out);
1936             unlink( $datafile ) if ($data);
1937             unlink( $keyfile ) if ($key);
1938             unlink( $certfile ) if ($cert);
1939             if ($? == -1)
1940             {
1941             $self->setError (7743073,
1942             $self->{gettext} ("OpenCA::OpenSSL->sign: openca-sv failed with errorcode -1. This usually means that the command __COMMAND__ is not present.",
1943             "__COMMAND__", $self->{openca_sv}));
1944             } elsif ($? == 32256) {
1945             $self->setError (7743074,
1946             $self->{gettext} ("OpenCA::OpenSSL->sign: openca-sv failed with errorcode 32256. This usually means that the file permissions are wrong for the command __COMMAND__.",
1947             "__COMMAND__", $self->{openca_sv}));
1948             } elsif ($? == 32512) {
1949             $self->setError (7743072,
1950             $self->{gettext} ("OpenCA::OpenSSL->sign: openca-sv failed with errorcode 32512. This usually means that the command openca-sv is malformed or not present (__COMMAND__).",
1951             "__COMMAND__", $self->{openca_sv}));
1952             } else {
1953             $self->setError (7743071,
1954             $self->{gettext} ("OpenCA::OpenSSL->sign: openca-sv failed (__ERRNO__).",
1955             "__ERRNO__", $?));
1956             }
1957             return undef;
1958             }
1959             unlink( $datafile ) if ($data);
1960             unlink( $keyfile ) if ($key);
1961             unlink( $certfile ) if ($cert);
1962              
1963             if( not $out ) {
1964             if (not open( TMP, "<$tmpfile" )) {
1965             $self->setError (7743081,
1966             $self->{gettext} ("OpenCA::OpenSSL->sign: Cannot open tmpfile __FILENAME__ for reading.",
1967             "__FILENAME__", $tmpfile));
1968             return undef;
1969             }
1970             do {
1971             $ret .= ;
1972             } while (not eof(TMP));
1973             close(TMP);
1974              
1975             unlink( $tmpfile );
1976             }
1977              
1978             ## If we are here there have been no errors, so
1979             ## if $ret is empty, let us return a true value...
1980             $ret = 1 if ( not $ret );
1981              
1982             return $ret;
1983             }
1984              
1985             sub encrypt {
1986              
1987             ## Encrypt PKCS7 containers
1988              
1989             my $self = shift;
1990             my $keys = { @_ };
1991             my $data = $keys->{DATA};
1992             my $datafile= $keys->{DATA_FILE};
1993             my $certfile= $keys->{CERT_FILE};
1994             $certfile = $self->{PEM_CERT} if (not $certfile);
1995             my $out = $keys->{OUTFILE};
1996             my $tmpfile = $self->{tmpDir} . "/${$}_decrypt.tmp";
1997             my $command = $self->{encrypt} . " ";
1998              
1999             my ( $ret, $tmp );
2000              
2001             if( (not $data) and (not $datafile) ) {
2002             $self->setError (7747011,
2003             $self->{gettext} ("OpenCA::OpenSSL->encrypt: No input source specified."));
2004             return undef;
2005             }
2006             if( not $certfile ) {
2007             $self->setError (7747012,
2008             $self->{gettext} ("OpenCA::OpenSSL->encrypt: No certificate specified."));
2009             return undef;
2010             }
2011              
2012             if (not $datafile) {
2013             $datafile = $self->{tmpDir} . "/${$}_data.tmp";
2014             if (not open (FD, ">".$datafile)) {
2015             $self->setError (7747023,
2016             $self->{gettext} ("OpenCA::OpenSSL->encrypt: Cannot open datafile __FILENAME__ for writing.",
2017             "__FILENAME__", $datafile));
2018             return undef;
2019             }
2020             print FD $data;
2021             close FD;
2022             } else {
2023             $data = 0;
2024             }
2025              
2026             $command .= "-in $datafile " if ($datafile);
2027             $command .= "-cert $certfile ";
2028             $command .= ">$out " if ( $out );
2029              
2030             if( not $out ) {
2031             $command .= " $tmpfile";
2032             }
2033              
2034             $self->_debug ("encrypt: command=$command");
2035              
2036             $ret =`$command`;
2037             my $org_err = $?;
2038             $self->_debug ("encrypt: question mark: ${?}");
2039             $self->_debug ("encrypt: \@: ${@}");
2040             $self->_debug ("encrypt: ret: $ret");
2041             unlink ($datafile ) if ($data);
2042              
2043             if (not $out)
2044             {
2045             $ret = "";
2046             if (not open( TMP, "<$tmpfile" )) {
2047             $self->_debug ("encrypt: Cannot open tmpfile for reading");
2048             $self->setError (7747082,
2049             $self->{gettext} ("OpenCA::OpenSSL->encrypt: Cannot open tmpfile __FILENAME__ for reading.",
2050             "__FILENAME__", $tmpfile));
2051             return undef;
2052             }
2053             while( not eof ( TMP ) ) {
2054             $ret .= ;
2055             }
2056             close( TMP );
2057             }
2058              
2059             if ( $? == 256 and not $@ )
2060             {
2061             $self->_debug ("encrypt: error detected");
2062             $self->_debug ("encrypt: original errorcode: ${?}");
2063             $self->_debug ("encrypt: deleting error");
2064             $? = 0;
2065             } elsif ($? != 0)
2066             {
2067             if ($? == -1)
2068             {
2069             $self->setError (7747071,
2070             $self->{gettext} ("OpenCA::OpenSSL->encrypt: openca-sv failed with errorcode -1. This usually means that the command __COMMAND__ is not present.",
2071             "__COMMAND__", $self->{encrypt}));
2072             } elsif ($? == 32256)
2073             {
2074             $self->setError (7747074,
2075             $self->{gettext} ("OpenCA::OpenSSL->encrypt: openca-sv failed with errorcode 32256. This usually means that the file permissions are wrong for the command __COMMAND__.",
2076             "__COMMAND__", $self->{encrypt}));
2077             } elsif ($? == 32512)
2078             {
2079             $self->setError (7747072,
2080             $self->{gettext} ("OpenCA::OpenSSL->encrypt: openca-sv failed with errorcode 32512. This usually means that the command openca-sv is malformed or not present (__COMMAND__).",
2081             "__COMMAND__", $self->{encrypt}));
2082             } else
2083             {
2084             $self->_debug ("encrypt: error detected");
2085             $self->_debug ("encrypt: original errorcode: ${?}");
2086             ## (my $h) =
2087             ## ( $ret =~ /(Encrypt Error\s*.*?\s*:\s*.*?)\n/ );
2088             my $h = $ret;
2089              
2090             $self->setError (7747073,
2091             $self->{gettext} ("OpenCA::OpenSSL->encrypt: openca-sv failed (__ERRNO__). __ERRVAL__",
2092             "__ERRNO__", $org_err,
2093             "__ERRVAL__", $h));
2094             $self->_debug ("encrypt: errorcode: $self->errno");
2095             $self->_debug ("encrypt: errormsg: $self->errval");
2096             }
2097             unlink( $tmpfile ) if (not $out);
2098             return undef;
2099             }
2100              
2101             $self->_debug ("encrypt: returned data:\n$ret");
2102             if( not $out) {
2103             unlink( $tmpfile );
2104             $self->_debug ("encrypt: finished successfully (return output)");
2105             return $ret;
2106             } else {
2107             $self->_debug ("encrypt: finished successfully (return 1)");
2108             return 1;
2109             }
2110             }
2111              
2112             sub decrypt {
2113              
2114             ## Extract data from a PKCS7 structure.
2115              
2116             my $self = shift;
2117             my $keys = { @_ };
2118              
2119             my $data = $keys->{DATA};
2120             my $datafile= $keys->{DATA_FILE};
2121             $datafile = $keys->{INFILE} if (not $datafile);
2122             my $out = $keys->{OUT_FILE};
2123             my $certfile= $keys->{CERT_FILE};
2124             $certfile = $self->{PEM_CERT} if (not $certfile);
2125             my $cert = $keys->{CERT};
2126             my $keyfile = $keys->{KEY_FILE};
2127             $keyfile = $self->{KEY} if (not $keyfile);
2128             my $key = $keys->{KEY};
2129             my $pwd = ( $keys->{PWD} or $keys->{PASSWD} );
2130             $pwd = $self->{PASSWD} if (not $pwd);
2131             my $tmpfile = $self->{tmpDir} . "/${$}_decrypt.tmp";
2132              
2133             my $command = $self->{decrypt} . " ";
2134             if( $self->{ENGINE} ) {
2135             my $init = $self->_build_engine_params(KEY_USAGE => "1");
2136             $command .= " -engine $self->{ENGINE} -keyform ".$self->{KEYFORM}." $init ";
2137             }
2138              
2139             my ( $ret );
2140              
2141             if( (not $data) and (not $datafile) ) {
2142             $self->setError (7746011,
2143             $self->{gettext} ("OpenCA::OpenSSL->decrypt: No input source."));
2144             return undef;
2145             }
2146             if( (not $cert) and (not $certfile) ) {
2147             $self->setError (7746012,
2148             $self->{gettext} ("OpenCA::OpenSSL->decrypt: No certificate specified."));
2149             return undef;
2150             }
2151             if( (not $key) and (not $keyfile) ) {
2152             $self->setError (7746012,
2153             $self->{gettext} ("OpenCA::OpenSSL->decrypt: No private key specified."));
2154             return undef;
2155             }
2156              
2157             if ( not $datafile ) {
2158             $datafile = $self->{tmpDir} . "/${$}_data.tmp";
2159             if (not open FD, ">".$datafile) {
2160             $self->setError (7746031,
2161             $self->{gettext} ("OpenCA::OpenSSL->decrypt: Cannot open datafile __FILENAME__ for writing.",
2162             "__FILENAME__", $datafile));
2163             return undef;
2164             }
2165             print FD $data;
2166             close FD;
2167             } else {
2168             $data = 0;
2169             }
2170             if ( not $keyfile ) {
2171             $keyfile = $self->{tmpDir} . "/${$}_key.tmp";
2172             if (not open FD, ">".$keyfile) {
2173             $self->setError (7746033,
2174             $self->{gettext} ("OpenCA::OpenSSL->decrypt: Cannot open keyfile __FILENAME__ for writing.",
2175             "__FILENAME__", $keyfile));
2176             unlink ($datafile) if ($data);
2177             return undef;
2178             }
2179             print FD $key;
2180             close FD;
2181             } else {
2182             $key = 0;
2183             }
2184             if ( not $certfile ) {
2185             $certfile = $self->{tmpDir} . "/${$}_cert.tmp";
2186             if (not open FD, ">".$certfile) {
2187             $self->setError (7746035,
2188             $self->{gettext} ("OpenCA::OpenSSL->decrypt: Cannot open certfile __FILENAME__ for writing.",
2189             "__FILENAME__", $certfile));
2190             unlink ($datafile) if ($data);
2191             unlink ($keyfile) if ($key);
2192             return undef;
2193             }
2194             print FD $cert;
2195             close FD;
2196             } else {
2197             $cert = 0;
2198             }
2199              
2200             $command .= "-in $datafile ";
2201             $command .= "-out $out " if ( $out );
2202             if (not $self->{GET_PIN_CALLBACK})
2203             {
2204             $command .= "-passin env:pwd " if ( $pwd );
2205             }
2206             $command .= "-cert $certfile ";
2207             $command .= " -keyfile $keyfile ";
2208              
2209             if( not $out) {
2210             $command .= " >$tmpfile";
2211             };
2212              
2213             $self->_debug ("decrypt: $command");
2214              
2215             $ENV{pwd} = "$pwd" if ( $pwd );
2216             $ret =`$command`;
2217             delete ($ENV{pwd});
2218              
2219             if ( $? ) {
2220             unlink( $tmpfile ) if (not $out);
2221             unlink( $datafile ) if ($data);
2222             unlink( $keyfile ) if ($key);
2223             unlink( $certfile ) if ($cert);
2224             if ($? == -1)
2225             {
2226             $self->setError (7746073,
2227             $self->{gettext} ("OpenCA::OpenSSL->decrypt: openca-sv failed with errorcode -1. This usually means that the command __COMMAND__ is not present.",
2228             "__COMMAND__", $self->{openca_sv}));
2229             } elsif ($? == 32256)
2230             {
2231             $self->setError (7746074,
2232             $self->{gettext} ("OpenCA::OpenSSL->decrypt: openca-sv failed with errorcode 32256. This usually means that the file permissions are wrong for the command __COMMAND__.",
2233             "__COMMAND__", $self->{openca_sv}));
2234             } elsif ($? == 32512)
2235             {
2236             $self->setError (7746072,
2237             $self->{gettext} ("OpenCA::OpenSSL->decrypt: openca-sv failed with errorcode 32512. This usually means that the command openca-sv is malformed or not present (__COMMAND__).",
2238             "__COMMAND__", $self->{openca_sv}));
2239             } else {
2240             $self->setError (7746071,
2241             $self->{gettext} ("OpenCA::OpenSSL->decrypt: openca-sv failed (__ERRNO__).",
2242             "__ERRNO__", $?));
2243             }
2244             return undef;
2245             }
2246             $self->_debug ("decrypt: openca-sv succeeded");
2247             unlink( $datafile ) if ($data);
2248             unlink( $keyfile ) if ($key);
2249             unlink( $certfile ) if ($cert);
2250              
2251             if( not $out ) {
2252             if (not open( TMP, "<$tmpfile" )) {
2253             $self->setError (7746081,
2254             $self->{gettext} ("OpenCA::OpenSSL->decrypt: Cannot open tmpfile __FILENAME__ for reading.",
2255             "__FILENAME__", $tmpfile));
2256             return undef;
2257             }
2258             do {
2259             $ret .= ;
2260             } while (not eof(TMP));
2261             close(TMP);
2262              
2263             unlink( $tmpfile );
2264             }
2265              
2266             ## If we are here there have been no errors, so
2267             ## if $ret is empty, let us return a true value...
2268             $ret = 1 if ( not $ret );
2269              
2270             return $ret;
2271             }
2272              
2273             sub getCertAttribute {
2274             my $self = shift;
2275             my $keys = { @_ };
2276              
2277             my $cert;
2278              
2279             # $self->_debug("OpenCA::OpenSSL::getCertAttribute() start");
2280              
2281             if ($keys->{INFORM} and $keys->{INFORM} =~ /DER/) {
2282             $cert = OpenCA::OpenSSL::X509::_new_from_der ($keys->{DATA});
2283             } else {
2284             $cert = OpenCA::OpenSSL::X509::_new_from_pem ($keys->{DATA});
2285             }
2286              
2287             # $self->_debug("OpenCA::OpenSSL::getCertAttribute() got cert");
2288              
2289             my @attribute = ();
2290             if( $keys->{ATTRIBUTE_LIST} && ref($keys->{ATTRIBUTE_LIST}) ) {
2291             @attribute = @{$keys->{ATTRIBUTE_LIST}};
2292             } else {
2293             @attribute = ( $keys->{ATTRIBUTE} );
2294             }
2295              
2296             return undef if (not $cert);
2297              
2298             my ( $ret );
2299              
2300             # initialize additional OIDs not present in default OPENSSL
2301             $cert->init_oids;
2302              
2303             foreach my $attribute ( @attribute ) {
2304             $_ = uc $attribute;
2305             my $func;
2306              
2307             SWITCH: {
2308             $func = lc $attribute;
2309             if (/^NOTBEFORE$/) {$func = "notBefore"};
2310             if (/^NOTAFTER$/) {$func = "notAfter"};
2311             if (/^DN$/) {$func = "subject"};
2312             if (/^HASH$/) {$func = "subject_hash"};
2313             }
2314              
2315             # $self->_debug("OpenCA::OpenSSL::getCertAttribute() calling $func ($attribute) ");
2316              
2317             $ret->{$attribute} = $cert->$func;
2318             }
2319              
2320             return $ret;
2321             }
2322              
2323             sub getReqAttribute {
2324             my $self = shift;
2325             my $keys = { @_ };
2326              
2327             ## timing test
2328             ##
2329             ## my $start;
2330             ## use Time::HiRes qw( usleep ualarm gettimeofday tv_interval );
2331             ## $start = [gettimeofday];
2332              
2333             my $csr;
2334             if ($keys->{INFORM} and $keys->{INFORM} =~ /DER/)
2335             {
2336             $csr = OpenCA::OpenSSL::PKCS10::_new_from_der ($keys->{DATA});
2337             } elsif ($keys->{INFORM} and $keys->{INFORM} =~ /SPKAC/) {
2338             $csr = OpenCA::OpenSSL::SPKAC::_new ($keys->{DATA});
2339             } else {
2340             $csr = OpenCA::OpenSSL::PKCS10::_new_from_pem ($keys->{DATA});
2341             }
2342              
2343             my @attribute = ();
2344             if( $keys->{ATTRIBUTE_LIST} && ref($keys->{ATTRIBUTE_LIST}) ) {
2345             @attribute = @{$keys->{ATTRIBUTE_LIST}};
2346             } else {
2347             @attribute = ( $keys->{ATTRIBUTE} );
2348             }
2349              
2350             return undef if (not $csr);
2351              
2352             my ( $ret );
2353              
2354             foreach my $attribute ( @attribute ) {
2355             $_ = uc $attribute;
2356             my $func;
2357             SWITCH: {
2358             $func = lc $attribute;
2359             if (/^DN$/) {$func = "subject"};
2360             }
2361             $ret->{$attribute} = $csr->$func;
2362             }
2363              
2364             ## timing test
2365             ##
2366             ## if ($self->{DEBUG}) {
2367             ## $errno += tv_interval ( $start ) if ($self->{DEBUG});
2368             ## print "OpenCA::OpenSSL::getReqAttribute: total_time=".$errno."
\n";
2369             ## }
2370              
2371             return $ret;
2372             }
2373              
2374             sub getCRLAttribute {
2375             my $self = shift;
2376             my $keys = { @_ };
2377              
2378             my $crl;
2379             if ($keys->{INFORM} and $keys->{INFORM} =~ /DER/)
2380             {
2381             $crl = OpenCA::OpenSSL::CRL::_new_from_der ($keys->{DATA});
2382             } else {
2383             $crl = OpenCA::OpenSSL::CRL::_new_from_pem ($keys->{DATA});
2384             }
2385              
2386             my @attribute = ();
2387             if( $keys->{ATTRIBUTE_LIST} && ref($keys->{ATTRIBUTE_LIST}) ) {
2388             @attribute = @{$keys->{ATTRIBUTE_LIST}};
2389             } else {
2390             @attribute = ( $keys->{ATTRIBUTE} );
2391             }
2392              
2393             return undef if (not $crl);
2394              
2395             my ( $ret );
2396              
2397             foreach my $attribute ( @attribute ) {
2398             $_ = uc $attribute;
2399             my $func;
2400             SWITCH: {
2401             $func = lc $attribute;
2402             if (/^LASTUPDATE$/) {$func = "lastUpdate"};
2403             if (/^NEXTUPDATE$/) {$func = "nextUpdate"};
2404             if (/^DN$/) {$func = "issuer"};
2405             }
2406             $ret->{$attribute} = $crl->$func;
2407             }
2408             return $ret;
2409             }
2410              
2411             sub pkcs7Certs {
2412              
2413             my $self = shift;
2414             my $keys = { @_ };
2415              
2416             my $infile = $keys->{INFILE};
2417             my $outfile = $keys->{OUTFILE};
2418             my $pkcs7 = $keys->{PKCS7};
2419              
2420             my $command = "pkcs7 -print_certs ";
2421             my $tmpfile = $self->{tmpDir} . "/${$}_SPKAC.tmp";
2422              
2423             my $engine = $self->{ENGINE};
2424              
2425             my $ret = "";
2426             my $retVal = 0;
2427             my $tmp;
2428              
2429             if( defined($pkcs7) && $pkcs7 ne "" ) {
2430             $infile = $self->{tmpDir} . "/${$}_in_SPKAC.tmp";
2431             if (not open( FD, ">$infile" )) {
2432             $self->setError (7744021,
2433             $self->{gettext} ("OpenCA::OpenSSL->pkcs7Certs: Cannot open infile __FILENAME__ for writing.",
2434             "__FILENAME__", $infile));
2435             return undef;
2436             }
2437             print FD $pkcs7."\n";
2438             close ( FD );
2439             }
2440              
2441             if( defined($engine) and ($engine ne "")) {
2442             $command .= "-engine $engine ";
2443             }
2444              
2445             $command .= "-in $infile " if( defined($infile) && $infile ne "" );
2446             if( defined($outfile) && $outfile ne "" ) {
2447             $command .= "-out $outfile ";
2448             } else {
2449             $command .= "-out $tmpfile ";
2450             }
2451              
2452             $self->_debug ("pkcs7Certs: command=$command");
2453             $ret = $self->_execute_command(COMMAND => $command);
2454             if( not $ret ) {
2455             $self->setError (7744071,
2456             $self->{gettext} ("OpenCA::OpenSSL->pkcs7Certs: OpenSSL failed (__ERRNO__). __ERRVAL__",
2457             "__ERRNO__", $self->errno,
2458             "__ERRVAL__", $self->errval));
2459             unlink $infile if( defined($pkcs7) && $pkcs7 ne "");
2460             unlink $tmpfile if (not (defined($outfile)) or $outfile eq "");
2461             return undef;
2462             }
2463              
2464             ## Unlink the infile if it was temporary
2465             unlink $infile if( defined($pkcs7) && $pkcs7 ne "");
2466              
2467             ## Get the output
2468             if (not open( TMP, $tmpfile )) {
2469             $self->setError (7744081,
2470             $self->{gettext} ("OpenCA::OpenSSL->pkcs7Certs: Cannot open tmpfile __FILENAME__ for reading.",
2471             "__FILENAME__", $tmpfile));
2472             return undef;
2473             }
2474             $ret = "";
2475             while ( $tmp = ) {
2476             $ret .= $tmp;
2477             }
2478             close( TMP );
2479             unlink $tmpfile if (not (defined($outfile)) or $outfile eq "");
2480              
2481             $self->_debug ("pkcs7Certs: finished successfully");
2482             return $ret;
2483             }
2484              
2485             sub updateDB {
2486              
2487             my $self = shift;
2488             my $keys = { @_ };
2489              
2490             my $cakey = $keys->{CAKEY};
2491             $cakey = $self->{KEY} if (not $cakey);
2492             my $cacert = $keys->{CACERT};
2493             $cacert = $self->{PEM_CERT} if (not $cacert);
2494             my $passwd = $keys->{PASSWD};
2495             $passwd = $self->{PASSWD} if (not $passwd);
2496             my $outfile = $keys->{OUTFILE};
2497              
2498             my ( $ret, $tmp );
2499             my $command = "ca -updatedb ";
2500              
2501             $command .= "-config " . $self->{cnf}. " " if ( defined($self->{'cnf'}) && $self->{cnf} ne "" );
2502             $command .= "-keyfile $cakey " if( defined($cakey) && $cakey ne "" );
2503             $command .= "-passin env:pwd " if ( defined($passwd) && $passwd ne "" );
2504             $command .= "-cert $cacert " if ( defined($cacert) && $cacert ne "" );
2505              
2506             $ENV{'pwd'} = "$passwd";
2507             $ret = $self->_execute_command (COMMAND => $command);
2508             delete( $ENV{'pwd'} );
2509              
2510             if( not $ret ) {
2511             $self->setError (7771071,
2512             $self->{gettext} ("OpenCA::OpenSSL->updateDB: OpenSSL failed (__ERRNO__). __ERRVAL__",
2513             "__ERRNO__", $self->errno,
2514             "__ERRVAL__", $self->errval));
2515             return undef;
2516             }
2517              
2518             if( defined($outfile) && $outfile ne "" ) {
2519             if (not open( FD, ">$outfile" )) {
2520             $self->setError (7771081,
2521             $self->{gettext} ("OpenCA::OpenSSL->updateDB: Cannot open outfile __FILENAME__ for writing.",
2522             "__FILENAME__", $outfile));
2523             return undef;
2524             }
2525             print FD "$ret";
2526             close( FD );
2527             return 1;
2528             }
2529             return "$ret";
2530             }
2531              
2532             sub getSMIME {
2533              
2534             ## DECRYPT => a true value
2535             ## ENCRYPT => a true value
2536             ## SIGN => a true value
2537             ## CERT => $cert
2538             ## KEY => $key
2539             ## PASSWD => $passwd
2540             ## ENCRYPT_CERT => $enc_cert
2541             ## SIGN_CERT => $sign_cert
2542             ## INFILE => $infile
2543             ## OUTFILE => $outfile
2544             ## DATA => $message
2545             ## MESSAGE => $message (higher priority)
2546             ## TO => $to
2547             ## FROM => $from
2548             ## SUBJECT => $subject
2549              
2550             my $self = shift;
2551             my $keys = { @_ };
2552              
2553             my $decrypt = $keys->{DECRYPT};
2554             my $encrypt = $keys->{ENCRYPT};
2555             my $sign = $keys->{SIGN};
2556             my $cert = $keys->{CERT};
2557             $cert = $self->{PEM_CERT} if (not $cert);
2558             my $key = $keys->{KEY};
2559             $key = $self->{KEY} if (not $key);
2560             my $enc_cert = $keys->{ENCRYPT_CERT};
2561             my $sign_cert = $keys->{SIGN_CERT};
2562             my $passwd = $keys->{PASSWD};
2563             $passwd = $self->{PASSWD} if (not $passwd);
2564             my $infile = $keys->{INFILE};
2565             my $outfile = $keys->{OUTFILE};
2566             my $message = $keys->{DATA};
2567             $message = $keys->{MESSAGE} if ($keys->{MESSAGE});
2568             my $to = $keys->{TO};
2569             my $cc = $keys->{CC};
2570             my $from = $keys->{FROM};
2571             my $subject = $keys->{SUBJECT};
2572              
2573             my $engine = $self->{ENGINE};
2574              
2575             my ( $ret, $tmp, $tmpfile );
2576              
2577             ## smime can only handle file and not stdin
2578             if ($message) {
2579             $infile = $self->{tmpDir} . "/${$}_data.msg";
2580             $self->_debug ("getSMIME: create temporary infile $infile");
2581             $self->_debug ("getSMIME: the data is like follows\n$message");
2582             if (not open FD, ">".$infile) {
2583             $self->setError (7752021,
2584             $self->{gettext} ("OpenCA::OpenSSL->getSMIME: Cannot write message to tmpfile __FILENAME__.",
2585             "__FILENAME__", $infile));
2586             return undef;
2587             }
2588             print FD "From: $from\n";
2589             print FD "To: $to\n";
2590             foreach my $address (@{$cc})
2591             {
2592             print FD "Cc: $address\n";
2593             }
2594             print FD "Subject: $subject\n";
2595             my $encoding = setlocale (LC_MESSAGES);
2596              
2597             if ($encoding ne "C") {
2598             $encoding =~ s/^.*\.//; ## remove language
2599             } else {
2600             $encoding = 'UTF-8';
2601             }
2602             $encoding =~ s/(UTF|ISO|EUC)([^-]{1})/$1-$2/i; ## on FreeBSD "locale" returns charset names
2603             ## which do not comply with IANA standard for
2604             ## MIME
2605            
2606             print FD "Content-Type: text/plain; charset=$encoding; format=flowed\n".
2607             "Content-Transfer-Encoding: 8bit\n";
2608             print FD "\n".$message;
2609             close FD;
2610             } else {
2611             $message = 0;
2612             }
2613              
2614             ## setup file with smime-message
2615             if ($outfile) {
2616             $tmpfile = $outfile;
2617             } else {
2618             $tmpfile = $self->{tmpDir}."/".$$."_SMIME.msg";
2619             }
2620              
2621             $enc_cert = $cert if (not $enc_cert);
2622             $sign_cert = $cert if (not $sign_cert);
2623              
2624             my ($enc_x509, $sign_x509);
2625             if ($enc_cert)
2626             {
2627             $enc_x509 = OpenCA::X509->new (
2628             SHELL => $self,
2629             GETTEXT => $self->{gettext},
2630             INFILE => $enc_cert);
2631             if (not $enc_x509)
2632             {
2633             unlink $infile if ($message);
2634             return $self->setError ($OpenCA::X509::errno, $OpenCA::X509::errval);
2635             }
2636             }
2637             $self->_debug ("getSMIME: enccert object ready");
2638             if ($sign_cert) {
2639             $sign_x509 = OpenCA::X509->new (
2640             SHELL => $self,
2641             GETTEXT => $self->{gettext},
2642             INFILE => $sign_cert);
2643             if (not $sign_x509) {
2644             unlink $infile if ($message);
2645             return $self->setError ($OpenCA::X509::errno, $OpenCA::X509::errval);
2646             }
2647             }
2648             $self->_debug ("getSMIME: signcert object ready");
2649              
2650             ## use OpenCA::OpenSSL::SMIME
2651             ## this is only a wrapper for old code !!!
2652              
2653             ## decryption
2654             my $smime = OpenCA::OpenSSL::SMIME->new(
2655             INFILE => $infile,
2656             SHELL => $self,
2657             ENGINE => $engine,
2658             KEYFORM => $self->{KEYFORM},
2659             GETTEXT => $self->{gettext},
2660             TMPDIR => $self->{tmpDir},
2661             DEBUG => $self->{DEBUG}
2662             # DEBUG => 1
2663             );
2664             if (not $smime) {
2665              
2666             $self->_debug ("getSMIME: smime object failed");
2667              
2668             unlink $infile if ($message);
2669             return $self->setError ($OpenCA::OpenSSL::SMIME::errno,
2670             $OpenCA::OpenSSL::SMIME::err);
2671             }
2672              
2673             $self->_debug ("getSMIME: smime object ready");
2674              
2675             if ($decrypt) {
2676             open(KEYF, '<', $key) or return;
2677             if (not $smime->decrypt(
2678             CERTIFICATE => $enc_x509,
2679             KEY_PASSWORD => $passwd,
2680             PRIVATE_KEY => \*KEYF)) {
2681             close (KEYF);
2682             unlink $infile if ($message);
2683             return $self->setError ($smime->errno, $smime->errval);
2684             }
2685             close (KEYF);
2686             } else {
2687             ## 1. signing
2688             if ( $sign eq "1" ) {
2689             open(KEYF, '<', $key) or return;
2690             if (not $smime->sign(
2691             CERTIFICATE => $sign_x509,
2692             KEY_PASSWORD => $passwd,
2693             PRIVATE_KEY => \*KEYF)) {
2694             close (KEYF);
2695              
2696             $self->_debug("ERROR::Can not sign SMIME (" .
2697             $smime->errno . "::" .
2698             $smime->errval );
2699              
2700             unlink $infile if ($message);
2701              
2702             return $self->setError ($smime->errno, $smime->errval);
2703             }
2704             close (KEYF);
2705             }
2706             if ($encrypt) {
2707             if (not $smime->encrypt(CERTIFICATE => $enc_x509))
2708             {
2709             unlink $infile if ($message);
2710             return $self->setError ($smime->errno, $smime->errval);
2711             }
2712             }
2713             }
2714              
2715              
2716             $self->_debug ("getSMIME: final steps ( $outfile / $smime )");
2717              
2718             unlink $infile if ($message);
2719              
2720             $self->_debug ("getSMIME: return data :: " . $smime->get_mime );
2721              
2722             ## if the caller want a file then we can finish
2723             if( defined($outfile) && $outfile ne "" ) {
2724             open (OUT, ">", $outfile);
2725             $smime->get_mime->print(\*OUT);
2726             close (OUT);
2727             return 1;
2728             }
2729              
2730             if( defined ($smime) and defined($smime->get_mime)
2731             and defined($smime->get_mime->stringify) ) {
2732             return $smime->get_mime->stringify
2733             } else {
2734             return $message;
2735             }
2736             }
2737              
2738             sub getPIN {
2739              
2740             ## PIN_LENGTH => $pin_length
2741             ## RANDOM_LENGTH => $random_length
2742             ## LENGTH => $pin_length
2743              
2744             my $self = shift;
2745             my $keys = { @_ };
2746              
2747             my $pin_length = $keys->{LENGTH};
2748             $pin_length = $keys->{PIN_LENGTH} if (defined $keys->{PIN_LENGTH});
2749             my $length = $keys->{RANDOM_LENGTH};
2750             my $hex = $keys->{HEX};
2751              
2752             my $engine = $self->{ENGINE};
2753              
2754             my ( $ret, $tmp, $tmpfile );
2755              
2756             my $command = " rand ";
2757             if ( $hex ) {
2758             $command .= " -hex ";
2759             } else {
2760             $command .= " -base64 ";
2761             }
2762              
2763             if( $engine ) {
2764             $command .= " -engine $engine ";
2765             }
2766             if ($length) {
2767             $command .= $length;
2768             } elsif ($pin_length) {
2769             $command .= $pin_length;
2770             } else {
2771             return undef;
2772             }
2773              
2774             ## create the PIN
2775             my $pin = $self->_execute_command (COMMAND => $command,
2776             HIDE_OUTPUT => 1);
2777              
2778             if (not $pin) {
2779             $self->setError (7753071,
2780             $self->{gettext} ("OpenCA::OpenSSL->getPIN: OpenSSL failed (__ERRNO). __ERRVAL__",
2781             "__ERRNO__", $self->errno,
2782             "__ERRVAL__", $self->errval));
2783             return undef;
2784             }
2785              
2786             ## remove trailing newline
2787             $pin =~ s/\n//gs;
2788             $pin =~ s/=*$//gs;
2789              
2790             if ($pin_length) {
2791             ## enforce the PIN-length
2792             ## SECURITY ADVICE: it is more secure to only set the
2793             ## number of randombytes
2794             $pin = substr ($pin, 0, $pin_length);
2795             } else {
2796             ## 2*$length is enough to encode $length randombytes in base64
2797             my $hl = 2*$length;
2798             $pin = substr ($pin, 0, $hl);
2799             }
2800              
2801             if ($pin) {
2802             return $pin;
2803             } else {
2804             $self->setError (7753075,
2805             $self->{gettext} ("OpenCA::OpenSSL->getPIN: PIN is empty."));
2806             return undef;
2807             }
2808              
2809             }
2810              
2811             sub getOpenSSLDate {
2812             my $self = shift;
2813              
2814             if (not defined $_[0]) {
2815             $self->setError (7754011,
2816             $self->{gettext} ("OpenCA::OpenSSL->getOpenSSLDate: No date specified."));
2817             return undef;
2818             }
2819             my $date = $self->getNumericDate ( $_[0] );
2820             if (not defined $date) {
2821             $self->{errval} = $self->{gettext} ("OpenCA::OpenSSL->getOpenSSLDate: Errorcode 7754021: __ERRVAL__",
2822             "__ERRVAL__", $self->{errval});
2823             return undef;
2824             }
2825              
2826             ## remove century
2827             $date =~ s/^..//;
2828              
2829             ## add trailing Z
2830             $date .= "Z";
2831              
2832             return $date;
2833             }
2834              
2835             sub getNumericDate {
2836             my $self = shift;
2837             my %help;
2838             my $new_date;
2839              
2840             my $date = $_[0];
2841              
2842             # if (not defined $_[0]) {
2843             # $self->setError (7755011,
2844             # $self->{gettext} ("OpenCA::OpenSSL->getNumericDate: No argument specified."));
2845             # return undef;
2846             # }
2847             if (not $date) {
2848             $date = gmtime();
2849              
2850             # $self->setError (7755012,
2851             # $self->{gettext} ("OpenCA::OpenSSL->getNumericDate: No date specified."));
2852             # return undef;
2853             }
2854              
2855             ## remove leading days like SUN or MON
2856             if ( $date =~ /^\s*[^\s]+\s+(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)/i ) {
2857             $date =~ s/^\s*[^\s]+//;
2858             }
2859              
2860             ## Mar 10 19:36:45 2001 GMT
2861              
2862             ## Month
2863             if ( $date =~ /^\s*JAN/i ) {
2864             ## january
2865             $help {MONTH} = "01";
2866             } elsif ( $date =~ /^\s*FEB/i ) {
2867             ## february
2868             $help {MONTH} = "02";
2869             } elsif ( $date =~ /^\s*MAR/i ) {
2870             ## march
2871             $help {MONTH} = "03";
2872             } elsif ( $date =~ /^\s*APR/i ) {
2873             ## april
2874             $help {MONTH} = "04";
2875             } elsif ( $date =~ /^\s*MAY/i ) {
2876             ## may
2877             $help {MONTH} = "05";
2878             } elsif ( $date =~ /^\s*JUN/i ) {
2879             ## june
2880             $help {MONTH} = "06";
2881             } elsif ( $date =~ /^\s*JUL/i ) {
2882             ## july
2883             $help {MONTH} = "07";
2884             } elsif ( $date =~ /^\s*AUG/i ) {
2885             ## august
2886             $help {MONTH} = "08";
2887             } elsif ( $date =~ /^\s*SEP/i ) {
2888             ## september
2889             $help {MONTH} = "09";
2890             } elsif ( $date =~ /^\s*OCT/i ) {
2891             ## october
2892             $help {MONTH} = "10";
2893             } elsif ( $date =~ /^\s*NOV/i ) {
2894             ## november
2895             $help {MONTH} = "11";
2896             } elsif ( $date =~ /^\s*DEC/i ) {
2897             ## december
2898             $help {MONTH} = "12";
2899             } else {
2900             my @call = caller ( 1 );
2901             ## return illegal
2902             $self->setError (7755022,
2903             $self->{gettext} ("OpenCA::OpenSSL->getNumericDate: Illegal month."));
2904             print STDERR $call[2] . "::" . $call[1] . "->" .
2905             "[orig was $date]\n";
2906              
2907             return undef;
2908             }
2909              
2910             ## day
2911             $date =~ s/^ *//;
2912             $date = substr ($date, 4, length ($date)-4);
2913             $help {DAY} = substr ($date, 0, 2);
2914             $help {DAY} =~ s/ /0/;
2915              
2916             ## hour
2917             $help {HOUR} = substr ($date, 3, 2);
2918              
2919             ## minute
2920             $help {MINUTE} = substr ($date, 6, 2);
2921              
2922             ## second
2923             $help {SECOND} = substr ($date, 9, 2);
2924              
2925             ## year
2926             $help {YEAR} = substr ($date, 12, 4);
2927              
2928             ## build date
2929             $new_date = $help {YEAR}.
2930             $help {MONTH}.
2931             $help {DAY}.
2932             $help {HOUR}.
2933             $help {MINUTE}.
2934             $help {SECOND};
2935              
2936             return $new_date;
2937              
2938             }
2939              
2940             sub getNumericDateDays {
2941             my $self = shift;
2942             my $date = shift;
2943             my $tmpVal = undef;
2944             my @monVals = ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 );
2945             my $counter = 0;
2946             my $ret = 0;
2947              
2948             if( not $date ) {
2949             $date = gmtime();
2950             }
2951              
2952             $date = $self->getNumericDate ( $date ) if ( $date =~ /[a-zA-Z]+/ );
2953              
2954             # Years * 365
2955             $tmpVal = substr ( $date, 0, 4) * 365;
2956             $ret += $tmpVal;
2957              
2958             # Months
2959             $tmpVal = substr ( $date, 4, 2 );
2960             for ( my $counter = 1; $counter < $tmpVal ; $counter++ ) {
2961             $ret += $monVals[$counter - 1];
2962             }
2963              
2964             $tmpVal = substr ( $date, 6, 2 );
2965             $ret += $tmpVal;
2966              
2967             return $ret;
2968             }
2969              
2970             ##############################################################
2971             ## OpenSSL execution environment ##
2972             ## BEGIN ##
2973             ##############################################################
2974              
2975             sub _start_shell
2976             {
2977             my $self = shift;
2978             $self->_debug ("_start_shell: try to start shell");
2979             my $keys = { @_ };
2980              
2981             return 1 if ($self->{OPENSSL});
2982              
2983             my $open = "| ".$self->{shell}.
2984             " 1>$self->{tmpDir}/${$}_stdout.log".
2985             " 2>$self->{tmpDir}/${$}_stderr.log";
2986             $self->_debug ("_start_shell: $open");
2987             if (not open $self->{OPENSSL}, $open)
2988             {
2989             my $msg = $self->{gettext} ("Cannot start OpenSSL shell. (__ERRVAL__)",
2990             "__ERRVAL__", $!);
2991             $self->setError (7777030, $msg);
2992             return undef;
2993             }
2994             $self->_debug ("_start_shell: shell started");
2995              
2996             if ($self->{ENGINE} and
2997             (
2998             exists $self->{PRE_ENGINE} or
2999             exists $self->{POST_ENGINE}
3000             )
3001             )
3002             {
3003             $self->_debug ("_start_shell: initializing engine");
3004             my $command;
3005             if ($self->{DYNAMIC_ENGINE}) {
3006             $command = "engine dynamic -pre ID:".$self->{ENGINE};
3007             } else {
3008             $command = "engine ".$self->{ENGINE};
3009             }
3010             $command .= $self->_build_engine_params(KEY_USAGE => $keys->{KEY_USAGE});
3011             $command .= "\n";
3012             if (not print {$self->{OPENSSL}} $command)
3013             {
3014             my $msg = $self->{gettext} ("Cannot write to the OpenSSL shell. (__ERRVAL__)",
3015             "__ERRVAL__", $!);
3016             $self->setError (7777040, $msg);
3017             return undef;
3018             }
3019              
3020             $self->_debug ("_start_shell: engine intialized");
3021             }
3022              
3023             return 1;
3024             }
3025              
3026             sub _stop_shell
3027             {
3028             my $self = shift;
3029             $self->_debug ("_stop_shell: try to stop shell");
3030              
3031             return 1 if (not $self->{OPENSSL});
3032              
3033             print {$self->{OPENSSL}} "exit\n";
3034             close $self->{OPENSSL};
3035             $self->{OPENSSL} = undef;
3036              
3037             return 1;
3038             }
3039              
3040             sub _execute_command
3041             {
3042             my $self = shift;
3043             $self->_debug ("_execute_command: entering function");
3044             my $keys = { @_ };
3045              
3046             ## initialize openssl (with engine if necessary)
3047              
3048             return undef if (not $self->_start_shell(KEY_USAGE => $keys->{KEY_USAGE}));
3049              
3050             ## run command
3051              
3052             my $command = $keys->{COMMAND};
3053             my $input = undef;
3054             $input = $keys->{INPUT} if (exists $keys->{INPUT});
3055             $command =~ s/\n*$//;
3056             $command .= "\n";
3057             $self->_debug ("_execute_command: $command");
3058             if (not print {$self->{OPENSSL}} $command)
3059             {
3060             my $msg = $self->{gettext} ("Cannot write to the OpenSSL shell. (__ERRVAL__)",
3061             "__ERRVAL__", $!);
3062             $self->setError (7777060, $msg);
3063             return undef;
3064             }
3065             $self->_debug ("_execute_command: executed");
3066              
3067             ## if key is used and pin callback is set then use it
3068            
3069             if ($keys->{KEY_USAGE} and
3070             $self->{PIN_CALLBACK} and
3071             $self->{CALLBACK_HANDLER})
3072             {
3073             $self->_debug ("_execute_command: executing pin callback");
3074             $self->{PIN_CALLBACK} ($self->{CALLBACK_HANDLER});
3075             $self->_debug ("_execute_command: pin callback executed");
3076             }
3077              
3078             ## send the input
3079              
3080             if ($input and not print {$self->{OPENSSL}} $input."\x00")
3081             {
3082             $self->_debug ("_execute_command: write input data");
3083             my $msg = $self->{gettext} ("Cannot write to the OpenSSL shell. (__ERRVAL__)",
3084             "__ERRVAL__", $!);
3085             $self->setError (7777065, $msg);
3086             return undef;
3087             }
3088             $self->_debug ("_execute_command: command executed - stopping shell");
3089             return undef if (not $self->_stop_shell());
3090              
3091             ## check for errors
3092              
3093             $self->_debug ("_execute_command: check for error");
3094              
3095             if (-e "$self->{tmpDir}/${$}_stderr.log")
3096             {
3097             $self->_debug ("_execute_command: detected error log");
3098             ## there was an error
3099             my $ret = "";
3100             if (open FD, "$self->{tmpDir}/${$}_stderr.log")
3101             {
3102             while( my $tmp = ) {
3103             $ret .= $tmp;
3104             }
3105             close(FD);
3106             }
3107             $self->_debug ("_execute_command: stderr: $ret");
3108             if ($self->{ENGINE} and
3109             (
3110             exists $self->{PRE_ENGINE} or
3111             exists $self->{POST_ENGINE}
3112             ) and
3113             $self->{STDERR_CALLBACK} and
3114             $self->{CALLBACK_HANDLER})
3115             {
3116             $self->_debug ("_execute_command: executing stderr callback");
3117             $ret = $self->{STDERR_CALLBACK} ($self->{CALLBACK_HANDLER}, $ret);
3118             $self->_debug ("_execute_command: stderr callback executed");
3119             }
3120             unlink ("$self->{tmpDir}/${$}_stderr.log");
3121             if ($ret =~ /error/i)
3122             {
3123             unlink ("$self->{tmpDir}/${$}_stdout.log");
3124             $self->setError (7777067, $ret);
3125             return undef;
3126             }
3127            
3128             }
3129              
3130             ## load the output
3131              
3132             my $ret = 1;
3133             if (-e "$self->{tmpDir}/${$}_stdout.log" and
3134             open FD, "$self->{tmpDir}/${$}_stdout.log")
3135             {
3136             ## there was an output
3137             $ret = "";
3138             while( my $tmp = ) {
3139             $ret .= $tmp;
3140             }
3141             close(FD);
3142             if ($self->{ENGINE} and
3143             (
3144             exists $self->{PRE_ENGINE} or
3145             exists $self->{POST_ENGINE}
3146             ) and
3147             $self->{STDOUT_CALLBACK} and
3148             $self->{CALLBACK_HANDLER})
3149             {
3150             $self->_debug ("_execute_command: executing stdout callback");
3151             $ret = $self->{STDOUT_CALLBACK} ($self->{CALLBACK_HANDLER}, $ret);
3152             $self->_debug ("_execute_command: stdout callback executed");
3153             }
3154             $ret =~ s/^(OpenSSL>\s)*//s;
3155             $ret =~ s/OpenSSL>\s$//s;
3156             $ret = 1 if ($ret eq "");
3157             }
3158             unlink ("$self->{tmpDir}/${$}_stdout.log");
3159              
3160             my $msg = $ret;
3161             $msg = "" if ($keys->{HIDE_OUTPUT});
3162              
3163             $self->_debug ("_execute_command: leaving successful (return: $msg)");
3164             return $ret;
3165             }
3166              
3167             sub _build_engine_params
3168             {
3169             my $self = shift;
3170             my $keys = { @_ };
3171              
3172             my $command = "";
3173              
3174             ## set the pre init commands for the engine
3175              
3176             if (exists $self->{PRE_ENGINE})
3177             {
3178             if (ref $self->{PRE_ENGINE})
3179             {
3180             foreach my $item (@{$self->{PRE_ENGINE}})
3181             {
3182             $command .= " -pre $item";
3183             }
3184             } else
3185             {
3186             $command .= " -pre ".$self->{PRE_ENGINE};
3187             }
3188             }
3189              
3190             ## set the post init commands for the engine
3191              
3192             if (exists $self->{POST_ENGINE})
3193             {
3194             if (ref $self->{POST_ENGINE})
3195             {
3196             foreach my $item (@{$self->{POST_ENGINE}})
3197             {
3198             $command .= " -post $item";
3199             }
3200             } else
3201             {
3202             $command .= " -post ".$self->{POST_ENGINE};
3203             }
3204             }
3205              
3206             $self->_debug ("_build_engine_params: $command");
3207              
3208             ## set the pin if there is no pin callback for the engine
3209             ## this must be present after -pre SO_PATH:... because
3210             ## otherwise PIN is executed on
3211             ## the original pkcs11 engine for example which is from Bull and does
3212             ## not support PINs like OpenSC
3213              
3214             if ($keys->{KEY_USAGE} and
3215             $self->{GET_PIN_CALLBACK} and
3216             $self->{CALLBACK_HANDLER}
3217             )
3218             {
3219             $self->_debug ("_build_engine_params: GET_PIN_CALLBACK used");
3220             $command .= " ".$self->{GET_PIN_CALLBACK} ($self->{CALLBACK_HANDLER});
3221             } else {
3222             $self->_debug ("_build_engine_params: GET_PIN_CALLBACK not present or not used");
3223             }
3224              
3225             return $command;
3226             }
3227              
3228             ##############################################################
3229             ## END ##
3230             ## OpenSSL execution environment ##
3231             ##############################################################
3232              
3233             sub _debug
3234             {
3235             my $self = shift;
3236              
3237             return 1 if (not $self->{DEBUG});
3238              
3239             my $text = join (" ", @_);
3240             $text =~ s/PIN:[^\s]*/PIN:ERASING_FOR_SECURITY/g;
3241             $text =~ s/-----BEGIN RSA PRIVATE KEY.*?END RSA PRIVATE KEY-----/RSA PRIVATE KEY ERASED FROM OUTPUT/gs;
3242              
3243             print STDERR "OpenCA::OpenSSL->$text\n";
3244              
3245             return 1;
3246             }
3247              
3248             sub DESTROY
3249             {
3250             my $self = shift;
3251              
3252             $self->_stop_shell();
3253             }
3254              
3255             ################################################################################
3256             ## OpenCA::OpenSSL::Fast area ##
3257             ################################################################################
3258              
3259             require Exporter;
3260             use AutoLoader;
3261              
3262             our @ISA = qw(Exporter);
3263              
3264             # Items to export into callers namespace by default. Note: do not export
3265             # names by default without a very good reason. Use EXPORT_OK instead.
3266             # Do not simply export all your public functions/methods/constants.
3267              
3268             # This allows declaration use OpenCA::OpenSSL::Fast ':all';
3269             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
3270             # will save memory.
3271             our %EXPORT_TAGS = ( 'all' => [ qw(
3272             CTX_TEST
3273             EXFLAG_BCONS
3274             EXFLAG_CA
3275             EXFLAG_INVALID
3276             EXFLAG_KUSAGE
3277             EXFLAG_NSCERT
3278             EXFLAG_SET
3279             EXFLAG_SS
3280             EXFLAG_V1
3281             EXFLAG_XKUSAGE
3282             GEN_DIRNAME
3283             GEN_DNS
3284             GEN_EDIPARTY
3285             GEN_EMAIL
3286             GEN_IPADD
3287             GEN_OTHERNAME
3288             GEN_RID
3289             GEN_URI
3290             GEN_X400
3291             KU_CRL_SIGN
3292             KU_DATA_ENCIPHERMENT
3293             KU_DECIPHER_ONLY
3294             KU_DIGITAL_SIGNATURE
3295             KU_ENCIPHER_ONLY
3296             KU_KEY_AGREEMENT
3297             KU_KEY_CERT_SIGN
3298             KU_KEY_ENCIPHERMENT
3299             KU_NON_REPUDIATION
3300             NS_OBJSIGN
3301             NS_OBJSIGN_CA
3302             NS_SMIME
3303             NS_SMIME_CA
3304             NS_SSL_CA
3305             NS_SSL_CLIENT
3306             NS_SSL_SERVER
3307             X509V3_EXT_CTX_DEP
3308             X509V3_EXT_DYNAMIC
3309             X509V3_EXT_MULTILINE
3310             X509V3_F_COPY_EMAIL
3311             X509V3_F_COPY_ISSUER
3312             X509V3_F_DO_EXT_CONF
3313             X509V3_F_DO_EXT_I2D
3314             X509V3_F_HEX_TO_STRING
3315             X509V3_F_I2S_ASN1_ENUMERATED
3316             X509V3_F_I2S_ASN1_INTEGER
3317             X509V3_F_I2V_AUTHORITY_INFO_ACCESS
3318             X509V3_F_NOTICE_SECTION
3319             X509V3_F_NREF_NOS
3320             X509V3_F_POLICY_SECTION
3321             X509V3_F_R2I_CERTPOL
3322             X509V3_F_S2I_ASN1_IA5STRING
3323             X509V3_F_S2I_ASN1_INTEGER
3324             X509V3_F_S2I_ASN1_OCTET_STRING
3325             X509V3_F_S2I_ASN1_SKEY_ID
3326             X509V3_F_S2I_S2I_SKEY_ID
3327             X509V3_F_STRING_TO_HEX
3328             X509V3_F_SXNET_ADD_ASC
3329             X509V3_F_SXNET_ADD_ID_INTEGER
3330             X509V3_F_SXNET_ADD_ID_ULONG
3331             X509V3_F_SXNET_GET_ID_ASC
3332             X509V3_F_SXNET_GET_ID_ULONG
3333             X509V3_F_V2I_ACCESS_DESCRIPTION
3334             X509V3_F_V2I_ASN1_BIT_STRING
3335             X509V3_F_V2I_AUTHORITY_KEYID
3336             X509V3_F_V2I_BASIC_CONSTRAINTS
3337             X509V3_F_V2I_CRLD
3338             X509V3_F_V2I_EXT_KU
3339             X509V3_F_V2I_GENERAL_NAME
3340             X509V3_F_V2I_GENERAL_NAMES
3341             X509V3_F_V3_GENERIC_EXTENSION
3342             X509V3_F_X509V3_ADD_VALUE
3343             X509V3_F_X509V3_EXT_ADD
3344             X509V3_F_X509V3_EXT_ADD_ALIAS
3345             X509V3_F_X509V3_EXT_CONF
3346             X509V3_F_X509V3_EXT_I2D
3347             X509V3_F_X509V3_GET_VALUE_BOOL
3348             X509V3_F_X509V3_PARSE_LIST
3349             X509V3_F_X509_PURPOSE_ADD
3350             X509V3_R_BAD_IP_ADDRESS
3351             X509V3_R_BAD_OBJECT
3352             X509V3_R_BN_DEC2BN_ERROR
3353             X509V3_R_BN_TO_ASN1_INTEGER_ERROR
3354             X509V3_R_DUPLICATE_ZONE_ID
3355             X509V3_R_ERROR_CONVERTING_ZONE
3356             X509V3_R_ERROR_IN_EXTENSION
3357             X509V3_R_EXPECTED_A_SECTION_NAME
3358             X509V3_R_EXTENSION_NAME_ERROR
3359             X509V3_R_EXTENSION_NOT_FOUND
3360             X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED
3361             X509V3_R_EXTENSION_VALUE_ERROR
3362             X509V3_R_ILLEGAL_HEX_DIGIT
3363             X509V3_R_INVALID_BOOLEAN_STRING
3364             X509V3_R_INVALID_EXTENSION_STRING
3365             X509V3_R_INVALID_NAME
3366             X509V3_R_INVALID_NULL_ARGUMENT
3367             X509V3_R_INVALID_NULL_NAME
3368             X509V3_R_INVALID_NULL_VALUE
3369             X509V3_R_INVALID_NUMBER
3370             X509V3_R_INVALID_NUMBERS
3371             X509V3_R_INVALID_OBJECT_IDENTIFIER
3372             X509V3_R_INVALID_OPTION
3373             X509V3_R_INVALID_POLICY_IDENTIFIER
3374             X509V3_R_INVALID_SECTION
3375             X509V3_R_INVALID_SYNTAX
3376             X509V3_R_ISSUER_DECODE_ERROR
3377             X509V3_R_MISSING_VALUE
3378             X509V3_R_NEED_ORGANIZATION_AND_NUMBERS
3379             X509V3_R_NO_CONFIG_DATABASE
3380             X509V3_R_NO_ISSUER_CERTIFICATE
3381             X509V3_R_NO_ISSUER_DETAILS
3382             X509V3_R_NO_POLICY_IDENTIFIER
3383             X509V3_R_NO_PUBLIC_KEY
3384             X509V3_R_NO_SUBJECT_DETAILS
3385             X509V3_R_ODD_NUMBER_OF_DIGITS
3386             X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS
3387             X509V3_R_UNABLE_TO_GET_ISSUER_KEYID
3388             X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT
3389             X509V3_R_UNKNOWN_EXTENSION
3390             X509V3_R_UNKNOWN_EXTENSION_NAME
3391             X509V3_R_UNKNOWN_OPTION
3392             X509V3_R_UNSUPPORTED_OPTION
3393             X509V3_R_USER_TOO_LONG
3394             X509_PURPOSE_ANY
3395             X509_PURPOSE_CRL_SIGN
3396             X509_PURPOSE_DYNAMIC
3397             X509_PURPOSE_DYNAMIC_NAME
3398             X509_PURPOSE_MAX
3399             X509_PURPOSE_MIN
3400             X509_PURPOSE_NS_SSL_SERVER
3401             X509_PURPOSE_SMIME_ENCRYPT
3402             X509_PURPOSE_SMIME_SIGN
3403             X509_PURPOSE_SSL_CLIENT
3404             X509_PURPOSE_SSL_SERVER
3405             XKU_CODE_SIGN
3406             XKU_SGC
3407             XKU_SMIME
3408             XKU_SSL_CLIENT
3409             XKU_SSL_SERVER
3410             ) ] );
3411              
3412             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
3413              
3414             our @EXPORT = qw(
3415             CTX_TEST
3416             EXFLAG_BCONS
3417             EXFLAG_CA
3418             EXFLAG_INVALID
3419             EXFLAG_KUSAGE
3420             EXFLAG_NSCERT
3421             EXFLAG_SET
3422             EXFLAG_SS
3423             EXFLAG_V1
3424             EXFLAG_XKUSAGE
3425             GEN_DIRNAME
3426             GEN_DNS
3427             GEN_EDIPARTY
3428             GEN_EMAIL
3429             GEN_IPADD
3430             GEN_OTHERNAME
3431             GEN_RID
3432             GEN_URI
3433             GEN_X400
3434             KU_CRL_SIGN
3435             KU_DATA_ENCIPHERMENT
3436             KU_DECIPHER_ONLY
3437             KU_DIGITAL_SIGNATURE
3438             KU_ENCIPHER_ONLY
3439             KU_KEY_AGREEMENT
3440             KU_KEY_CERT_SIGN
3441             KU_KEY_ENCIPHERMENT
3442             KU_NON_REPUDIATION
3443             NS_OBJSIGN
3444             NS_OBJSIGN_CA
3445             NS_SMIME
3446             NS_SMIME_CA
3447             NS_SSL_CA
3448             NS_SSL_CLIENT
3449             NS_SSL_SERVER
3450             X509V3_EXT_CTX_DEP
3451             X509V3_EXT_DYNAMIC
3452             X509V3_EXT_MULTILINE
3453             X509V3_F_COPY_EMAIL
3454             X509V3_F_COPY_ISSUER
3455             X509V3_F_DO_EXT_CONF
3456             X509V3_F_DO_EXT_I2D
3457             X509V3_F_HEX_TO_STRING
3458             X509V3_F_I2S_ASN1_ENUMERATED
3459             X509V3_F_I2S_ASN1_INTEGER
3460             X509V3_F_I2V_AUTHORITY_INFO_ACCESS
3461             X509V3_F_NOTICE_SECTION
3462             X509V3_F_NREF_NOS
3463             X509V3_F_POLICY_SECTION
3464             X509V3_F_R2I_CERTPOL
3465             X509V3_F_S2I_ASN1_IA5STRING
3466             X509V3_F_S2I_ASN1_INTEGER
3467             X509V3_F_S2I_ASN1_OCTET_STRING
3468             X509V3_F_S2I_ASN1_SKEY_ID
3469             X509V3_F_S2I_S2I_SKEY_ID
3470             X509V3_F_STRING_TO_HEX
3471             X509V3_F_SXNET_ADD_ASC
3472             X509V3_F_SXNET_ADD_ID_INTEGER
3473             X509V3_F_SXNET_ADD_ID_ULONG
3474             X509V3_F_SXNET_GET_ID_ASC
3475             X509V3_F_SXNET_GET_ID_ULONG
3476             X509V3_F_V2I_ACCESS_DESCRIPTION
3477             X509V3_F_V2I_ASN1_BIT_STRING
3478             X509V3_F_V2I_AUTHORITY_KEYID
3479             X509V3_F_V2I_BASIC_CONSTRAINTS
3480             X509V3_F_V2I_CRLD
3481             X509V3_F_V2I_EXT_KU
3482             X509V3_F_V2I_GENERAL_NAME
3483             X509V3_F_V2I_GENERAL_NAMES
3484             X509V3_F_V3_GENERIC_EXTENSION
3485             X509V3_F_X509V3_ADD_VALUE
3486             X509V3_F_X509V3_EXT_ADD
3487             X509V3_F_X509V3_EXT_ADD_ALIAS
3488             X509V3_F_X509V3_EXT_CONF
3489             X509V3_F_X509V3_EXT_I2D
3490             X509V3_F_X509V3_GET_VALUE_BOOL
3491             X509V3_F_X509V3_PARSE_LIST
3492             X509V3_F_X509_PURPOSE_ADD
3493             X509V3_R_BAD_IP_ADDRESS
3494             X509V3_R_BAD_OBJECT
3495             X509V3_R_BN_DEC2BN_ERROR
3496             X509V3_R_BN_TO_ASN1_INTEGER_ERROR
3497             X509V3_R_DUPLICATE_ZONE_ID
3498             X509V3_R_ERROR_CONVERTING_ZONE
3499             X509V3_R_ERROR_IN_EXTENSION
3500             X509V3_R_EXPECTED_A_SECTION_NAME
3501             X509V3_R_EXTENSION_NAME_ERROR
3502             X509V3_R_EXTENSION_NOT_FOUND
3503             X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED
3504             X509V3_R_EXTENSION_VALUE_ERROR
3505             X509V3_R_ILLEGAL_HEX_DIGIT
3506             X509V3_R_INVALID_BOOLEAN_STRING
3507             X509V3_R_INVALID_EXTENSION_STRING
3508             X509V3_R_INVALID_NAME
3509             X509V3_R_INVALID_NULL_ARGUMENT
3510             X509V3_R_INVALID_NULL_NAME
3511             X509V3_R_INVALID_NULL_VALUE
3512             X509V3_R_INVALID_NUMBER
3513             X509V3_R_INVALID_NUMBERS
3514             X509V3_R_INVALID_OBJECT_IDENTIFIER
3515             X509V3_R_INVALID_OPTION
3516             X509V3_R_INVALID_POLICY_IDENTIFIER
3517             X509V3_R_INVALID_SECTION
3518             X509V3_R_INVALID_SYNTAX
3519             X509V3_R_ISSUER_DECODE_ERROR
3520             X509V3_R_MISSING_VALUE
3521             X509V3_R_NEED_ORGANIZATION_AND_NUMBERS
3522             X509V3_R_NO_CONFIG_DATABASE
3523             X509V3_R_NO_ISSUER_CERTIFICATE
3524             X509V3_R_NO_ISSUER_DETAILS
3525             X509V3_R_NO_POLICY_IDENTIFIER
3526             X509V3_R_NO_PUBLIC_KEY
3527             X509V3_R_NO_SUBJECT_DETAILS
3528             X509V3_R_ODD_NUMBER_OF_DIGITS
3529             X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS
3530             X509V3_R_UNABLE_TO_GET_ISSUER_KEYID
3531             X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT
3532             X509V3_R_UNKNOWN_EXTENSION
3533             X509V3_R_UNKNOWN_EXTENSION_NAME
3534             X509V3_R_UNKNOWN_OPTION
3535             X509V3_R_UNSUPPORTED_OPTION
3536             X509V3_R_USER_TOO_LONG
3537             X509_PURPOSE_ANY
3538             X509_PURPOSE_CRL_SIGN
3539             X509_PURPOSE_DYNAMIC
3540             X509_PURPOSE_DYNAMIC_NAME
3541             X509_PURPOSE_MAX
3542             X509_PURPOSE_MIN
3543             X509_PURPOSE_NS_SSL_SERVER
3544             X509_PURPOSE_SMIME_ENCRYPT
3545             X509_PURPOSE_SMIME_SIGN
3546             X509_PURPOSE_SSL_CLIENT
3547             X509_PURPOSE_SSL_SERVER
3548             XKU_CODE_SIGN
3549             XKU_SGC
3550             XKU_SMIME
3551             XKU_SSL_CLIENT
3552             XKU_SSL_SERVER
3553             );
3554              
3555             ## we take the version from OpenSSL.pm
3556             ## our $VERSION = '0.02';
3557              
3558             sub AUTOLOAD {
3559             # This AUTOLOAD is used to 'autoload' constants from the constant()
3560             # XS function.
3561              
3562             my $constname;
3563             our $AUTOLOAD;
3564             ($constname = $AUTOLOAD) =~ s/.*:://;
3565             croak "&OpenCA::OpenSSL::constant not defined" if $constname eq 'constant';
3566             my ($error, $val) = constant($constname);
3567             if ($error) { croak $error; }
3568             {
3569             no strict 'refs';
3570             # Fixed between 5.005_53 and 5.005_61
3571             #XXX if ($] >= 5.00561) {
3572             #XXX *$AUTOLOAD = sub () { $val };
3573             #XXX }
3574             #XXX else {
3575             *$AUTOLOAD = sub { $val };
3576             #XXX }
3577             }
3578             goto &$AUTOLOAD;
3579             }
3580              
3581             require XSLoader;
3582             XSLoader::load('OpenCA::OpenSSL', $OpenCA::OpenSSL::VERSION);
3583              
3584             # Autoload methods go after =cut, and are processed by the autosplit program.
3585              
3586             1;
3587              
3588             __END__