You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
			
		
		
		
		
			
		
			
				
					
					
						
							1431 lines
						
					
					
						
							40 KiB
						
					
					
				
			
		
		
	
	
							1431 lines
						
					
					
						
							40 KiB
						
					
					
				| # Copyright (c) Stephan Martin <sm@sm-zone.net>
 | |
| #
 | |
| # $Id: CA.pm,v 1.9 2006/06/28 21:50:41 sm Exp $
 | |
| # 
 | |
| # This program is free software; you can redistribute it and/or modify
 | |
| # it under the terms of the GNU General Public License as published by
 | |
| # the Free Software Foundation; either version 2 of the License, or
 | |
| # (at your option) any later version.
 | |
| # 
 | |
| # This program is distributed in the hope that it will be useful,
 | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| # GNU General Public License for more details.
 | |
| # 
 | |
| # You should have received a copy of the GNU General Public License
 | |
| # along with this program; if not, write to the Free Software
 | |
| # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 | |
| 
 | |
| use strict;
 | |
| 
 | |
| package CA;
 | |
| 
 | |
| use POSIX;
 | |
| 
 | |
| sub new {
 | |
|    my $that = shift;
 | |
|    my $self = {};
 | |
| 
 | |
|    my $class = ref($that) || $that;
 | |
| 
 | |
|    $self->{'init'} = shift;
 | |
| 
 | |
|    if(not -d $self->{'init'}->{'basedir'}) {
 | |
|       print "create basedir: $self->{'init'}->{'basedir'}\n";
 | |
|       mkdir($self->{'init'}->{'basedir'}, 0700);
 | |
|    }
 | |
| 
 | |
|    if(not -d $self->{'init'}->{'tmpdir'}) {
 | |
|       print "create temp dir: $self->{'init'}->{'tmpdir'}\n";
 | |
|       mkdir($self->{'init'}->{'tmpdir'}, 0700);
 | |
|    }
 | |
| 
 | |
|    opendir(DIR, $self->{'init'}->{'basedir'}) || do {
 | |
|       print _("error: can't open basedir: ").$!;
 | |
|       exit(1);
 | |
|    };
 | |
| 
 | |
|    $self->{'calist'} = [];
 | |
| 
 | |
|       while(my $ca = readdir(DIR)) { 
 | |
|          chomp($ca);
 | |
|          next if $ca eq ".";
 | |
|          next if $ca eq "..";
 | |
|          next if $ca eq "tmp";
 | |
| 
 | |
|          my $dir = $self->{'init'}->{'basedir'}."/".$ca;
 | |
|          next unless -d $dir;
 | |
|          next unless -s $dir."/cacert.pem";
 | |
|          next unless -s $dir."/cacert.key";
 | |
|          push(@{$self->{'calist'}}, $ca);
 | |
|          @{$self->{'calist'}} = sort(@{$self->{'calist'}});
 | |
|          $self->{$ca}->{'dir'} = $dir;
 | |
|          $self->{$ca}->{'cnf'} = $dir."/openssl.cnf";
 | |
|       }
 | |
|       closedir(DIR);
 | |
| 
 | |
|    bless($self, $class);
 | |
| }
 | |
| 
 | |
| #
 | |
| # see if the ca can be opened without asking the user
 | |
| # or show the open dialog
 | |
| #
 | |
| sub get_open_name {
 | |
|    my ($self, $main, $opts) = @_;
 | |
| 
 | |
|    my ($ind);
 | |
| 
 | |
|    if((not defined($opts->{'name'})) || ($opts->{'name'} eq "")) {
 | |
|       # if only one CA is defined, open it without prompting
 | |
|       if($#{$self->{'calist'}} == 0) {
 | |
|          $opts->{'name'} = $self->{'calist'}->[0];
 | |
|          $self->open_ca($main, $opts);
 | |
|       } else {
 | |
|          $main->show_select_ca_dialog('open');
 | |
|       }
 | |
|    }
 | |
| }
 | |
| 
 | |
| #
 | |
| # open the ca with the given name
 | |
| #
 | |
| sub open_ca {
 | |
|    my ($self, $main, $opts, $box) = @_;
 | |
| 
 | |
|    $box->destroy() if(defined($box));
 | |
| 
 | |
|    GUI::HELPERS::set_cursor($main, 1);
 | |
| 
 | |
|    my ($i, $cnf, @lines, $oldca, $index, $bak, $t);
 | |
| 
 | |
|    main::printd("Opening ca $opts->{'name'}");
 | |
|    GUI::HELPERS::set_status($main, _("  Opening CA: ").$opts->{'name'});
 | |
|    while(Gtk2->events_pending) {
 | |
|       Gtk2->main_iteration;
 | |
|    }
 | |
| 
 | |
|    if(!exists($self->{$opts->{'name'}})) {
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       GUI::HELPERS::print_warning(_("Invalid CA selected"));
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    # selected CA is already open
 | |
|    if ((defined($self->{'actca'})) && 
 | |
|        ($opts->{'name'} eq $self->{'actca'})) { 
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       print STDERR "DEBUG: ca $opts->{'name'} already opened\n";
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    $self->{'actca'} = $opts->{'name'};
 | |
|    $self->{'cadir'} = $self->{$opts->{'name'}}->{'dir'};
 | |
|    $main->{'cadir'} = $self->{'cadir'};
 | |
| 
 | |
|    if(my $dir = HELPERS::get_export_dir($main)) {
 | |
|       $main->{'exportdir'} = $dir;
 | |
|    }
 | |
| 
 | |
|    # read per CA configuration
 | |
|    $self->{'cfg'} = HELPERS::read_cfg($self->{'cadir'});
 | |
|    main::printd("Request-Type: " . ($self->{'cfg'}->{global}{default_req_type} // 'none'));
 | |
|    main::printd("Default bits server: " . ($self->{'cfg'}->{server}{default_bits} // 'none'));
 | |
|    main::printd("Default bits user: " . ($self->{'cfg'}->{user}{default_bits} // 'none'));
 | |
|    main::printd("Default key cipher: " . ($self->{'cfg'}->{user}{default_cipher} // 'none'));
 | |
| 
 | |
|    # update config (necessary for update from old tinyca)
 | |
|    $cnf =  $self->{$opts->{'name'}}->{'cnf'};
 | |
|    open(IN, "<$cnf");
 | |
|    @lines = <IN>;
 | |
|    close(IN);
 | |
|    for($i = 0; $lines[$i]; $i++) {
 | |
|       $lines[$i] =~ s/private\/cakey.pem/cacert.key/;
 | |
|    }
 | |
|    open(OUT, ">$cnf");
 | |
|    print OUT @lines;
 | |
|    close(OUT);
 | |
| 
 | |
|    $main->{'mw'}->set_title( "Tiny CA Management $main->{'version'}".
 | |
|                              " - $self->{'actca'}"
 | |
|          );
 | |
| 
 | |
|    $main->{'CERT'}->{'lastread'} = 0;
 | |
|    $main->{'REQ'}->{'lastread'}  = 0;
 | |
|    $main->{'KEY'}->{'lastread'}  = 0;
 | |
| 
 | |
|    delete($main->{'OpenSSL'}->{'CACHE'});
 | |
|    delete($main->{'CERT'}->{'OpenSSL'}->{'CACHE'});
 | |
|    delete($main->{'REQ'}->{'OpenSSL'}->{'CACHE'});
 | |
|    delete($main->{'OpenSSL'});
 | |
| 
 | |
|    GUI::HELPERS::set_status($main, _("  Initializing OpenSSL"));
 | |
|    $main->{'OpenSSL'} = OpenSSL->new(
 | |
|          $main->{'init'}->{'opensslbin'}, $main->{'tmpdir'});
 | |
| 
 | |
|    $index = $self->{'cadir'}."/index.txt";
 | |
| 
 | |
|    GUI::HELPERS::set_status($main, _("  Check for CA Version"));
 | |
|    while(Gtk2->events_pending) {
 | |
|       Gtk2->main_iteration;
 | |
|    }
 | |
| 
 | |
|    open(INDEX, "+<$index") || do {
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       GUI::HELPERS::print_error(_("Can't open index file: ".$!));
 | |
|       return;
 | |
|    };
 | |
| 
 | |
|    while(<INDEX>) {
 | |
|       if(/Email=/) {
 | |
|          $oldca = 1;
 | |
|          last;
 | |
|       }
 | |
|    }
 | |
|    close(INDEX);
 | |
| 
 | |
|    # offer CA conversion for old CAs and openssl >= 0.9.7
 | |
|    if($oldca && ($main->{'OpenSSL'}->{'version'} eq "0.9.7") &&
 | |
|          !$opts->{'noconv'} && !$opts->{'doconv'}) {
 | |
|       GUI::HELPERS::set_status($main, _("  Convert CA"));
 | |
|       while(Gtk2->events_pending) {
 | |
|          Gtk2->main_iteration;
 | |
|       }
 | |
|       $self->{'actca'} = undef;
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       $main->show_ca_convert_dialog($opts);
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    if($opts->{'doconv'}) {
 | |
|       open(INDEX, "+<$index") || do {
 | |
|          GUI::HELPERS::set_cursor($main, 0);
 | |
|          GUI::HELPERS::print_error(_("Can't open index file: ".$!));
 | |
|          return;
 | |
|       };
 | |
|       $bak = $index.".bak";
 | |
|       open(BAK, "+>$bak") || do {
 | |
|          GUI::HELPERS::set_cursor($main, 0);
 | |
|          GUI::HELPERS::print_error(_("Can't open index backup: ").$!);
 | |
|          return;
 | |
|       };
 | |
|       seek(INDEX, 0, 0);
 | |
|       while(<INDEX>) {
 | |
|          print BAK;
 | |
|       }
 | |
|       seek(INDEX, 0, 0);
 | |
|       truncate(INDEX, 0);
 | |
|       seek(BAK, 0, 0);
 | |
|       while(<BAK>) {
 | |
|          $_ =~ s/Email=/emailAddress=/;
 | |
|          print INDEX;
 | |
|       }
 | |
|       close(INDEX);
 | |
|       close(BAK);
 | |
| 
 | |
|       $t = _("This CA is converted for openssl 0.9.7x now.");
 | |
|       $t .= "\n";
 | |
|       $t .= _("You will find a backup copy of the index file at: ");
 | |
|       $t .= $bak;
 | |
| 
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       GUI::HELPERS::print_info($t);
 | |
|    }
 | |
| 
 | |
|    GUI::HELPERS::set_cursor($main, 1);
 | |
| 
 | |
|    GUI::HELPERS::set_status($main, _("  Read Configuration"));
 | |
|    while(Gtk2->events_pending) {
 | |
|       Gtk2->main_iteration;
 | |
|    }
 | |
|    $main->{'TCONFIG'}->init_config($main, $opts->{'name'});
 | |
| 
 | |
|    GUI::HELPERS::set_status($main, _("  Create GUI"));
 | |
|    while(Gtk2->events_pending) {
 | |
|       Gtk2->main_iteration;
 | |
|    }
 | |
|    $main->create_mframe(1);
 | |
| 
 | |
|    GUI::HELPERS::set_status($main, _("  Create Toolbar"));
 | |
|    while(Gtk2->events_pending) {
 | |
|       Gtk2->main_iteration;
 | |
|    }
 | |
|    $main->create_toolbar('ca');
 | |
| 
 | |
|    GUI::HELPERS::set_status($main, _("  Actual CA: ").$self->{'actca'});
 | |
|    while(Gtk2->events_pending) {
 | |
|       Gtk2->main_iteration;
 | |
|    }
 | |
| 
 | |
|    GUI::HELPERS::set_cursor($main, 0);
 | |
| 
 | |
|    $main->{'nb'}->set_current_page(0);
 | |
| 
 | |
|    return;
 | |
| }
 | |
| 
 | |
| #
 | |
| # get name for deleting a CA
 | |
| #
 | |
| sub get_ca_delete {
 | |
|    my ($self, $main, $name) = @_;
 | |
| 
 | |
|    if(!defined($name)) {
 | |
|       $main->show_select_ca_dialog('delete');
 | |
|       return;
 | |
|    }elsif(!exists($self->{$name})) {
 | |
|       $main->show_select_ca_dialog('delete');
 | |
|       GUI::HELPERS::print_warning(_("Invalid CA selected"));
 | |
|       return;
 | |
|    }else {
 | |
|       $self->delete_ca($main, $name);
 | |
|    }
 | |
| 
 | |
|    return;
 | |
| }
 | |
| 
 | |
| #
 | |
| # delete given CA
 | |
| #
 | |
| sub delete_ca {
 | |
|    my ($self, $main, $name, $box) = @_;
 | |
| 
 | |
|    my ($ind, @tmp, $t);
 | |
| 
 | |
|    $box->destroy() if(defined($box));
 | |
| 
 | |
|    GUI::HELPERS::set_cursor($main, 1);
 | |
| 
 | |
|    _rm_dir($self->{$name}->{'dir'});
 | |
| 
 | |
|    if((defined($self->{'actca'})) && 
 | |
|       ($name eq $self->{'actca'})) { 
 | |
|       $self->{'actca'} = undef;
 | |
|    }
 | |
|    
 | |
|    $main->{'cabox'}->destroy() if(defined($main->{'cabox'}));
 | |
|    delete($main->{'cabox'});
 | |
| 
 | |
|    $main->{'reqbox'}->destroy() if(defined($main->{'reqbox'}));
 | |
|    delete($main->{'reqbox'});
 | |
| 
 | |
|    $main->{'keybox'}->destroy() if(defined($main->{'keybox'}));
 | |
|    delete($main->{'keybox'});
 | |
| 
 | |
|    $main->{'certbox'}->destroy() if(defined($main->{'certbox'}));
 | |
|    delete($main->{'certbox'});
 | |
| 
 | |
|    for(my $i = 0; $i < 4; $i++) {
 | |
|       $main->{'nb'}->remove_page($i);
 | |
|    }
 | |
| 
 | |
|    delete($main->{'reqbrowser'});
 | |
|    delete($main->{'certbrowser'});
 | |
| 
 | |
|    delete($main->{'REQ'}->{'reqlist'});
 | |
|    delete($main->{'CERT'}->{'certlist'});
 | |
| 
 | |
|    foreach(@{$self->{'calist'}}) {
 | |
|       next if $_ eq $name;
 | |
|       push(@tmp, $_);
 | |
|    }
 | |
|    $self->{'calist'} = \@tmp;
 | |
| 
 | |
|    delete($self->{$name});
 | |
| 
 | |
|    $main->create_mframe();
 | |
| 
 | |
|    GUI::HELPERS::set_cursor($main, 0);
 | |
| 
 | |
|    $t = sprintf(_("CA: %s deleted"), $name);
 | |
|    GUI::HELPERS::print_info($t);
 | |
| 
 | |
|    return;
 | |
| }
 | |
| 
 | |
| #
 | |
| # check if all data for creating a ca is available
 | |
| #
 | |
| sub get_ca_create {
 | |
|    my ($self, $main, $opts, $box, $mode) = @_;
 | |
| 
 | |
|    $box->destroy() if(defined($box));
 | |
| 
 | |
|    my ($action, $index, $serial, $t, $parsed);
 | |
| 
 | |
|    if(not(defined($opts))) { 
 | |
|       $opts = {};
 | |
|       $opts->{'days'} = 3650; # set default to 10 years
 | |
|       $opts->{'bits'} = 4096;
 | |
|       $opts->{'digest'} = 'sha256';
 | |
| 
 | |
|       if(defined($mode) && $mode eq "sub") { # create SubCA, use defaults
 | |
|          $opts->{'parentca'} = $main->{'CA'}->{'actca'};
 | |
|          
 | |
|          $parsed = $main->{'CERT'}->parse_cert($main, 'CA');
 | |
|          if(defined $parsed->{'C'}) {
 | |
|             $opts->{'C'} = $parsed->{'C'};
 | |
|          }
 | |
|          if(defined $parsed->{'ST'}) {
 | |
|             $opts->{'ST'} = $parsed->{'ST'};
 | |
|          }
 | |
|          if(defined $parsed->{'L'}) {
 | |
|             $opts->{'L'} = $parsed->{'L'};
 | |
|          }
 | |
|          if(defined $parsed->{'O'}) {
 | |
|             $opts->{'O'} = $parsed->{'O'};
 | |
|          }
 | |
|          if(defined $parsed->{'OU'}) {
 | |
|             my $cc = 0;
 | |
|             foreach my $ou (@{$parsed->{'OU'}}) {
 | |
|                $opts->{'OU'}->[$cc++] = $ou;
 | |
|             }
 | |
|          }
 | |
|       }
 | |
|       
 | |
|       $main->show_ca_dialog($opts, $mode);
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    if(defined($mode) && $mode eq "sub") {
 | |
|       if(not defined($opts->{'parentpw'})) {
 | |
|          $main->show_ca_dialog($opts, $mode);
 | |
|          GUI::HELPERS::print_warning(
 | |
|              _("Password of parent CA is needed for creating a Sub CA"));
 | |
|          return;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if((not defined($opts->{'name'})) || 
 | |
| 	   ($opts->{'name'} eq "") ||
 | |
| 	   ($opts->{'name'} =~ /\s/)) { 
 | |
|       $main->show_ca_dialog($opts, $mode);
 | |
|       GUI::HELPERS::print_warning(_("Name must be filled in and must")
 | |
|                           ._(" not contain Spaces"));
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    if((not defined($opts->{'C'})) ||
 | |
|       ($opts->{'C'} eq "") ||
 | |
|       (not defined($opts->{'CN'})) ||
 | |
|       ($opts->{'CN'} eq "") ||
 | |
|       (not defined($opts->{'passwd'})) ||
 | |
|       ($opts->{'passwd'} eq "")) { 
 | |
|       $main->show_ca_dialog($opts, $mode);
 | |
|       GUI::HELPERS::print_warning(
 | |
|             _("Please specify at least Common Name, ") 
 | |
|            ._("Country and Password"));
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    if((not defined($opts->{'passwd2'})) ||
 | |
|       $opts->{'passwd'} ne $opts->{'passwd2'}) { 
 | |
|       $main->show_ca_dialog($opts, $mode);
 | |
|       GUI::HELPERS::print_warning(_("Passwords don't match"));
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    $opts->{'C'} = uc($opts->{'C'});
 | |
| 
 | |
|    if(length($opts->{'C'}) != 2) { 
 | |
|       $main->show_ca_dialog($opts, $mode);
 | |
|       GUI::HELPERS::print_warning(_("Country must be exact 2 letter code"));
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    $t = sprintf(_("CA: %s already exists"), $opts->{'name'});
 | |
|    if(defined($self->{$opts->{'name'}})) { 
 | |
|       $main->show_ca_dialog($opts, $mode);
 | |
|       GUI::HELPERS::print_warning($t);
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    # warn "call create_ca_env with bits: $opts->{'bits'}\n";
 | |
| 
 | |
|    $self->create_ca_env($main, $opts, $mode);
 | |
| 
 | |
|    return;
 | |
| }
 | |
| 
 | |
| #
 | |
| # check if all data for importing a CA is available
 | |
| #
 | |
| sub get_ca_import {
 | |
|    my ($self, $main, $opts, $box) = @_;
 | |
| 
 | |
|    $box->destroy() if(defined($box));
 | |
| 
 | |
|    my ($name, $t, $parsed, $constr);
 | |
| 
 | |
|    if(!(defined($opts))) { 
 | |
|       $opts = {};
 | |
|       $opts->{'days'} = 3650; # set default to 10 years
 | |
|       $opts->{'bits'} = 4096;
 | |
|       $opts->{'digest'} = 'sha256';
 | |
|       
 | |
|       $main->show_ca_import_dialog($opts);
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    # check options given in dialog
 | |
|    if((not defined($opts->{'name'})) || 
 | |
| 	   ($opts->{'name'} eq "") ||
 | |
| 	   ($opts->{'name'} =~ /\s/)) { 
 | |
|       $main->show_ca_import_dialog($opts);
 | |
|       GUI::HELPERS::print_warning(
 | |
|             _("Name for storage must be filled in and must not contain spaces"));
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    if(((not defined($opts->{'passwd'})) ||
 | |
|        ($opts->{'passwd'} eq '')) &&
 | |
|        (!$opts->{'pwwarning'})) {
 | |
|       $main->show_ca_import_dialog($opts);
 | |
|       GUI::HELPERS::print_warning(
 | |
|             _("You didn't give a password for the private CA key.").
 | |
|             "\n".
 | |
|             _("The import will fail, if the key is encrypted."));
 | |
|          $opts->{'pwwarning'} = 1;
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    if((not defined($opts->{'newpasswd'})) ||
 | |
|       ($opts->{'newpasswd'} eq '')) {
 | |
|       $main->show_ca_import_dialog($opts);
 | |
|       GUI::HELPERS::print_warning(
 | |
|             _("Please give a new password for the CA"));
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    if((not defined($opts->{'newpasswd2'})) ||
 | |
|       $opts->{'newpasswd'} ne $opts->{'newpasswd2'}) { 
 | |
|       $main->show_ca_import_dialog($opts);
 | |
|       GUI::HELPERS::print_warning(_("New passwords don't match"));
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    if((not defined($opts->{'cacertfile'})) ||
 | |
|       ($opts->{'cacertfile'} eq '')) {
 | |
|       $main->show_ca_import_dialog($opts);
 | |
|       GUI::HELPERS::print_warning(
 | |
|             _("Please give a CA certificate to import"));
 | |
|       return;
 | |
|    }
 | |
|    if(not -r $opts->{'cacertfile'}) {
 | |
|       $main->show_ca_import_dialog($opts);
 | |
|       $t = sprintf(_("Can't read CA certificate file:\n%s"), 
 | |
|             $opts->{'cacertfile'});
 | |
|       GUI::HELPERS::print_warning($t);
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    if((not defined($opts->{'cakeyfile'})) ||
 | |
|       ($opts->{'cakeyfile'} eq '')) {
 | |
|       $main->show_ca_import_dialog($opts);
 | |
|       GUI::HELPERS::print_warning(
 | |
|             _("Please give a CA keyfile to import"));
 | |
|       return;
 | |
|    }
 | |
|    if(not -r $opts->{'cakeyfile'}) {
 | |
|       $main->show_ca_import_dialog($opts);
 | |
|       $t = sprintf(_("Can't read CA key file:\n%s"), 
 | |
|             $opts->{'cakeyfile'});
 | |
|       GUI::HELPERS::print_warning($t);
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    if(((not defined($opts->{'indexfile'})) ||
 | |
|        ($opts->{'indexfile'} eq '')) &&
 | |
|       (not defined($opts->{'indexwarning'}))) {
 | |
| 
 | |
|       $main->show_ca_import_dialog($opts);
 | |
| 
 | |
|       $t = _("Please give an Index file to import.\n");
 | |
|       $t .= _("If you don't have an Index file, i'll try to generate one.\n");
 | |
|       $t .= _("Attention: This will cause all Certificates to show up as valid.\n");
 | |
|       $t .= _("Attention: Revoked Certificates will not be determined.");
 | |
| 
 | |
|       $opts->{'indexwarning'} = 1;
 | |
| 
 | |
|       GUI::HELPERS::print_warning($t);
 | |
|       return;
 | |
|    }
 | |
|    if(defined($opts->{'indexfile'}) && 
 | |
|       $opts->{'indexfile'} ne '' &&
 | |
|       not -r $opts->{'indexfile'}) {
 | |
|       $main->show_ca_import_dialog($opts);
 | |
|       $t = sprintf(_("Can't read Index file:\n%s"), 
 | |
|             $opts->{'indexfile'});
 | |
|       GUI::HELPERS::print_warning($t);
 | |
|       return;
 | |
|    } elsif(defined($opts->{'indexfile'}) &&
 | |
|            $opts->{'indexfile'} ne '') {
 | |
|       $opts->{'gotindex'} = 1;
 | |
|    }
 | |
| 
 | |
|    if((not defined($opts->{'certdir'})) ||
 | |
|       ($opts->{'certdir'} eq '')) {
 | |
|       $main->show_ca_import_dialog($opts);
 | |
|       GUI::HELPERS::print_warning(
 | |
|             _("Please give a directory containing the certificates to import"));
 | |
|       return;
 | |
|    }
 | |
|    if(not -d $opts->{'certdir'}) {
 | |
|       $main->show_ca_import_dialog($opts);
 | |
|       $t = sprintf(_("Can't find certificate directory:\n%s"), 
 | |
|             $opts->{'certdir'});
 | |
|       GUI::HELPERS::print_warning($t);
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    $name = $opts->{'name'};
 | |
| 
 | |
|    if(defined($self->{$name})) { 
 | |
|       $main->show_ca_import_dialog($opts);
 | |
|       $t = sprintf(
 | |
|             _("CA: %s already exists. Please choose another name"), 
 | |
|             $name);
 | |
|       GUI::HELPERS::print_warning($t);
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    # check ca certificate and key
 | |
|    $parsed = $main->{'OpenSSL'}->parsecert(
 | |
|          undef, undef, $opts->{'cacertfile'}, 1);
 | |
| 
 | |
|    # check if it's really a CA certificate
 | |
|    if(defined($parsed->{'EXT'}->{'X509v3 Basic Constraints: critical'})) {
 | |
|       $constr = $parsed->{'EXT'}->{'X509v3 Basic Constraints: critical'}->[0];
 | |
|    } elsif(defined($parsed->{'EXT'}->{'X509v3 Basic Constraints'})) {
 | |
|       $constr = $parsed->{'EXT'}->{'X509v3 Basic Constraints'}->[0];
 | |
|    } else {
 | |
|       $t = _("Can't find X509v3 Basic Constraints in CA Certificate\n");
 | |
|       $t .= _("Import canceled");
 | |
|       GUI::HELPERS::print_warning($t);
 | |
|       return;
 | |
|    }
 | |
|    
 | |
|    if($constr !~ /CA:TRUE/i) {
 | |
|       $t = _("The selected CA Certificate is no valid CA certificate\n");
 | |
|       $t .= sprintf(_("X509v3 Basic Constraint is set to: %s"), $constr);
 | |
|       GUI::HELPERS::print_warning($t);
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    $opts->{'cacertdata'} = $parsed->{'PEM'};
 | |
| 
 | |
|    # now read the data from the files
 | |
|    if(defined($opts->{'gotindex'})) {
 | |
|       open(INDEX, "<$opts->{'indexfile'}") || do {
 | |
|          $t = sprintf(_("Can't open Index file:\n%s"), 
 | |
|                $opts->{'indexfile'});
 | |
|          GUI::HELPERS::print_warning($t);
 | |
|          return;
 | |
|       };
 | |
|       while(<INDEX>) {
 | |
|          $opts->{'serial'} = hex((split(/\t/, $_))[3]);
 | |
|          $opts->{'indexdata'} .= $_;
 | |
|       }
 | |
|       close(INDEX);
 | |
|       $opts->{'serial'} +=1;
 | |
|       $opts->{'serial'} = sprintf("%x", $opts->{'serial'});
 | |
|    }
 | |
| 
 | |
|    $main->show_import_verification("cacert", $opts, $parsed);
 | |
| 
 | |
|    return;
 | |
| }
 | |
| 
 | |
| #
 | |
| # do the real import
 | |
| #
 | |
| sub import_ca {
 | |
|    my ($self, $main, $opts, $box) = @_;
 | |
| 
 | |
|    my ($t, $f, $cacertfile, $cakeyfile, $certfile, $c, $p, @files, $ext, $ret,
 | |
|          @d, $timestring, $indexline, $index, $serial, $subjects, $serials,
 | |
|          $timestrings);
 | |
| 
 | |
|    my $format = "DER";
 | |
|    my $data   = {};
 | |
|    my $ca     = $opts->{'name'};
 | |
| 
 | |
|    if (hex($opts->{'serial'}) < 1) {
 | |
|       $opts->{'serial'} = "01";
 | |
|    }
 | |
| 
 | |
|    if(defined($box)) {
 | |
|       $box->destroy();
 | |
|    }
 | |
| 
 | |
|    $opts->{'cakeydata'} = $main->{'KEY'}->key_change_passwd(
 | |
|          $main, $opts->{'cakeyfile'}, $opts->{'passwd'},
 | |
|          $opts->{'newpasswd'}, 'ca');
 | |
| 
 | |
|    if($opts->{'cakeydata'} eq 1) {
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    $self->create_ca_env($main, $opts, 'import');
 | |
| 
 | |
|    # now read all certificates
 | |
|    opendir(DIR, $opts->{'certdir'}) || do {
 | |
|       $t = sprintf(_("Can't open Certificate directory: %s"),
 | |
|             $opts->{'certdir'}); 
 | |
|       GUI::HELPERS::print_warning($t); 
 | |
|       return; 
 | |
|    };
 | |
| 
 | |
|    # just count the files
 | |
|    while($f = readdir(DIR)) {
 | |
|       next if($f =~ /^\./);
 | |
|       $certfile = $opts->{'certdir'}."/".$f;
 | |
|       push (@files, $certfile);
 | |
|       $c++;
 | |
|    }
 | |
| 
 | |
|    GUI::HELPERS::set_cursor($main, 1);
 | |
| 
 | |
|    # import all the certificate files and gather information if necessary
 | |
|    $main->{'barbox'}->pack_start($main->{'progress'}, 0, 0, 0);
 | |
|    foreach $certfile (@files) {
 | |
|       $t = sprintf(_("   Read Certificate: %s"), $certfile);
 | |
|       GUI::HELPERS::set_status($main, $t);
 | |
|       $p += 100/$c;
 | |
|       $main->{'progress'}->set_fraction($p/100);
 | |
|       while(Gtk2->events_pending) {
 | |
|          Gtk2->main_iteration;
 | |
|       }
 | |
| 
 | |
|       open(IN, "<$certfile") || do {
 | |
|          GUI::HELPERS::set_cursor($main, 0);
 | |
|          $t = sprintf(_("Can't read Certificate file: %s"), $certfile);
 | |
|          return;
 | |
|       };
 | |
|       $data->{'raw'} = '';
 | |
|       $data->{'raw'} .= $_ while(<IN>);
 | |
|       close(IN);
 | |
|       $format = "PEM" if($data->{'raw'} =~ /BEGIN CERTIFICATE/);
 | |
| 
 | |
|       if($format eq "PEM") {
 | |
|          $data->{'PEM'} = $data->{'raw'};
 | |
|       }
 | |
|       
 | |
|       $data->{'parsed'} = $main->{'OpenSSL'}->parsecert(
 | |
|             undef, undef, $certfile, 1
 | |
|             );
 | |
| 
 | |
|       $data->{'name'} = HELPERS::gen_name($data->{'parsed'});
 | |
|       $data->{'name'} = HELPERS::enc_base64($data->{'name'});
 | |
|       $data->{'name'} .= ".pem";
 | |
| 
 | |
|       $data->{'file'} = $self->{$ca}->{'dir'}."/certs/".$data->{'name'};
 | |
| 
 | |
|       open(OUT, ">$data->{'file'}") || do {
 | |
|          GUI::HELPERS::set_cursor($main, 0);
 | |
|          $t = sprintf(_("Can't write Certificate file: %s"),
 | |
|                $data->{'file'}); 
 | |
|          return; 
 | |
|       };
 | |
|       print OUT $data->{'PEM'};
 | |
| 
 | |
|       if(not defined($opts->{'gotindex'})) {
 | |
|          # get information for index.txt file
 | |
|          @d = localtime($data->{'parsed'}->{'EXPDATE'});
 | |
|          $timestring = sprintf("%02d%02d%02d%02d%02d%02dZ",
 | |
|                $d[5]%100, $d[4]+1, $d[3], $d[2], $d[1], $d[0]);
 | |
| 
 | |
|          # try to detect index clashes FIXME: only the newer is kept
 | |
|          if(exists($subjects->{$data->{'parsed'}->{'SUBJECT'}})) {
 | |
|             if(hex($data->{'parsed'}->{'SERIAL'}) >=
 | |
|                   hex($serials->{$data->{'parsed'}->{'SUBJECT'}})) {
 | |
|                $subjects->{$data->{'parsed'}->{'SUBJECT'}} = 1;
 | |
|                $serials->{$data->{'parsed'}->{'SUBJECT'}} =
 | |
|                   $data->{'parsed'}->{'SERIAL'};
 | |
|                $timestrings->{$data->{'parsed'}->{'SUBJECT'}} =
 | |
|                   $timestring;
 | |
|             }
 | |
|          } else { 
 | |
|             $subjects->{$data->{'parsed'}->{'SUBJECT'}} = 1;
 | |
|             $serials->{$data->{'parsed'}->{'SUBJECT'}} = 
 | |
|                $data->{'parsed'}->{'SERIAL'}; 
 | |
|             $timestrings->{$data->{'parsed'}->{'SUBJECT'}} = 
 | |
|                $timestring;
 | |
|          }
 | |
| 
 | |
|          # get information for serial file
 | |
|          if(hex($data->{'parsed'}->{'SERIAL'}) >= hex($opts->{'serial'})) {
 | |
|             $opts->{'serial'} = sprintf("%x", hex($data->{'parsed'}->{'SERIAL'}));
 | |
|          }
 | |
|          $opts->{'serial'} = hex($opts->{'serial'}) + 1;
 | |
|          $opts->{'serial'} = sprintf("%x", $opts->{'serial'});
 | |
|       }
 | |
| 
 | |
|       close(OUT);
 | |
|    }
 | |
| 
 | |
|    # now build the indexdata
 | |
|    foreach my $s (keys(%$subjects)) {
 | |
|       $indexline = "V\t$timestrings->{$s}\t\t$serials->{$s}\tunknown\t$s\n";
 | |
|       $opts->{'indexdata'} .= $indexline;
 | |
|    }
 | |
|    
 | |
|    # create index file
 | |
|    $index = $self->{$ca}->{'dir'}."/index.txt";
 | |
|    open(OUT, ">$index") || do {
 | |
|       GUI::HELPERS::print_error(_("Can't open Index file: ").$!);
 | |
|       return;
 | |
|    };
 | |
|    print OUT $opts->{'indexdata'};
 | |
|    close OUT;
 | |
| 
 | |
|    $cacertfile = $self->{$ca}->{'dir'}."/cacert.pem";
 | |
|    $cakeyfile  = $self->{$ca}->{'dir'}."/cacert.key";
 | |
| 
 | |
|    # write cacertfile
 | |
|    open(OUT, ">$cacertfile") || do {
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       $t = sprintf(_("Can't write CA Certificate file: %s"),
 | |
|             $cacertfile); 
 | |
|       return; 
 | |
|    };
 | |
|    print OUT $opts->{'cacertdata'};
 | |
|    close(OUT);
 | |
| 
 | |
|    # check serial number of CA file
 | |
|    $data->{'parsed'} = $main->{'OpenSSL'}->parsecert( 
 | |
|          undef, undef, $cacertfile, 1
 | |
|          );
 | |
|    if(hex($data->{'parsed'}->{'SERIAL'}) >= hex($opts->{'serial'})) {
 | |
|       $opts->{'serial'} = sprintf("%x", hex($opts->{'serial'}));
 | |
|    }
 | |
|    $opts->{'serial'} = hex($opts->{'serial'}) + 1;
 | |
|    $opts->{'serial'} = sprintf("%x", $opts->{'serial'});
 | |
| 
 | |
|    # create serial file
 | |
|    $serial = $self->{$ca}->{'dir'}."/serial";
 | |
|    open(OUT, ">$serial") || do {
 | |
|       GUI::HELPERS::print_error(_("Can't write Serial file: ").$!);
 | |
|       return;
 | |
|    };
 | |
| 
 | |
|    if($opts->{'serial'} ne "") {
 | |
|       print OUT uc($opts->{'serial'});
 | |
|    }else{
 | |
|       print OUT "01";
 | |
|    }
 | |
|    close OUT;
 | |
| 
 | |
|    # write keyfile
 | |
|    open(OUT, ">$cakeyfile") || do {
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       $t = sprintf(_("Can't write CA Key file: %s"),
 | |
|             $cakeyfile); 
 | |
|       return; 
 | |
|    };
 | |
|    print OUT $opts->{'cakeydata'};
 | |
|    close(OUT);
 | |
| 
 | |
|    ($ret, $ext) = $main->{'OpenSSL'}->newcrl(
 | |
|          config  => $self->{$ca}->{'cnf'},
 | |
|          pass    => $opts->{'newpasswd'},
 | |
|          crldays => 30,
 | |
|          outfile => $self->{$ca}->{'dir'}."/crl/crl.pem",
 | |
|          format  => 'PEM'
 | |
|          );
 | |
| 
 | |
|    if ((not -s $self->{$ca}->{'dir'}."/crl/crl.pem") || $ret) {
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       GUI::HELPERS::print_error(_("Generating CRL failed"), $ext);
 | |
|       print STDERR "DEBUG: newcrl returned $ext\n";
 | |
|       die;
 | |
|       return;
 | |
|    }
 | |
| 
 | |
| 
 | |
|    GUI::HELPERS::set_cursor($main, 0);
 | |
|    $main->{'barbox'}->remove($main->{'progress'});
 | |
| 
 | |
|    push(@{$self->{'calist'}}, $ca);
 | |
|    @{$self->{'calist'}} = sort(@{$self->{'calist'}});
 | |
| 
 | |
|    $t = sprintf(_("Succesfully imported %d certificates\n"), $c);
 | |
|    $t.= _("Check the configuration of your imported CA.");
 | |
|    GUI::HELPERS::print_info($t);
 | |
| 
 | |
|    $self->open_ca($main, $opts);
 | |
| 
 | |
|    return;
 | |
| }
 | |
| 
 | |
| #
 | |
| # create a new CA, environment: dirs, etc.
 | |
| #
 | |
| sub create_ca_env {
 | |
|    my ($self, $main, $opts, $mode) = @_;
 | |
| 
 | |
|    my ($t, $index, $serial);
 | |
| 
 | |
|    if((!defined($opts->{'name'})) || $opts->{'name'} eq '') {
 | |
|       GUI::HELPERS::print_error(_("No CA name given"));
 | |
|       return;
 | |
|    }
 | |
|  
 | |
|    # create directories
 | |
|    $self->{$opts->{'name'}}->{'dir'} = 
 | |
|       $self->{'init'}->{'basedir'}."/".$opts->{'name'};
 | |
| 
 | |
|    mkdir($self->{$opts->{'name'}}->{'dir'}, 0700) || do { 
 | |
|       GUI::HELPERS::print_warning(_("Can't create directory: ").$!);
 | |
|       return;
 | |
|    };
 | |
| 
 | |
|    mkdir($self->{$opts->{'name'}}->{'dir'}."/req", 0700) || do { 
 | |
|       GUI::HELPERS::print_warning(_("Can't create directory: ").$!);
 | |
|       return;
 | |
|    };
 | |
| 
 | |
|    mkdir($self->{$opts->{'name'}}->{'dir'}."/keys", 0700) || do { 
 | |
|       GUI::HELPERS::print_warning(_("Can't create directory: ").$!);
 | |
|       return;
 | |
|    };
 | |
| 
 | |
|    mkdir($self->{$opts->{'name'}}->{'dir'}."/certs", 0700) || do { 
 | |
|       GUI::HELPERS::print_warning(_("Can't create directory: ").$!);
 | |
|       return;
 | |
|    };
 | |
| 
 | |
|    mkdir($self->{$opts->{'name'}}->{'dir'}."/crl", 0700) || do { 
 | |
|       GUI::HELPERS::print_warning(_("Can't create directory: ").$!);
 | |
|       return;
 | |
|    };
 | |
| 
 | |
|    mkdir($self->{$opts->{'name'}}->{'dir'}."/newcerts", 0700) || do { 
 | |
|       GUI::HELPERS::print_warning(_("Can't create directory: ").$!);
 | |
|       return;
 | |
|    };
 | |
| 
 | |
|    # create configuration file
 | |
|    my $in  = $self->{'init'}->{'templatedir'}."/openssl.cnf";
 | |
|    my $out = $self->{$opts->{'name'}}->{'dir'}."/openssl.cnf";
 | |
| 
 | |
|    open(IN, "<$in") || do {
 | |
|       $t = sprintf(_("Can't open template file %s %s"), $in, $!);
 | |
|       GUI::HELPERS::print_error($t);
 | |
|       return;
 | |
|    };
 | |
|    open(OUT, ">$out") || do {
 | |
|       $t = sprintf(_("Can't open output file: %s: %s"),$out, $!);
 | |
|       GUI::HELPERS::print_error($t);
 | |
|       return;
 | |
|    };
 | |
|    while(<IN>) {
 | |
|       s/\%dir\%/$self->{$opts->{'name'}}->{'dir'}/;
 | |
|       print OUT;
 | |
|    }
 | |
|    close IN;
 | |
|    close OUT;
 | |
|    $self->{$opts->{'name'}}->{'cnf'} = $out;
 | |
| 
 | |
|    $main->{'TCONFIG'}->init_config($main, $opts->{'name'});
 | |
| 
 | |
|    # create some more files
 | |
|    $index = $self->{$opts->{'name'}}->{'dir'}."/index.txt";
 | |
|    open(OUT, ">$index") || do {
 | |
|       GUI::HELPERS::print_error(_("Can't open Index file: ").$!);
 | |
|       return;
 | |
|    };
 | |
|    close(OUT);
 | |
| 
 | |
|    $serial = $self->{$opts->{'name'}}->{'dir'}."/serial";
 | |
|    open(OUT, ">$serial") || do {
 | |
|       GUI::HELPERS::print_error(_("Can't write Serial file: ").$!);
 | |
|       return;
 | |
|    };
 | |
| 
 | |
|    if(defined($opts->{'serial'}) && $opts->{'serial'} ne "") {
 | |
|       print OUT uc($opts->{'serial'});
 | |
|    }else{
 | |
|       print OUT "01";
 | |
|    }
 | |
|    close(OUT);
 | |
| 
 | |
|    # create ca config file based on template
 | |
|    $in  = $self->{'init'}->{'templatedir'}."/tinyca.cnf";
 | |
|    $out = $self->{$opts->{'name'}}->{'dir'}."/tinyca.cnf";
 | |
|    open(IN, "<$in") || do {
 | |
|       $t = sprintf(_("Can't open config template file %s %s"), $in, $!);
 | |
|       GUI::HELPERS::print_error($t);
 | |
|       return;
 | |
|    };
 | |
|    open(OUT, ">$out") || do {
 | |
|       $t = sprintf(_("Can't open config output file: %s: %s"),$out, $!);
 | |
|       GUI::HELPERS::print_error($t);
 | |
|       return;
 | |
|    };
 | |
|    while(<IN>) {
 | |
|       print OUT;
 | |
|    }
 | |
|    close(IN);
 | |
|    close(OUT);
 | |
| 
 | |
|    if(defined($mode) && $mode eq "sub") {
 | |
|       $self->create_ca($main, $opts, undef, $mode);
 | |
|    } elsif(defined($mode) && $mode eq "import") {
 | |
|    } else {
 | |
|       GUI::TCONFIG::show_config_ca($main, $opts, $mode);
 | |
|    }
 | |
| 
 | |
|    return;
 | |
| }
 | |
| 
 | |
| #
 | |
| # now create the CA certificate and CRL
 | |
| #
 | |
| sub create_ca {
 | |
|    my ($self, $main, $opts, $box, $mode) = @_;
 | |
| 
 | |
|    my ($fname, $t, $index, $serial, $ca, $ret, $ext);
 | |
| 
 | |
|    $ca = $self->{'actca'};
 | |
| 
 | |
|    $box->destroy() if(defined($box));
 | |
| 
 | |
|    GUI::HELPERS::set_cursor($main, 1);
 | |
| 
 | |
|    if((!defined($opts->{'name'})) || $opts->{'name'} eq '') {
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       GUI::HELPERS::print_error(_("No CA name given"));
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    # create CA certifikate
 | |
|    ($ret, $ext) = $main->{'OpenSSL'}->newkey( 
 | |
|          'bits'    => $opts->{'bits'},
 | |
|          'outfile' => $self->{$opts->{'name'}}->{'dir'}."/cacert.key",
 | |
|          'pass'    => $opts->{'passwd'}
 | |
|          );
 | |
|    
 | |
|    if (not -s $self->{$opts->{'name'}}->{'dir'}."/cacert.key" || $ret) {
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       GUI::HELPERS::print_warning(_("Generating key failed"), $ext);
 | |
|       _rm_dir($self->{$opts->{'name'}}->{'dir'});
 | |
|       delete($self->{$opts->{'name'}});
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    my @dn = ( 
 | |
|          $opts->{'C'}, 
 | |
|          $opts->{'ST'}, 
 | |
|          $opts->{'L'}, 
 | |
|          $opts->{'O'}, 
 | |
|          $opts->{'OU'}->[0],
 | |
|          $opts->{'CN'}, 
 | |
|          $opts->{'EMAIL'}, 
 | |
|          '', 
 | |
|          '');
 | |
| 
 | |
|    ($ret, $ext) = $main->{'OpenSSL'}->newreq( 
 | |
|          'config'  => $self->{$opts->{'name'}}->{'cnf'},
 | |
|          'outfile' => $self->{$opts->{'name'}}->{'dir'}."/cacert.req",
 | |
|          'digest'   => $opts->{'digest'},
 | |
|          'pass'    => $opts->{'passwd'},
 | |
|          'dn'      => \@dn,
 | |
|          'keyfile' => $self->{$opts->{'name'}}->{'dir'}."/cacert.key"
 | |
|          );
 | |
| 
 | |
|    $fname = HELPERS::gen_name($opts);
 | |
| 
 | |
|    $opts->{'reqname'} = HELPERS::enc_base64($fname);
 | |
|    
 | |
|    if (not -s $self->{$opts->{'name'}}->{'dir'}."/cacert.req" || $ret) {
 | |
|       unlink($self->{$opts->{'name'}}->{'dir'}."/cacert.key");
 | |
|       unlink($self->{$opts->{'name'}}->{'dir'}."/cacert.req");
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       GUI::HELPERS::print_warning(_("Generating Request failed"), $ext);
 | |
|       _rm_dir($self->{$opts->{'name'}}->{'dir'});
 | |
|       delete($self->{$opts->{'name'}});
 | |
|       return;
 | |
|    } else {
 | |
|    if(defined($mode) && $mode eq "sub") {
 | |
|       # for SubCAs: copy the request to the signing CA
 | |
|       open(IN, "<$self->{$opts->{'name'}}->{'dir'}"."/cacert.req") || do {
 | |
|          GUI::HELPERS::set_cursor($main, 0);
 | |
|          GUI::HELPERS::print_warning(_("Can't read Certificate"));
 | |
|          return;
 | |
|       };
 | |
|       open(OUT, ">$self->{$ca}->{'dir'}"."/req/".$opts->{'reqname'}.".pem") || do {
 | |
|          GUI::HELPERS::set_cursor($main, 0);
 | |
|          GUI::HELPERS::print_warning(_("Can't write Certificate"));
 | |
|          return;
 | |
|       };
 | |
|       print OUT while(<IN>);
 | |
|       close IN; close OUT;
 | |
| 
 | |
|       # for SubCAs: copy the key to the signing CA
 | |
|       open(IN, "<$self->{$opts->{'name'}}->{'dir'}"."/cacert.key") || do {
 | |
|          GUI::HELPERS::set_cursor($main, 0);
 | |
|          GUI::HELPERS::print_warning(_("Can't read Certificate"));
 | |
|          return;
 | |
|       };
 | |
|       open(OUT, ">$self->{$ca}->{'dir'}"."/keys/".$opts->{'reqname'}.".pem") || do {
 | |
|          GUI::HELPERS::set_cursor($main, 0);
 | |
|          GUI::HELPERS::print_warning(_("Can't write Certificate"));
 | |
|          return;
 | |
|       };
 | |
|       print OUT while(<IN>);
 | |
|       close IN; close OUT;
 | |
|     }
 | |
|    }
 | |
| 
 | |
|    if(defined($mode) && $mode eq "sub") {
 | |
|       ($ret, $ext) = $main->{'REQ'}->sign_req(
 | |
|             $main,
 | |
|             {
 | |
|             'mode'       => "sub",
 | |
|             'config'     => $self->{$opts->{'name'}}->{'cnf'},
 | |
|             'outfile'    => $self->{$opts->{'name'}}->{'dir'}."/cacert.pem",
 | |
|             'reqfile'    => $self->{$opts->{'name'}}->{'dir'}."/cacert.req",
 | |
|             'outdir'     => $self->{$ca}->{'dir'}."/newcerts/",
 | |
|             'keyfile'    => $self->{$ca}->{'dir'}."/cacert.key",
 | |
|             'cacertfile' => $self->{$ca}->{'dir'}."/cacert.pem",
 | |
|             'digest'     => $opts->{'digest'},
 | |
|             'pass'       => $opts->{'passwd'},
 | |
|             'days'       => $opts->{'days'},
 | |
|             'parentpw'   => $opts->{'parentpw'},
 | |
|             'reqname'    => $opts->{'reqname'}
 | |
|             }
 | |
|             );
 | |
|    } else {
 | |
|       ($ret, $ext) = $main->{'OpenSSL'}->newcert( 
 | |
|             'config'  => $self->{$opts->{'name'}}->{'cnf'},
 | |
|             'outfile' => $self->{$opts->{'name'}}->{'dir'}."/cacert.pem",
 | |
|             'keyfile' => $self->{$opts->{'name'}}->{'dir'}."/cacert.key",
 | |
|             'reqfile' => $self->{$opts->{'name'}}->{'dir'}."/cacert.req",
 | |
|             'digest'  => $opts->{'digest'},
 | |
|             'pass'    => $opts->{'passwd'},
 | |
|             'days'    => $opts->{'days'}
 | |
|             );
 | |
|    }
 | |
|    
 | |
|    if (not -s $self->{$opts->{'name'}}->{'dir'}."/cacert.pem" || $ret) {
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       GUI::HELPERS::print_warning(
 | |
|             _("Generating certificate failed"), $ext);
 | |
|       _rm_dir($self->{$opts->{'name'}}->{'dir'});
 | |
|       delete($self->{$opts->{'name'}});
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    unlink($self->{$opts->{'name'}}->{'dir'}."/cacert.req");
 | |
| 
 | |
|    if(defined($mode) && $mode eq "sub") {
 | |
|      # create file containing chain of ca certificates
 | |
|      my $in;
 | |
|      if (-f $self->{$ca}->{'dir'}."/cachain.pem") {
 | |
|        $in   = $self->{$ca}->{'dir'}."/cachain.pem";
 | |
|      } else {
 | |
|        $in   = $self->{$ca}->{'dir'}."/cacert.pem";
 | |
|      }
 | |
|      my $out  = $self->{$opts->{'name'}}->{'dir'}."/cachain.pem";
 | |
| 
 | |
|      open(IN, "<$in") || do {
 | |
|         $t = sprintf(
 | |
|               _("Can't open ca certificate file %s %s"), $in, $!);
 | |
|         GUI::HELPERS::set_cursor($main, 0);
 | |
|         GUI::HELPERS::print_warning($t);
 | |
|         _rm_dir($self->{$opts->{'name'}}->{'dir'});
 | |
|         delete($self->{$opts->{'name'}});
 | |
|         return;
 | |
|      };
 | |
|      open(OUT, ">$out") || do {
 | |
|         $t = sprintf(
 | |
|               _("Can't create certificate chain file: %s: %s"),$out, $!);
 | |
|         GUI::HELPERS::set_cursor($main, 0);
 | |
|         $main->print_warning($t);
 | |
|         _rm_dir($self->{$opts->{'name'}}->{'dir'});
 | |
|         delete($self->{$opts->{'name'}});
 | |
|         return;
 | |
|      };
 | |
|      while(<IN>) {
 | |
|         print OUT;
 | |
|      }
 | |
|      close IN;
 | |
| 
 | |
|      # now append the certificate of the created SubCA
 | |
|      $in  = $self->{$opts->{'name'}}->{'dir'}."/cacert.pem";
 | |
|      open(IN, "<$in") || do {
 | |
|         $t = sprintf(
 | |
|               _("Can't open ca certificate file %s %s"), $in, $!);
 | |
|         GUI::HELPERS::set_cursor($main, 0);
 | |
|         GUI::HELPERS::print_warning($t);
 | |
|         _rm_dir($self->{$opts->{'name'}}->{'dir'});
 | |
|         delete($self->{$opts->{'name'}});
 | |
|         return;
 | |
|      };
 | |
| 
 | |
|      while(<IN>) {
 | |
|         print OUT;
 | |
|      }
 | |
|      close OUT;
 | |
|    }
 | |
| 
 | |
|    ($ret, $ext) = $main->{'OpenSSL'}->newcrl(
 | |
|          config  => $self->{$opts->{'name'}}->{'cnf'},
 | |
|          pass    => $opts->{'passwd'},
 | |
|          crldays => $main->{'TCONFIG'}->{'server_ca'}->{'default_crl_days'},
 | |
|          outfile => $self->{$opts->{'name'}}->{'dir'}."/crl/crl.pem",
 | |
|          format  => 'PEM'
 | |
|          );
 | |
| 
 | |
|    if (not -s $self->{$opts->{'name'}}->{'dir'}."/crl/crl.pem" || $ret) {
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       GUI::HELPERS::print_warning(_("Generating CRL failed"), $ext);
 | |
|       _rm_dir($self->{$opts->{'name'}}->{'dir'});
 | |
|       delete($self->{$opts->{'name'}});
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    # seems to be done
 | |
|    push(@{$self->{'calist'}}, $opts->{'name'});
 | |
|    @{$self->{'calist'}} = sort(@{$self->{'calist'}});
 | |
|    $t = sprintf(_("CA: %s created"), $opts->{'name'});
 | |
|    GUI::HELPERS::set_cursor($main, 0);
 | |
| 
 | |
|    GUI::HELPERS::print_info($t);
 | |
| 
 | |
|    $self->open_ca($main, $opts);
 | |
|    return;
 | |
| }
 | |
| 
 | |
| #
 | |
| # export ca certificate chain
 | |
| #
 | |
| sub export_ca_chain {
 | |
|    my ($self, $main, $opts, $box) = @_;
 | |
| 
 | |
|    my($ca, $chainfile, $parsed, $out, $t);
 | |
| 
 | |
|    $box->destroy() if(defined($box));
 | |
| 
 | |
|    $ca = $self->{'actca'};
 | |
| 
 | |
|    if(not defined($opts)) {
 | |
|       $opts->{'format'}  = 'PEM';
 | |
|       $opts->{'outfile'} = "$main->{'exportdir'}/$ca-cachain.pem";
 | |
|       $main->show_ca_chain_export_dialog($opts);
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    GUI::HELPERS::set_cursor($main, 1);
 | |
| 
 | |
|    $chainfile = $self->{$ca}->{'dir'}."/cachain.pem";
 | |
| 
 | |
|    open(IN, "<$self->{$ca}->{'dir'}"."/cachain.pem") || do {
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       GUI::HELPERS::print_warning(
 | |
|             _("Can't open certificate chain file: %s: %s"),
 | |
|             $self->{$ca}->{'dir'}."/cachain.pem", $!);
 | |
|       return;
 | |
|    };
 | |
| 
 | |
|    open(OUT, ">$opts->{'outfile'}") || do {
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       GUI::HELPERS::print_warning(
 | |
|             _("Can't open output file: %s: %s"), 
 | |
|             $opts->{'outfile'}, $!);
 | |
|       return;
 | |
|    };
 | |
| 
 | |
|    print OUT while(<IN>);
 | |
|    close OUT;
 | |
| 
 | |
|    $main->{'exportdir'} = HELPERS::write_export_dir($main, 
 | |
|          $opts->{'outfile'});
 | |
|    
 | |
|    GUI::HELPERS::set_cursor($main, 0);
 | |
| 
 | |
|    $t = sprintf(_("Certificate Chain succesfully exported to: %s"), 
 | |
|          $opts->{'outfile'});
 | |
|    GUI::HELPERS::print_info($t);
 | |
| 
 | |
|    return;
 | |
| }
 | |
| 
 | |
| #
 | |
| # export ca certificate
 | |
| #
 | |
| sub export_ca_cert {
 | |
|    my ($self, $main, $opts, $box) = @_;
 | |
|     
 | |
|    my($ca, $certfile, $parsed, $out, $t);
 | |
| 
 | |
|    $box->destroy() if(defined($box));
 | |
| 
 | |
|    GUI::HELPERS::set_cursor($main, 1);
 | |
| 
 | |
|    $ca = $self->{'actca'};
 | |
| 
 | |
|    $certfile = $self->{$ca}->{'dir'}."/cacert.pem";
 | |
| 
 | |
|    if(not defined($opts)) {
 | |
|       $opts->{'format'}  = 'PEM';
 | |
|       $opts->{'outfile'} = "$main->{'exportdir'}/$ca-cacert.pem";
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       $main->show_ca_export_dialog($opts);
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    $parsed = $main->{'CERT'}->parse_cert($main, 'CA');
 | |
| 
 | |
|    if(not defined $parsed) {
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       GUI::HELPERS::print_error(_("Can't read CA certificate"));
 | |
|    }
 | |
| 
 | |
|    if($opts->{'format'} eq "PEM") {
 | |
|       $out = $parsed->{'PEM'};
 | |
|    } elsif ($opts->{'format'} eq "DER") {
 | |
|       $out = $parsed->{'DER'};
 | |
|    } elsif ($opts->{'format'} eq "TXT") {
 | |
|       $out = $parsed->{'TEXT'};
 | |
|    } else {
 | |
|       $t = sprintf(_("Invalid Format for export_ca_cert(): %s"), 
 | |
|             $opts->{'format'});
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       GUI::HELPERS::print_warning($t);
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    open(OUT, ">$opts->{'outfile'}") || do {
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       $t = sprintf(_("Can't open output file: %s: %s"), 
 | |
|             $opts->{'outfile'}, $!);
 | |
|       GUI::HELPERS::print_warning($t);
 | |
|       return;
 | |
|    };
 | |
| 
 | |
|    print OUT $out;
 | |
|    close OUT;
 | |
| 
 | |
|    $main->{'exportdir'} = HELPERS::write_export_dir($main, 
 | |
|          $opts->{'outfile'});
 | |
|    
 | |
|    GUI::HELPERS::set_cursor($main, 0);
 | |
|    $t = sprintf(_("Certificate succesfully exported to: %s"), 
 | |
|          $opts->{'outfile'});
 | |
|    GUI::HELPERS::print_info($t);
 | |
| 
 | |
|    return;
 | |
| }
 | |
| 
 | |
| #
 | |
| # export crl
 | |
| #
 | |
| sub export_crl {
 | |
|    my ($self, $main, $opts, $box) = @_;
 | |
|     
 | |
|    my($ca, $t, $ret, $ext);
 | |
| 
 | |
|    $box->destroy() if(defined($box));
 | |
| 
 | |
|    GUI::HELPERS::set_cursor($main, 1);
 | |
| 
 | |
|    $ca = $self->{'actca'};
 | |
| 
 | |
|    if(not defined($opts)) {
 | |
|       $opts->{'outfile'} = "$main->{'exportdir'}/$ca-crl.pem";
 | |
|       $opts->{'format'}  = 'PEM';
 | |
|       $opts->{'days'} = $main->{'TCONFIG'}->{'server_ca'}->{'default_crl_days'};
 | |
| 
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       $main->show_crl_export_dialog($opts);
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    if((not defined($opts->{'outfile'})) || ($opts->{'outfile'} eq '')) { 
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       $t = _("Please give the output file");
 | |
|       $main->show_crl_export_dialog($opts);
 | |
|       GUI::HELPERS::print_warning($t);
 | |
| 	   return;
 | |
|       };
 | |
| 
 | |
|    if((not defined($opts->{'passwd'})) || ($opts->{'passwd'} eq '')) { 
 | |
|       GUI::HELPERS::set_cursor($main, 0);
 | |
|       $t = _("Please give the CA password to create the Revocation List");
 | |
|       $main->show_crl_export_dialog($opts);
 | |
|       GUI::HELPERS::print_warning($t);
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    if(not defined($main->{'OpenSSL'})) {
 | |
|       $main->init_openssl($ca);
 | |
|    }
 | |
| 
 | |
|    ($ret, $ext) = $main->{'OpenSSL'}->newcrl(
 | |
|          config  => $self->{$ca}->{'cnf'},
 | |
|          pass    => $opts->{'passwd'},
 | |
|          crldays => $opts->{'days'},
 | |
|          outfile => $opts->{'outfile'},
 | |
|          format  => $opts->{'format'}
 | |
|          );
 | |
| 
 | |
|    GUI::HELPERS::set_cursor($main, 0);
 | |
| 
 | |
|    if($ret eq 1) {
 | |
|       $t = _("Wrong CA password given\nGenerating Revocation List failed");
 | |
|       GUI::HELPERS::print_warning($t, $ext);
 | |
|       return;
 | |
|    } elsif($ret eq 2) {
 | |
|       $t = _("CA Key not found\nGenerating Revocation List failed");
 | |
|       GUI::HELPERS::print_warning($t, $ext);
 | |
|       return;
 | |
|    } elsif($ret) {
 | |
|       $t = _("Generating Revocation List failed");
 | |
|       GUI::HELPERS::print_warning($t, $ext);
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    if (not -s $opts->{'outfile'}) {
 | |
|       $t = _("Generating Revocation List failed");
 | |
|       GUI::HELPERS::print_warning($t);
 | |
|       return;
 | |
|    }
 | |
| 
 | |
|    $main->{'exportdir'} = HELPERS::write_export_dir($main, 
 | |
|          $opts->{'outfile'});
 | |
| 
 | |
|    $t = sprintf(_("CRL successfully exported to: %s"), 
 | |
|          $opts->{'outfile'});
 | |
|    GUI::HELPERS::print_info($t, $ext);
 | |
| 
 | |
|    return;
 | |
| }
 | |
| 
 | |
| sub _rm_dir {
 | |
|    my $dir = shift;
 | |
| 
 | |
|    my ($dirh, $path);
 | |
| 
 | |
|    opendir($dirh, $dir);
 | |
| 
 | |
|    while(my $f = readdir($dirh)) {
 | |
|       next if $f eq '.';
 | |
|       next if $f eq '..';
 | |
| 
 | |
|       $path = $dir."/".$f;
 | |
|       if(-d $path) {
 | |
|          _rm_dir($path);
 | |
|       } else {
 | |
|          unlink($path);
 | |
|       }
 | |
|    }
 | |
|    closedir($dirh);
 | |
| 
 | |
|    rmdir($dir);
 | |
|    
 | |
|    return(0);
 | |
| }
 | |
| 
 | |
| 1
 | |
| 
 |