|
|
|
# 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
|