> Projeto Final schrieb:
> 
> Hello,
> 
> When we tried to change the passphrase of the key, still in the
> initialization
> of the CA (phase 2 and 3 - handle the certificate), we received an
> error stating
> that we couldn�t change the passphrase of the key. The apache error
> log states
> that:
> 
> no keyfile specified
> unable to load key
> General Error Trapped 700: Cannot change passphrase of key! at
> /usr/lib/perl5/5.6.0/i386-linux/misc-utils.lib line 32.
> Compilation failed in require at /usr/local/OpenCA/cgi-bin/ca/ca line
> 192

The problem is that "openssl pkcs8" cannot handle stdin but the
documentation says it can do it. I changed OpenSSL.pm in
src/modules/openca-openssl/. I attached the changed OpenSSL.pm.

Best Regards,

Michael
-- 
-------------------------------------------------------------------
Michael Bell                   Email (private): [EMAIL PROTECTED]
Rechenzentrum - Datacenter     Email:  [EMAIL PROTECTED]
Humboldt-University of Berlin  Tel.: +49 (0)30-2093 2482
Unter den Linden 6             Fax:  +49 (0)30-2093 2959
10099 Berlin
Germany                                       http://www.openca.org
## OpenCA::OpenSSL
##
## Copyright (C) 1998-2001 Massimiliano Pala ([EMAIL PROTECTED])
## All rights reserved.
##
## This library is free for commercial and non-commercial use as long as
## the following conditions are aheared to.  The following conditions
## apply to all code found in this distribution, be it the RC4, RSA,
## lhash, DES, etc., code; not just the SSL code.  The documentation
## included with this distribution is covered by the same copyright terms
## 
## Copyright remains Massimiliano Pala's, and as such any Copyright notices
## in the code are not to be removed.
## If this package is used in a product, Massimiliano Pala should be given
## attribution as the author of the parts of the library used.
## This can be in the form of a textual message at program startup or
## in documentation (online or textual) provided with the package.
## 
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## 1. Redistributions of source code must retain the copyright
##    notice, this list of conditions and the following disclaimer.
## 2. Redistributions in binary form must reproduce the above copyright
##    notice, this list of conditions and the following disclaimer in the
##    documentation and/or other materials provided with the distribution.
## 3. All advertising materials mentioning features or use of this software
##    must display the following acknowledgement:
##    "This product includes OpenCA software written by Massimiliano Pala
##     ([EMAIL PROTECTED]) and the OpenCA Group (www.openca.org)"
## 4. If you include any Windows specific code (or a derivative thereof) from 
##    some directory (application code) you must include an acknowledgement:
##    "This product includes OpenCA software (www.openca.org)"
## 
## THIS SOFTWARE IS PROVIDED BY OPENCA DEVELOPERS ``AS IS'' AND
## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
## ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
## SUCH DAMAGE.
## 
## The licence and distribution terms for any publically available version or
## derivative of this code cannot be changed.  i.e. this code cannot simply be
## copied and put under another distribution licence
## [including the GNU Public Licence.]
##
## Contributions by:
##          Martin Leung <[EMAIL PROTECTED]>
##          Uwe Gansert <[EMAIL PROTECTED]>

use strict;

package OpenCA::OpenSSL;

$OpenCA::OpenSSL::VERSION = '0.9.51';
($OpenCA::OpenSSL::VERSION = '$Revision: 1.25 $' )=~ s/(?:^.*: 
(\d+))|(?:\s+\$$)/defined $1?"0\.9":"a"/eg;

## Global Variables Go HERE
my %params = (
         shell => undef,
         cnf => undef,
         tmpDir => undef,
         baseDir => undef,
         verify => undef,
         sign => undef,
         errno => undef,
         errval => undef
);

## Create an instance of the Class
sub new {
        my $that = shift;
        my $class = ref($that) || $that;

        my $self = {
                %params,
        };

        bless $self, $class;

        my $keys = { @_ };

        $self->setParams( @_ );

        if( not $self->{binDir} ) {
                $self->{binDir} = "/usr/bin";
        };

        if( not $self->{shell} ) {
                $self->{shell} = "$self->{binDir}/openssl";
        };

        if( not $self->{verify} ) {
                $self->{verify} = "$self->{binDir}/verify";
        };

        if( not $self->{sign} ) {
                $self->{sign} = "$self->{binDir}/sign";
        };

        if( not $self->{tmpDir} ) {
                $self->{tmpDir} = '/tmp';
        };

        if( not -e "$self->{shell}" ) {
                return;
        };

        $self->{errno} = 0;
        $self->{errval} = "";

        return $self;
}


sub setParams {

        my $self = shift;
        my $params = { @_ };
        my $key;

        foreach $key ( keys %{$params} ) {

                $self->{cnf} = $params->{$key}     if ( $key =~ /CONFIG/ );
                $self->{shell} = $params->{$key}   if ( $key =~ /SHELL/  );
                $self->{tmpDir} = $params->{$key}  if ( $key =~ /TMPDIR/ );
                $self->{binDir} = $params->{$key} if ( $key =~ /BINDIR/ );
                $self->{verify} = $params->{$key}  if ( $key =~ /VERIFY/ );
                $self->{sign} = $params->{$key}  if ( $key =~ /SIGN/ );
                open STDERR, $params->{$key} if ( $key =~ /STDERR/ );
        }

        return 1;
}

sub errno {
        my $self = shift;

        return $self->{errno};
}

sub errval {
        my $self = shift;

        return $self->{errval};
}

sub genKey {

        ## Generate a new key, arguments accepted are, in order
        ##  ( BITS=>$bits, OUTFILE=>$outfile, ALGORITHM=>$alg, PASSWD=>$passwd )

        my $self = shift;
        my $keys = { @_ };

        my $bits    = $keys->{BITS};
        my $outfile = $keys->{OUTFILE};
        my $alg     = $keys->{ALGORITHM};
        my $passwd  = $keys->{PASSWD};
        my $engine  = ( $ENV{'engine'} or $keys->{ENGINE} );
        my $rand    = $keys->{RAND};

        my $command = "$self->{shell} genrsa ";

        if( $engine ) {
                $command .= "-engine $engine ";
        }

        if( $passwd ) {
                $command .= "-passout env:pwd ";
                $alg = "des" if ( not(defined($alg)) or $alg eq "" );
        }

        if ( defined($alg) && $alg ne "" ) {
                $command .= "-$alg ";
        }

        if ( defined($outfile) && $outfile ne "" ) {
                $command .= "-out $outfile ";
        }

        $ENV{'pwd'} = "$passwd" if( defined($passwd) );

        if ( defined($rand) && $rand ne "" ) {
                $command .= "-rand \"$rand\" ";
        } else {
                $ENV{'RANDFILE'} = "/tmp/.rand_${$}";
        }

        $command .= $bits if( defined($bits) );

        $ENV{'pwd'} = "$passwd" if( defined( $passwd));
        open(FD, "$command|" ) or return;
                ## Send Password
                ## if( $passwd ) {
                ##      print FD "$passwd\n";
                ## }

                ## Send Confirmation Password
                ## print FD "$passwd\n";
        close(FD);

        delete ($ENV{'pwd'}) if( defined($passwd));
        delete ($ENV{'RANDFILE'}) if (defined($ENV{'RANDFILE'}));

        if( not defined( $rand )) {
                unlink( "/tmp/.rand_${$}" );
        }

        return if( $? != 0 );
        return "$!";
}

sub genReq {

        ## Generate a Request file, parameter accepted are
        ## ( $outfile, $keyfile, $passwd , [email, cn, ou, o, c ] )
        ## To utilize null passwd simply pass a "" reference.

        my $self = shift;
        my $keys = { @_ };

        my $engine  = ( $ENV{'engine'} or $keys->{ENGINE} );

        my $outfile = $keys->{OUTFILE};
        my $outform = $keys->{OUTFORM};
        my $keyfile = $keys->{KEYFILE};
        my $subject = $keys->{SUBJECT};
        my $passwd  = $keys->{PASSWD};
        my $command = "$self->{shell} req -new ";
        my $tmpfile = $self->{tmpDir} . "/${$}_req.pem";
        my ( $ret, $tmp, @DN );

        return if( not $keyfile );

        if( defined $keys->{DN} ) {
                @DN = @{ $keys->{DN} };
        }

        if ( defined($self->{cnf}) && $self->{cnf} ne "" ) {
                $command .= "-config " . $self->{cnf} . " ";
        }

        $command .= "-passin env:pwd " if ( defined($passwd) && $passwd ne "" );
        $command .= "-subj \"$subject\" " if ( defined( $subject) && $subject ne "" );

        if( $engine ) {
                $command .= "-engine $engine ";
        }


        if( defined($outform) ) {
                $outform = uc( $outform );

                if ( $outform =~ /(PEM|DER)/i ) {
                        $command .= "-outform $outform ";
                } elsif ( $outform =~ /(TXT)/ ) {
                        $command .= "-text -noout ";
                }
        }

        if ( $outfile ne "" ) {
                $command .= "-out $outfile ";
        } else {
                $command .= " >$tmpfile ";
        }
        
        $command .= "-key $keyfile ";

        $ENV{'pwd'} = "$passwd" if( defined($passwd));
        open( FD, "|$command" ) or return ;
                if( not defined ($subject) or ( $subject eq "") ) {
                        foreach $tmp (@DN) {
                                print FD "$tmp\n";
                        }
                }
        close(FD);
        delete( $ENV{'pwd'} ) if( defined($passwd) );

        if( $? != 0 ) {
                return;
        }

        if( not(defined($outfile)) || $outfile eq "" ) {
                open( FD, "<$tmpfile" ) or return;
                        while( $tmp = <FD> ) {
                                $ret .= $tmp;
                        }
                close(FD);
                unlink( "$tmpfile" );

                return $ret;
        }

        
        return defined;
}

sub genCert {

        ## Generate a new Certificate file, parameter accepted are
        ## (OUTFILE=>$outfile,KEYFILE=>$keyfile,REQFILE=>$reqfile,
        ## PASSWD=>$passwd, DN=>[ @list ] )

        my $self = shift;
        my $keys = { @_ };

        my $outfile = $keys->{OUTFILE};
        my $keyfile = $keys->{KEYFILE};
        my $reqfile = $keys->{REQFILE};
        my $subject = $keys->{SUBJECT};
        my $noemail = $keys->{NOEMAILDN};
        my $passwd  = $keys->{PASSWD};
        my $days    = $keys->{DAYS};
        my $tmpfile = $self->{tmpDir} . "/${$}_crt.tmp";

        my $engine  = ( $ENV{'engine'} or $keys->{ENGINE} );

        my $command = "$self->{shell} req -x509 ";

        my ( $ret, $tmp );

        return if( (not $keyfile) or (not $reqfile) );

        if( $engine ) {
                $command .= "-engine $engine ";
        }

        ## $command .= "-subj \"$subject\" "
        ##      if ( defined($subject) && ($subject ne "") );

        ## $command .= "-noemailDN "
        ##      if ( defined($noemail) && ($noemail ne "") );

        $command .= "-passin env:pwd " 
                if ( defined($passwd) && $passwd ne "" );

        $command .= "-config ". $self->{cnf} . " "
                if ( defined($self->{'cnf'}) && $self->{cnf} ne "" );

        $command .= "-days $days " 
                if ( defined($days) && $days =~ /\d+/ && $days > 0 );

        $command .= "-in \"$reqfile\" -key \"$keyfile\" ";


        if( defined($outfile) && $outfile ne "" ) {
                $command .= "-out \"$outfile\" ";
        } else {
                $command .= "-out \"$tmpfile\" ";
        }

        $ENV{'pwd'} = "$passwd" if( defined($passwd) );
        $ret = `$command`;
        delete( $ENV{'pwd'} ) if( defined($passwd) );

        return if( $? != 0 );

        if( $? != 0 ) {
                return;
        }

        ## if( defined($outfile) && $outfile eq "" ) {

        if( not(defined($outfile)) or $outfile eq "" ) {
                open( FD, "<$tmpfile" ) or return;
                        while( $tmp = <FD> ) {
                                $ret .= $tmp;
                        }
                close(FD);
                unlink( "$tmpfile" );
        }

        return "$ret";
}

sub crl2pkcs7 {
        my $self = shift;
        my $keys = { @_ };

        my $data    = $keys->{DATA};
        my $crlfile = $keys->{CRLFILE};
        my $inform  = $keys->{INFORM};
        my $outfile = $keys->{OUTFILE};
        my $outform = $keys->{OUTFORM};

        my ( $ret, $tmp, $tmpfile, $command );
        my $command = "$self->{shell} crl2pkcs7 ";

        if( (not(defined($data)) or $data eq "") and
                        (not(defined($crlfile)) or $crlfile eq "" )) {
                $command .= "-nocrl ";
        }

        if ( not(defined($crlfile)) || $crlfile eq "" ){
                $tmpfile = $self->{tmpDir} . "/${$}_incrl.tmp";
                open( FD, ">$tmpfile" ) or exit 1;
                print FD "$data";
                close( FD );
        } else {
                $tmpfile = $crlfile;
        }
        $command .= "-in $tmpfile ";

        $command .= "-out $outfile "
                if ( defined($outfile) and $outfile ne "");
        $command .= "-inform $inform "
                if ( defined($inform) and $inform ne "");
        $command .= "-outform $outform "
                if ( defined($outform) and $outform ne "");

        if( defined $keys->{CERTSLIST} ) {
                my @certs = @{ $keys->{CERTSLIST}};

                for (@certs) {
                        $command .= "-certfile \"$_\" "
                                if( ("$_" ne "") and (-f "$_") );
                }
        }

        $ret = `$command`;
        if($? != 0) {
                $self->{errno} = $?;
                $self->{errval} = "Impossible converting to pkcs7 structure";
                $ret = undef;
        } else {
                $ret = 1 if( $outfile ne "" );
        }
        unlink("$tmpfile") if ( $crlfile eq "" );

        return $ret;
}

sub dataConvert {

        ## You can convert data structures to different formats
        ## Accepted parameters are:
        ##
        ##    DATATYPE=> CRL|CERTIFICATE|REQUEST|KEY
        ##    OUTFORM => PEM|DER|NET|TXT|PKCS12|PKCS8
        ##    INFORM  => PEM|DER|NET|TXT|PKCS12|PKCS8
        ##    OUTFILE => $outfile
        ##    INFILE  => $infile
        ##    DATA    => $data
        ##    KEYFILE => $keyfile

        ##    PKCS12 encode parameter :
        ##    INFILE or DATA (must be PEM encoded)
        ##    KEYFILE (might be in front of the DATA or in INFILE)
        ##    P12PASSWD = password for pkcs12 file (optional)
        ##    PASSWD  = password for KEYFILE (optional)
        ##    INPASSWD  = password for KEYFILE (optional)
        ##    OUTPASSWD  = password for KEYFILE (optional)
        ##    OUTFILE = optional
        ##    ALGO    = optionl, default = des3
        ##    DATATYPE must be 'CERTIFICATE'

        ##    PKCS12 decode parameter
        ##    INFILE or DATA (must be PKCS12 encoded)
        ##    P12PASSWD
        ##    PASSWD (PEM password optional)
        ##    OUTFILE = optional
        ##    DATATYPE must be 'CERTIFICATE'    

        my $self = shift;
        my $keys = { @_ };

        my $data    = $keys->{DATA};
        my $type    = $keys->{DATATYPE};
        my $outform = $keys->{OUTFORM};
        my $inform  = $keys->{INFORM};
        my $outfile = $keys->{OUTFILE};
        my $infile  = $keys->{INFILE};
        my $keyfile = $keys->{KEYFILE};
        my $passwd  = $keys->{'PASSWD'};
        my $p12pass = $keys->{'P12PASSWD'};
        my $inpwd   = $keys->{'INPASSWD'};
        my $outpwd  = $keys->{'OUTPASSWD'};
        my $algo    = $keys->{'ALGO'} || 'des3';
        my $nokeys  = $keys->{'NOKEYS'};

        my ( $command, $tmp, $ret, $tmpfile );

        return if ( not $type);
        return if ( (not $data) and (not $infile));
        return if ( not $algo =~ /des3|des|idea/ );
        return if ( defined($nokeys) and ($outform eq 'PKCS12') ); # impossible

        ## Return if $infile does not exists
        return if( defined($infile) and ( not -e $infile ));
        return if( (not $data) and (not $infile) );
        if (not $infile) {
                $infile = $self->{tmpDir} . "/${$}_data.tmp";
                open FD, ">".$infile;
                print FD $data;
                close FD;
        } else {
                $data = 0;
        }

        $outform = "PEM" if( not $outform ); 
        $inform  = "PEM" if( not $inform ); 

        $tmpfile = "$self->{tmpDir}/${$}_cnv.tmp";
        $command = "$self->{shell} ";

        if( $type =~ /CRL/i ) {
                $command .= " crl ";
        } elsif ( $type =~ /CERTIFICATE/i ) {
                if( $outform eq 'PKCS12' or $inform eq 'PKCS12' ) {
                        $command .= ' pkcs12 ';
                } else {
                        $command .= " x509 ";
                }
        } elsif ( $type =~ /REQ/i ) {
                $command .= " req ";
                if ( defined($self->{cnf}) && $self->{cnf} ne "" ) {
                        $command .= "-config " . $self->{cnf} . " ";
                }
        } elsif ( $type =~ /KEY/i ) {
                ## PKCS8 enforces PEM because the OpenSSL command req can
                ## only handle PEM-encoded PKCS#8 keys
                if ( ($outform =~ /PKCS8/i) or ($inform =~ /PKCS8/i) ) {
                        $command .= " pkcs8 ";
                } else {
                        $command .= " rsa ";
                }
                if (not $inpwd or not $outpwd) {
                        unlink ($infile) if ($data);
                        return undef;
                }
                $command .= ' -passin env:inpwd ';
                $command .= ' -passout env:outpwd ';
        } else {
                ## if no known type is given...
                return;
        }

        $outfile = $tmpfile if ( not $outfile );

        $command .= "-out $outfile ";
        $command .= "-in $infile "; 
        $command .= "-inkey $keyfile " if( defined($keyfile) ); #PKCS12 only

        # outform in PKCS12 is always PEM
        if( $outform =~ /TXT/i ) {
                $command .= "-text -noout ";
        } elsif ( $outform =~ /(PEM|DER|NET)/i ) {
                if( $inform eq 'PKCS12' ) {
                        $command .= '-passout env:pempwd 'if( defined($passwd) );
                        $command .= '-passin env:p12pwd ' if( defined($p12pass) );
                        $command .= '-nokeys ' if( defined($nokeys) );
                        if( defined($passwd) ) {
                                $command .= "-$algo " if( $algo eq 'des' or
                                                          $algo eq 'des3' or
                                                          $algo eq 'idea' );
                        } else {
                                $command .= '-nodes' if( not defined($passwd) );
                        }
                } else {
                        $command .= "-outform " . uc($outform) . " ";
                }
        } elsif ( $outform eq 'PKCS12' ) {
                $command .= "-export ";
        } elsif ( $outform =~ /PKCS8/i ) {
                $command .= " -topk8 -outform PEM ";
        } else {
                ## no valid format received...
                unlink ($infile) if ($data);
                return undef;
        }
        if( $outform eq 'PKCS12' ) {
                $command .= '-passout env:p12pwd ';
                $command .= '-passin env:pempwd ' if( defined($passwd) );
        } elsif( $inform =~ /(PEM|DER|NET)/i ) {
                $command .= "-inform " . uc($inform) ." ";
        } elsif( $inform eq 'PKCS12' ) {
                # nothing to do here.
        } else {
                ## no valid format received ...
                unlink ($infile) if ($data);
                return undef;
        }

        $ENV{'p12pwd'} = "$p12pass" if( defined($p12pass) );
        $ENV{'pempwd'} = "$passwd"  if( defined($passwd) );
        $ENV{'inpwd'}  = "$inpwd"   if( defined($inpwd) );
        $ENV{'outpwd'} = "$outpwd"  if( defined($outpwd) );

        if ($self->{DEBUG}) {
                print "OpenCA::OpenSSL->dataConvert: p12pass is set<br>\n" if( 
defined($p12pass) );
                print "OpenCA::OpenSSL->dataConvert: passwd is set<br>\n" if( 
defined($passwd) );
                print "OpenCA::OpenSSL->dataConvert: inpwd is set<br>\n" if( 
defined($inpwd) );
                print "OpenCA::OpenSSL->dataConvert: outpwd is set<br>\n" if( 
defined($outpwd) );
                print "OpenCA::OpenSSL->dataConvert: command=\"".$command."\"<br>\n";
        }

        if( defined($infile) && $infile ne "" ) {
                print "OpenCA::OpenSSL->dataConvert: using infile<br>\n" if 
($self->{DEBUG});
                $ret=`$command`;
        } else {
                print "OpenCA::OpenSSL->dataConvert: piping data<br>\n" if 
($self->{DEBUG});
                print "OpenCA::OpenSSL->dataConvert: data<br>\n$data<br>\n" if 
($self->{DEBUG});
                open( FD, "|$command" ) or return;
                        print FD "$data";
                close( FD );
        }

        ## return if( $? != 0 );
        delete($ENV{'pwd'});
        delete($ENV{'pempwd'});
        delete($ENV{'inpwd'});
        delete($ENV{'outpwd'});

        if( exists $keys->{OUTFILE} ) {
                unlink ($infile) if ($data);
                return 1;
        }

        $ret = "";
        if (not open( TMP, "<$outfile" )) {
                unlink ($infile) if ($data);
                return undef;
        }
        while( $tmp = <TMP> ) {
                $ret .= $tmp;
        }
        close( TMP );
        unlink ($infile) if ($data);
        unlink ($outfile);

        return $ret;
                
}

sub issueCert {

        ## Use this function to issue a certificate using the
        ## ca utility. Use this if you already own a valid CA
        ## certificate. Accepted parameters are:

        ## REQDATA => $data
        ## REQFILE => $reqfilename
        ## INFORM  => PEM|DER|NET|SPKAC   ; defaults to PEM
        ## PRESERVE_DN => Y/N             ; defaults to Y/N
        ## CAKEY   => $CAkeyfile
        ## CACERT  => $CAcertfile
        ## DAYS    => $days
        ## PASSWD  => $passwd
        ## EXTS    => $extentions
        ## REQTYPE => NETSCAPE|MSIE

        my $self = shift;
        my $keys = { @_ };

        my $reqdata  = $keys->{REQDATA};
        my $reqfile  = $keys->{REQFILE};
        my $inform   = $keys->{INFORM};
        my $preserve = ( $keys->{PRESERVE_DN} or "N" );
        my $cakey    = $keys->{CAKEY};
        my $days     = $keys->{DAYS};
        my $startDate= $keys->{START_DATE};
        my $endDate  = $keys->{END_DATE};
        my $passwd   = $keys->{PASSWD};
        my $exts     = $keys->{EXTS};
        my $extFile  = $keys->{EXTFILE};
        my $reqtype  = $keys->{REQTYPE};
        my $subject  = $keys->{SUBJECT};
        my $noemail  = $keys->{NOEMAILDN};

        my $reqfiles =$keys->{REQFILES};
        my $outdir   =$keys->{OUTDIR};
        my $caName   = $keys->{CA_NAME};
        
        my $engine  = ( $ENV{'engine'} or $keys->{ENGINE} );

        my ( $ret, $tmpfile );


        #return if( (not $reqdata) and (not $reqfile));
        # to make multi certs you need to tell openssl 
        # what directory to put it.
        return if( (not $reqdata) and (not $reqfile) and
                ((not $reqfiles) and (not $outdir)) );

        $inform   = "PEM" if( not $inform ); 
        $reqtype  = "NETSCAPE" if( not $reqtype ); 

        my $command = "$self->{shell} ca -batch ";

        if( $engine ) {
                $command .= "-engine $engine ";
        }

        $command .= "-config " .$self->{cnf}." " if ( $self->{cnf} );
        $command .= "-keyfile $cakey " if( $cakey );
        $command .= "-passin env:pwd " if ( $passwd ne "" );
        $command .= "-days $days " if ( $days );
        $command .= "-extfile $extFile " if ( $extFile );
        $command .= "-extensions $exts " if ( $exts );
        $command .= "-preserveDN " if ( $preserve =~ /Y/i );
        $command .= "-startdate $startDate " if ( $startDate );
        $command .= "-enddate $endDate " if ( $endDate );
        $command .= "-name $caName " if ( $caName );
        $command .= "-subj \"$subject\" " if ( $subject );
        $command .= "-noemailDN " if ( exists $keys->{NOEMAILDN} );

        # this got moved because if -infiles
        # is going to be used it has to be the last
        # option.
        if ( $reqtype =~ /MSIE/i ) {
                ## $command .= "-msie_hack ";
        } elsif ($reqtype =~ /NETSCAPE/i ) {
                ## Nothing to do...
        } else {
                return;
        }

        if( $inform =~ /(PEM|DER|NET)/i ) {

                #this has to be the last option
                $command .= "-outdir $outdir " if ($outdir);
                $command .=  "-infiles @$reqfiles" if ($reqfiles);

                $command .= "-in $reqfile " if ( $reqfile );
        } elsif ( $inform =~ /SPKAC/ ) {
                return if ( not $reqfile );
                $command .= "-spkac $reqfile ";
        } else {
                ## no valid format received ...
                return;
        }

        print "OpenCA::OpenSSL: openssl command is as follows\n<br>".
              "\n$command<br>\n"
          if ($self->{DEBUG});
        if( $reqfile ne "" ) {
                $ENV{'pwd'} = "$passwd";
                $ret = `$command`;
                $ENV{'pwd'} = "";
                return if( $? != 0);
        } else {
                $ENV{'pwd'} = "$passwd";
                open( FD, "|$command" ) or return;
                        print "$reqdata";
                close(FD);
                $ENV{'pwd'} = "";

                return if( $? != 0);
        }

        return 1;
}

sub revoke {

        ## CAKEY  => $CAkeyfile (Optional)
        ## CACERT => $CAcertfile (Optional)
        ## PASSWD => $passwd (Optional - if not needed)
        ## INFILE => $certFile (PEM Formatted certificate file);

        my $self = shift;
        my $keys = { @_ };

        my $cakey    = $keys->{CAKEY};
        my $cacert   = $keys->{CACERT};
        my $passwd   = $keys->{PASSWD};
        my $certFile = $keys->{INFILE};

        my $engine  = ( $ENV{'engine'} or $keys->{ENGINE} );

        my ( $tmp, $ret );
        my $command = "$self->{shell} ca -revoke \"$certFile\" ";

        return if (not $certFile);

        if( $engine ) {
                $command .= "-engine $engine ";
        }

        $command .= "-config " . $self->{cnf}. " " if ( defined($self->{'cnf'}) && 
$self->{cnf} ne "" );
        $command .= "-keyfile $cakey " if( defined($cakey) && $cakey ne "" );
        $command .= "-passin env:pwd " if ( defined($passwd) && $passwd ne "" );
        ## $command .= "-key $passwd " if ( $passwd ne "" );
        $command .= "-cert $cacert " if ( defined($cacert) && $cacert ne "" );

        $ENV{'pwd'} = "$passwd";
        open( FD, "$command|" ) or return;
                while( $tmp = <FD> ) {
                        $ret .= $tmp;
                }
        close(FD);
        #$ENV{'pwd'} = "";
        delete( $ENV{'pwd'} ) if( defined($passwd) );
        if( $? != 0) {
                return;
        } else {
                return 1;
        }
}


sub issueCrl {

        ## CAKEY   => $CAkeyfile
        ## CACERT  => $CAcertfile
        ## PASSWD  => $passwd
        ## DAYS    => $days
        ## EXTS    => $extentions
        ## OUTFILE => $outfile
        ## OUTFORM => PEM|DER|NET|TXT

        my $self = shift;
        my $keys = { @_ };

        my $cakey    = $keys->{CAKEY};
        my $cacert   = $keys->{CACERT};
        my $days     = $keys->{DAYS};
        my $passwd   = $keys->{PASSWD};
        my $outfile  = $keys->{OUTFILE};
        my $outform  = $keys->{OUTFORM};
        my $exts     = $keys->{EXTS};
        my $extfile  = $keys->{EXTFILE};

        my $engine  = ( $ENV{'engine'} or $keys->{ENGINE} );
        
        my ( $ret, $tmp, $tmpfile );
        my $command = "$self->{shell} ca -gencrl ";

        if( $engine ) {
                $command .= "-engine $engine ";
        }

        if ( not(defined($outfile)) || $outfile eq "" ){
                $tmpfile = $self->{tmpDir} . "/${$}_crl.tmp";
        } else {
                $tmpfile = $outfile;
        }
        $command .= "-out $tmpfile ";

        $command .= "-config " . $self->{cnf}. " " if ( defined($self->{'cnf'}) && 
$self->{cnf} ne "" );
        $command .= "-keyfile $cakey " if( defined($cakey) && $cakey ne "" );
        $command .= "-passin env:pwd " if ( defined($passwd) && $passwd ne "" );
        $command .= "-cert $cacert " if ( defined($cacert) && $cacert ne "" );
        $command .= "-crldays $days " if ( defined($days) && $days ne "" );
        $command .= "-crlexts $exts " if ( defined($exts) && $exts ne "" );
        $command .= "-extfile $extfile " if ( defined($extfile) && $extfile ne "" );

        $ENV{'pwd'} = "$passwd";
        $ret = `$command`;
        delete( $ENV{'pwd'} );

        return if( $? != 0);

        $ret = $self->dataConvert( INFILE  =>$tmpfile,
                                   OUTFORM =>$outform,
                                   DATATYPE=>"CRL" );

        return if( not $ret );

        if( defined($outfile) && $outfile ne "" ) {
                open( FD, ">$outfile" ) or return;
                        print FD "$ret";
                close( FD );
                return 1;
        }

        unlink( $tmpfile );
        return "$ret";
}

sub SPKAC {

        my $self = shift;
        my $keys = { @_ };

        my $infile  = $keys->{INFILE};
        my $outfile = $keys->{OUTFILE};
        my $spkac   = $keys->{SPKAC};

        my $command = $self->{shell} . " spkac -verify ";
        my $tmpfile = $self->{tmpDir} . "/${$}_SPKAC.tmp";

        my $engine  = ( $ENV{'engine'} or $keys->{ENGINE} );

        my $ret = "";
        my $retVal = 0;
        my $tmp;

        if( defined($spkac) && $spkac ne "" ) {
                $infile = $self->{tmpDir} . "/${$}_in_SPKAC.tmp";
                open( FD, ">$infile" ) or return;
                        print FD "$spkac\n";
                close ( FD );
        }

        if( $engine ) {
                $command .= "-engine $engine ";
        }

        $command .= "-in $infile " if( defined($infile) && $infile ne "" );
        if( defined($outfile) && $outfile ne "" ) {
                $command .= "-out $outfile ";
        } else {
                $command .= "-out $tmpfile ";
        }

        open( FD, "|$command" ) or return;
        close( FD );

        ## Store the ret value
        $retVal = $?;

        ## Unlink the infile if it was temporary
        unlink $infile if( defined($spkac) && $spkac ne "");

        if( defined($outfile) && $outfile ne "" ) {
                return if ( $retVal != 0 );

                return 1;
        }

        ## Get the output
        open( TMP, "$tmpfile" ) or return;
                while ( $tmp = <TMP> ) {
                        $ret .= $tmp;
                }
        close( TMP );
        unlink $tmpfile if (not(defined($outfile)) || $outfile eq "");

        return if ( $retVal != 0 );

        return $ret;
}

sub getDigest {

        ## Returns Digest of the provided message
        ## DATA=>$data, ALGORITHM=>$alg

        my $self = shift;
        my $keys = { @_ };
        
        my $data    = $keys->{DATA};
        my $alg     = lc( $keys->{ALGORITHM} );
        my $tmpfile = $self->{tmpDir} . "/${$}_dgst.tmp";

        my $engine  = ( $ENV{'engine'} or $keys->{ENGINE} );

        my ( $command, $ret );

        $alg = "md5" if( not $alg );

        return if (not $data);
        open( FD, ">$tmpfile" ) or return;
                print FD $data;
        close( FD );

        $command = "$self->{shell} dgst -$alg ";

        if( defined($engine) and ($engine ne "")) {
                $command .= "-engine $engine ";
        }

        $command .= "<\"$tmpfile\"";

        $ret = `$command`;
        $ret =~ s/\n//g;

        unlink( $tmpfile );

        if( $? != 0 ) {
                return;
        } else {
                return $ret;
        }
}

sub verify {

        ## Verify PKCS7 signatures (new OpenCA::verify command
        ## should be used )

        my $self = shift;
        my $keys = { @_ };

        my $data    = $keys->{DATA};
        my $infile  = $keys->{DATA_FILE};
        my $sig     = $keys->{SIGNATURE};
        my $sigfile = $keys->{SIGNATURE_FILE};
        my $cacert  = $keys->{CA_CERT};
        my $cadir   = $keys->{CA_DIR};
        my $verbose = $keys->{VERBOSE};
        my $out     = $keys->{OUTFILE};
        my $noChain = $keys->{NOCHAIN};
        my $tmpfile = $self->{tmpDir} . "/${$}_vrfy.tmp";
        my $command = $self->{verify} . " ";

        my ( $ret, $tmp );

        return if( (not $data) and (not $infile) );
        if (not $infile) {
                $infile = $self->{tmpDir} . "/${$}_data.tmp";
                open FD, ">".$infile;
                print FD $data;
                close FD;
        } else {
                $data = 0;
        }

        $command   .= "-verbose " if ( $verbose );
        $command   .= "-cf $cacert " if ( $cacert );
        $command   .= "-cd $cadir " if ($cadir);
        $command   .= "-data $infile " if ($infile);
        $command   .= ">\"$out\" " if ( $out );
        $command   .= "-no_chain " if ( $noChain and not($cacert or $cadir));
        $command   .= "-in $sigfile" if ( $sigfile );

        ## if( $sigfile ) {
        ##      open( SIG, "<$sigfile" ) or return;
        ##              while( not eof( SIG ) ) {
        ##                      $sig .= <SIG>;
        ##              }
        ##      close( SIG );
        ## }

        if( not $out ) {
                $command .= " >\"$tmpfile\"";
        }

        $command .= " 2>\&1";

        open( FD, "|$command" ) or return;
                if( (defined($sig)) and ($sig ne "") ) {
                        print FD "$sig";
                }
        close( FD );

        $self->{errno} = $?;

        unlink( $infile ) if ($data);

        $ret = "";
        open( TMP, "<$tmpfile" ) or return;
                while( not eof ( TMP ) ) {
                        $ret .= <TMP>;
                }
        close( TMP );

        if ( $self->{errno} ) {
                unlink( $tmpfile ) if (not $out);
                ( $self->{errno}, $self->{errval} ) = 
                        ( $ret =~ /Verify Error\s*(.*?)\s*:\s*(.*?)\n/ );
                return;
        }

        if( not $out) {
                unlink( $tmpfile );
                return $ret;
        } else {
                return 1;
        }
}

sub sign {

        ## Generate a PKCS7 signature.

        my $self = shift;
        my $keys = { @_ };

        my $data    = $keys->{DATA};
        my $datafile= $keys->{DATA_FILE};
        my $out     = $keys->{OUT_FILE};
        my $certfile= $keys->{CERT_FILE};
        my $cert    = $keys->{CERT};
        my $keyfile = $keys->{KEY_FILE};
        my $key     = $keys->{KEY};
        my $nonDetach = $keys->{INCLUDE_DATA};
        my $pwd     = ( $keys->{PWD} or $keys->{PASSWD} );
        my $tmpfile = $self->{tmpDir} . "/${$}_sign.tmp";
        my $command = $self->{sign} . " ";

        my ( $ret );

        return if( (not $data) and (not $datafile) );
        return if( (not $cert) and (not $certfile) );
        return if( (not $key)  and (not $keyfile) );

        $ENV{pwd} = "$pwd" if ( $pwd );
        if ( not $datafile ) {
                $datafile = $self->{tmpDir} . "/${$}_data.tmp";
                open FD, ">".$datafile;
                print FD $data;
                close FD;
        } else {
                $data = 0;
        }
        if ( not $keyfile ) {
                $keyfile = $self->{tmpDir} . "/${$}_key.tmp";
                open FD, ">".$keyfile;
                print FD $key;
                close FD;
        } else {
                $key = 0;
        }
        if ( not $certfile ) {
                $certfile = $self->{tmpDir} . "/${$}_cert.tmp";
                open FD, ">".$certfile;
                print FD $cert;
                close FD;
        } else {
                $cert = 0;
        }

        $command   .= "-in $datafile ";
        $command   .= "-out $out "            if ( $out );
        $command   .= "-passin env:pwd " if ( $pwd );
        $command   .= "-nd "                  if ( $nonDetach );

        $command   .= "-cert $certfile ";
        $command   .= " -keyfile $keyfile ";

        if( not $out) {
                $command .= " >$tmpfile";
        };

        print "OpenCA::OpenSSL: the command is as follows<br>\n".
              "$command<br>\n"
                if ($self->{DEBUG});

        $ret =`$command`;

        if ( $? ) {
                unlink( $tmpfile )  if (not $out);
                unlink( $datafile ) if ($data);
                unlink( $keyfile )  if ($key);
                unlink( $certfile ) if ($cert);
                return;
        }
        unlink( $datafile ) if ($data);
        unlink( $keyfile )  if ($key);
        unlink( $certfile ) if ($cert);

        if( not $out ) {
                open( TMP, "<$tmpfile" ) or return;
                        do {
                                $ret .= <TMP>;
                        } while (not eof($ret));
                close(TMP);

                unlink( $tmpfile );
        }

        ## If we are here there have been no errors, so
        ## if $ret is empty, let's return a true value...
        $ret = 1 if ( not $ret );

        return $ret;
}

sub getCertAttribute {
        my $self = shift;
        my $keys = { @_ };

        my $cert        = ( $keys->{DATA} or $keys->{FILE} );
        my $inform      = ( $keys->{INFORM} or "PEM" );

        my @attribute = ();
        if( exists($keys->{ATTRIBUTE_LIST}) && ref($keys->{ATTRIBUTE_LIST}) ) {
                @attribute = @{$keys->{ATTRIBUTE_LIST}};
        } else {
                @attribute = ( $keys->{ATTRIBUTE} );
        }
        my $cmd         = "$self->{shell} x509 -noout ";

        my $engine  = ( $ENV{'engine'} or $keys->{ENGINE} );

        my ( $ret );

        my $tmpfile = $self->{tmpDir} . "/${$}_ATTRIBUTE.tmp";

        if( exists $keys->{FILE} ) {
                $cmd .= "-in \"$cert\" ";
        } elsif ( exists $keys->{DATA} ) {
                $cmd .= "-in \"$tmpfile\" ";
                open ( FD, ">$tmpfile" ) or return;
                        print FD "$cert";
                close( FD );
        } else {
                return;
        }
        foreach my $attribute ( @attribute ) {
                $attribute = "startdate" if( uc ($attribute) eq "NOTBEFORE" );
                $attribute = "enddate" if( uc ($attribute) eq "NOTAFTER" );
                $attribute = "subject" if( uc ($attribute) eq "DN" );
                $attribute = "pubkey" if( uc ($attribute) eq "PUBKEY" );
                $attribute = lc($attribute);
                $cmd .= "-$attribute ";
        }
        if( defined($engine) and ($engine ne "") ) {
                 $cmd .= "-engine $engine ";
        }

        $ret = `$cmd`;
        my @ret = split /\n/, $ret;
        my $return = {};
        my $i=0;
        foreach( @attribute ) {
                $_ = uc($_);
                if( $_ eq 'SUBJECT' ) {
                        $_ = 'DN';
                } elsif( $_ eq 'STARTDATE' ) {
                        $_ = 'NOTBEFORE';
                } elsif( $_ eq 'ENDDATE' ) {
                        $_ = 'NOTAFTER';
                } elsif($_ eq 'PUBKEY') {
                        do {
                                $return->{$_} .= $ret[$i] . "\n";
                        } while( $ret[$i] and $ret[++$i] !~ /^-----END PUBLIC 
KEY-----/ );
                }
                $return->{$_} .= $ret[$i++];
        }
        unlink( $tmpfile );
        if ( $? != 0 ) {
                return;
        } else {
                foreach ( keys(%$return) ) {
                        next if ( $_ eq "PUBKEY" );
                        $return->{$_} =~ s/(.*?)=[\s]*//;
                        $return->{$_} =~ s/$(\n|\r)//;
                }
                return 
(ref($keys->{ATTRIBUTE_LIST}))?($return):($return->{$attribute[0]});
        }

}

sub getReqAttribute {
        my $self = shift;
        my $keys = { @_ };

        my $req         = ( $keys->{DATA} or $keys->{FILE} );
        my $inform      = ( $keys->{FORMAT} or $keys->{INFORM} or "PEM" );

        my @attribute = ();
        my ( $cmd );

        if( exists($keys->{ATTRIBUTE_LIST}) && ref($keys->{ATTRIBUTE_LIST}) ) {
                @attribute = @{$keys->{ATTRIBUTE_LIST}};
        } else {
                @attribute = ( $keys->{ATTRIBUTE} );
        }

        if( $inform =~ /SPKAC/ ) {
                $cmd    = "$self->{shell} spkac -noout ";
        } else {
                $cmd    = "$self->{shell} req -noout ";
                if ( defined($self->{cnf}) && $self->{cnf} ne "" ) {
                        $cmd .= "-config " . $self->{cnf} . " ";
                }
        }

        my $engine  = ( $ENV{'engine'} or $keys->{ENGINE} );

        my ( $ret );

        my $tmpfile = $self->{tmpDir} . "/${$}_ATTRIBUTE.tmp";

        if( exists $keys->{FILE} ) {
                $cmd .= "-in \"$req\" ";
        } elsif ( exists $keys->{DATA} ) {
                $cmd .= "-in \"$tmpfile\" ";
                open ( FD, ">$tmpfile" ) or return;
                print FD "$req";
                close( FD );
        } else {
                return;
        }
        foreach my $attribute ( @attribute ) {
                $attribute = "startdate" if( uc ($attribute) eq "NOTBEFORE" );
                $attribute = "enddate" if( uc ($attribute) eq "NOTAFTER" );
                $attribute = "subject" if( uc ($attribute) eq "DN" );
                $attribute = "pubkey" if( uc ($attribute) eq "PUBKEY");
                $attribute = lc($attribute);
                $cmd .= "-$attribute ";
        }
        if( defined($engine) and ($engine ne "") ) {
                $cmd .= "-engine $engine ";
        }

        $ret = `$cmd`;
        my $return = {};
        my $i=0;

        my @ret = split /\n/, $ret;
        foreach( @attribute ) {
                $_ = uc($_);
                if( $_ eq 'SUBJECT' ) {
                        $_ = 'DN';
                } elsif( $_ eq 'STARTDATE' ) {
                        $_ = 'NOTBEFORE';
                } elsif( $_ eq 'ENDDATE' ) {
                        $_ = 'NOTAFTER';
                } elsif($_ eq 'PUBKEY') {
                        do {
                                $return->{$_} .= $ret[$i] . "\n";
                        } while( $ret[$i] and $ret[++$i] !~ /^-----END PUBLIC 
KEY-----/ );
                }
                $return->{$_} .= $ret[$i++];
        }
        # unlink( $tmpfile );
        if ( $? != 0 ) {
                return;
        } else {
                foreach ( keys(%$return) ) {
                        next if ( $_ eq "PUBKEY" );
                        $return->{$_} =~ s/(.*?)=[\s]*//;
                        $return->{$_} =~ s/$(\n|\r)//;
                }
                return 
(ref($keys->{ATTRIBUTE_LIST}))?($return):($return->{$attribute[0]});
        }
}

sub pkcs7Certs {

        my $self = shift;
        my $keys = { @_ };

        my $infile  = $keys->{INFILE};
        my $outfile = $keys->{OUTFILE};
        my $pkcs7   = $keys->{PKCS7};

        my $command = $self->{shell} . " pkcs7 -print_certs ";
        my $tmpfile = $self->{tmpDir} . "/${$}_SPKAC.tmp";

        my $engine  = ( $ENV{'engine'} or $keys->{ENGINE} );

        my $ret = "";
        my $retVal = 0;
        my $tmp;

        $self->{errno} = 0;

        if( defined($pkcs7) && $pkcs7 ne "" ) {
                $infile = $self->{tmpDir} . "/${$}_in_SPKAC.tmp";
                open( FD, ">$infile" ) or return;
                        print FD "$pkcs7\n";
                close ( FD );
        }

        if( defined($engine) and ($engine ne "")) {
                $command .= "-engine $engine ";
        }

        $command .= "-in $infile " if( defined($infile) && $infile ne "" );
        if( defined($outfile) && $outfile ne "" ) {
                $command .= "-out $outfile ";
        } else {
                $command .= "-out $tmpfile ";
        }

        $ret = `$command 2>&1`;
        if( $? > 0 ) {
                $self->{errno} = "$?";
                $self->{errval} = "$ret";
        }

        ## Unlink the infile if it was temporary
        unlink $infile if( defined($pkcs7) && $pkcs7 ne "");

        ## Get the output
        open( TMP, "$tmpfile" ) or return;
                while ( $tmp = <TMP> ) {
                        $ret .= $tmp;
                }
        close( TMP );
        unlink $tmpfile if (not (defined($outfile)) or $outfile eq "");

        if ( $self->{errno} != 0 ) {
                return;
        } else {
                return $ret;
        }
}

sub updateDB {

        my $self = shift;
        my $keys = { @_ };

        my $cakey    = $keys->{CAKEY};
        my $cacert   = $keys->{CACERT};
        my $passwd   = $keys->{PASSWD};
        my $outfile  = $keys->{OUTFILE};

        my ( $ret, $tmp );
        my $command = "$self->{shell} ca -updatedb ";

        $command .= "-config " . $self->{cnf}. " " if ( defined($self->{'cnf'}) && 
$self->{cnf} ne "" );
        $command .= "-keyfile $cakey " if( defined($cakey) && $cakey ne "" );
        $command .= "-passin env:pwd " if ( defined($passwd) && $passwd ne "" );
        $command .= "-cert $cacert " if ( defined($cacert) && $cacert ne "" );

        $ENV{'pwd'} = "$passwd";
        $ret = `$command`;
        delete( $ENV{'pwd'} );

        return if( $? != 0);

        if( defined($outfile) && $outfile ne "" ) {
                open( FD, ">$outfile" ) or return;
                        print FD "$ret";
                close( FD );
                return 1;
        }
        return "$ret";
}

sub getSMIME {

        ## ENCRYPT => a true value
        ## SIGN    => a true value
        ## ENCRYPT_CERT => $enc_cert
        ## SIGN_CERT    => $sign_cert
        ## SIGN_KEY     => $sign_key
        ## SIGN_PASSWD  => $sign_passwd
        ## INFILE       => $infile
        ## OUTFILE      => $outfile
        ## DATA         => $message
        ## MESSAGE      => $message (higher priority)
        ## ENGINE       => openssl engine
        ## TO           => $to
        ## FROM         => $from
        ## SUBJECT      => $subject

        my $self = shift;
        my $keys = { @_ };

        my $encrypt     = $keys->{ENCRYPT};
        my $sign        = $keys->{SIGN};
        my $enc_cert    = $keys->{ENCRYPT_CERT};
        my $sign_cert   = $keys->{SIGN_CERT};
        my $sign_key    = $keys->{SIGN_KEY};
        my $sign_passwd = $keys->{SIGN_PASSWD};
        my $infile      = $keys->{INFILE};
        my $outfile     = $keys->{OUTFILE};
        my $message     = $keys->{DATA};
        my $message     = $keys->{MESSAGE};
        my $to          = $keys->{TO};
        my $from        = $keys->{FROM};
        my $subject     = $keys->{SUBJECT};

        my $engine  = ( $ENV{'engine'} or $keys->{ENGINE} );

        my ( $ret, $tmp, $tmpfile );

        ## setup file with smime-message
        if ($outfile) {
          $tmpfile = $outfile;
        } else {
          $tmpfile = $self->{tmpDir}."/".$$."_SMIME.msg";
        }

        my $command = "$self->{shell} smime ";
        if ($infile) {
          $command .= " -in $infile ";
        }

        ## 1. signing
        if ($sign) {
          $command .= " -sign ".
                      " -text ".
                      " -signer $sign_cert ".
                      " -inkey $sign_key ".
                      " -passin env:pwd ";
          if (not $encrypt) {
            $command .= " -to \"$to\" ".
                        " -from \"$from\" ".
                        " -subject \"$subject\" ";
          }
          if( $engine ) {
            $command .= " -engine $engine ";
          }
        }

        ## 2. encrypt
        if ($encrypt) {
          if ($sign) {
            $command .= " | $self->{shell} smime ";
          }
          if( $engine ) {
            $command .= " -engine $engine ";
          }
          $command .= " -encrypt ".
                      " -to \"$to\" ".
                      " -from \"$from\" ".
                      " -subject \"$subject\" ".
                      " -des3 ";
        }

        # set outputfile
        $command .= " -out $tmpfile ";

        ## 2. encrypt
        if ($encrypt) {
          $command .= " $enc_cert ";
        }

        print "OpenCA::OpenSSL: getSMIME<br>\n".
              "command is as follows<br>\n".
              "$command<br>\n"
          if ($self->{DEBUG});

        print "OpenCA::OpenSSL: getSMIME<br>\n".
                "message is as follows<br>\n".
                "$message<br>\n"
          if ($self->{DEBUG} && not ( defined $infile && $infile ne "" ));

        ## execute command
        $ENV{'pwd'} = "$sign_passwd";
        if( defined($infile) && $infile ne "" ) {
          $ret=`$command`;
        } else {
          open( FD, "|$command" ) or return;
          print FD "$message";
          close( FD );
        }

        print "OpenCA::OpenSSL: getSMIME: FD does not fail<br>\n"
          if ($self->{DEBUG});
        print "OpenCA::OpenSSL: getSMIME: last errorcode=".$?."<br>\n"
          if ($self->{DEBUG});

        ## check the errorcode
        return if( $? != 0);

        ## if the caller want a file then we can finish
        if( defined($outfile) && $outfile ne "" ) {
          return 1;
        }

        print "OpenCA::OpenSSL: getSMIME: load tmpfile<br>\n"
          if ($self->{DEBUG});

        ## load the output
        $ret = "";
        open( TMP, "$tmpfile" ) or return;
                while ( $tmp = <TMP> ) {
                        $ret .= $tmp;
                }
        close( TMP );
        unlink $tmpfile;

        print "OpenCA::OpenSSL: getSMIME: succeeded<br>\n"
          if ($self->{DEBUG});
        print "OpenCA::OpenSSL: getSMIME: ret: $ret<br>\n"
          if ($self->{DEBUG});

        return $ret;
}

sub getPIN {

        ## PIN_LENGTH    => $pin_length
        ## RANDOM_LENGTH => $random_length
        ## LENGTH        => $pin_length
        ## ENGINE        => openssl engine

        my $self = shift;
        my $keys = { @_ };

        my $pin_length = $keys->{PIN_LENGTH};
        my $length     = $keys->{RANDOM_LENGTH};
        my $pin_length = $keys->{LENGTH};

        my $engine  = ( $ENV{'engine'} or $keys->{ENGINE} );

        my ( $ret, $tmp, $tmpfile );

        my $command = "$self->{shell} rand -base64 ";
        if( $engine ) {
          $command .= " -engine $engine ";
        }
        if ($length) {
          $command .= $length;
        } elsif ($pin_length) {
          $command .= $pin_length;
        } else {
          return undef;
        }

        ## create the PIN
        my $pin;
        open (FD, "$command|") or return;
        if ($pin_length) {
          ## enforce the PIN-length
          ## SECURITY ADVICE: it is more secure to only set the
          ##                  number of randombytes
          read FD, $pin, $pin_length;
        } else {
          ## 2*$length is enough to encode $length randombytes in base64
          read FD, $pin, 2*$length;
        }

        ## remove trailing newline
        $pin =~ s/\n//g;

        if ($pin) {
          return $pin;
        } else {
          return undef;
        }

}

sub getOpenSSLDate {
        my $self = shift;

        my $date = $self->getNumericDate ( $_[0] );
        return undef if (not defined $date);

        ## remove century
        $date =~ s/^..//;

        ## add trailing Z
        $date .= "Z";

        return $date; 
}

sub getNumericDate {
        my $self = shift;

        my $date = $_[0];
        my %help;
        my $new_date;

        ## remove leading days like SUN or MON
        if ( $date =~ /^[^ ]+ +(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)/i ) {
                $date =~ s/^[^ ]+//;
        }

        ##  Mar 10 19:36:45 2001 GMT

        ## Month
        if ( $date =~ /^ *JAN/i ) {
                ##  january
                $help {MONTH} = "01";
        } elsif ( $date =~ /^ *FEB/i ) {
                ## february
                $help {MONTH} = "02";
        } elsif ( $date =~ /^ *MAR/i ) {
                ## march
                $help {MONTH} = "03";
        } elsif ( $date =~ /^ *APR/i ) {
                ## april
                $help {MONTH} = "04";
        } elsif ( $date =~ /^ *MAY/i ) {
                ## may
                $help {MONTH} = "05";
        } elsif ( $date =~ /^ *JUN/i ) {
                ## june
                $help {MONTH} = "06";
        } elsif ( $date =~ /^ *JUL/i ) {
                ## july
                $help {MONTH} = "07";
        } elsif ( $date =~ /^ *AUG/i ) {
                ## august
                $help {MONTH} = "08";
        } elsif ( $date =~ /^ *SEP/i ) {
                ## september
                $help {MONTH} = "09";
        } elsif ( $date =~ /^ *OCT/i ) {
                ## october
                $help {MONTH} = "10";
        } elsif ( $date =~ /^ *NOV/i ) {
                ## november
                $help {MONTH} = "11";
        } elsif ( $date =~ /^ *DEC/i ) {
                ## december
                $help {MONTH} = "12";
        } else {
                ## return illegal
                return undef;
        }

        ## day
        $date =~ s/^ *//;
        $date = substr ($date, 4, length ($date)-4);
        $help {DAY} = substr ($date, 0, 2);
        $help {DAY} =~ s/ /0/;

        ## hour
        $help {HOUR} = substr ($date, 3, 2);

        ## minute
        $help {MINUTE} = substr ($date, 6, 2);

        ## second
        $help {SECOND} = substr ($date, 9, 2);

        ## year
        $help {YEAR} = substr ($date, 12, 4);

        ## build date
        $new_date =     $help {YEAR}.
                        $help {MONTH}.
                        $help {DAY}.
                        $help {HOUR}.
                        $help {MINUTE}.
                        $help {SECOND};

        return $new_date; 

}

# Autoload methods go after =cut, and are processed by the autosplit program.

1;

Reply via email to