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.
604 lines
16 KiB
604 lines
16 KiB
# Copyright (c) Stephan Martin <sm@sm-zone.net>
|
|
#
|
|
# $Id: KEY.pm,v 1.8 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 KEY;
|
|
use File::Copy qw(copy);
|
|
|
|
use POSIX;
|
|
|
|
sub new {
|
|
my $self = {};
|
|
my $that = shift;
|
|
my $class = ref($that) || $that;
|
|
|
|
bless($self, $class);
|
|
}
|
|
|
|
#
|
|
# import key from file
|
|
#
|
|
sub get_import_key {
|
|
my ($self, $main, $opts, $box) = @_;
|
|
my ($name, $keyfile, $ca, $cadir);
|
|
|
|
$box->destroy() if(defined($box));
|
|
|
|
if(not defined($opts)) {
|
|
$main->show_key_import_dialog();
|
|
return;
|
|
}
|
|
|
|
$name = HELPERS::gen_name($opts);
|
|
$opts->{'keyname'} = HELPERS::enc_base64($name);
|
|
|
|
$ca = $main->{'CA'}->{'actca'};
|
|
$cadir = $main->{'CA'}->{$ca}->{'dir'};
|
|
$keyfile = $cadir . "/keys/" . $opts->{'keyname'} . ".pem";
|
|
|
|
# TODO: Check if valid key, key with password?
|
|
if (not -s $opts->{'infile'}) {
|
|
GUI::HELPERS::print_warning(_("Key not found: ") . $opts->{'infile'});
|
|
return;
|
|
}
|
|
if (not -e $keyfile) {
|
|
copy($opts->{'infile'}, $keyfile);
|
|
$main->{'keybrowser'}->update($cadir."/keys",
|
|
$cadir."/crl/crl.pem",
|
|
$cadir."/index.txt",
|
|
0);
|
|
} else {
|
|
GUI::HELPERS::print_warning(_("Key file already exists: ".$keyfile));
|
|
}
|
|
return;
|
|
}
|
|
|
|
#
|
|
# get name of keyfile to delete
|
|
#
|
|
sub get_del_key {
|
|
my ($self, $main) = @_;
|
|
|
|
my($keyname, $key, $keyfile, $row, $ind, $ca, $type);
|
|
|
|
$ca = $main->{'keybrowser'}->selection_caname();
|
|
$key = $main->{'keybrowser'}->selection_dn();
|
|
|
|
if(not defined $key) {
|
|
GUI::HELPERS::print_info(_("Please select a Key first"));
|
|
return;
|
|
}
|
|
|
|
$keyname = HELPERS::enc_base64($key);
|
|
|
|
$keyfile = $main->{'cadir'}."/keys/".$keyname.".pem";
|
|
|
|
if(not -s $keyfile) {
|
|
GUI::HELPERS::print_warning(_("Key file not found:".$keyfile));
|
|
return;
|
|
}
|
|
|
|
$main->show_del_confirm($keyfile, 'key');
|
|
|
|
return;
|
|
}
|
|
|
|
#
|
|
# now really delete the key
|
|
#
|
|
sub del_key {
|
|
my ($self, $main, $file) = @_;
|
|
|
|
unlink($file);
|
|
|
|
my $cadir = $main->{'keybrowser'}->selection_cadir();
|
|
|
|
$main->{'keybrowser'}->update($cadir."/keys",
|
|
$cadir."/crl/crl.pem",
|
|
$cadir."/index.txt",
|
|
0);
|
|
|
|
return;
|
|
}
|
|
|
|
#
|
|
# read keys in directory into list
|
|
#
|
|
sub read_keylist {
|
|
my ($self, $main) = @_;
|
|
|
|
my ($f, $modt, $tmp, $ca, $keydir, $keylist);
|
|
|
|
$ca = $main->{'CA'}->{'actca'};
|
|
$keydir = $main->{'cadir'}."/keys";
|
|
$keylist = [];
|
|
|
|
$modt = (stat($keydir))[9];
|
|
|
|
if(defined($self->{'lastread'}) &&
|
|
$self->{'lastread'} >= $modt) {
|
|
return(0);
|
|
}
|
|
|
|
opendir(DIR, $keydir) || do {
|
|
GUI::HELPERS::print_warning(_("Can't open key directory"));
|
|
return(0);
|
|
};
|
|
|
|
while($f = readdir(DIR)) {
|
|
next if $f =~ /^\./;
|
|
$f =~ s/\.pem//;
|
|
$tmp = HELPERS::dec_base64($f);
|
|
next if not defined($tmp);
|
|
next if $tmp eq "";
|
|
$tmp = _check_key($main, $keydir."/".$f.".pem", $tmp);
|
|
push(@{$keylist}, $tmp);
|
|
}
|
|
@{$keylist} = sort(@{$keylist});
|
|
closedir(DIR);
|
|
|
|
$self->{'keylist'} = $keylist;
|
|
|
|
$self->{'lastread'} = time();
|
|
return(1); # got new list
|
|
}
|
|
|
|
#
|
|
# get the information to export the key
|
|
#
|
|
sub get_export_key {
|
|
my ($self, $main, $opts, $box) = @_;
|
|
|
|
$box->destroy() if(defined($box));
|
|
|
|
my($ca, $ind, $row, $t, $out, $cn, $email, $ret, $ext, $cadir);
|
|
|
|
if(not defined($opts)) {
|
|
$cn = $main->{'keybrowser'}->selection_cn();
|
|
|
|
if(not defined $cn) {
|
|
GUI::HELPERS::print_info(_("Please select a Key first"));
|
|
return;
|
|
}
|
|
|
|
$ca = $main->{'keybrowser'}->selection_caname();
|
|
$cadir = $main->{'keybrowser'}->selection_cadir();
|
|
$email = $main->{'keybrowser'}->selection_email();
|
|
|
|
$opts->{'type'} = $main->{'keybrowser'}->selection_type();
|
|
$opts->{'key'} = $main->{'keybrowser'}->selection_dn();
|
|
|
|
$opts->{'keyname'} = HELPERS::enc_base64($opts->{'key'});
|
|
$opts->{'keyfile'} = $cadir."/keys/".$opts->{'keyname'}.".pem";
|
|
$opts->{'certfile'} = $cadir."/certs/".$opts->{'keyname'}.".pem";
|
|
|
|
# set some defaults
|
|
$opts->{'nopass'} = 0;
|
|
$opts->{'include'} = 0;
|
|
$opts->{'format'} = 'PEM';
|
|
$opts->{'friendlyname'} = '';
|
|
|
|
if((defined($email)) && $email ne '' && $email ne ' ') {
|
|
$opts->{'outfile'} = "$main->{'exportdir'}/$email-key.pem";
|
|
}elsif((defined($cn)) && $cn ne '' && $cn ne ' ') {
|
|
$opts->{'outfile'} = "$main->{'exportdir'}/$cn-key.pem";
|
|
}else{
|
|
$opts->{'outfile'} = "$main->{'exportdir'}/key.pem";
|
|
}
|
|
|
|
$main->show_export_dialog($opts, 'key');
|
|
return;
|
|
}
|
|
|
|
if((not defined($opts->{'outfile'})) || ($opts->{'outfile'} eq '')) {
|
|
$main->show_export_dialog($opts, 'key');
|
|
GUI::HELPERS::print_warning(_("Please give at least the output file"));
|
|
return;
|
|
}
|
|
|
|
if(($opts->{'nopass'} || $opts->{'format'} eq 'DER') &&
|
|
((not defined($opts->{'passwd'})) || ($opts->{'passwd'} eq ''))) {
|
|
$main->show_key_nopasswd_dialog($opts);
|
|
return;
|
|
}
|
|
|
|
if(($opts->{'format'} eq 'PEM') || ($opts->{'format'} eq 'DER')) {
|
|
unless(($opts->{'format'} eq 'PEM') && not $opts->{'nopass'}) {
|
|
($out, $ext) = $main->{'OpenSSL'}->convkey(
|
|
'type' => $opts->{'type'},
|
|
'inform' => 'PEM',
|
|
'outform' => $opts->{'format'},
|
|
'nopass' => $opts->{'nopass'},
|
|
'pass' => $opts->{'passwd'},
|
|
'keyfile' => $opts->{'keyfile'}
|
|
);
|
|
|
|
if(defined($out) && $out eq 1) {
|
|
$t = _("Wrong password given\nDecrypting of the Key failed\nExport is not possible");
|
|
GUI::HELPERS::print_warning($t, $ext);
|
|
return;
|
|
} elsif((not defined($out)) || (length($out) < 3)) {
|
|
GUI::HELPERS::print_warning(
|
|
_("Converting failed, Export not possible"), $ext);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(($opts->{'format'} eq 'PEM') && not $opts->{'nopass'}) {
|
|
open(IN, "<$opts->{'keyfile'}") || do {
|
|
$t = sprintf(_("Can't open Key file: %s: %s"),
|
|
$opts->{'keyfile'}, $!);
|
|
GUI::HELPERS::print_warning($t);
|
|
return;
|
|
};
|
|
$out .= $_ while(<IN>);
|
|
close(IN);
|
|
}
|
|
if($opts->{'include'}) {
|
|
open(IN, "<$opts->{'certfile'}") || do {
|
|
$t = sprintf(_("Can't open Certificate file: %s: %s"),
|
|
$opts->{'certfile'}, $!);
|
|
GUI::HELPERS::print_warning($t);
|
|
return;
|
|
};
|
|
$out .= "\n";
|
|
$out .= $_ while(<IN>);
|
|
close(IN);
|
|
}
|
|
|
|
open(OUT, ">$opts->{'outfile'}") || do {
|
|
$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'});
|
|
|
|
$t = sprintf(_("Key succesfully exported to %s"),
|
|
$opts->{'outfile'});
|
|
GUI::HELPERS::print_info($t);
|
|
return;
|
|
|
|
} elsif ($opts->{'format'} eq 'P12') {
|
|
$opts->{'certfile'} =
|
|
$main->{'cadir'}."/certs/".$opts->{'keyname'}.".pem";
|
|
$opts->{'cafile'} =
|
|
$main->{'cadir'}."/cacert.pem";
|
|
|
|
if (-f $main->{'cadir'}."/cachain.pem") {
|
|
$opts->{'cafile'} = $main->{'cadir'}."/cachain.pem";
|
|
}
|
|
|
|
if(not -s $opts->{'certfile'}) {
|
|
$t = _("Certificate is necessary for export as PKCS#12");
|
|
$t .= "\n";
|
|
$t .= _("Export is not possible!");
|
|
GUI::HELPERS::print_warning($t);
|
|
return;
|
|
}
|
|
|
|
if((not defined($opts->{'p12passwd'})) &&
|
|
(not $opts->{'nopass'})) {
|
|
$opts->{'includeca'} = 1;
|
|
$main->show_p12_export_dialog($opts, 'key');
|
|
return;
|
|
}
|
|
|
|
unlink($opts->{'outfile'});
|
|
($ret, $ext) = $main->{'OpenSSL'}->genp12(
|
|
type => $opts->{'type'},
|
|
certfile => $opts->{'certfile'},
|
|
keyfile => $opts->{'keyfile'},
|
|
cafile => $opts->{'cafile'},
|
|
outfile => $opts->{'outfile'},
|
|
passwd => $opts->{'passwd'},
|
|
p12passwd => $opts->{'p12passwd'},
|
|
includeca => $opts->{'includeca'},
|
|
nopass => $opts->{'nopass'},
|
|
friendly => $opts->{'friendlyname'}
|
|
);
|
|
|
|
if($ret eq 1) {
|
|
$t = "Wrong password given\nDecrypting Key failed\nGenerating PKCS#12 failed";
|
|
GUI::HELPERS::print_warning($t, $ext);
|
|
return;
|
|
} elsif($ret || (not -s $opts->{'outfile'})) {
|
|
$t = _("Generating PKCS#12 failed");
|
|
return;
|
|
}
|
|
|
|
$main->{'exportdir'} = HELPERS::write_export_dir($main,
|
|
$opts->{'outfile'});
|
|
|
|
$t = sprintf(_("Certificate and Key successfully exported to %s"),
|
|
$opts->{'outfile'});
|
|
GUI::HELPERS::print_info($t, $ext);
|
|
return;
|
|
|
|
} elsif (($opts->{'format'} eq "ZIP") || ($opts->{'format'} eq "TAR")) {
|
|
$opts->{'certfile'} =
|
|
$main->{'cadir'}."/certs/".$opts->{'keyname'}.".pem";
|
|
if(not -s $opts->{'certfile'}) {
|
|
$t = sprintf(
|
|
_("Certificate is necessary for export as %s file"),
|
|
$opts->{'format'});
|
|
$t .= "\n";
|
|
$t .= _("Export is not possible!");
|
|
GUI::HELPERS::print_warning($t);
|
|
return;
|
|
}
|
|
|
|
$opts->{'parsed'} =
|
|
$main->{'CERT'}->parse_cert($main, $opts->{'keyname'});
|
|
|
|
my $tmpcert = "$main->{'tmpdir'}/cert.pem";
|
|
my $tmpkey = "$main->{'tmpdir'}/key.pem";
|
|
my $tmpcacert = "$main->{'tmpdir'}/cacert.pem";
|
|
|
|
open(OUT, ">$tmpcert") || do {
|
|
GUI::HELPERS::print_warning(_("Can't create temporary file"));
|
|
return;
|
|
};
|
|
print OUT $opts->{'parsed'}->{'PEM'};
|
|
close OUT;
|
|
|
|
# store key in temporary location
|
|
{
|
|
open(IN, "<$opts->{'keyfile'}") || do {
|
|
GUI::HELPERS::print_warning(_("Can't read Key file"));
|
|
return;
|
|
};
|
|
my @key = <IN>;
|
|
close IN;
|
|
|
|
open(OUT, ">$tmpkey") || do {
|
|
GUI::HELPERS::print_warning(_("Can't create temporary file"));
|
|
return;
|
|
};
|
|
print OUT @key;
|
|
close OUT;
|
|
}
|
|
|
|
# store cacert in temporary location
|
|
{
|
|
$opts->{'cafile'} = $main->{'cadir'}."/cacert.pem";
|
|
open(IN, "<$opts->{'cafile'}") || do {
|
|
GUI::HELPERS::print_warning(_("Can't read CA certificate"));
|
|
return;
|
|
};
|
|
my @cacert = <IN>;
|
|
close IN;
|
|
|
|
open(OUT, ">$tmpcacert") || do {
|
|
GUI::HELPERS::print_warning(_("Can't create temporary file"));
|
|
return;
|
|
};
|
|
print OUT @cacert;
|
|
close OUT;
|
|
}
|
|
|
|
unlink($opts->{'outfile'});
|
|
if($opts->{'format'} eq 'ZIP') {
|
|
system($main->{'init'}->{'zipbin'}, '-j', $opts->{'outfile'},
|
|
$tmpcacert, $tmpkey, $tmpcert);
|
|
my $ret = $? >> 8;
|
|
} elsif ($opts->{'format'} eq 'TAR') {
|
|
system($main->{'init'}->{'tarbin'}, 'cfv', $opts->{'outfile'},
|
|
$tmpcacert, $tmpkey, $tmpcert);
|
|
my $ret = $? >> 8;
|
|
}
|
|
|
|
if(not -s $opts->{'outfile'} || $ret) {
|
|
GUI::HELPERS::print_warning(
|
|
sprintf(_("Generating %s file failed"),
|
|
$opts->{'format'}));
|
|
} else {
|
|
$main->{'exportdir'} = HELPERS::write_export_dir($main,
|
|
$opts->{'outfile'});
|
|
$t = sprintf(
|
|
_("Certificate and Key successfully exported to %s"),
|
|
$opts->{'outfile'});
|
|
GUI::HELPERS::print_info($t);
|
|
}
|
|
unlink($tmpcacert);
|
|
unlink($tmpcert);
|
|
unlink($tmpkey);
|
|
|
|
return;
|
|
|
|
} else {
|
|
$t = sprintf(_("Invalid format for export requested: %s"),
|
|
$opts->{'format'});
|
|
GUI::HELPERS::print_warning($t);
|
|
return;
|
|
}
|
|
|
|
GUI::HELPERS::print_warning(_("Something Failed ??"));
|
|
|
|
return;
|
|
}
|
|
|
|
# check if its a dsa or rsa key
|
|
sub _check_key {
|
|
my ($main, $file, $name) = @_;
|
|
|
|
my ($t, $type);
|
|
|
|
open(KEY, "<$file") || do {
|
|
$t = sprintf(_("Can't open Key file: %s: %s"),
|
|
$file, $!);
|
|
GUI::HELPERS::print_warning($t);
|
|
return;
|
|
};
|
|
|
|
$type = "#ERR";
|
|
while(<KEY>) {
|
|
if(/RSA PRIVATE KEY/i) {
|
|
$type = "RSA";
|
|
last;
|
|
} elsif(/DSA PRIVATE KEY/i) {
|
|
$type = "DSA";
|
|
last;
|
|
} else {
|
|
$type = "UNKNOWN";
|
|
}
|
|
}
|
|
close(KEY);
|
|
|
|
if(defined($type) && $type ne "") {
|
|
$name .= "%".$type;
|
|
}
|
|
|
|
return($name);
|
|
}
|
|
|
|
#
|
|
# Check password
|
|
#
|
|
sub check_passwd {
|
|
my ($self, $main) = @_;
|
|
|
|
my ($keyname, $key, $keyfile);
|
|
|
|
$key = $main->{'keybrowser'}->selection_dn();
|
|
|
|
if(not defined $key) {
|
|
GUI::HELPERS::print_info(_("Please select a Key first"));
|
|
return;
|
|
}
|
|
|
|
$keyname = HELPERS::enc_base64($key);
|
|
$keyfile = $main->{'cadir'}."/keys/".$keyname.".pem";
|
|
|
|
if(not -s $keyfile) {
|
|
GUI::HELPERS::print_warning(_("Key file not found:".$keyfile));
|
|
return;
|
|
}
|
|
|
|
$main->show_key_check_dialog($keyfile);
|
|
|
|
return;
|
|
}
|
|
|
|
#
|
|
# Set new password for key
|
|
#
|
|
sub set_password {
|
|
my ($self, $main) = @_;
|
|
|
|
my ($keyname, $key, $keyfile);
|
|
|
|
$key = $main->{'keybrowser'}->selection_dn();
|
|
|
|
if(not defined $key) {
|
|
GUI::HELPERS::print_info(_("Please select a Key first"));
|
|
return;
|
|
}
|
|
|
|
$keyname = HELPERS::enc_base64($key);
|
|
$keyfile = $main->{'cadir'}."/keys/".$keyname.".pem";
|
|
|
|
if(not -s $keyfile) {
|
|
GUI::HELPERS::print_warning(_("Key file not found:".$keyfile));
|
|
return;
|
|
}
|
|
|
|
$main->show_key_passwd_dialog($keyfile);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
sub key_change_passwd {
|
|
my ($self, $main, $file, $oldpass, $newpass, $mode) = @_;
|
|
my $opts = {};
|
|
my ($t, $ret, $ext);
|
|
|
|
my $inform = "DER";
|
|
my $outform = "PEM";
|
|
|
|
my($type);
|
|
|
|
# check file format
|
|
open(KEY, "<$file") || do {
|
|
$t = sprintf(_("Can't open Key file:\n%s"),
|
|
$file);
|
|
GUI::HELPERS::print_warning($t);
|
|
return(1);
|
|
};
|
|
while(<KEY>) {
|
|
if(/BEGIN RSA PRIVATE KEY/) {
|
|
$inform = "PEM";
|
|
$type = "RSA";
|
|
last;
|
|
} elsif(/BEGIN DSA PRIVATE KEY/){
|
|
$inform = "PEM";
|
|
$type = "DSA";
|
|
last;
|
|
} else {
|
|
$type = "UNKNOWN";
|
|
}
|
|
}
|
|
|
|
GUI::HELPERS::set_cursor($main, 1);
|
|
|
|
($ret, $ext) = $main->{'OpenSSL'}->convkey(
|
|
'type' => $type,
|
|
'inform' => $inform,
|
|
'outform' => $outform,
|
|
'nopass' => 0,
|
|
'pass' => $newpass,
|
|
'oldpass' => $oldpass,
|
|
'keyfile' => $file
|
|
);
|
|
|
|
GUI::HELPERS::set_cursor($main, 0);
|
|
|
|
if($ret eq 1) {
|
|
if($mode eq 'ca') {
|
|
$t = _("Generating key failed");
|
|
if($ext =~ /unable to load Private Key/) {
|
|
$t .= _("The password for your old CA Key is wrong");
|
|
}
|
|
} else {
|
|
$t = _("Change password failed");
|
|
}
|
|
GUI::HELPERS::print_warning(($t), $ext);
|
|
return(1);
|
|
}
|
|
|
|
if($mode eq 'key') {
|
|
# Write out key with new password
|
|
open(OUT, ">$file") || do {
|
|
GUI::HELPERS::print_warning(sprintf(_("Can't open output file: %s: %s"), $file, $!));
|
|
return(1);
|
|
};
|
|
print OUT $ret;
|
|
close(OUT);
|
|
return(0);
|
|
}
|
|
return($ret);
|
|
}
|
|
|
|
1
|
|
|