alexandru matei schrieb:
> 
> Hello,
> In export-import.lib the function "build_openssl_date" is missing.
> Where canI find it?

This function moved from crypto-utils.lib into the module
OpenCA::OpenSSL. I attached the fixed library.

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                                     [OpenCA Core Developer]

http://www.openca.org
## export/import library of OpenCA Group
##
## (c) 1998-2001 by OpenCA Group
## the license is the general project license
## (see http://openca.sourceforge.net)
##
## Usage:
##
## Export
## ------
## $tmp = createStructure ();
## exportXYZ ($tmp);
## exportABC ($tmp);
## createArchive ( $tmp);
## removeDirectory ( $tmp );
##
## Import
## ------
## $tmp = createStructure ();
## extractArchive ($tmp);
## importXYZ ($tmp);
## importABC ($tmp);
## removeDirectory ( $tmp );
##
## export/import functions:
##   * CSRs
##   * Certs
##   * CRRs
##   * CRLs
##   * CAs
##   * Configuration 
##      * directory (RBAC, OpenSSL, extfiles)
##      * file (openssl.cnf)
##   * Mails
##   * ImportFromCA/ExportToCA
##   * ImportFromRAServer/ExportToRAServer
##   * DB
##   * replayLog (for SQL-DBs only today)
##  
## other functions:
##   * createDirectory
##   * createStructure
##   * createArchive
##   * extractArchive
##   * removeDirectory
##
## directories for the different objects:
##   * CA_CERTIFICATE
##   * REQUEST
##   * CERTIFICATE
##   * CRR
##   * CRL
##   * Configuration
##      * RBAC
##      * OpenSSL
##      * extfiles
##      * others (for the rest)
##   * Mail

## the variables which start with $exim_ are reserved for this library

####################################
## general function for archiving ##
####################################

## 
## createDirectory
##
## this function prepare a temporary directory for the files
## which should be exported
##
sub createDirectory {

  my $exim_tmp_dir;
  if ( not $_[0] ) {
    $exim_tmp_dir = getRequired ('TempDir')."/tmp_".$$;
  } else {
    $exim_tmp_dir = $_[0];
  }

  if (not mkdir ( $exim_tmp_dir, 0700 )) {
    ## output is only necessary if something going wrong
    print addLogSection ("Creating Temporary Directory $exim_tmp_dir ...");
    print addErrorLog ("Cannot create temporary directory $exim_tmp_dir!");
    print closeLogSection();
    return "";
  }

  return $exim_tmp_dir;
}

##
## createStructure
##
## this function prepare a temporary directory for the files
## which should be exported
##
sub createStructure {

  ## get the base directory
  my $dir;
  if ( not $_[0]) {
    $dir = createDirectory ();
  } else {
    $dir = $_[0];
  }
  if (not defined $dir or not $dir) {
    return undef;
  }

  ## create the subdirectories

  ## create structure
  $list          = {
    CERTIFICATE    => [ "VALID", "EXPIRED", "REVOKED", "SUSPENDED" ],
    REQUEST        => [ "PENDING", "APPROVED", "ARCHIVIED", "DELETED", "RENEW" ],
    CA_CERTIFICATE => [ "VALID", "EXPIRED" ],
    CRL            => [ "VALID" ],
    CRR            => [ "PENDING", "APPROVED", "ARCHIVIED", "DELETED" ],
    LOG            => [ "ALL" ],
                   };

  foreach $object (keys %{$list}) {
    return undef if (not createDirectory ( $dir."/".$object ));
    foreach $status (@{$list->{$object}}) {
      return undef if (not createDirectory ( $dir."/".$object."/".$status ));
    }
  }
    
  return $dir;

}

##
## createArchive
##
## this function generates an archive from a special directory
## parameters : DIRECTORY as $_[0]
##
sub createArchive {

  my $exim_tmp_dir = $_[0];

  print addLogSection ("Creating Archive ...");
  print addLogLine    ( "" );

  print addPreLogLine ("Load required variables ...");

  ## Get required parameters from the configuration file
  my $creat  = getRequired( 'CreateArchive' );
  my $test   = getRequired( 'TestArchive' );
  my $dest   = getRequired( 'ExportDev' );

  ## Build the right $cmd with substitution of the $dest
  ## with the 'ExportDest' and in 'TestArchive'
  my $arc  = $query->subVar( $creat, '$dest', $dest );
  my $test = $query->subVar( $test,  '$dest', $dest );

  print addPreLogLine ("Changing to directory $exim_tmp_dir ...");
  if (not chdir $exim_tmp_dir) {
    print addErrorLog ( "failed");
    print closeLogSection();
    return 0;
  }

  print addPreLogLine ("Build Archive ...");
  $ret = `$arc . 2>&1`;
  if( $? != 0 ) {
    print addErrorLog("Archiving Failed to $dest!");
    print addLogLine( "$arc ." );
    print closeLogSection();
    return 0;
  }

  print addPreLogLine ("Test Archive ...");
  $ret = `$test 2>&1`;
  if( $? != 0 ) {
    print addErrorLog("Testing Archive Failed for $dest!");
    print addLogLine( "$arc" );
    print closeLogSection();
    return 0;
  }
  
  print addPreLogLine ("Archive created successfully.");

  print closeLogSection();

  return 1;
}

##
## extractArchive
##
## this function extracts an archive from a special media
## parameters : DIRECTORY as $_[0]
##
sub extractArchive {

  my $exim_tmp_dir = $_[0];

  ## Get required parameters from the configuration file
  my $unpack  = getRequired( 'UnpackArchive' );
  my $test   = getRequired( 'TestArchive' );
  my $dest   = getRequired( 'ImportDev' );

  ## Build the right $cmd with substitution of the $dest
  ## with the 'ExportDest' and in 'TestArchive'
  my $arc  = $query->subVar( $unpack, '$orig', $dest );
  my $arc  = $query->subVar( $arc, '$dest', $exim_tmp_dir );
  my $test = $query->subVar( $test,  '$dest', $dest );

  if (not chdir $exim_tmp_dir) {
    print addLogLine ("Changing to directory $exim_tmp_dir ...");
    printErrorLog ( "failed");
    return 0;
  }

  $ret = `$test 2>&1`;
  if( $? != 0 ) {
    print addLogSection ("Extracting Archive ...");
    print addErrorLog("Testing Archive Failed for $dest!");
    print addLogLine( "$arc" );
    print closeLogSection ();
    return 0;
  }

  $ret = `$arc . 2>&1`;
  if( $? != 0 ) {
    print addLogSection ("Extracting Archive ...");
    print addErrorLog("Extracting Archive Failed from $dest!");
    print addLogLine( "$arc" );
    print closeLogSection ();
    return 0;
  }

  return 1;
}

## 
## removeArchive
##
## this function remove a temporary directory
##
sub removeDirectory {

  my $exim_tmp_dir = $_[0];

  print addLogSection ("Clean up ...");

  if ( length ( $exim_tmp_dir ) < 10 ) {
    print addErrorLog ("Stop removing temporary directory $exim_tmp_dir ".
                       " because the length of it is smaller than 10!");
    print closeLogSection();
    return 0;
  }

  $ret = `rm -rf $exim_tmp_dir`;
  if( $? != 0 ) {
    print addErrorLog("Cannot remove temporary directory $exim_tmp_dir");
    print addLogLine( "rm -rf $exim_tmp_dir" );
    print closeLogSection();
    return 0;
  }
  print addLogLine( "Ok." );
  print closeLogSection();

  return 1;
}

######################################
## functions for DB-backup/recovery ##
######################################

#####################################################
##                general warning                  ##
#####################################################
## * all actions are handled by this function      ##
##   (except of html-header and -footer)           ##
## * use importDB only on an empty DB              ##
## * if importDB detects an already existing       ##
##   object it only signal this event and continue ##
## * every import of an object is documented in    ##
##   the logs if you use OpenCA::DB and importDB   ##
## * replayLog only use the logs and replay all    ##
##   actions of the CA or RAServer                 ##
## * if you want to use replayLog you MUST create  ##
##   the database again to get consistent state,   ##
##   if you replay on a not newly created database ##
##   then the result is undefined                  ##
#####################################################

sub exportDB {

  ## create initial structure
  my $dir = createStructure ();
  if (not defined $dir or not $dir) {
    return undef;
  }

  ## structure
  $list          = {
    CERTIFICATE    => [ "VALID", "EXPIRED", "REVOKED", "SUSPENDED" ],
    REQUEST        => [ "PENDING", "APPROVED", "ARCHIVIED", "DELETED", "RENEW" ],
    CA_CERTIFICATE => [ "VALID", "EXPIRED" ],
    CRL            => [ "VALID" ],
    CRR            => [ "PENDING", "APPROVED", "ARCHIVIED", "DELETED" ],
    LOG            => [ "ALL" ],
                   };

  ## iterate over all types of object
  foreach my $object (keys %{$list}) {

    if ( ($object =~ /LOG/) and (getRequired ('DBmodule') !~ /DBI/i) ) {
      next;
    }

    ## iterate over all states
    foreach my $status (@{$list->{$object}}) {

      exportObjects ( DATATYPE => $object, STATUS => $status, DIR => $dir );

    }

  }

  ## create the archive
  return undef if (not createArchive ( $dir ));

  ## remove the hole structure
  return undef if (not removeDirectory ( $dir ));

  return 1;
}

sub importDB {

  ## create initial structure
  my $dir = createDirectory ();
  if (not defined $dir or not $dir) {
    return undef;
  }

  ## extract archive
  if (not extractArchive ( $dir )) {
    return undef;
  }

  ## structure
  $list          = {
    CERTIFICATE    => [ "VALID", "EXPIRED", "REVOKED", "SUSPENDED" ],
    REQUEST        => [ "PENDING", "APPROVED", "ARCHIVIED", "DELETED", "RENEW" ],
    CA_CERTIFICATE => [ "VALID", "EXPIRED" ],
    CRL            => [ "VALID" ],
    CRR            => [ "PENDING", "APPROVED", "ARCHIVIED", "DELETED" ],
    LOG            => [ "ALL" ],
                   };

  ## iterate over all types of object
  foreach my $object (keys %{$list}) {

    if ( ($object =~ /LOG/) and (getRequired ('DBmodule') !~ /DBI/i) ) {
      next;
    }

    ## iterate over all states
    foreach my $status (@{$list->{$object}}) {

      importObjects ( DATATYPE => $object, STATUS => $status, DIR => $dir );

    }

  }

  ## remove the hole structure
  return undef if (not removeDirectory ( $dir ));

  return 1;
}

## this function recovers a database only from the logs!
## so if you want to have a secure replay you can use
## this function (we are doing datalogging)
sub replayLog {
  
  ## create initial structure
  my $dir = createDirectory ();
  if (not defined $dir or not $dir) {
    print addPreLogLine ( "<FONT COLOR=#FF0000>FAILURE: You can only replay the logs 
if you are using a SQL-database</FONT>");
    print addPreLogLine ( "<FONT COLOR=#FF0000>ABORTING ...</FONT>");
    print closeLogSection ();
    return undef;
  }

  ## extract archive
  if (not extractArchive ( $dir )) {
    return undef;
  }

  ## start output
  print addLogSection ("Replaying logs (on a new and empty sql-database only) ...");

  if ( ($object =~ /LOG/) and (getRequired ('DBmodule') !~ /DBI/i) ) {
    return undef;
  }

  my $directory = $dir."/LOG/ALL";
  opendir( DIR, $directory );
  my @dirList = grep (/^[^\.]/, readdir( DIR ));
  closedir( DIR );

  if (not scalar @dirList) {
    print addPreLogLine ("<i>The log is empty.</i>");
  }
  for (my $i=1; $i <= scalar @dirList; $i++) {

    ## setup filename
    my $filename = $directory."/".$i.".log";

    ## load the file
    my $content = $tools->getFile ( $filename );

    ## load the datatype
    my ( $object ) = ( $content =~ /^([^\n]*)/ );
    $content =~ s/^[^\n]*\n//;

    ## load the status
    my ( $status ) = ( $content =~ /^([^\n]*)/ );
    $content =~ s/^[^\n]*\n//;

    ## write back the file
    ( $filename ) = ( $content =~ /^([^\n]*)/ );
    $content =~ s/^[^\n]*\n//;

    ## write back filename
    $filename = $dir."/LOG/".$filename;
    if (not $tools->saveFile (FILENAME => $filename, DATA => $content)) {
      print addPreLogLine ( "<FONT COLOR=#FF0000>FAILURE: Cannot write file</FONT>");
      print addPreLogLine ( "<FONT COLOR=#FF0000>FILE: ".$filename."</FONT>");
      print addPreLogLine ( "<FONT COLOR=#FF0000>ABORTING ...</FONT>");
      print closeLogSection ();
      return undef;
    }

    ## create object
    my $db_object;
    if ($object =~ /CERTIFICATE/) {
      $db_object = new OpenCA::X509 ( SHELL  => $cryptoShell,
                                      INFILE => $filename,
                                      FORMAT => "PEM" );
    } elsif ($object =~ /^(REQUEST|CRR)$/) {
      $db_object = new OpenCA::REQ ( SHELL  => $cryptoShell,
                                     INFILE => $filename);
    } else {
      $db_object = new OpenCA::CRL ( INFILE => $filename,
                                     SHELL  => $cryptoShell );
    }
    if (not defined $db_object or not $db_object) {
      print addPreLogLine ( "<FONT COLOR=#FF0000>FAILURE: Cannot create object from 
file</FONT>");
      print addPreLogLine ( "<FONT COLOR=#FF0000>FILE: ".$filename."</FONT>");
      print addPreLogLine ( "<FONT COLOR=#FF0000>ABORTING ...</FONT>");
      print closeLogSection ();
      return undef;
    }

    if ( defined $db->storeItem ( DATATYPE => $status."_".$object,
                                  OBJECT   => $db_object,
                                  MODE     => "UPDATE" )) {
      $filename =~ s/.*\///;
      print addPreLogLine ($status."_".$object." updated from $filename");
    } else {
      if ( defined $db->storeItem ( DATATYPE => $status."_".$object,
                                    OBJECT   => $db_object,
                                    MODE     => "INSERT" )) {
        $filename =~ s/.*\///;
        print addPreLogLine ($status."_".$object." inserted from $filename");
      } else {
        print addPreLogLine ( "<FONT COLOR=#FF0000>FAILURE: Cannot insert/update 
object</FONT>");
        print addPreLogLine ( "<FONT COLOR=#FF0000>FILE: ".$filename."</FONT>");
        print addPreLogLine ( "<FONT COLOR=#FF0000>ABORTING ...</FONT>");
        print closeLogSection ();
        return undef;
      }
    }
  }

  ## end output
  print closeLogSection ();

  ## remove the hole structure
  return undef if (not removeDirectory ( $dir ));

  return 1;
}

###########################
## functions for objects ##
###########################

# Input: DATATYPE and/or STATUS
# Output: array with the ex-/imported Objects

# determine status and datatype
sub eximObjectsGetParams {
  my $keys = { @_ };
  my @result = ();

  # determine status
  if ($keys->{STATUS}) {
    $result [1] = $keys->{STATUS};
  } else {
    $result [1] = $keys->{DATATYPE};
    $result [1] =~ s/_.*$//;
    $result [1] = "" if ($result [1] =~ /^(CA|CERTIFICATE|REQUEST|CRR|CRL|LOG)$/);
  }
  
  # determine datatype
  $result [0] = $keys->{DATATYPE};
  $result [0] =~ s/^$result[1]_// if ($result [1]);

  return @result;
}

sub exportObjects {
  my $keys = { @_ };
  my @datatype = eximObjectsGetParams ( @_ );

  print addLogSection ( "Exporting ".lc $datatype [1]." ".$datatype [0]." ..." );

  ## load objects
  my @list;
  if ($datatype [1] and ($datatype [0] !~ /LOG/)) {
    @list = $db->searchItems ( DATATYPE => $datatype [1]."_".$datatype [0] );
  } else {
    @list = $db->searchItems ( DATATYPE => $datatype [0] );
  }

  ## write objects
  my @result = ();
  if (not scalar @list) {
    print addPreLogLine ("<i>No objects are present.</i>");
  }
  my $count = 0;
  foreach my $value (@list) {

    my $txtItem;

    my $log = 0;
    if ($datatype [0] =~ /LOG/) {
       $log = 1;
       $count++;
       $datatype [0] = $value-> [0];
       $datatype [1] = $value-> [1];
       my $h   = $value-> [2];
       $value  = undef;
       $value  = $h;
    }

    ## get content and format for file
    if( $datatype [0] =~ /(REQUEST|CRR)/i ) {
      $txtItem = $value->getParsed()->{ITEM};
      $format = $value->getParsed()->{TYPE};
    } else {
      if ( $datatype [0] =~ /CERTIFICATE/i) {
        $txtItem = $value->getPEMHeader ()."\n";
      } else {
        $txtItem = "-----BEGIN HEADER-----\n".$value->getHeader ()."-----END 
HEADER-----\n";
      }
      $txtItem .= $value->getPEM();
      $txtItem .= $value->getParsed()->{KEY};
      $format = "PEM";
    }
    $format =~ s/\s/_/g;

    # serial
    my $serial;
    if ($datatype [0] =~ /^CERTIFICATE/) {
      $serial = $value->getParsed()->{SERIAL};
    } elsif ($datatype [0] =~ /(REQUEST|CRR)/) {
      $serial = $value->getParsed()->{DBKEY};
    } else { # CRL,CA_CERTIFICATE
      $serial = $cryptoShell->getDigest ( DATA => $value->getPEM());
    }

    ## corrections for logs
    if ($log) {

      # filename
      $txtItem = $serial.".".(lc $format)."\n".$txtItem;
      # status
      $txtItem = $datatype [1]."\n".$txtItem;
      # datatype
      $txtItem = $datatype [0]."\n".$txtItem;

      $datatype [0] = "LOG";
      $datatype [1] = "ALL";
      $format       = "log";
      $serial       = $count;
    }

    ## write file
    my $filename = $keys->{DIR}."/".$datatype [0]."/".$datatype 
[1]."/".$serial.".".(lc $format);
    if ($tools->saveFile (FILENAME => $filename,
                          DATA     => $txtItem)) {
      print addPreLogLine ($serial.".".(lc $format));
      push (@result, $serial);
    } else {
      print addPreLogLine ( "<FONT COLOR=#FF0000>FAILURE: ".$serial.".".(lc 
$format)."</FONT>");
      print addPreLogLine ( "<FONT COLOR=#FF0000>FILE: ".$filename."</FONT>");
    }
  }

  print closeLogSection ();

  return @result;

}

sub importObjects {
  my $keys = { @_ };
  my @datatype = eximObjectsGetParams ( @_ );

  print addLogSection ( "Importing ".lc $datatype [1]." ".$datatype [0]." ..." );

  if ( ($datatype [0] =~ /LOG/) and (getRequired ('DBmodule') !~ /DBI/i) ) {
    print addPreLogLine ("iLogs are only available on SQL-Databases!");
    print closeLogSection ();
    return ();
  }

  my $dir = $keys->{DIR};

  my $directory = $dir."/".$datatype [0]."/".$datatype [1];
  opendir( DIR, $directory );
  my @dirList = grep (/^[^\.]/, readdir( DIR ));
  closedir( DIR );

  my @result = ();
  if (not scalar @dirList) {
    print addPreLogLine ("<i>No objects are present.</i>");
  }
  foreach my $value (@dirList) {

    ## setup filename
    my $filename = $directory."/".$value;

    ## if we load the the logs we have to do a little bit more
    my $log = 0;
    if ($datatype [0] =~ /LOG/) {
      $log = 1;

      ## value
      $value =~ s/\.log$//;

      ## load the file
      my $content = $tools->getFile ( $filename );

      ## load the datatype
      ( $datatype [0] ) = ( $content =~ /^([^\n]*)/ );
      $content =~ s/^[^\n]*\n//;

      ## load the status
      ( $datatype [1] ) = ( $content =~ /^([^\n]*)/ );
      $content =~ s/^[^\n]*\n//;

      ## write back the file
      ( $filename ) = ( $content =~ /^([^\n]*)/ );
      $content =~ s/^[^\n]*\n//;

      ## write back filename
      $filename = $dir."/LOG/".$filename;
      if (not $tools->saveFile (FILENAME => $filename, DATA => $content)) {
        print addPreLogLine ( "<FONT COLOR=#FF0000>FAILURE: Cannot write file</FONT>");
        print addPreLogLine ( "<FONT COLOR=#FF0000>FILE: ".$filename."</FONT>");
        next;
      }
    }

    ## create object
    my $db_object;
    if ($datatype [0] =~ /CERTIFICATE/) {
      $db_object = new OpenCA::X509 ( SHELL  => $cryptoShell,
                                      INFILE => $filename,
                                      FORMAT => "PEM" );
    } elsif ($datatype [0] =~ /^(REQUEST|CRR)$/) {
      $db_object = new OpenCA::REQ ( SHELL  => $cryptoShell,
                                     INFILE => $filename);
    } else {
      $db_object = new OpenCA::CRL ( INFILE => $filename,
                                     SHELL  => $cryptoShell );
    }
    if (not defined $db_object or not $db_object) {
      print addPreLogLine ( "<FONT COLOR=#FF0000>FAILURE: Cannot create object from 
file</FONT>");
      print addPreLogLine ( "<FONT COLOR=#FF0000>FILE: ".$filename."</FONT>");
      next;
    }

    ## insert object
    my $h;
    my $db_mode = "INSERT";
    if ($log) {
      $h = $db->storeItem ( DATATYPE        => "LOG",
                            OBJECT_DATATYPE => $datatype [1]."_".$datatype [0],
                            OBJECT          => $db_object,
                            KEY             => $value,
                            MODE            => $db_mode );
      $datatype [0] = "LOG";
      $value       .= ".log";
      $datatype [1] = "ALL";
    } else {

      my @help_list = ();
      if ($datatype [0] =~ /(CRR|REQUEST)/) {
        $serial = $db_object->getParsed()->{HEADER}->{SERIAL};
        @help_list = $db->searchItems ( DATATYPE => "PENDING_".$datatype [0],
                                        KEY      => $serial );
      }

      ## request already in the database ?
      if ( @help_list and scalar @help_list ) {
        $db_mode = "UPDATE";
      }

      $h = $db->storeItem ( DATATYPE => $datatype [1]."_".$datatype [0],
                            OBJECT   => $db_object,
                            MODE     => $db_mode );

      if ( (not defined $h) and
           (defined $keys->{ENFORCE} and $keys->{ENFORCE}) and
           ($db_mode !~ /UPDATE/) ) {
        $db_mode = "UPDATE";
        $h = $db->storeItem ( DATATYPE => $datatype [1]."_".$datatype [0],
                              OBJECT   => $db_object,
                              MODE     => $db_mode );
      }
    }
    if (defined $h) {
      push (@result, $db_object);

      if ($db_mode =~ /UPDATE/) {
        print addPreLogLine ($value." updated");
      } else {
        print addPreLogLine ($value." inserted");
      }
    } else {
      # serial
      my $serial;
      if ($datatype [0] =~ /^CERTIFICATE/) {
        $serial = $db_object->getParsed()->{SERIAL};
      } elsif ($datatype [0] =~ /(REQUEST|CRR)/) {
        $serial = $db_object->getParsed()->{DBKEY};
      } else { # CRL,CA_CERTIFICATE
        $serial = $cryptoShell->getDigest ( DATA => $db_object->getPEM());
      }
      ## advanced information
      if ($db->searchItems ( DATATYPE => $datatype [0], KEY => $serial )) {
        if ($db_mode !~ /UPDATE/) {
          print addPreLogLine ( "<FONT COLOR=#FF0000>WARNING: Cannot insert object but 
object is present in database</FONT>");
          print addPreLogLine ( "<FONT COLOR=#FF0000>FILE: ".$filename."</FONT>");
        } else {
          print addPreLogLine ( "<FONT COLOR=#FF0000>WARNING: Cannot update object but 
object is present in database</FONT>");
          print addPreLogLine ( "<FONT COLOR=#FF0000>FILE: ".$filename."</FONT>");
        }
      } elsif ($db_mode !~ /UPDATE/) {
        print addPreLogLine ( "<FONT COLOR=#FF0000>FAILURE: Cannot insert object and 
object is not present in database</FONT>");
        print addPreLogLine ( "<FONT COLOR=#FF0000>FILE: ".$filename."</FONT>");
      } else {
        print addPreLogLine ( "<FONT COLOR=#FF0000>FAILURE: Cannot insert and/or 
update object and object is not present in database</FONT>");
        print addPreLogLine ( "<FONT COLOR=#FF0000>FILE: ".$filename."</FONT>");
      }
    }
  }

  print closeLogSection ();

  return @result;

}

############################
## functions for Requests ##
############################

## the requests are only archived during the import of the certificates
## to handle crashed disks etc.

sub exportCSRs {

  my $exim_tmp_dir = $_[0];

  exportObjects ( DATATYPE => "APPROVED_REQUEST", DIR => $exim_tmp_dir );
  exportObjects ( DATATYPE => "PENDING_REQUEST", DIR => $exim_tmp_dir );
  exportObjects ( DATATYPE => "RENEW_REQUEST", DIR => $exim_tmp_dir );

  return 1;
}

sub importCSRs {

  my $exim_tmp_dir = $_[0];

  importObjects ( DATATYPE => "APPROVED_REQUEST", DIR => $exim_tmp_dir );
  importObjects ( DATATYPE => "PENDING_REQUEST", DIR => $exim_tmp_dir );
  importObjects ( DATATYPE => "RENEW_REQUEST", DIR => $exim_tmp_dir );

  return 1;

}

###############################
## functions for Certifcates ##
###############################

sub exportCerts {

  my $exim_tmp_dir = $_[0];

  exportObjects ( DATATYPE => "VALID_CERTIFICATE", DIR => $exim_tmp_dir );
  exportObjects ( DATATYPE => "ARCHIVIED_REQUEST", DIR => $exim_tmp_dir );
  exportObjects ( DATATYPE => "DELETED_REQUEST", DIR => $exim_tmp_dir );

  return 1;
}

sub importCerts {

  my $keys = { @_ };

  my $exim_tmp_dir = $keys->{TMP};
  my $certDir = getRequired ( 'CertDir' );

  my @list = importObjects ( DATATYPE => "VALID_CERTIFICATE", DIR => $exim_tmp_dir );
  importObjects ( DATATYPE => "ARCHIVIED_REQUEST", DIR => $exim_tmp_dir, ENFORCE => 1 
);
  importObjects ( DATATYPE => "DELETED_REQUEST", DIR => $exim_tmp_dir, ENFORCE => 1 );

  my $dir = $exim_tmp_dir."/CERTIFICATE/VALID/";

  return 1 if (not $keys->{LDAP}); 

  print addLogSection( "Importing Certificates into ldap ... ");

  if ( not scalar @list) {
    print addPreLogLine ("<i>No certificates present.</i>");
  }
  foreach my $data (@list) {
    my $result = eximObjectToLDAP ( CERTIFICATE => $data );
    if ( not $result or not $result->{STATUS} ) {
      $ret .= "\n<FONT COLOR=#FF0000>Cannot write CERTIFICATE 
".$data->getParsed()->{SERIAL}." to LDAP</FONT>";
    } else {
      $ret .= "\nCERTIFICATE ".$data->getParsed()->{SERIAL}." is available via LDAP";
    }
    print addPreLogLine ($ret);
  }

  ## what I'm doing here???
  ## upating lastImport
  my $txt = "";
  foreach $line  (@list) {
    $txt .= $line->getParsed()->{SERIAL}."\n";
  };
  unlink( "$certDir/lastImport.txt" );
  if (not $tools->saveFile (FILENAME => "$certDir/lastImport.txt",
                            DATA     => $txt ) ) {
    print addPreLogLine ("<FONT COLOR=#FF0000>".
                         "Cannot update file ".
                         $certDir."/lastImport.txt".
                         "with certificates of last import".
                         "</FONT>");
  }
  print closeLogSection();

  return 1;
}

##################################
## functions for CA-Certifcates ##
##################################

sub exportCAs {

  my $exim_tmp_dir = $_[0];

  exportObjects ( DATATYPE => "VALID_CA_CERTIFICATE", DIR => $exim_tmp_dir );

  return 1;
}

sub importCAs {

  my $keys = { @_ };

  my $exim_tmp_dir = $keys->{TMP};

  my @list = importObjects ( DATATYPE => "VALID_CA_CERTIFICATE", DIR => $exim_tmp_dir, 
ENFORCE => 1 );

  if ($keys->{LDAP}) {

    print addLogSection( "Importing CA-Certificates into ldap ... ");

    foreach my $data (@list) {
      my $tmpSerial, $tmpFormat;

      $tmpSerial = $cryptoShell->getDigest ( DATA => $data->getPEM());

      ## update LDAP ?
      my $result = eximObjectToLDAP ( AUTHORITY_CERTIFICATE => $data );
      if ( not $result or not $result->{STATUS} ) {
        print addPreLogLine ("<FONT COLOR=#FF0000>Cannot write CA-Certificate 
$tmpSerial to LDAP</FONT>" );
      } else {
        print addPreLogLine ("CA-Certificate $tmpSerial is available via LDAP") ;
      }
    }
    print closeLogSection();
  }

  print addLogSection ("Make CA-Certificate available on the server ...");
  my @cacerts = $db->searchItems ( DATATYPE => "VALID_CA_CERTIFICATE" );
  my $key;
  my $serial = -1;
  my $cert_data = "";
  foreach my $cert (@cacerts) {
    if ( $cert->getParsed ()->{SERIAL} > $serial ) {
      $serial    = $cert->getParsed ()->{SERIAL};
      $cert_data = $cert->getPEM ();
    }
  }
  $tools->saveFile ( FILENAME => "${exim_tmp_dir}/${key}.pem", DATA => $cert_data);
  my $CACert = getRequired ( 'CACertificate');
  if( not $tools->copyFiles ( SRC  => "${exim_tmp_dir}/${key}.pem",
                                 DEST => $CACert ) ) {
    print addLogLine ( "FAILED." );
    print addPreLogLine( "<FONT COLOR=#FF0000>".
                         "Copying latest ca-certificate into ".
                         "the RAServer failed ".
                         "(from ${exim_tmp_dir}/${key}.pem ".
                         "to $CACert)!</FONT>");
    print closeLogSection ();
    return 0;
  }
  print addLogLine ("OK.");
  print closeLogSection (); 

  # Now we copy the CA's certificate to the chain dir
  my $cacertCRT = gteRequired ('CACertificateCRT');
  if (not $tools->copyFiles( SRC => $CACert,
                     DEST => $cacertCRT )) {
    print addLogSection( "<FONT COLOR=#FF0000>".
                         "Copying latest ca-certificate into ".
                         "chain's directory failed ".
                         "(from $CACert ".
                         "to ${cacertCRT})!</FONT>");
    print closeLogSection ();
    return 0;
  }

  # Let's make Chain verification
  print addLogSection("Re-Building CA Chain ... ");
  my $chainDir = getRequired ( 'ChainDir' );
  chdir( "${chainDir}" );
  ## what for command?
  my $makeCmd = getRequired ('MakePath');
  $ret = `$makeCmd clean ; $makeCmd 2>&1`;
  if ( $? ) {
    print addLogLine ("<FONT COLOR=#FF0000>FAILED</FONT>");
    print closeLogSection();
    return 0;
  } else {
    print addLogLine("Ok.");
  }
  print closeLogSection();

  return 1;
}


########################
## functions for CRRs ##
########################

sub exportCRRs {

  my $exim_tmp_dir = $_[0];

  exportObjects ( DATATYPE => "APPROVED_CRR", DIR => $exim_tmp_dir );
  exportObjects ( DATATYPE => "PENDING_CRR", DIR => $exim_tmp_dir );

  return 1;
}

sub importCRRs {


  my $exim_tmp_dir = $_[0];

  my @list = importObjects ( DATATYPE => "APPROVED_CRR", DIR => $exim_tmp_dir );
  push (@list, importObjects ( DATATYPE => "PENDING_CRR", DIR => $exim_tmp_dir ));

  print addLogSection ("Updating certificates status ...");
  foreach my $data (@list) {

    if ($db->updateStatus (
          DATATYPE => "VALID_CERTIFICATE",
          NEWTYPE  => "SUSPENDED_CERTIFICATE",
          OBJECT   => $db->getItem (
                        DATATYPE => "VALID_CERTIFICATE",
                        KEY      => $data->getParsed()->{REVOKE_CERTIFICATE_SERIAL}
                                   )
                          )) {
      print addPreLogLine ("Changed the status of the certificate <I>" . 
                           $data->getParsed()->{REVOKE_CERTIFICATE_DN} .
                           " (" . $data->getParsed()->{REVOKE_CERTIFICATE_SERIAL} . 
")</I>");
    } else {
      print addPreLogLine ("<FONT COLOR=##FF0000>".
                           "Cannot change the status of the certificate <I>" . 
                           $data->getParsed()->{REVOKE_CERTIFICATE_DN} .
                           " (" . $data->getParsed->{REVOKE_CERTIFICATE_SERIAL} . 
")</I>".
                           "</FONT>");
    }
  }
  print closeLogSection();

  return 1;
}

########################
## functions for CRLs ##
########################

sub exportCRLs {

  my $exim_tmp_dir = $_[0];

  exportObjects ( DATATYPE => "VALID_CRL", DIR => $exim_tmp_dir );
  exportObjects ( DATATYPE => "ARCHIVIED_CRR", DIR => $exim_tmp_dir );
  exportObjects ( DATATYPE => "REVOKED_CERTIFICATE", DIR => $exim_tmp_dir );

  return 1;
}

sub importCRLs {

  my $keys = { @_ };

  my $exim_tmp_dir = $keys->{TMP};

  my @list = importObjects ( DATATYPE => "VALID_CRL", DIR => $exim_tmp_dir, ENFORCE => 
1 );
  importObjects ( DATATYPE => "ARCHIVIED_CRR", DIR => $exim_tmp_dir, ENFORCE => 1 );
  importObjects ( DATATYPE => "DELETED_CRR", DIR => $exim_tmp_dir, ENFORCE => 1 );
  importObjects ( DATATYPE => "REVOKED_CERTIFICATE", DIR => $exim_tmp_dir, ENFORCE => 
1 );

  return 1 if (not defined @list or not scalar @list);

  if ( $keys->{LDAP} ) {
    print addLogSection("Importing CRL into LDAP ... ");
    foreach my $data (@list) {
      my $result = eximObjectToLDAP ( CRL => $data );
      if ( not $result or not $result->{STATUS} ) {
        print addPreLogLine ( "<FONT COLOR=#FF0000>".
                              "Cannot write CRL to LDAP\n\tLast Update: ".
                              $data->getParsed()->{LAST_UPDATE} ."\n" .
                              "\tNext Update: " .
                              $data->getParsed()->{NEXT_UPDATE} . "\n".
                              "</FONT>");
      } else {
        print addPreLogLine (
              "Added CRL to LDAP\n\tLast Update: " .
              $data->getParsed()->{LAST_UPDATE} ."\n" .
              "\tNext Update: " .
              $data->getParsed()->{NEXT_UPDATE} . "\n");
      }
    }
    print closeLogSection ();
  }

  my $crlDir = getRequired ( 'CRLDir');

  print addLogSection("Importing CRL into servers ... ");

  my $serial = 0;
  my $data;
  foreach my $tmpCRL (@list) {

    if ($cryptoShell->getNumericDate ($tmpCRL->getParsed()->{LAST_UPDATE}) > $serial) {
      $serial = $cryptoShell->getNumericDate ($tmpCRL->getParsed()->{LAST_UPDATE});
      $data = $tmpCRL;
    }
  }

  ## RAServer
  if (not $tools->saveFile ( FILENAME=>"$crlDir/cacrl.pem",
                             DATA=>$data->getPEM())) {
    print addPreLogLine ( "<FONT COLOR=#FF0000>".
                          "Cannot update CRL on RAServer. FILE: $crlDir/cacrl.pem".
                          "</FONT>");
  }
  if (not $tools->saveFile ( FILENAME=>"$crlDir/cacrl.der",
                             DATA=>$data->getDER())) {
    print addPreLogLine ( "<FONT COLOR=#FF0000>".
                          "Cannot update CRL on RAServer. FILE: $crlDir/cacrl.der".
                          "</FONT>");
  }
  if (not $tools->saveFile ( FILENAME=>"$crlDir/cacrl.crl",
                             DATA=>$data->getDER())) {
    print addPreLogLine ( "<FONT COLOR=#FF0000>".
                          "Cannot update CRL on RAServer. FILE: $crlDir/cacrl.crl".
                          "</FONT>");
  }
  if (not $tools->saveFile ( FILENAME=>"$crlDir/cacrl.txt",
                             DATA=>$data->getTXT())) {
    print addPreLogLine ( "<FONT COLOR=#FF0000>".
                          "Cannot update CRL on RAServer. FILE: $crlDir/cacrl.txt".
                          "</FONT>");
  }

  print addPreLogLine (
              "Added CRL to servers\n\tLast Update: " .
              $data->getParsed()->{LAST_UPDATE} ."\n" .
              "\tNext Update: " .
              $data->getParsed()->{NEXT_UPDATE} . "\n");

  print closeLogSection();

  return 1;
}

#################################
## functions for Configuration ##
#################################

sub exportConfiguration {

  my $exim_tmp_dir = $_[0];
  my $dir = $exim_tmp_dir."/Configuration";

  if ( not createDirectory ($dir) ) {
    return 0;
  }

#  my $openssl     = getRequired ( 'sslconfig'   );
  my $rbac_dir    = getRequired ( 'RBAC_DIR'    );
#  my $openssl_dir = getRequired ( 'OPENSSL_DIR' );
#  my $ext_dir     = getRequired ( 'EXT_DIR'     );
  my $config_dir  = $rbac_dir;

  $config_dir  =~ s/\/[^\/]*$//;
  $rbac_dir    =~ s/^.*\///g;
#  $openssl_dir =~ s/^.*\///g;
#  $ext_dir     =~ s/^.*\///g;

  my $tmpdir = $dir;
  if( not chdir( "$tmpdir" )) {
    print addErrorLog( "Failed changing dir to $tmpdir" );
    print closeLogSection ();
    return 0;
  }

#  ## bring openssl.cnf to tmp-dir
#
#  print addLogSection("Exporting the OpenSSL-configurationfile of the CA ... ");
#  $ret = `cp $openssl . 2>&1`;
#  if( $? != 0 ) {
#    print addErrorLog("Cannot copy $openssl to $tmpdir!");
#    print addLogLine( "cp $openssl ." );
#    print closeLogSection ();
#    return 0;
#  }
#  print addLogLine( "Ok." );
#  print closeLogSection ();

  ## bring RBAC/ to tmp-dir

  print addLogSection("Exporting the RBAC-configuration ... ");
  $ret = `cd $config_dir; tar -c $rbac_dir | tar -x -C $tmpdir 2>&1`;
  if( $? != 0 ) {
    print addErrorLog("Cannot copy $rbac_dir to $tmpdir!");
    print addLogLine( "cd $config_dir; tar -c $rbac_dir | tar -x -C $tmpdir" );
    print closeLogSection ();
    return 0;
  }
  print addLogLine( "Ok." );
  print closeLogSection ();

#  ## bring OpenSSL/ to tmp-dir
#
#  print addLogSection("Exporting the OpenSSL-configuration of the roles ... ");
#  $ret = `cd $config_dir; tar -c $openssl_dir | tar -x -C $tmpdir 2>&1`;
#  if( $? != 0 ) {
#    print addErrorLog("Cannot copy $openssl_dir to $tmpdir!");
#    print addLogLine( "cd $config_dir; tar -c $openssl_dir | tar -x -C $tmpdir" );
#    print closeLogSection ();
#    return 0;
#  }
#  print addLogLine( "Ok." );
#  print closeLogSection ();

#  ## bring extfiles/ to tmp-dir
#
#  print addLogSection("Exporting the configuration of the extensions of the roles ... 
");
#  $ret = `cd $config_dir; tar -c $ext_dir | tar -x -C $tmpdir 2>&1`;
#  if( $? != 0 ) {
#    print addErrorLog("Cannot copy $ext_dir to $tmpdir!");
#    print addLogLine( "cd $config_dir; tar -c $ext_dir | tar -x -C $tmpdir" );
#    print closeLogSection ();
#    return 0;
#  }
#  print addLogLine( "Ok." );
#  print closeLogSection ();

  return 1;
}

sub importConfiguration {

  my $exim_tmp_dir = $_[0];
  my $dir = $exim_tmp_dir."/Configuration";

#  my $openssl     = getRequired ( 'sslconfig'   );
  my $rbac_dir    = getRequired ( 'RBAC_DIR'    );
#  my $openssl_dir = getRequired ( 'OPENSSL_DIR' );
#  my $ext_dir     = getRequired ( 'EXT_DIR'     );
  my $config_dir  = $rbac_dir;
 
  $config_dir  =~ s/\/[^\/]*$//;
  $rbac_dir    =~ s/^.*\///g;
#  $openssl_dir =~ s/^.*\///g;
#  $ext_dir     =~ s/^.*\///g;                                                         
         

  my ( @lastExport );

  my $tmpdir = $dir;
  if (not chdir ( $tmpdir ) ) {
    print addErrorLog("Cannot change directory to $tmpdir!");
    print closeLogSection ();
    return 0;
  }

#  ## importing openssl.cnf
#
#  my $sslconfig = $openssl;
#  $sslconfig =~ s/.*\///g;
#  print addLogSection("Importing the OpenSSL-configurationfile of the CA ... ");
#  $ret = `cp $sslconfig $openssl 2>&1`;
#  if( $? != 0 ) {
#    print addErrorLog("Cannot copy $sslconfig to $openssl!");
#    print addLogLine( "cp $sslconfig $openssl" );
#    print closeLogSection ();
#    return 0;
#  }
#  print addLogLine( "Ok." );
#  print closeLogSection ();

  ## importing RBAC/

  print addLogSection("Importing the RBAC-configuration ... ");
  $ret = `tar -c $rbac_dir | tar -x -C $config_dir 2>&1`;
  if( $? != 0 ) {
    print addErrorLog("Cannot copy $rbac_dir to $config_dir!");
    print addLogLine( "tar -c $rbac_dir | tar -x -C $config_dir" );
    print closeLogSection ();
    return 0;
  }
  print addLogLine( "Ok." );
  print closeLogSection ();

#  ## importing OpenSSL/
#
#  print addLogSection("Importing the OpenSSL-configuration of the roles  ... ");
#  $ret = `tar -c $openssl_dir | tar -x -C $config_dir 2>&1`;
#  if( $? != 0 ) {
#    print addErrorLog("Cannot copy $openssl_dir to $config_dir!");
#    print addLogLine( "tar -c $openssl_dir | tar -x -C $config_dir" );
#    print closeLogSection ();
#    return 0;
#  }
#  print addLogLine( "Ok." );
#  print closeLogSection ();

#  ## importing extfiles/
#
#  print addLogSection("Importing the configuration of the extensions of the roles ... 
");
#  $ret = `tar -c $ext_dir | tar -x -C $config_dir 2>&1`;
#  if( $? != 0 ) {
#    print addErrorLog("Cannot copy $ext_dir to $config_dir!");
#    print addLogLine( "tar -c $ext_dir | tar -x -C $config_dir" );
#    print closeLogSection ();
#    return 0;
#  }
#  print addLogLine( "Ok." );
#  print closeLogSection ();

  return 1;
}

#########################
## functions for Mails ##
#########################

sub exportMails {

  my $exim_tmp_dir = $_[0];
  my $dir = $exim_tmp_dir."/Mail";

  if ( not createDirectory ($dir) ) {
    return 0;
  }

  my $mail_dir    = getRequired ( 'MAIL_DIR' );

  print addLogSection("Exporting the Mails ... ");
  $ret = `cd $mail_dir; tar -c * | tar -x -C $dir 2>&1`;
  if( $? != 0 ) {
    print addErrorLog("Cannot copy $mail_dir to $dir!");
    print addLogLine( "cd $mail_dir; tar -c * | tar -x -C $dir" );
    print closeLogSection ();
    return 0;
  }
  print addLogLine( "Ok." );
  print closeLogSection ();

  return 1;
}

sub importMails {

  my $exim_tmp_dir = $_[0];
  my $dir = $exim_tmp_dir."/Mail";

  my $mail_dir    = getRequired ( 'MAIL_DIR'    );
 
  print addLogSection("Importing the Mails ... ");
  $ret = `cd $dir; tar -c * | tar -x -C $mail_dir 2>&1`;
  if( $? != 0 ) {
    print addErrorLog("Cannot copy $dir to $mail_dir!");
    print addLogLine( "cd $dir; tar -c * | tar -x -C $mail_dir" );
    print closeLogSection ();
    return 0;
  }
  print addLogLine( "Ok." );
  print closeLogSection ();

  ## perhaps I have to send the mails ?
  ## coded in mail-utils.lib
  if (getRequired ('SEND_MAIL_DURING_IMPORT') and
      (getRequired ('SEND_MAIL_DURING_IMPORT') !~ /^NO$/i)) {
    sendPreparedMails ();
  }

  return 1;
}

##########################################
## ldap import and export functionality ##
##########################################

sub eximObjectToLDAP {

  my $keys = { @_ };
 
  ## determine type of object
  if ( $keys->{CERTIFICATE} ) {
    ## create object in LDAP
    my $result = addLDAPobject ( CERTIFICATE => $keys->{CERTIFICATE} );
    if ( not $result or not $result->{STATUS} ) {
      return (0);
    }
    ## add attribute
    return addLDAPattribute ( CERTIFICATE => $keys->{CERTIFICATE},
                              NOPRINT     => 1 );
  } elsif ( $keys->{AUTHORITY_CERTIFICATE} ) {
    ## create object in LDAP
    my $result = addLDAPobject ( CERTIFICATE => $keys->{AUTHORITY_CERTIFICATE} );
    if ( not $result and not $result->{STATUS} ) {
      return (0);
    }
    ## add attribute
    return addLDAPattribute ( AUTHORITY_CERTIFICATE => $keys->{AUTHORITY_CERTIFICATE},
                              NOPRINT               => 1 );
  } elsif ( $keys->{CRL} ) {
    ## create object in LDAP is not necessary because it is the CA
    ## add attribute
    return addLDAPattribute ( CRL     => $keys->{CRL},
                              NOPRINT => 1 );
  } elsif ( $keys->{AUTHORITY_CRL} ) {
    ## create object in LDAP is not necessary because it is the CA
    ## add attribute
    return addLDAPattribute ( AUTHORITY_CRL => $keys->{AUTHORITY_CRL},
                              NOPRINT       => 1 );
  } else {
    return (0);
  }
}

######################################
## full export/import functionality ##
######################################

sub exportToCA {
  my $tmp = createStructure ();
  exportCSRs      ( $tmp );
  exportCRRs      ( $tmp );
  createArchive   ( $tmp );
  removeDirectory ( $tmp );
}

sub importFromCA {

  my $keys = { @_ };

  my $tmp = createStructure ();
  extractArchive      ( $tmp );
  if (withLDAPsupport) {
    importCerts         ( TMP => $tmp, LDAP => "1" );
    importCAs           ( TMP => $tmp, LDAP => "1" );
    importCRLs          ( TMP => $tmp, LDAP => "1" );
  } else {
    importCerts         ( TMP => $tmp, LDAP => "0" );
    importCAs           ( TMP => $tmp, LDAP => "0" );
    importCRLs          ( TMP => $tmp, LDAP => "0" );
  }
  importMails         ( $tmp );
  importConfiguration ( $tmp );
  removeDirectory     ( $tmp );
}

sub exportToRAServer {
  my $tmp = createStructure ();
  exportCerts         ( $tmp );
  exportCAs           ( $tmp );
  exportCRLs          ( $tmp );
  exportMails         ( $tmp );
  exportConfiguration ( $tmp );
  createArchive       ( $tmp );
  removeDirectory     ( $tmp );
}

sub importFromRAServer {
  my $tmp = createStructure ();
  extractArchive  ( $tmp );
  importCSRs      ( $tmp );
  importCRRs      ( $tmp );
  removeDirectory ( $tmp );
}

sub withLDAPsupport {
  my $ldap = getRequired ('LDAP');

  print addLogSection ("LDAP support is ");
  if ( $ldap =~ /^(off|no)$/i ) {
    print addLogLine ("deactivated");
    print closeLogSection ();
    return 0;
  } else {
    print addLogLine ("activated");
    print closeLogSection ();
    return 1;
  }
}
    
1;

Reply via email to