Imported former upstream version 0.7.5
This commit is contained in:
commit
e136e7cbbf
|
@ -0,0 +1,212 @@
|
||||||
|
$Id: CHANGES,v 1.23 2006/07/25 20:10:54 sm Exp $
|
||||||
|
|
||||||
|
version 0.7.5 - Tue July 25 2006
|
||||||
|
* added swedish translation
|
||||||
|
many thanks to Daniel Nylander
|
||||||
|
|
||||||
|
version 0.7.4 - Thu June 29 2006
|
||||||
|
* fixed invalid filename encoding with german umlauts in base64
|
||||||
|
thanks to Bruno Blumenthal
|
||||||
|
* Fixed display of UTF8 characters in the GUI
|
||||||
|
Debian #367829
|
||||||
|
|
||||||
|
version 0.7.3 - Tue May 23 2006
|
||||||
|
* Add environment variable
|
||||||
|
Gentoo #78576
|
||||||
|
thanks to dragonheart at gentoo dot org
|
||||||
|
* Fixed crash when CA is created with nsCertType
|
||||||
|
Debian #354386
|
||||||
|
|
||||||
|
version 0.7.3 - Tue May 23 2006
|
||||||
|
* Enhanced version detection
|
||||||
|
thanks to Peter Marschall
|
||||||
|
Debian #360766 #360555
|
||||||
|
* Changed command for openssl due to changed openssl behavior
|
||||||
|
regarding fingerprints
|
||||||
|
thanks to Peter Marschall
|
||||||
|
Debian #360768
|
||||||
|
* Added "friendly name" to PKCS#12 export
|
||||||
|
Debian #364617
|
||||||
|
* Corrected exit call
|
||||||
|
thanks to Peter Marschall
|
||||||
|
Debian #360767
|
||||||
|
|
||||||
|
|
||||||
|
version 0.7.2 - Sat Feb 18 2006
|
||||||
|
* Fixed bug, which made keysize always 4096
|
||||||
|
* Implemented correct usage of openssl crl depending on openssl version
|
||||||
|
* Added tar file support for export
|
||||||
|
|
||||||
|
version 0.7.1 - Sat Oct 22 2005
|
||||||
|
* Fixed possible crashbug, thanks to
|
||||||
|
* Choose CA validity as maximal certificate lifetime
|
||||||
|
* correctly include/don't include keys in exported certificate files
|
||||||
|
thanks to "thus0 at free dot fr"
|
||||||
|
* added ripemd160 support, thanks to Wim Lewis
|
||||||
|
* added possibility to create pkcs#12 without password
|
||||||
|
* fixed broken OU in SubCA, thanks to Charles Lepple
|
||||||
|
* fixed bug which made saving options with comboboxes impossible
|
||||||
|
thanks to "thus0 at free dot fr"
|
||||||
|
* fixed bug inseting the right serial number during import
|
||||||
|
thanks to Daniel Kahn Gillmor
|
||||||
|
|
||||||
|
version 0.7.0 - Sun Apr 10 2005
|
||||||
|
* migrated to perl-Gtk2
|
||||||
|
* added advanced export options (Debian #293931)
|
||||||
|
* added CA history
|
||||||
|
* fixed some minor bugs
|
||||||
|
|
||||||
|
version 0.6.8 (beta) - Sun Feb 20 2004
|
||||||
|
* added detection for openssl 0.9.8
|
||||||
|
* removed crlDistributionPoint for Root-CA
|
||||||
|
* added patch for multiple OUs
|
||||||
|
Thanks to Uwe Arndt <arndt@uni-koblenz.de>
|
||||||
|
* added patch for multiple subjectAltName extensions (Debian #271183)
|
||||||
|
Thanks to Peter Marschall <peter@adpm.de>
|
||||||
|
|
||||||
|
version 0.6.7 (beta) - Mon Dec 5 2004
|
||||||
|
* added import functionality
|
||||||
|
|
||||||
|
version 0.6.6 (beta) - Fri Aug 13 2004
|
||||||
|
* added czech translation
|
||||||
|
Thanks to Robert Wolf <gentoo@slave.umbr.cas.cz>
|
||||||
|
|
||||||
|
version 0.6.5 (beta) - Thu Aug 05 2004
|
||||||
|
* added spanish translation
|
||||||
|
Thanks to Ramon Pons Vivanco <rpons@rinu.org>
|
||||||
|
* force (re)parsing a newly created request
|
||||||
|
* force delete of internal structures, when deleting a CA
|
||||||
|
|
||||||
|
version 0.6.4 (beta) - Thu Jul 15 2004
|
||||||
|
* fixed bug, showing wrong options for renewal of certificates
|
||||||
|
* fixed bug creating requests via rightclick directly after creating a new CA
|
||||||
|
(thanks to wbx@openbsd.de)
|
||||||
|
* fixed bug which added ugly empty box to cert/req page
|
||||||
|
* fixed bug with wrong openssl.conf during startup (server-cert with
|
||||||
|
ca-extensions)
|
||||||
|
(thanks to bernhard.dawuidow@tronicplanet.de)
|
||||||
|
* fixed ca-config dialog during creation of root-ca (drop-downs)
|
||||||
|
(thanks to X_KurJ@viessmann.com)
|
||||||
|
* revocation reason can be given with openssl 0.9.7
|
||||||
|
* changed default exportdir to users home
|
||||||
|
* remeber exportdir from last export
|
||||||
|
* added possibility to set the extension extendedKeyUsage
|
||||||
|
* added possibility to leave email out of the subject dn (0.9.7)
|
||||||
|
|
||||||
|
version 0.6.3 (beta) - Wed Jun 16 2004
|
||||||
|
* fixed bug which made it impossible to create new requests
|
||||||
|
|
||||||
|
version 0.6.2 (beta) - Sun Jun 13 2004
|
||||||
|
* added new look for some functions
|
||||||
|
* key, request and certificate can be generated in one step
|
||||||
|
* code cleanup
|
||||||
|
|
||||||
|
version 0.6.1 (beta) - Sat May 22 2004
|
||||||
|
* fixed bug, which made it impossible to create a new Root-CA
|
||||||
|
Thanks to Olaf Gellert <og@pre-secure.de>
|
||||||
|
|
||||||
|
version 0.6.0 (beta) - Tue May 11 2004
|
||||||
|
* some minor usability improvements
|
||||||
|
* added possibility to create SubCAs now
|
||||||
|
* added possibility also to use DSA keys
|
||||||
|
* added possibility to select the digest during key creation
|
||||||
|
* added possibility to export the complete CA-chain of a SubCA
|
||||||
|
Thanks a lot to Olaf Gellert <og@pre-secure.de> for ideas and patches.
|
||||||
|
|
||||||
|
version 0.5.4 (beta) - Fri Oct 3 2003
|
||||||
|
* added a lot of configuration options
|
||||||
|
* correctly import/show details of requests without extensions
|
||||||
|
(thanks to James.Leavitt@anywaregroup.com)
|
||||||
|
|
||||||
|
version 0.5.3 (beta) - Mon Sep 29 2003
|
||||||
|
* fixed wrong label while creating new CA
|
||||||
|
* fixed bug, saving configuration is possible again
|
||||||
|
|
||||||
|
version 0.5.2 (beta) - Mon Sep 1 2003
|
||||||
|
* added renewal of certificates
|
||||||
|
|
||||||
|
version 0.5.1 (beta) - Tue Aug 26 2003
|
||||||
|
* code cleanup
|
||||||
|
* fixed some minor bugs and typos
|
||||||
|
* corrected some window sizes and tables
|
||||||
|
* added accelerators to the menu
|
||||||
|
|
||||||
|
version 0.5.0 (beta) - Sat Aug 16 2003
|
||||||
|
* GUI rewriten with perl-Gtk/Gnome
|
||||||
|
|
||||||
|
version 0.4.9 (beta) - Sat Jul 5 2003
|
||||||
|
* added german translation
|
||||||
|
|
||||||
|
version 0.4.8 (beta) - Tue Jul 1 2003
|
||||||
|
* convert index.txt if openssl changed from 0.9.6x to 0.9.7x
|
||||||
|
|
||||||
|
version 0.4.7 (beta) - Fri Jun 27 2003
|
||||||
|
* added export into zip-file
|
||||||
|
thanks to ludwig.nussel@suse.de
|
||||||
|
|
||||||
|
version 0.4.6 (beta) - Mon Jun 23 2003
|
||||||
|
* some tiny usability improvements
|
||||||
|
thanks to ludwig.nussel@suse.de again
|
||||||
|
|
||||||
|
version 0.4.5 (beta) - Thu Jun 19 2003
|
||||||
|
* some usability improvements
|
||||||
|
thanks to ludwig.nussel@suse.de
|
||||||
|
* some more configuration options
|
||||||
|
|
||||||
|
version 0.4.4 (beta) - Fri Oct 4 2002
|
||||||
|
* Fixed bug exporting keys in PEM format
|
||||||
|
* Fixed possible empty lines in cert/key/reqlist
|
||||||
|
thanks to waldemar.mertke@gmx.de
|
||||||
|
|
||||||
|
version 0.4.3 (beta) - Fri Sep 27 2002
|
||||||
|
* Fixed some minor bugs and typos (e.g. concerning openssl 0.9.7)
|
||||||
|
thanks to iebgener@yahoo.com and waldemar.mertke@gmx.de
|
||||||
|
|
||||||
|
version 0.4.2 (beta) - Sat Aug 24 2002
|
||||||
|
* fixed revocation when serial is > 15
|
||||||
|
thanks to curly@e-card.bg
|
||||||
|
* fixed recognition of java-generated requests
|
||||||
|
thanks to matthew.lewis@syntegra.com
|
||||||
|
* code cleanup
|
||||||
|
|
||||||
|
version 0.4.1 (beta) - Wed Aug 21 2002
|
||||||
|
* fixed revocation
|
||||||
|
* added some colors
|
||||||
|
* thanks to curly@e-card.bg
|
||||||
|
|
||||||
|
version 0.4.0 (beta) - Sun Aug 18 2002
|
||||||
|
* works independent of OpenCA modules now
|
||||||
|
* some enhancements to functionality (e.g. export of key without
|
||||||
|
passwd)
|
||||||
|
* some smaller bugfixes in usability
|
||||||
|
* new specfile (thanks to oron@actcom.co.il)
|
||||||
|
|
||||||
|
version 0.3.4 (beta) - Mon Jun 3 2002
|
||||||
|
* fixed wrong templatedir when creating a new CA
|
||||||
|
|
||||||
|
version 0.3.3 (beta) - Sun Jun 2 2002
|
||||||
|
* fixed some minor bugs and typos
|
||||||
|
import of requests from ssh-sentinel should work now without problems
|
||||||
|
|
||||||
|
version 0.3.2 (beta) - Sat May 11 2002
|
||||||
|
* added parser for x509 extensions when viewing certificate details
|
||||||
|
|
||||||
|
version 0.3.1 (beta) - Fri May 3 2002
|
||||||
|
* added option to view complete certificate/request as text
|
||||||
|
|
||||||
|
version 0.3.0 (beta) - Thu Apr 18 2002
|
||||||
|
* added possibility to configure openssl
|
||||||
|
* fixed some minor bugs
|
||||||
|
|
||||||
|
version 0.2.5 (beta) - Sun Apr 7 2002
|
||||||
|
* improved usabilty and errorhandling
|
||||||
|
* fixed some minor bugs and typos
|
||||||
|
|
||||||
|
version 0.2.4 (beta) - Sun Mar 31 2002
|
||||||
|
* added possibilty to import PKCS#10 requests
|
||||||
|
* added function to delete a configured CA
|
||||||
|
|
||||||
|
version 0.2.3 (beta) - Tue Mar 26 2002
|
||||||
|
* fixed bug with expiration date defaults to 30 days when creating
|
||||||
|
a new CA
|
||||||
|
* change status to E in index.txt, if certificate is expired
|
|
@ -0,0 +1,30 @@
|
||||||
|
1. Unpack the sources (seems like you got it already)
|
||||||
|
|
||||||
|
2. Configure the following paths for your setup. These variables
|
||||||
|
are located in the file tinyca itself.
|
||||||
|
|
||||||
|
@INC (location of the directory lib)
|
||||||
|
$init->{'opensslbin'} (location of your openssl binary)
|
||||||
|
$init->{'templatedir'} (location of the directory templates)
|
||||||
|
$init->{'zipbin'} (location of your zip binary)
|
||||||
|
$init->{'tarbin'} (location of your tar binary)
|
||||||
|
|
||||||
|
3. If you want to have german/spanish/czech/swedish texts:
|
||||||
|
Generate the file tinyca.mo from po/de.po:
|
||||||
|
msgfmt po/de.po -o locale/de/LC_MESSAGES/tinyca.mo
|
||||||
|
msgfmt po/es.po -o locale/es/LC_MESSAGES/tinyca.mo
|
||||||
|
msgfmt po/cs.po -o locale/cs/LC_MESSAGES/tinyca.mo
|
||||||
|
msgfmt po/sv.po -o locale/sv/LC_MESSAGES/tinyca.mo
|
||||||
|
or even more simple: call make in the directory po/
|
||||||
|
|
||||||
|
If your locale is not set to german/spanish:
|
||||||
|
export LC_ALL=de_DE.UTF-8
|
||||||
|
or
|
||||||
|
export LC_ALL=es_ES.UTF-8
|
||||||
|
or
|
||||||
|
export LC_ALL=cs_CZ.UTF-8
|
||||||
|
or
|
||||||
|
export LC_ALL=sv_SE.UTF-8
|
||||||
|
before you call tinyca.
|
||||||
|
|
||||||
|
4. Call tinyca2, use it and report bugs :-))
|
|
@ -0,0 +1,9 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
mkdir -p locale/de/LC_MESSAGES
|
||||||
|
mkdir -p locale/es/LC_MESSAGES
|
||||||
|
mkdir -p locale/cs/LC_MESSAGES
|
||||||
|
|
||||||
|
msgfmt po/de.po -o locale/de/LC_MESSAGES/tinyca2.mo
|
||||||
|
msgfmt po/es.po -o locale/es/LC_MESSAGES/tinyca2.mo
|
||||||
|
msgfmt po/cs.po -o locale/cs/LC_MESSAGES/tinyca2.mo
|
|
@ -0,0 +1,713 @@
|
||||||
|
# Copyright (c) Stephan Martin <sm@sm-zone.net>
|
||||||
|
#
|
||||||
|
# $Id: CERT.pm,v 1.11 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 CERT;
|
||||||
|
|
||||||
|
use POSIX;
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my $that = shift;
|
||||||
|
my $class = ref($that) || $that;
|
||||||
|
|
||||||
|
my $self = {};
|
||||||
|
|
||||||
|
$self->{'OpenSSL'} = shift;
|
||||||
|
|
||||||
|
bless($self, $class);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# read certificates in directory into list
|
||||||
|
#
|
||||||
|
sub read_certlist {
|
||||||
|
my ($self, $certdir, $crlfile, $indexfile, $force, $main) = @_;
|
||||||
|
|
||||||
|
my($f, $certlist, $crl, $modt, $parsed, $tmp, $t, $c, $p, @files);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 1);
|
||||||
|
|
||||||
|
$certlist = [];
|
||||||
|
|
||||||
|
$modt = (stat($certdir))[9];
|
||||||
|
|
||||||
|
if(defined($self->{'lastread'}) &&
|
||||||
|
($self->{'lastread'} >= $modt) &&
|
||||||
|
not defined($force)) {
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
$crl = $self->{'OpenSSL'}->parsecrl($crlfile, $force);
|
||||||
|
|
||||||
|
opendir(DIR, $certdir) || do {
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
$t = sprintf(_("Can't open Certificate directory: %s"), $certdir);
|
||||||
|
GUI::HELPERS::print_warning($t);
|
||||||
|
return(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
while($f = readdir(DIR)) {
|
||||||
|
next if $f =~ /^\./;
|
||||||
|
push(@files, $f);
|
||||||
|
$c++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$main->{'barbox'}->pack_start($main->{'progress'}, 0, 0, 0);
|
||||||
|
$main->{'progress'}->show();
|
||||||
|
foreach $f (@files) {
|
||||||
|
next if $f =~ /^\./;
|
||||||
|
|
||||||
|
$f =~ s/\.pem//;
|
||||||
|
|
||||||
|
$tmp = HELPERS::dec_base64($f);
|
||||||
|
next if not defined($tmp);
|
||||||
|
next if $tmp eq "";
|
||||||
|
|
||||||
|
if(defined($main)) {
|
||||||
|
$t = sprintf(_(" Read Certificate: %s"), $tmp);
|
||||||
|
GUI::HELPERS::set_status($main, $t);
|
||||||
|
$p += 100/$c;
|
||||||
|
if($p/100 <= 1) {
|
||||||
|
$main->{'progress'}->set_fraction($p/100);
|
||||||
|
while(Gtk2->events_pending) {
|
||||||
|
Gtk2->main_iteration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $debugf = $certdir."/".$f.".pem";
|
||||||
|
|
||||||
|
$parsed = $self->{'OpenSSL'}->parsecert($crlfile, $indexfile,
|
||||||
|
$certdir."/".$f.".pem", $force);
|
||||||
|
|
||||||
|
defined($parsed) || do {
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
GUI::HELPERS::print_error(_("Can't read Certificate"));
|
||||||
|
};
|
||||||
|
|
||||||
|
$tmp .= "%".$parsed->{'STATUS'};
|
||||||
|
|
||||||
|
push(@{$certlist}, $tmp);
|
||||||
|
}
|
||||||
|
@{$certlist} = sort(@{$certlist});
|
||||||
|
closedir(DIR);
|
||||||
|
|
||||||
|
$self->{'certlist'} = $certlist;
|
||||||
|
|
||||||
|
$self->{'lastread'} = time();
|
||||||
|
|
||||||
|
if(defined($main)) {
|
||||||
|
$main->{'progress'}->set_fraction(0);
|
||||||
|
$main->{'barbox'}->remove($main->{'progress'});
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(1); # got new list
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# get information for renewing a certifikate
|
||||||
|
#
|
||||||
|
sub get_renew_cert {
|
||||||
|
my ($self, $main, $opts, $box) = @_;
|
||||||
|
|
||||||
|
my ($cert, $status, $t, $ca, $cadir);
|
||||||
|
|
||||||
|
$box->destroy() if(defined($box));
|
||||||
|
|
||||||
|
if((not defined($opts->{'certfile'})) ||
|
||||||
|
(not defined($opts->{'passwd'})) ||
|
||||||
|
($opts->{'certfile'} eq '') ||
|
||||||
|
($opts->{'passwd'} eq '')) {
|
||||||
|
|
||||||
|
$cert = $main->{'certbrowser'}->selection_dn();
|
||||||
|
|
||||||
|
if(not defined($cert)) {
|
||||||
|
GUI::HELPERS::print_info(_("Please select a Certificate first"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ca = $main->{'certbrowser'}->selection_caname();
|
||||||
|
$cadir = $main->{'certbrowser'}->selection_cadir();
|
||||||
|
$status = $main->{'certbrowser'}->selection_status();
|
||||||
|
|
||||||
|
if($status eq _("VALID")) {
|
||||||
|
$t = sprintf(
|
||||||
|
_("Can't renew Certifikate with Status: %s\nPlease revoke the Certificate first"),
|
||||||
|
$status);
|
||||||
|
GUI::HELPERS::print_warning($t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$opts->{'certname'} = HELPERS::enc_base64($cert);
|
||||||
|
$opts->{'reqname'} = $opts->{'certname'};
|
||||||
|
$opts->{'certfile'} = $cadir."/certs/".$opts->{'certname'}.".pem";
|
||||||
|
$opts->{'keyfile'} = $cadir."/keys/".$opts->{'certname'}.".pem";
|
||||||
|
$opts->{'reqfile'} = $cadir."/req/".$opts->{'certname'}.".pem";
|
||||||
|
|
||||||
|
if((not -s $opts->{'certfile'}) ||
|
||||||
|
(not -s $opts->{'keyfile'}) ||
|
||||||
|
(not -s $opts->{'reqfile'})) {
|
||||||
|
$t = _("Key and Request are necessary for renewal of a Certificate\nRenewal is not possible!");
|
||||||
|
GUI::HELPERS::print_warning($t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$main->show_req_sign_dialog($opts);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$main->{'REQ'}->sign_req($main, $opts);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# get information for revoking a certifikate
|
||||||
|
#
|
||||||
|
sub get_revoke_cert {
|
||||||
|
my ($self, $main, $opts, $box) = @_;
|
||||||
|
|
||||||
|
my ($cert, $status, $t, $ca, $cadir);
|
||||||
|
|
||||||
|
$box->destroy() if(defined($box));
|
||||||
|
|
||||||
|
if((not defined($opts->{'certfile'})) ||
|
||||||
|
(not defined($opts->{'passwd'})) ||
|
||||||
|
($opts->{'certfile'} eq '') ||
|
||||||
|
($opts->{'passwd'} eq '')) {
|
||||||
|
$opts->{'certfile'} = $main->{'certbrowser'}->selection_fname();
|
||||||
|
|
||||||
|
if(not defined($opts->{'certfile'})) {
|
||||||
|
$t = _("Please select a Certificate first");
|
||||||
|
GUI::HELPERS::print_info($t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ca = $main->{'certbrowser'}->selection_caname();
|
||||||
|
$cadir = $main->{'certbrowser'}->selection_cadir();
|
||||||
|
$cert = $main->{'certbrowser'}->selection_dn();
|
||||||
|
$status = $main->{'certbrowser'}->selection_status();
|
||||||
|
|
||||||
|
if($status ne _("VALID")) {
|
||||||
|
$t = sprintf(_("Can't revoke Certifikate with Status: %s"),
|
||||||
|
$status);
|
||||||
|
GUI::HELPERS::print_warning($t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$opts->{'certname'} = HELPERS::enc_base64($cert);
|
||||||
|
$opts->{'cert'} = $cert;
|
||||||
|
|
||||||
|
$main->show_cert_revoke_dialog($opts);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->revoke_cert($main, $opts);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# now really revoke the certificate
|
||||||
|
#
|
||||||
|
sub revoke_cert {
|
||||||
|
my ($self, $main, $opts) = @_;
|
||||||
|
|
||||||
|
my($ca, $cadir, $ret, $t, $ext, $reason);
|
||||||
|
|
||||||
|
$ca = $main->{'certbrowser'}->selection_caname();
|
||||||
|
$cadir = $main->{'certbrowser'}->selection_cadir();
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 1);
|
||||||
|
|
||||||
|
if(defined($opts->{'reason'}) && $opts->{'reason'} ne '') {
|
||||||
|
$reason = $opts->{'reason'};
|
||||||
|
} else {
|
||||||
|
$reason = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
($ret, $ext) = $self->{'OpenSSL'}->revoke(
|
||||||
|
'config' => $main->{'CA'}->{$ca}->{'cnf'},
|
||||||
|
'infile' => $cadir."/certs/".$opts->{'certname'}.".pem",
|
||||||
|
'pass' => $opts->{'passwd'},
|
||||||
|
'reason' => $reason
|
||||||
|
);
|
||||||
|
|
||||||
|
if($ret eq 1) {
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
$t = _("Wrong CA password given\nRevoking the Certificate failed");
|
||||||
|
GUI::HELPERS::print_warning($t, $ext);
|
||||||
|
delete($opts->{$_}) foreach(keys(%$opts));
|
||||||
|
$opts = undef;
|
||||||
|
return;
|
||||||
|
} elsif($ret eq 2) {
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
$t = _("CA Key not found\nRevoking the Certificate failed");
|
||||||
|
GUI::HELPERS::print_warning($t, $ext);
|
||||||
|
delete($opts->{$_}) foreach(keys(%$opts));
|
||||||
|
$opts = undef;
|
||||||
|
return;
|
||||||
|
} elsif($ret) {
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
$t = _("Revoking the Certificate failed");
|
||||||
|
GUI::HELPERS::print_warning($t, $ext);
|
||||||
|
delete($opts->{$_}) foreach(keys(%$opts));
|
||||||
|
$opts = undef;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
($ret, $ext) = $self->{'OpenSSL'}->newcrl(
|
||||||
|
'config' => $main->{'CA'}->{$ca}->{'cnf'},
|
||||||
|
'pass' => $opts->{'passwd'},
|
||||||
|
'crldays' => 365,
|
||||||
|
'outfile' => $cadir."/crl/crl.pem"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (not -s $cadir."/crl/crl.pem" || $ret) {
|
||||||
|
delete($opts->{$_}) foreach(keys(%$opts));
|
||||||
|
$opts = undef;
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
GUI::HELPERS::print_error(
|
||||||
|
_("Generating a new Revocation List failed"), $ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->{'OpenSSL'}->parsecrl( $cadir."/crl/crl.pem", 1);
|
||||||
|
|
||||||
|
$self->reread_cert($main, $opts->{'cert'});
|
||||||
|
|
||||||
|
# force reread of certlist
|
||||||
|
$main->{'certbrowser'}->update($cadir."/certs",
|
||||||
|
$cadir."/crl/crl.pem",
|
||||||
|
$cadir."/index.txt",
|
||||||
|
0);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
|
||||||
|
delete($opts->{$_}) foreach(keys(%$opts));
|
||||||
|
$opts = undef;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# get name of certificatefile to delete
|
||||||
|
#
|
||||||
|
sub get_del_cert {
|
||||||
|
my ($self, $main) = @_;
|
||||||
|
|
||||||
|
my($certname, $cert, $certfile, $status, $t, $cadir, $ca);
|
||||||
|
|
||||||
|
$certfile = $main->{'certbrowser'}->selection_fname();
|
||||||
|
|
||||||
|
if(not defined $certfile) {
|
||||||
|
GUI::HELPERS::print_info(_("Please select a Certificate first"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ca = $main->{'certbrowser'}->selection_caname();
|
||||||
|
$cadir = $main->{'certbrowser'}->selection_cadir();
|
||||||
|
$cert = $main->{'certbrowser'}->selection_dn();
|
||||||
|
$status = $main->{'certbrowser'}->selection_status();
|
||||||
|
|
||||||
|
$certname = HELPERS::enc_base64($cert);
|
||||||
|
|
||||||
|
if($status eq _("VALID")) {
|
||||||
|
GUI::HELPERS::print_warning(
|
||||||
|
_("Can't delete VALID certificate!\nPlease revoke the Certificate first."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$main->show_del_confirm($certfile, 'cert');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# now really delete the certificatefile
|
||||||
|
#
|
||||||
|
sub del_cert {
|
||||||
|
my ($self, $main, $file) = @_;
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 1);
|
||||||
|
|
||||||
|
unlink($file);
|
||||||
|
|
||||||
|
my $cadir = $main->{'certbrowser'}->selection_cadir();
|
||||||
|
|
||||||
|
$main->{'certbrowser'}->update($cadir."/certs",
|
||||||
|
$cadir."/crl/crl.pem",
|
||||||
|
$cadir."/index.txt",
|
||||||
|
0);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# get informations for exporting a certificate
|
||||||
|
#
|
||||||
|
sub get_export_cert {
|
||||||
|
my ($self, $main, $opts, $box) = @_;
|
||||||
|
|
||||||
|
$box->destroy() if(defined($box));
|
||||||
|
|
||||||
|
my($ca, $t, $cn, $email, $cadir);
|
||||||
|
|
||||||
|
if(not defined($opts)) {
|
||||||
|
$cn = $main->{'certbrowser'}->selection_cn();
|
||||||
|
$email = $main->{'certbrowser'}->selection_email();
|
||||||
|
|
||||||
|
if(not defined $cn) {
|
||||||
|
GUI::HELPERS::print_info(_("Please select a Certificate first"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ca = $main->{'certbrowser'}->selection_caname();
|
||||||
|
$cadir = $main->{'certbrowser'}->selection_cadir();
|
||||||
|
|
||||||
|
$opts->{'status'} = $main->{'certbrowser'}->selection_status();
|
||||||
|
$opts->{'cert'} = $main->{'certbrowser'}->selection_dn();
|
||||||
|
|
||||||
|
$opts->{'certname'} = HELPERS::enc_base64($opts->{'cert'});
|
||||||
|
$opts->{'certfile'} = $cadir."/certs/".$opts->{'certname'}.".pem";
|
||||||
|
$opts->{'keyfile'} = $cadir."/keys/".$opts->{'certname'}.".pem";
|
||||||
|
$opts->{'cafile'} = $cadir."/cacert.pem";
|
||||||
|
|
||||||
|
if (-f $cadir."/cachain.pem") {
|
||||||
|
$opts->{'cafile'} = $cadir."/cachain.pem";
|
||||||
|
}
|
||||||
|
|
||||||
|
if($opts->{'status'} ne _("VALID")) {
|
||||||
|
$t = _("Certificate seems not to be VALID");
|
||||||
|
$t .= "\n";
|
||||||
|
$t .= _("Export is not possible");
|
||||||
|
GUI::HELPERS::print_warning($t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$opts->{'parsed'} = $self->parse_cert($main, $opts->{'certname'});
|
||||||
|
|
||||||
|
if((defined($email)) && $email ne '' && $email ne ' ') {
|
||||||
|
$opts->{'outfile'} = "$main->{'exportdir'}/$email-cert.pem";
|
||||||
|
}elsif((defined($cn)) && $cn ne '' && $cn ne ' ') {
|
||||||
|
$opts->{'outfile'} = "$main->{'exportdir'}/$cn-cert.pem";
|
||||||
|
}else{
|
||||||
|
$opts->{'outfile'} = "$main->{'exportdir'}/cert.pem";
|
||||||
|
}
|
||||||
|
$opts->{'format'} = 'PEM';
|
||||||
|
$opts->{'include'} = 0;
|
||||||
|
$opts->{'incfp'} = 0;
|
||||||
|
$opts->{'nopass'} = 0;
|
||||||
|
$opts->{'friendlyname'} = '';
|
||||||
|
|
||||||
|
$main->show_export_dialog($opts, 'cert');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((not defined($opts->{'outfile'})) || ($opts->{'outfile'} eq '')) {
|
||||||
|
$main->show_export_dialog($opts, 'cert');
|
||||||
|
GUI::HELPERS::print_warning(
|
||||||
|
_("Please give at least the output file"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($opts->{'format'} eq 'P12') {
|
||||||
|
if(not -s $opts->{'keyfile'}) {
|
||||||
|
$t = _("Key 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, 'cert');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} elsif(($opts->{'format'} eq 'ZIP') || ($opts->{'format'} eq 'TAR')) {
|
||||||
|
if(not -s $opts->{'keyfile'}) {
|
||||||
|
$t = sprintf(
|
||||||
|
_("Key is necessary for export as %s"), $opts->{'format'});
|
||||||
|
$t .= "\n";
|
||||||
|
$t .= _("Export is not possible!");
|
||||||
|
GUI::HELPERS::print_warning($t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->export_cert($main, $opts); #FIXME no need for two functions
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# now really export the certificate
|
||||||
|
#
|
||||||
|
sub export_cert {
|
||||||
|
my ($self, $main, $opts) = @_;
|
||||||
|
|
||||||
|
my($ca, $t, $out, $ret, $ext);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 1);
|
||||||
|
|
||||||
|
$ca = $main->{'CA'}->{'actca'};
|
||||||
|
|
||||||
|
if($opts->{'format'} eq 'PEM') {
|
||||||
|
if($opts->{'incfp'}) {
|
||||||
|
$out = '';
|
||||||
|
$out .= "Fingerprint (MD5): $opts->{'parsed'}->{'FINGERPRINTMD5'}\n";
|
||||||
|
$out .= "Fingerprint (SHA1): $opts->{'parsed'}->{'FINGERPRINTSHA1'}\n\n";
|
||||||
|
} else {
|
||||||
|
$out = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$out .= $opts->{'parsed'}->{'PEM'};
|
||||||
|
|
||||||
|
if($opts->{'include'}) {
|
||||||
|
open(IN, "<$opts->{'keyfile'}") || do {
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
$t = sprintf(_("Can't open Certificate file: %s: %s"),
|
||||||
|
$opts->{'keyfile'}, $!);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
$out .= "\n";
|
||||||
|
$out .= $_ while(<IN>);
|
||||||
|
close(IN);
|
||||||
|
}
|
||||||
|
} elsif ($opts->{'format'} eq 'DER') {
|
||||||
|
$out = $opts->{'parsed'}->{'DER'};
|
||||||
|
} elsif ($opts->{'format'} eq 'TXT') {
|
||||||
|
$out = $opts->{'parsed'}->{'TEXT'};
|
||||||
|
} elsif ($opts->{'format'} eq 'P12') {
|
||||||
|
unlink($opts->{'outfile'});
|
||||||
|
($ret, $ext) = $self->{'OpenSSL'}->genp12(
|
||||||
|
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'}
|
||||||
|
);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
|
||||||
|
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");
|
||||||
|
GUI::HELPERS::print_warning($t, $ext);
|
||||||
|
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")) {
|
||||||
|
|
||||||
|
my $tmpcert = "$main->{'tmpdir'}/cert.pem";
|
||||||
|
my $tmpkey = "$main->{'tmpdir'}/key.pem";
|
||||||
|
my $tmpcacert = "$main->{'tmpdir'}/cacert.pem";
|
||||||
|
|
||||||
|
open(OUT, ">$tmpcert") || do {
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
$t = sprintf(_("Can't create temporary file: %s: %s"),
|
||||||
|
$tmpcert, $!);
|
||||||
|
GUI::HELPERS::print_warning($t);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
print OUT $opts->{'parsed'}->{'PEM'};
|
||||||
|
close OUT;
|
||||||
|
|
||||||
|
# store key in temporary location
|
||||||
|
{
|
||||||
|
open(IN, "<$opts->{'keyfile'}") || do {
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
$t = sprintf(_("Can't read Key file: %s: %s"), $tmpcert, $!);
|
||||||
|
GUI::HELPERS::print_warning($t);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
my @key = <IN>;
|
||||||
|
close IN;
|
||||||
|
|
||||||
|
open(OUT, ">$tmpkey") || do {
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
$t = sprintf(_("Can't create temporary file: %s: %s"),
|
||||||
|
$tmpcert, $!);
|
||||||
|
GUI::HELPERS::print_warning($t);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
print OUT @key;
|
||||||
|
close OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
# store cacert in temporary location
|
||||||
|
{
|
||||||
|
open(IN, "<$opts->{'cafile'}") || do {
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
GUI::HELPERS::print_warning(_("Can't read CA certificate"));
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
my @cacert = <IN>;
|
||||||
|
close IN;
|
||||||
|
|
||||||
|
open(OUT, ">$tmpcacert") || do {
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
|
||||||
|
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 {
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
$t = sprintf(_("Invalid Format for export_cert(): %s"),
|
||||||
|
$opts->{'format'});
|
||||||
|
GUI::HELPERS::print_warning($t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
|
||||||
|
open(OUT, ">$opts->{'outfile'}") || do {
|
||||||
|
GUI::HELPERS::print_warning(_("Can't open output file: %s: %s"),
|
||||||
|
$opts->{'outfile'}, $!);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
print OUT $out;
|
||||||
|
close OUT;
|
||||||
|
|
||||||
|
$main->{'exportdir'} = HELPERS::write_export_dir($main,
|
||||||
|
$opts->{'outfile'});
|
||||||
|
|
||||||
|
$t = sprintf(_("Certificate successfully exported to: %s"),
|
||||||
|
$opts->{'outfile'});
|
||||||
|
GUI::HELPERS::print_info($t);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub reread_cert {
|
||||||
|
my ($self, $main, $name) = @_;
|
||||||
|
|
||||||
|
my ($parsed, $tmp);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 1);
|
||||||
|
|
||||||
|
$name = HELPERS::enc_base64($name);
|
||||||
|
|
||||||
|
$parsed = $self->parse_cert($main, $name, 1);
|
||||||
|
|
||||||
|
# print STDERR "DEBUG: status $parsed->{'STATUS'}\n";
|
||||||
|
|
||||||
|
foreach(@{$self->{'certlist'}}) {
|
||||||
|
if(/^$name%/) {
|
||||||
|
; #delete
|
||||||
|
} else {
|
||||||
|
push(@{$tmp}, $_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
push(@{$tmp}, $name."%".$parsed->{'STATUS'});
|
||||||
|
@{$tmp} = sort(@{$tmp});
|
||||||
|
|
||||||
|
delete($self->{'certlist'});
|
||||||
|
$self->{'certlist'} = $tmp;
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub parse_cert {
|
||||||
|
my ($self, $main, $name, $force) = @_;
|
||||||
|
|
||||||
|
my($ca, $certfile, $x509, $parsed);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 1);
|
||||||
|
|
||||||
|
$ca = $main->{'CA'}->{'actca'};
|
||||||
|
|
||||||
|
if($name eq 'CA') {
|
||||||
|
$certfile = $main->{'CA'}->{$ca}->{'dir'}."/cacert.pem";
|
||||||
|
} else {
|
||||||
|
$certfile = $main->{'CA'}->{$ca}->{'dir'}."/certs/".$name.".pem";
|
||||||
|
}
|
||||||
|
|
||||||
|
$parsed = $self->{'OpenSSL'}->parsecert(
|
||||||
|
$main->{'CA'}->{$ca}->{'dir'}."/crl/crl.pem",
|
||||||
|
$main->{'CA'}->{$ca}->{'dir'}."/index.txt",
|
||||||
|
$certfile,
|
||||||
|
$force
|
||||||
|
);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
|
||||||
|
return($parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
1
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,173 @@
|
||||||
|
# Copyright (c) Stephan Martin <sm@sm-zone.net>
|
||||||
|
#
|
||||||
|
# $Id: CALLBACK.pm,v 1.6 2006/06/28 21:50:42 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 GUI::CALLBACK;
|
||||||
|
|
||||||
|
use POSIX;
|
||||||
|
|
||||||
|
#
|
||||||
|
# fill given var-reference with text from entry
|
||||||
|
#
|
||||||
|
sub entry_to_var {
|
||||||
|
my ($widget, $entry, $var, $box, $words) = @_;
|
||||||
|
|
||||||
|
if(defined($words)) {
|
||||||
|
$$var = $words->{$entry->get_text()};
|
||||||
|
}else{
|
||||||
|
$$var = $entry->get_text();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(defined($box)) {
|
||||||
|
$box->{'button_ok'}->set_sensitive(1);
|
||||||
|
$box->{'button_apply'}->set_sensitive(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# fill given var-reference with text from entry subjectAltName
|
||||||
|
# and set senitivity of togglebuttons
|
||||||
|
#
|
||||||
|
sub entry_to_var_san {
|
||||||
|
my ($widget, $entry, $var, $box, $words, $radio1, $radio2, $radio3, $radio4) = @_;
|
||||||
|
|
||||||
|
if(defined($words)) {
|
||||||
|
if(my $tmp = $words->{$entry->get_text()}) {
|
||||||
|
$$var = $tmp;
|
||||||
|
} else {
|
||||||
|
$$var = $entry->get_text();
|
||||||
|
}
|
||||||
|
#print STDERR "DEBUG: var: $$var\n";
|
||||||
|
if($$var eq 'user') {
|
||||||
|
#print STDERR "set sensitive(1)\n";
|
||||||
|
$radio1->set_sensitive(1) if(defined($radio1));
|
||||||
|
$radio2->set_sensitive(1) if(defined($radio2));
|
||||||
|
$radio3->set_sensitive(1) if(defined($radio3));
|
||||||
|
$radio4->set_sensitive(1) if(defined($radio4));
|
||||||
|
}else{
|
||||||
|
#print STDERR "DEBUG: set sensitive(0)\n";
|
||||||
|
#print STDERR "DEBUG: r1 $radio1 r2 $radio2 r3 $radio3 r4 $radio4\n";
|
||||||
|
$radio1->set_sensitive(0) if(defined($radio1));
|
||||||
|
$radio2->set_sensitive(0) if(defined($radio2));
|
||||||
|
$radio3->set_sensitive(0) if(defined($radio3));
|
||||||
|
$radio4->set_sensitive(0) if(defined($radio4));
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
$$var = $entry->get_text();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(defined($box)) {
|
||||||
|
$box->{'button_ok'}->set_sensitive(1);
|
||||||
|
$box->{'button_apply'}->set_sensitive(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# fill given var-reference with text from entry subjectAltName
|
||||||
|
# and set senitivity of togglebuttons
|
||||||
|
#
|
||||||
|
sub entry_to_var_key {
|
||||||
|
my ($widget, $entry, $var, $box, $words, $radio1, $radio2, $radio3) = @_;
|
||||||
|
|
||||||
|
if(defined($words)) {
|
||||||
|
if(my $tmp = $words->{$entry->get_text()}) {
|
||||||
|
$$var = $tmp;
|
||||||
|
} else {
|
||||||
|
$$var = $entry->get_text();
|
||||||
|
}
|
||||||
|
if(($$var ne '') && ($$var ne 'none')) {
|
||||||
|
$radio1->set_sensitive(1) if(defined($radio1));
|
||||||
|
$radio2->set_sensitive(1) if(defined($radio2));
|
||||||
|
$radio3->set_sensitive(1) if(defined($radio3));
|
||||||
|
}else{
|
||||||
|
$radio1->set_sensitive(0) if(defined($radio1));
|
||||||
|
$radio2->set_sensitive(0) if(defined($radio2));
|
||||||
|
$radio3->set_sensitive(0) if(defined($radio3));
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
$$var = $entry->get_text();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(defined($box)) {
|
||||||
|
$box->{'button_ok'}->set_sensitive(1);
|
||||||
|
$box->{'button_apply'}->set_sensitive(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# fill given var-reference with value from togglebutton
|
||||||
|
#
|
||||||
|
sub toggle_to_var {
|
||||||
|
my ($button, $var, $value, $outfileref, $formatref, $fileentry, $pass1,
|
||||||
|
$pass2) = @_;
|
||||||
|
|
||||||
|
$$var = $value;
|
||||||
|
|
||||||
|
if(defined($outfileref) && defined($formatref)) {
|
||||||
|
if($$outfileref =~ s/\.(pem|der|txt|p12|zip|tar)$//i) {
|
||||||
|
$$outfileref .= "." . lc $$formatref;
|
||||||
|
# something seem broken, need tmp var
|
||||||
|
my $tmp = $$outfileref;
|
||||||
|
$fileentry->set_text($tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(defined($pass1) && defined($pass2)) {
|
||||||
|
if($$formatref eq "PEM") {
|
||||||
|
$pass1->set_sensitive(1);
|
||||||
|
$pass2->set_sensitive(1);
|
||||||
|
} elsif ($$formatref eq "DER") {
|
||||||
|
$pass1->set_sensitive(0);
|
||||||
|
$pass2->set_sensitive(0);
|
||||||
|
} elsif ($$formatref eq "P12") {
|
||||||
|
$pass1->set_sensitive(0);
|
||||||
|
$pass2->set_sensitive(0);
|
||||||
|
} elsif ($$formatref eq "ZIP") {
|
||||||
|
$pass1->set_sensitive(0);
|
||||||
|
$pass2->set_sensitive(0);
|
||||||
|
} elsif ($$formatref eq "TAR") {
|
||||||
|
$pass1->set_sensitive(0);
|
||||||
|
$pass2->set_sensitive(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# fill given var-reference with value from togglebutton
|
||||||
|
#
|
||||||
|
sub toggle_to_var_pref {
|
||||||
|
my ($button, $var, $value, $box) = @_;
|
||||||
|
|
||||||
|
$$var = $value;
|
||||||
|
|
||||||
|
if(defined($box) && defined($box->{'nb'}->get_current_page())) {
|
||||||
|
$box->{'button_ok'}->set_sensitive(1);
|
||||||
|
$box->{'button_apply'}->set_sensitive(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
1
|
||||||
|
|
|
@ -0,0 +1,479 @@
|
||||||
|
# Copyright (c) Stephan Martin <sm@sm-zone.net>
|
||||||
|
#
|
||||||
|
# $Id: HELPERS.pm,v 1.6 2006/06/28 21:50:42 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 GUI::HELPERS;
|
||||||
|
|
||||||
|
use POSIX;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Error message box, kills application
|
||||||
|
#
|
||||||
|
sub print_error {
|
||||||
|
my ($t, $ext) = @_;
|
||||||
|
|
||||||
|
my ($box, $button, $dbutton, $expander, $text, $scrolled, $buffer);
|
||||||
|
|
||||||
|
$button = Gtk2::Button->new_from_stock('gtk-ok');
|
||||||
|
$button->signal_connect('clicked', sub { HELPERS::exit_clean(1) });
|
||||||
|
$button->can_default(1);
|
||||||
|
|
||||||
|
$box = Gtk2::MessageDialog->new(
|
||||||
|
undef, [qw/destroy-with-parent modal/], 'error', 'none', $t);
|
||||||
|
$box->set_default_size(600, 0);
|
||||||
|
$box->set_resizable(1);
|
||||||
|
|
||||||
|
if(defined($ext)) {
|
||||||
|
$buffer = Gtk2::TextBuffer->new();
|
||||||
|
$buffer->set_text($ext);
|
||||||
|
|
||||||
|
$text = Gtk2::TextView->new_with_buffer($buffer);
|
||||||
|
$text->set_editable(0);
|
||||||
|
$text->set_wrap_mode('word');
|
||||||
|
|
||||||
|
$scrolled = Gtk2::ScrolledWindow->new(undef, undef);
|
||||||
|
$scrolled->set_policy('never', 'automatic');
|
||||||
|
$scrolled->set_shadow_type('etched-in');
|
||||||
|
$scrolled->add($text);
|
||||||
|
|
||||||
|
$expander = Gtk2::Expander->new(_("Command Details"));
|
||||||
|
$expander->add($scrolled);
|
||||||
|
$box->vbox->add($expander);
|
||||||
|
}
|
||||||
|
|
||||||
|
$box->add_action_widget($button, 0);
|
||||||
|
|
||||||
|
$box->show_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Warning message box
|
||||||
|
#
|
||||||
|
sub print_warning {
|
||||||
|
my ($t, $ext) = @_;
|
||||||
|
|
||||||
|
my ($box, $button, $dbutton, $expander, $text, $scrolled, $buffer);
|
||||||
|
|
||||||
|
$button = Gtk2::Button->new_from_stock('gtk-ok');
|
||||||
|
$button->signal_connect('clicked', sub { $box->destroy() });
|
||||||
|
$button->can_default(1);
|
||||||
|
|
||||||
|
$box = Gtk2::MessageDialog->new(
|
||||||
|
undef, [qw/destroy-with-parent modal/], 'warning', 'none', $t);
|
||||||
|
$box->set_default_size(600, 0);
|
||||||
|
$box->set_resizable(1);
|
||||||
|
|
||||||
|
if(defined($ext)) {
|
||||||
|
$buffer = Gtk2::TextBuffer->new();
|
||||||
|
$buffer->set_text($ext);
|
||||||
|
|
||||||
|
$text = Gtk2::TextView->new_with_buffer($buffer);
|
||||||
|
$text->set_editable(0);
|
||||||
|
$text->set_wrap_mode('word');
|
||||||
|
|
||||||
|
$scrolled = Gtk2::ScrolledWindow->new(undef, undef);
|
||||||
|
$scrolled->set_policy('never', 'automatic');
|
||||||
|
$scrolled->set_shadow_type('etched-in');
|
||||||
|
$scrolled->add($text);
|
||||||
|
|
||||||
|
$expander = Gtk2::Expander->new(_("Command Details"));
|
||||||
|
$expander->add($scrolled);
|
||||||
|
$box->vbox->add($expander);
|
||||||
|
}
|
||||||
|
$box->add_action_widget($button, 0);
|
||||||
|
|
||||||
|
$box->show_all();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Info message box
|
||||||
|
#
|
||||||
|
sub print_info {
|
||||||
|
my ($t, $ext) = @_;
|
||||||
|
|
||||||
|
my ($box, $button, $dbutton, $buffer, $text, $scrolled, $expander);
|
||||||
|
|
||||||
|
$button = Gtk2::Button->new_from_stock('gtk-ok');
|
||||||
|
$button->signal_connect('clicked', sub { $box->destroy() });
|
||||||
|
$button->can_default(1);
|
||||||
|
|
||||||
|
$box = Gtk2::MessageDialog->new(
|
||||||
|
undef, [qw/destroy-with-parent modal/], 'info', 'none', $t);
|
||||||
|
$box->set_default_size(600, 0);
|
||||||
|
$box->set_resizable(1);
|
||||||
|
|
||||||
|
if(defined($ext)) {
|
||||||
|
$buffer = Gtk2::TextBuffer->new();
|
||||||
|
$buffer->set_text($ext);
|
||||||
|
|
||||||
|
$text = Gtk2::TextView->new_with_buffer($buffer);
|
||||||
|
$text->set_editable(0);
|
||||||
|
$text->set_wrap_mode('word');
|
||||||
|
|
||||||
|
$scrolled = Gtk2::ScrolledWindow->new(undef, undef);
|
||||||
|
$scrolled->set_policy('never', 'automatic');
|
||||||
|
$scrolled->set_shadow_type('etched-in');
|
||||||
|
$scrolled->add($text);
|
||||||
|
|
||||||
|
$expander = Gtk2::Expander->new(_("Command Details"));
|
||||||
|
$expander->add($scrolled);
|
||||||
|
$box->vbox->add($expander);
|
||||||
|
}
|
||||||
|
$box->add_action_widget($button, 0);
|
||||||
|
|
||||||
|
$box->show_all();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# create standard dialog box
|
||||||
|
#
|
||||||
|
sub dialog_box {
|
||||||
|
my ($title, $text, $button1, $button2) = @_;
|
||||||
|
|
||||||
|
my $box = Gtk2::Dialog->new($title, undef, ["destroy-with-parent"]);
|
||||||
|
|
||||||
|
$box->add_action_widget($button1, 0);
|
||||||
|
|
||||||
|
if(defined($button2)) {
|
||||||
|
$box->add_action_widget($button2, 0);
|
||||||
|
$box->action_area->set_layout('spread');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(defined($text)) {
|
||||||
|
my $label = create_label($text, 'center', 0, 1);
|
||||||
|
$box->vbox->pack_start($label, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
$box->signal_connect(response => sub { $box->destroy });
|
||||||
|
|
||||||
|
return($box);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# create standard label
|
||||||
|
#
|
||||||
|
sub create_label {
|
||||||
|
my ($text, $mode, $wrap, $bold) = @_;
|
||||||
|
|
||||||
|
$text = "<b>$text</b>" if($bold);
|
||||||
|
|
||||||
|
my $label = Gtk2::Label->new($text);
|
||||||
|
|
||||||
|
$label->set_justify($mode);
|
||||||
|
if($mode eq 'center') {
|
||||||
|
$label->set_alignment(0.5, 0.5);
|
||||||
|
}elsif($mode eq 'left') {
|
||||||
|
$label->set_alignment(0, 0);
|
||||||
|
}elsif($mode eq 'right') {
|
||||||
|
$label->set_alignment(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$label->set_line_wrap($wrap);
|
||||||
|
|
||||||
|
$label->set_markup($text) if($bold);
|
||||||
|
|
||||||
|
return($label);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# write two labels to table
|
||||||
|
#
|
||||||
|
sub label_to_table {
|
||||||
|
my ($key, $val, $table, $row, $mode, $wrap, $bold) = @_;
|
||||||
|
|
||||||
|
my ($label, $entry);
|
||||||
|
|
||||||
|
$label = create_label($key, $mode, $wrap, $bold);
|
||||||
|
$label->set_padding(20, 0);
|
||||||
|
$table->attach_defaults($label, 0, 1, $row, $row+1);
|
||||||
|
|
||||||
|
$label = create_label($val, $mode, $wrap, $bold);
|
||||||
|
$label->set_padding(20, 0);
|
||||||
|
$table->attach_defaults($label, 1, 2, $row, $row+1);
|
||||||
|
|
||||||
|
$row++;
|
||||||
|
$table->resize($row, 2);
|
||||||
|
|
||||||
|
return($row);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# write label and entry to table
|
||||||
|
#
|
||||||
|
sub entry_to_table {
|
||||||
|
my ($text, $var, $table, $row, $visibility, $box) = @_;
|
||||||
|
|
||||||
|
my ($label, $entry);
|
||||||
|
|
||||||
|
$label = create_label($text, 'left', 0, 0);
|
||||||
|
$table->attach_defaults($label, 0, 1, $row, $row+1);
|
||||||
|
|
||||||
|
$entry = Gtk2::Entry->new();
|
||||||
|
$entry->set_text($$var) if(defined($$var));
|
||||||
|
|
||||||
|
$table->attach_defaults($entry, 1, 2, $row, $row+1);
|
||||||
|
$entry->signal_connect('changed' =>
|
||||||
|
sub {GUI::CALLBACK::entry_to_var($entry, $entry, $var, $box)} );
|
||||||
|
$entry->set_visibility($visibility);
|
||||||
|
|
||||||
|
return($entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# sort the table by the clicked column
|
||||||
|
#
|
||||||
|
sub sort_clist {
|
||||||
|
my ($clist, $col) = @_;
|
||||||
|
|
||||||
|
$clist->set_sort_column($col);
|
||||||
|
$clist->sort();
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub create_activity_bar {
|
||||||
|
my ($t) = @_;
|
||||||
|
|
||||||
|
my($box, $bar);
|
||||||
|
|
||||||
|
$box = Gtk2::MessageDialog->new(
|
||||||
|
undef, [qw/destroy-with-parent modal/], 'info', 'none', $t);
|
||||||
|
|
||||||
|
$bar = Gtk2::ProgressBar->new();
|
||||||
|
$bar->pulse();
|
||||||
|
$bar->set_pulse_step(0.1);
|
||||||
|
|
||||||
|
$box->vbox->add($bar);
|
||||||
|
|
||||||
|
$box->show_all();
|
||||||
|
|
||||||
|
return($box, $bar);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# set curser busy
|
||||||
|
#
|
||||||
|
sub set_cursor {
|
||||||
|
my $main = shift;
|
||||||
|
my $busy = shift;
|
||||||
|
|
||||||
|
if($busy) {
|
||||||
|
$main->{'rootwin'}->set_cursor($main->{'busycursor'});
|
||||||
|
} else {
|
||||||
|
$main->{'rootwin'}->set_cursor($main->{'cursor'});
|
||||||
|
}
|
||||||
|
while(Gtk2->events_pending) {
|
||||||
|
Gtk2->main_iteration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# call file chooser
|
||||||
|
#
|
||||||
|
sub browse_file {
|
||||||
|
my($title, $entry, $mode) = @_;
|
||||||
|
|
||||||
|
my($file_chooser, $filename, $filter);
|
||||||
|
|
||||||
|
$file_chooser = Gtk2::FileChooserDialog->new ($title, undef, $mode,
|
||||||
|
'gtk-cancel' => 'cancel',
|
||||||
|
'gtk-ok' => 'ok');
|
||||||
|
|
||||||
|
$file_chooser->add_shortcut_folder ('/tmp');
|
||||||
|
|
||||||
|
if($mode eq 'open') {
|
||||||
|
$filter = Gtk2::FileFilter->new();
|
||||||
|
$filter->set_name(_("Request Files (*.pem, *.der, *.req)"));
|
||||||
|
$filter->add_pattern("*.pem");
|
||||||
|
$filter->add_pattern("*.der");
|
||||||
|
$filter->add_pattern("*.req");
|
||||||
|
$file_chooser->add_filter($filter);
|
||||||
|
|
||||||
|
$filter = Gtk2::FileFilter->new();
|
||||||
|
$filter->set_name(_("All Files (*.*)"));
|
||||||
|
$filter->add_pattern("*");
|
||||||
|
$file_chooser->add_filter($filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('ok' eq $file_chooser->run) {
|
||||||
|
$filename = $file_chooser->get_filename();
|
||||||
|
$entry->set_text($filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
$file_chooser->destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# set text in statusbar
|
||||||
|
#
|
||||||
|
sub set_status {
|
||||||
|
my ($main, $t) = @_;
|
||||||
|
|
||||||
|
$main->{'bar'}->pop($main->{'lastid'}) if(defined($main->{'lastid'}));
|
||||||
|
$main->{'lastid'} = $main->{'bar'}->get_context_id('gargs');
|
||||||
|
$main->{'bar'}->push($main->{'lastid'}, $t);
|
||||||
|
}
|
||||||
|
|
||||||
|
1
|
||||||
|
|
||||||
|
__END__
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
GUI::HELPERS - helper functions for TinyCA, doing small jobs related to the
|
||||||
|
GUI
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
use GUI::HELPERS;
|
||||||
|
|
||||||
|
GUI::HELPERS::print_info($text, $ext);
|
||||||
|
GUI::HELPERS::print_warning($text, $ext);
|
||||||
|
GUI::HELPERS::print_error($text, $ext);
|
||||||
|
GUI::HELPERS::sort_clist($clist, $col);
|
||||||
|
GUI::HELPERS::set_cursor($main, $busy);
|
||||||
|
GUI::HELPERS::browse_file($main, $entry, $mode);
|
||||||
|
GUI::HELPERS::set_status($main, $text);
|
||||||
|
|
||||||
|
$box = GUI::HELPERS::dialog_box(
|
||||||
|
$title, $text, $button1, $button2);
|
||||||
|
$label = GUI::HELPERS::create_label(
|
||||||
|
$text, $mode, $wrap, $bold);
|
||||||
|
$row = GUI::HELPERS::label_to_table(
|
||||||
|
$key, $val, $table, $row, $mode, $wrap, $bold);
|
||||||
|
$entry = GUI::HELPERS::entry_to_table(
|
||||||
|
$text, $var, $table, $row, $visibility, $box);
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
GUI::HELPERS.pm is a library, containing some useful functions used by other
|
||||||
|
TinyCA2 modules. All functions are related to the GUI.
|
||||||
|
|
||||||
|
=head2 GUI::HELPERS::print_info($text, $ext);
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
creates an Gtk2::MessageDialog of the type info. The string given in $text is
|
||||||
|
shown as message, the (multiline) string $ext is available through the
|
||||||
|
"Details" Button.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 GUI::HELPERS::print_warning($text, $ext);
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
is identically with GUI::HELPERS::print_warning(), only the
|
||||||
|
Gtk2::MessageDialog is of type warning.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 GUI::HELPERS::print_error($text, $ext);
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
is identically with GUI::HELPERS::print_info(), only the Gtk2::MessageDialogog
|
||||||
|
is of type error and the program will shut down after closing the message.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 GUI::HELPERS::sort_clist($clist, $col);
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
sorts the clist with the values from the given column $col.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 GUI::HELPERS::dialog_box($title, $text, $button1, $button2);
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
returns the reference to a new window of type Gtk2::Dialog. $title and
|
||||||
|
$button1 must be given. $text and $button2 are optional arguments and can be
|
||||||
|
undef.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 GUI::HELPERS::create_label($text, $mode, $wrap, $bold);
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
returns the reference to a new Gtk2::Label. $mode can be "center", "left" or
|
||||||
|
"right". $wrap and $bold are boolean values.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 GUI::HELPERS::label_to_table($key, $val, $table, $row, $mode, $wrap, $bold);
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
adds a new row to $table. The new row is appended at $row and has two columns:
|
||||||
|
the first will contain a label with the content of string $k, the second the
|
||||||
|
content of string $v. $mode, $wrap, $bold are the arguments for
|
||||||
|
GUI::HELPERS::create_label(), mentioned above.
|
||||||
|
The function returns the number of the next free row in the table.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 GUI::HELPERS::entry_to_table($text, $var, $table, $row, $visibility, $box);
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
adds a new row to $table. The new row is appended at $row and has two columns:
|
||||||
|
the first will contain a label with the content of the string $text, the
|
||||||
|
second one will contain a textentry Gtk2::Entry, associated with the variable
|
||||||
|
$var. $visibility controls, if the entered text will be displayed or not
|
||||||
|
(passwords).
|
||||||
|
The function returns the reference to the new created entry.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 GUI::HELPERS::set_cursor($main, $busy);
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
sets the actual cursor to busy or back to normal. The value of $busy is
|
||||||
|
boolean.
|
||||||
|
This functions returns nothing;
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 GUI::HELPERS::browse_file($main, $entry, $mode);
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
opens a FileChooser dialog to select files or directories. $entry is a
|
||||||
|
reference to the variable, where the selected path shall be stored. If $mode
|
||||||
|
is set to "open", then only files with appropriate suffixes are displyed.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 GUI::HELPERS::set_status($main, $text);
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
sets the text in $text to the statusbar at the bottom of the window.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,112 @@
|
||||||
|
# Copyright (c) Stephan Martin <sm@sm-zone.net>
|
||||||
|
#
|
||||||
|
# $Id: WORDS.pm,v 1.2 2006/06/28 21:50:42 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 GUI::WORDS;
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my $that = shift;
|
||||||
|
|
||||||
|
my $self = {
|
||||||
|
'none' => _("Not set"),
|
||||||
|
'user' => _("Ask User"),
|
||||||
|
'critical' => _("critical"),
|
||||||
|
'noncritical' => _("not critical"),
|
||||||
|
'emailcopy' => _("Copy Email"),
|
||||||
|
'raw' => _("raw"),
|
||||||
|
'dns' => _("DNS Name"),
|
||||||
|
'ip' => _("IP Address"),
|
||||||
|
'mail' => _("Email"),
|
||||||
|
'server' => _("SSL Server"),
|
||||||
|
'server, client' => _("SSL Server, SSL Client"),
|
||||||
|
'key' => _("Key Encipherment"),
|
||||||
|
'sig' => _("Digital Signature"),
|
||||||
|
'keysig' => _("Key Encipherment, Digital Signature"),
|
||||||
|
'objsign' => _("Object Signing"),
|
||||||
|
'client, objsign' => _("SSL Client, Object Signing"),
|
||||||
|
'client, email' => _("SSL Client, Email(S/MIME)"),
|
||||||
|
'client' => _("SSL Client"),
|
||||||
|
'email' => _("Email(S/MIME)"),
|
||||||
|
'client, email, objsign'=> _("SSL Client, Email, Object Signing"),
|
||||||
|
'objCA' => _("Object Signing CA"),
|
||||||
|
'emailCA' => _("S/MIME CA"),
|
||||||
|
'sslCA' => _("SSL CA"),
|
||||||
|
'sslCA, emailCA' => _("SSL CA, S/MIME CA"),
|
||||||
|
'sslCA, objCA' => _("SSL CA, Object Signing CA"),
|
||||||
|
'emailCA, objCA' => _("S/MIME CA, Object Signing CA"),
|
||||||
|
'sslCA, emailCA, objCA' => _("SSL CA, S/MIME CA, Object Signing CA"),
|
||||||
|
'keyCertSign' => _("Certificate Signing"),
|
||||||
|
'cRLSign' => _("CRL Signing"),
|
||||||
|
'keyCertSign, cRLSign' => _("Certificate Signing, CRL Signing"),
|
||||||
|
'CN' => _("Common Name"),
|
||||||
|
'EMAIL' => _("eMail Address"),
|
||||||
|
'O' => _("Organization"),
|
||||||
|
'OU' => _("Organizational Unit"),
|
||||||
|
'L' => _("Location"),
|
||||||
|
'ST' => _("State"),
|
||||||
|
'C' => _("Country"),
|
||||||
|
'NOTBEFORE' => _("Creation Date"),
|
||||||
|
'NOTAFTER' => _("Expiration Date"),
|
||||||
|
'KEYSIZE' => _("Keylength"),
|
||||||
|
'PK_ALGORITHM' => _("Public Key Algorithm"),
|
||||||
|
'SIG_ALGORITHM' => _("Signature Algorithm"),
|
||||||
|
'TYPE' => _("Type"),
|
||||||
|
'SERIAL' => _("Serial"),
|
||||||
|
'STATUS' => _("Status"),
|
||||||
|
'FINGERPRINTMD5' => _("Fingerprint (MD5)"),
|
||||||
|
'FINGERPRINTSHA1' => _("Fingerprint (SHA1)"),
|
||||||
|
_("Not set") => 'none',
|
||||||
|
_("Ask User") => 'user',
|
||||||
|
_("critical") => 'critical',
|
||||||
|
_("not critical") => 'noncritical',
|
||||||
|
_("Copy Email") => 'emailcopy',
|
||||||
|
_("raw") => 'raw',
|
||||||
|
_("DNS Name") => 'dns',
|
||||||
|
_("Email") => 'email',
|
||||||
|
_("IP Address") => 'ip',
|
||||||
|
_("SSL Server") => 'server',
|
||||||
|
_("SSL Server, SSL Client") => 'server, client',
|
||||||
|
_("Key Encipherment") => 'key',
|
||||||
|
_("Digital Signature") => 'sig',
|
||||||
|
_("Key Encipherment, Digital Signature") => 'keysig',
|
||||||
|
_("Object Signing") => 'objsign',
|
||||||
|
_("Email(S/MIME)") => 'email',
|
||||||
|
_("SSL Client, Email(S/MIME)") => 'client, email',
|
||||||
|
_("SSL Client") => 'client',
|
||||||
|
_("SSL Client, Object Signing") => 'client, objsign',
|
||||||
|
_("SSL Client, Email, Object Signing") => 'client, email, objsign',
|
||||||
|
_("Object Signing CA") => 'objCA',
|
||||||
|
_("S/MIME CA") => 'emailCA',
|
||||||
|
_("SSL CA") => 'sslCA',
|
||||||
|
_("SSL CA, S/MIME CA") => 'sslCA, emailCA',
|
||||||
|
_("SSL CA, Object Signing CA") => 'sslCA, objCA',
|
||||||
|
_("S/MIME CA, Object Signing CA") => 'emailCA, objCA',
|
||||||
|
_("SSL CA, S/MIME CA, Object Signing CA")=> 'sslCA, emailCA, objCA',
|
||||||
|
_("Certificate Signing") => 'keyCertSign',
|
||||||
|
_("CRL Signing") => 'cRLSign',
|
||||||
|
_("Certificate Signing, CRL Signing") => 'keyCertSign, cRLSign'
|
||||||
|
};
|
||||||
|
|
||||||
|
my $class = ref($that) || $that;
|
||||||
|
|
||||||
|
bless($self, $class);
|
||||||
|
|
||||||
|
$self;
|
||||||
|
}
|
||||||
|
|
||||||
|
1
|
|
@ -0,0 +1,879 @@
|
||||||
|
# Copyright (c) Olaf Gellert <og@pre-secure.de> and
|
||||||
|
# Stephan Martin <sm@sm-zone.net>
|
||||||
|
#
|
||||||
|
# $Id: X509_browser.pm,v 1.6 2006/06/28 21:50:42 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 GUI::X509_browser;
|
||||||
|
|
||||||
|
use HELPERS;
|
||||||
|
use GUI::HELPERS;
|
||||||
|
use GUI::X509_infobox;
|
||||||
|
|
||||||
|
use POSIX;
|
||||||
|
|
||||||
|
my $tmpdefault="/tmp";
|
||||||
|
|
||||||
|
my $version = "0.1";
|
||||||
|
my $true = 1;
|
||||||
|
my $false = undef;
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my $that = shift;
|
||||||
|
my $self = {};
|
||||||
|
|
||||||
|
$self->{'main'} = shift;
|
||||||
|
my $mode = shift;
|
||||||
|
|
||||||
|
my ($font, $fontfix);
|
||||||
|
|
||||||
|
my $class = ref($that) || $that;
|
||||||
|
|
||||||
|
|
||||||
|
if ((defined $mode) &&
|
||||||
|
(($mode eq 'cert') || ($mode eq 'req') || ($mode eq 'key'))) {
|
||||||
|
$self->{'mode'} = $mode;
|
||||||
|
} else {
|
||||||
|
printf STDERR "No mode specified for X509browser\n";
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
# initialize fonts and styles
|
||||||
|
$font = Gtk2::Pango::FontDescription->from_string(
|
||||||
|
"-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*");
|
||||||
|
if(defined($font)) {
|
||||||
|
$self->{'stylebold'} = Gtk2::Style->new();
|
||||||
|
$self->{'stylebold'}->font_desc->from_string(
|
||||||
|
"-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*");
|
||||||
|
} else {
|
||||||
|
$self->{'stylebold'} = undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
$fontfix = Gtk2::Pango::FontDescription->from_string(
|
||||||
|
"-adobe-courier-medium-r-normal--*-100-*-*-*-*-*-*");
|
||||||
|
if(defined($fontfix)) {
|
||||||
|
$self->{'stylefix'} = Gtk2::Style->new();
|
||||||
|
$self->{'stylefix'}->font_desc->from_string(
|
||||||
|
"-adobe-courier-medium-r-normal--*-100-*-*-*-*-*-*");
|
||||||
|
} else {
|
||||||
|
$self->{'stylefix'} = undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
bless($self, $class);
|
||||||
|
|
||||||
|
$self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# sub create_window {
|
||||||
|
# my ($self, $title, $ok_text, $cancel_text,
|
||||||
|
# $ok_function, $cancel_function) = @_;
|
||||||
|
#
|
||||||
|
# my ($button_ok, $button_cancel);
|
||||||
|
#
|
||||||
|
# if ( $self->{'dialog_shown'} == $true ) {
|
||||||
|
# return(undef);
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# # check arguments
|
||||||
|
# if ($title eq undef) {
|
||||||
|
# $title = "CA browser, V$version";
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# if (not defined($ok_text)) {
|
||||||
|
# $ok_text = _("OK");
|
||||||
|
# }
|
||||||
|
# if (not defined($cancel_text)) {
|
||||||
|
# $cancel_text = _("Cancel");
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# # initialize main window
|
||||||
|
# $self->{'window'} = new Gtk::Dialog();
|
||||||
|
#
|
||||||
|
# # $self->{'window'}->set_policy($false,$false,$true);
|
||||||
|
#
|
||||||
|
# # store pointer to vbox as "browser widget"
|
||||||
|
# $self->{'browser'}=$self->{'window'}->vbox;
|
||||||
|
#
|
||||||
|
# if (defined $ok_function) {
|
||||||
|
# # todo: we should check if this is a function reference
|
||||||
|
# $self->{'User_OK_function'} = $ok_function;
|
||||||
|
# }
|
||||||
|
# $self->{'OK_function'} = sub { $self->ok_function(); };
|
||||||
|
#
|
||||||
|
# if (defined $cancel_function) {
|
||||||
|
# # todo: we should check if this is a function reference
|
||||||
|
# $self->{'User_CANCEL_function'} = $cancel_function;
|
||||||
|
# }
|
||||||
|
# $self->{'CANCEL_function'} = sub { $self->cancel_function(); };
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# $button_ok = new Gtk::Button( "$ok_text" );
|
||||||
|
# $button_ok->signal_connect( "clicked", $self->{'OK_function'});
|
||||||
|
# $self->{'window'}->action_area->pack_start( $button_ok, $true, $true, 0 );
|
||||||
|
#
|
||||||
|
# $button_cancel = new Gtk::Button( "$cancel_text" );
|
||||||
|
# $button_cancel->signal_connect('clicked', $self->{'CANCEL_function'});
|
||||||
|
# $self->{'window'}->action_area->pack_start( $button_cancel, $true, $true, 0 );
|
||||||
|
#
|
||||||
|
# $self->{'window'}->set_title( "$title" );
|
||||||
|
#
|
||||||
|
# $self->{'window'}->show_all();
|
||||||
|
#
|
||||||
|
# }
|
||||||
|
|
||||||
|
sub set_window {
|
||||||
|
my $self = shift;
|
||||||
|
my $widget = shift;
|
||||||
|
|
||||||
|
if ( (not defined $self->{'browser'}) || ( $self->{'browser'} == undef )) {
|
||||||
|
$self->{'browser'}=$widget;
|
||||||
|
} else {
|
||||||
|
# browser widget already exists
|
||||||
|
return $false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub add_list {
|
||||||
|
my ($self, $actca, $directory, $crlfile, $indexfile) = @_;
|
||||||
|
|
||||||
|
my ($x509listwin, @titles, @certtitles, @reqtitles, @keytitles, $column,
|
||||||
|
$color, $text, $iter, $renderer);
|
||||||
|
|
||||||
|
# printf STDERR "AddList: Self: $self, Dir $directory, CRL $crlfile, Index: $indexfile\n";
|
||||||
|
|
||||||
|
@reqtitles = (_("Common Name"),
|
||||||
|
_("eMail Address"),
|
||||||
|
_("Organizational Unit"),
|
||||||
|
_("Organization"),
|
||||||
|
_("Location"),
|
||||||
|
_("State"),
|
||||||
|
_("Country"));
|
||||||
|
|
||||||
|
@certtitles = (_("Common Name"),
|
||||||
|
_("eMail Address"),
|
||||||
|
_("Organizational Unit"),
|
||||||
|
_("Organization"),
|
||||||
|
_("Location"),
|
||||||
|
_("State"),
|
||||||
|
_("Country"),
|
||||||
|
_("Status"));
|
||||||
|
|
||||||
|
@keytitles = (_("Common Name"),
|
||||||
|
_("eMail Address"),
|
||||||
|
_("Organizational Unit"),
|
||||||
|
_("Organization"),
|
||||||
|
_("Location"),
|
||||||
|
_("State"),
|
||||||
|
_("Country"),
|
||||||
|
_("Type"));
|
||||||
|
|
||||||
|
$self->{'actca'} = $actca;
|
||||||
|
$self->{'actdir'} = $directory;
|
||||||
|
$self->{'actcrl'} = $crlfile;
|
||||||
|
$self->{'actindex'} = $indexfile;
|
||||||
|
|
||||||
|
if(defined($self->{'x509box'})) {
|
||||||
|
$self->{'browser'}->remove($self->{'x509box'});
|
||||||
|
$self->{'x509box'}->destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->{'x509box'} = Gtk2::VBox->new(0, 0);
|
||||||
|
|
||||||
|
# pane for list (top) and cert infos (bottom)
|
||||||
|
$self->{'x509pane'} = Gtk2::VPaned->new();
|
||||||
|
$self->{'x509pane'}->set_position(250);
|
||||||
|
$self->{'x509box'}->add($self->{'x509pane'});
|
||||||
|
|
||||||
|
$self->{'browser'}->pack_start($self->{'x509box'}, 1, 1, 0);
|
||||||
|
|
||||||
|
# now the list
|
||||||
|
$x509listwin = Gtk2::ScrolledWindow->new(undef, undef);
|
||||||
|
$x509listwin->set_policy('automatic', 'automatic');
|
||||||
|
$x509listwin->set_shadow_type('etched-in');
|
||||||
|
$self->{'x509pane'}->pack1($x509listwin, 1, 1);
|
||||||
|
|
||||||
|
# shall we display certificates, requests or keys?
|
||||||
|
if ((defined $self->{'mode'}) && ($self->{'mode'} eq "cert")) {
|
||||||
|
|
||||||
|
$self->{'x509store'} = Gtk2::ListStore->new(
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::Int');
|
||||||
|
|
||||||
|
@titles = @certtitles;
|
||||||
|
|
||||||
|
} elsif ((defined $self->{'mode'}) && ($self->{'mode'} eq "req")) {
|
||||||
|
|
||||||
|
$self->{'x509store'} = Gtk2::ListStore->new(
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::Int');
|
||||||
|
|
||||||
|
@titles = @reqtitles;
|
||||||
|
|
||||||
|
} elsif ((defined $self->{'mode'}) && ($self->{'mode'} eq "key")) {
|
||||||
|
|
||||||
|
$self->{'x509store'} = Gtk2::ListStore->new(
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::String',
|
||||||
|
'Glib::Int');
|
||||||
|
|
||||||
|
@titles = @keytitles;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
# undefined mode
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->{'x509store'}->set_sort_column_id(0, 'ascending');
|
||||||
|
|
||||||
|
$self->{'x509clist'} = Gtk2::TreeView->new_with_model($self->{'x509store'});
|
||||||
|
$self->{'x509clist'}->get_selection->set_mode ('single');
|
||||||
|
|
||||||
|
for(my $i = 0; $titles[$i]; $i++) {
|
||||||
|
$renderer = Gtk2::CellRendererText->new();
|
||||||
|
$column = Gtk2::TreeViewColumn->new_with_attributes(
|
||||||
|
$titles[$i], $renderer, 'text' => $i);
|
||||||
|
$column->set_sort_column_id($i);
|
||||||
|
$column->set_resizable(1);
|
||||||
|
if (($i == 7) && ($self->{'mode'} eq 'cert')) {
|
||||||
|
$column->set_cell_data_func ($renderer, sub {
|
||||||
|
my ($column, $cell, $model, $iter) = @_;
|
||||||
|
$text = $model->get($iter, 7);
|
||||||
|
$color = $text eq _("VALID")?'green':'red';
|
||||||
|
$cell->set (text => $text, foreground => $color);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$self->{'x509clist'}->append_column($column);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((defined $self->{'mode'}) && ($self->{'mode'} eq 'cert')) {
|
||||||
|
$self->{'x509clist'}->get_selection->signal_connect('changed' =>
|
||||||
|
sub { _fill_info($self, 'cert') });
|
||||||
|
} elsif ((defined $self->{'mode'}) && ($self->{'mode'} eq 'req')) {
|
||||||
|
$self->{'x509clist'}->get_selection->signal_connect('changed' =>
|
||||||
|
sub { _fill_info($self, 'req') });
|
||||||
|
}
|
||||||
|
|
||||||
|
$x509listwin->add($self->{'x509clist'});
|
||||||
|
|
||||||
|
update($self, $directory, $crlfile, $indexfile, $true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sub update {
|
||||||
|
my ($self, $directory, $crlfile, $indexfile, $force) = @_;
|
||||||
|
|
||||||
|
$self->{'actdir'} = $directory;
|
||||||
|
$self->{'actcrl'} = $crlfile;
|
||||||
|
$self->{'actindex'} = $indexfile;
|
||||||
|
|
||||||
|
# print STDERR "DEBUG: set new dir: $self->{'actdir'}\n";
|
||||||
|
|
||||||
|
if ($self->{'mode'} eq "cert") {
|
||||||
|
update_cert($self, $directory, $crlfile, $indexfile, $force);
|
||||||
|
} elsif ($self->{'mode'} eq "req") {
|
||||||
|
update_req($self, $directory, $crlfile, $indexfile, $force);
|
||||||
|
} elsif ($self->{'mode'} eq "key") {
|
||||||
|
update_key($self, $directory, $crlfile, $indexfile, $force);
|
||||||
|
} else {
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((defined $self->{'infowin'}) && ($self->{'infowin'} ne "")) {
|
||||||
|
update_info($self);
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->{'browser'}->show_all();
|
||||||
|
|
||||||
|
return($true);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub update_req {
|
||||||
|
my ($self, $directory, $crlfile, $indexfile, $force) = @_;
|
||||||
|
|
||||||
|
my ($ind, $name, $state, @line, $iter);
|
||||||
|
|
||||||
|
$self->{'main'}->{'REQ'}->read_reqlist(
|
||||||
|
$directory, $crlfile, $indexfile, $force, $self->{'main'});
|
||||||
|
|
||||||
|
$self->{'x509store'}->clear();
|
||||||
|
|
||||||
|
$ind = 0;
|
||||||
|
foreach my $n (@{$self->{'main'}->{'REQ'}->{'reqlist'}}) {
|
||||||
|
($name, $state) = split(/\%/, $n);
|
||||||
|
@line = split(/\:/, $name);
|
||||||
|
$iter = $self->{'x509store'}->append();
|
||||||
|
$self->{'x509store'}->set($iter,
|
||||||
|
0 => $line[0],
|
||||||
|
1 => $line[1],
|
||||||
|
2 => $line[2],
|
||||||
|
3 => $line[3],
|
||||||
|
4 => $line[4],
|
||||||
|
5 => $line[5],
|
||||||
|
6 => $line[6],
|
||||||
|
7 => $ind);
|
||||||
|
$ind++;
|
||||||
|
}
|
||||||
|
# now select the first row to display certificate informations
|
||||||
|
$self->{'x509clist'}->get_selection->select_path(
|
||||||
|
Gtk2::TreePath->new_first());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sub update_cert {
|
||||||
|
my ($self, $directory, $crlfile, $indexfile, $force) = @_;
|
||||||
|
|
||||||
|
my ($ind, $name, $state, @line, $iter);
|
||||||
|
|
||||||
|
$self->{'main'}->{'CERT'}->read_certlist(
|
||||||
|
$directory, $crlfile, $indexfile, $force, $self->{'main'});
|
||||||
|
|
||||||
|
$self->{'x509store'}->clear();
|
||||||
|
|
||||||
|
$ind = 0;
|
||||||
|
foreach my $n (@{$self->{'main'}->{'CERT'}->{'certlist'}}) {
|
||||||
|
($name, $state) = split(/\%/, $n);
|
||||||
|
@line = split(/\:/, $name);
|
||||||
|
$iter = $self->{'x509store'}->append();
|
||||||
|
$self->{'x509store'}->set($iter,
|
||||||
|
0 => $line[0],
|
||||||
|
1 => $line[1],
|
||||||
|
2 => $line[2],
|
||||||
|
3 => $line[3],
|
||||||
|
4 => $line[4],
|
||||||
|
5 => $line[5],
|
||||||
|
6 => $line[6],
|
||||||
|
7 => $state,
|
||||||
|
8 => $ind);
|
||||||
|
|
||||||
|
|
||||||
|
# $self->{'x509clist'}->set_text($row, 7, $state);
|
||||||
|
# if($state eq _("VALID")) {
|
||||||
|
# $self->{'x509clist'}->set_cell_style($row, 7, $self->{'stylegreen'});
|
||||||
|
# } else {
|
||||||
|
# $self->{'x509clist'}->set_cell_style($row, 7, $self->{'stylered'});
|
||||||
|
# }
|
||||||
|
# $self->{'x509clist'}->set_text($row, 8, $ind);
|
||||||
|
$ind++;
|
||||||
|
}
|
||||||
|
# now select the first row to display certificate informations
|
||||||
|
$self->{'x509clist'}->get_selection->select_path(
|
||||||
|
Gtk2::TreePath->new_first());
|
||||||
|
}
|
||||||
|
|
||||||
|
sub update_key {
|
||||||
|
my ($self, $directory, $crlfile, $indexfile, $force) = @_;
|
||||||
|
|
||||||
|
my ($ind, $name, @line, $iter, $state);
|
||||||
|
|
||||||
|
$self->{'main'}->{'KEY'}->read_keylist($self->{'main'});
|
||||||
|
|
||||||
|
$self->{'x509store'}->clear();
|
||||||
|
|
||||||
|
$ind = 0;
|
||||||
|
foreach my $n (@{$self->{'main'}->{'KEY'}->{'keylist'}}) {
|
||||||
|
($name, $state) = split(/\%/, $n);
|
||||||
|
@line = split(/\:/, $name);
|
||||||
|
$iter = $self->{'x509store'}->append();
|
||||||
|
$self->{'x509store'}->set($iter,
|
||||||
|
0 => $line[0],
|
||||||
|
1 => $line[1],
|
||||||
|
2 => $line[2],
|
||||||
|
3 => $line[3],
|
||||||
|
4 => $line[4],
|
||||||
|
5 => $line[5],
|
||||||
|
6 => $line[6],
|
||||||
|
7 => $state,
|
||||||
|
8 => $ind);
|
||||||
|
|
||||||
|
|
||||||
|
# $self->{'x509clist'}->set_text($row, 7, $state);
|
||||||
|
# if($state eq _("VALID")) {
|
||||||
|
# $self->{'x509clist'}->set_cell_style($row, 7, $self->{'stylegreen'});
|
||||||
|
# } else {
|
||||||
|
# $self->{'x509clist'}->set_cell_style($row, 7, $self->{'stylered'});
|
||||||
|
# }
|
||||||
|
# $self->{'x509clist'}->set_text($row, 8, $ind);
|
||||||
|
$ind++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub update_info {
|
||||||
|
my ($self)=@_;
|
||||||
|
|
||||||
|
my ($title, $parsed, $dn);
|
||||||
|
|
||||||
|
$dn = selection_dn($self);
|
||||||
|
|
||||||
|
if (defined $dn) {
|
||||||
|
$dn = HELPERS::enc_base64($dn);
|
||||||
|
|
||||||
|
if ($self->{'mode'} eq 'cert') {
|
||||||
|
$parsed = $self->{'main'}->{'CERT'}->parse_cert($self->{'main'},
|
||||||
|
$dn, $false);
|
||||||
|
$title = _("Certificate Information");
|
||||||
|
} else {
|
||||||
|
$parsed = $self->{'main'}->{'REQ'}->parse_req($self->{'main'}, $dn,
|
||||||
|
$false);
|
||||||
|
$title = _("Request Information");
|
||||||
|
}
|
||||||
|
|
||||||
|
defined($parsed) ||
|
||||||
|
GUI::HELPERS::print_error(_("Can't read file"));
|
||||||
|
|
||||||
|
if(not defined($self->{'infobox'})) {
|
||||||
|
$self->{'infobox'} = Gtk2::VBox->new();
|
||||||
|
}
|
||||||
|
|
||||||
|
# printf STDERR "DEBUG: Infowin: $self->{'infowin'}, infobox: $self->{'infobox'}\n";
|
||||||
|
$self->{'infowin'}->display($self->{'infobox'}, $parsed,
|
||||||
|
$self->{'mode'}, $title);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
# nothing selected
|
||||||
|
$self->{'infowin'}->hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# add infobox to the browser window
|
||||||
|
#
|
||||||
|
sub add_info {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my ($row, $index, $parsed, $title, $status, $list, $dn);
|
||||||
|
|
||||||
|
if ((defined $self->{'infowin'}) && ($self->{'infowin'} ne "")) {
|
||||||
|
$self->{'infowin'}->hide();
|
||||||
|
} else {
|
||||||
|
$self->{'infowin'} = GUI::X509_infobox->new();
|
||||||
|
}
|
||||||
|
|
||||||
|
# printf STDERR "Infowin: $self->{'infowin'}\n";
|
||||||
|
# printf STDERR "x509clist: $self->{'x509clist'}\n";
|
||||||
|
|
||||||
|
$row = $self->{'x509clist'}->get_selection->get_selected();
|
||||||
|
|
||||||
|
if(defined($row)) {
|
||||||
|
if ($self->{'mode'} eq 'cert') {
|
||||||
|
$index = ($self->{'x509store'}->get($row))[8];
|
||||||
|
$list = $self->{'main'}->{'CERT'}->{'certlist'};
|
||||||
|
} else {
|
||||||
|
$index = ($self->{'x509store'}->get($row))[7];
|
||||||
|
$list = $self->{'main'}->{'REQ'}->{'reqlist'};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined $index) {
|
||||||
|
($dn, $status) = split(/\%/, $list->[$index]);
|
||||||
|
$dn = HELPERS::enc_base64($dn);
|
||||||
|
|
||||||
|
if ($self->{'mode'} eq 'cert') {
|
||||||
|
$parsed = $self->{'main'}->{'CERT'}->parse_cert($self->{'main'}, $dn,
|
||||||
|
$false);
|
||||||
|
$title="Certificate Information";
|
||||||
|
} else {
|
||||||
|
$parsed = $self->{'main'}->{'REQ'}->parse_req($self->{'main'}, $dn,
|
||||||
|
$false);
|
||||||
|
$title="Request Information";
|
||||||
|
}
|
||||||
|
|
||||||
|
defined($parsed) || GUI::HELPERS::print_error(_("Can't read file"));
|
||||||
|
|
||||||
|
# printf STDERR "Infowin: $self->{'infowin'}\n";
|
||||||
|
$self->{'infobox'} = Gtk2::VBox->new();
|
||||||
|
$self->{'x509pane'}->pack2($self->{'infobox'}, 1, 1);
|
||||||
|
$self->{'infowin'}->display($self->{'infobox'}, $parsed, $self->{'mode'},
|
||||||
|
$title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub hide {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
$self->{'window'}->hide();
|
||||||
|
$self->{'dialog_shown'} = $false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub destroy {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
$self->{'window'}->destroy();
|
||||||
|
$self->{'dialog_shown'} = $false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# signal handler for selected list items
|
||||||
|
# (updates the X509_infobox window)
|
||||||
|
# XXX why is that function needed??
|
||||||
|
#
|
||||||
|
sub _fill_info {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
# print STDERR "DEBUG: fill_info: @_\n";
|
||||||
|
update_info($self) if (defined $self->{'infowin'});
|
||||||
|
}
|
||||||
|
|
||||||
|
sub selection_fname {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my ($selected, $row, $index, $dn, $status, $filename, $list);
|
||||||
|
|
||||||
|
$row = $self->{'x509clist'}->get_selection->get_selected();
|
||||||
|
|
||||||
|
return undef if (not defined $row);
|
||||||
|
|
||||||
|
if ($self->{'mode'} eq 'req') {
|
||||||
|
$index = ($self->{'x509store'}->get($row))[7];
|
||||||
|
$list = $self->{'main'}->{'REQ'}->{'reqlist'};
|
||||||
|
} elsif ($self->{'mode'} eq 'cert') {
|
||||||
|
$index = ($self->{'x509store'}->get($row))[8];
|
||||||
|
$list = $self->{'main'}->{'CERT'}->{'certlist'};
|
||||||
|
} elsif ($self->{'mode'} eq 'key') {
|
||||||
|
$index = ($self->{'x509store'}->get($row))[8];
|
||||||
|
$list = $self->{'main'}->{'KEY'}->{'certlist'};
|
||||||
|
} else {
|
||||||
|
GUI::HELPERS::print_error(
|
||||||
|
_("Invalid browser mode for selection_fname():"." "
|
||||||
|
.$self->{'mode'}));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (defined $index) {
|
||||||
|
($dn, $status) = split(/\%/, $list->[$index]);
|
||||||
|
$filename= HELPERS::enc_base64($dn);
|
||||||
|
$filename=$self->{'actdir'}."/$filename".".pem";
|
||||||
|
} else {
|
||||||
|
$filename = undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
return($filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub selection_dn {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my ($selected, $row, $index, $dn, $status, $list);
|
||||||
|
|
||||||
|
$row = $self->{'x509clist'}->get_selection->get_selected();
|
||||||
|
|
||||||
|
return undef if (not defined $row);
|
||||||
|
|
||||||
|
if ($self->{'mode'} eq 'req') {
|
||||||
|
$index = ($self->{'x509store'}->get($row))[7];
|
||||||
|
$list = $self->{'main'}->{'REQ'}->{'reqlist'};
|
||||||
|
} elsif ($self->{'mode'} eq 'cert') {
|
||||||
|
$index = ($self->{'x509store'}->get($row))[8];
|
||||||
|
$list = $self->{'main'}->{'CERT'}->{'certlist'};
|
||||||
|
} elsif ($self->{'mode'} eq 'key') {
|
||||||
|
$index = ($self->{'x509store'}->get($row))[8];
|
||||||
|
$list = $self->{'main'}->{'KEY'}->{'keylist'};
|
||||||
|
} else {
|
||||||
|
GUI::HELPERS::print_error(
|
||||||
|
_("Invalid browser mode for selection_dn():"." "
|
||||||
|
.$self->{'mode'}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined $index) {
|
||||||
|
($dn, $status) = split(/\%/, $list->[$index]);
|
||||||
|
} else {
|
||||||
|
$dn = undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
return($dn);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub selection_cadir {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my $dir;
|
||||||
|
|
||||||
|
$dir = $self->{'actdir'};
|
||||||
|
# cut off the last directory name to provide the ca-directory
|
||||||
|
$dir =~ s/\/certs|\/req|\/keys$//;
|
||||||
|
return($dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub selection_caname {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my ($selected, $caname);
|
||||||
|
|
||||||
|
$caname = $self->{'actca'};
|
||||||
|
return($caname);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub selection_cn {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my ($selected, $row, $index, $cn);
|
||||||
|
|
||||||
|
$row = $self->{'x509clist'}->get_selection->get_selected();
|
||||||
|
|
||||||
|
return undef if (not defined $row);
|
||||||
|
|
||||||
|
if (($self->{'mode'} eq 'req') ||
|
||||||
|
($self->{'mode'} eq 'cert')||
|
||||||
|
($self->{'mode'} eq 'key')) {
|
||||||
|
$cn = ($self->{'x509store'}->get($row))[0];
|
||||||
|
} else {
|
||||||
|
GUI::HELPERS::print_error(
|
||||||
|
_("Invalid browser mode for selection_cn():"." "
|
||||||
|
.$self->{'mode'}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return($cn);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub selection_email {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my ($selected, $row, $index, $email);
|
||||||
|
|
||||||
|
$row = $self->{'x509clist'}->get_selection->get_selected();
|
||||||
|
return undef if (not defined $row);
|
||||||
|
|
||||||
|
if (($self->{'mode'} eq 'req') ||
|
||||||
|
($self->{'mode'} eq 'cert') ||
|
||||||
|
($self->{'mode'} eq 'key')) {
|
||||||
|
$email = ($self->{'x509store'}->get($row))[1];
|
||||||
|
} else {
|
||||||
|
GUI::HELPERS::print_error(
|
||||||
|
_("Invalid browser mode for selection_cn():"." "
|
||||||
|
.$self->{'mode'}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return($email);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub selection_status {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my ($selected, $row, $index, $dn, $status, $list);
|
||||||
|
|
||||||
|
$row = $self->{'x509clist'}->get_selection->get_selected();
|
||||||
|
|
||||||
|
return undef if (not defined $row);
|
||||||
|
|
||||||
|
if ($self->{'mode'} eq 'cert') {
|
||||||
|
$index = ($self->{'x509store'}->get($row))[8];
|
||||||
|
$list = $self->{'main'}->{'CERT'}->{'certlist'};
|
||||||
|
} else {
|
||||||
|
GUI::HELPERS::print_error(
|
||||||
|
_("Invalid browser mode for selection_status():"." "
|
||||||
|
.$self->{'mode'}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined $index) {
|
||||||
|
($dn, $status) = split(/\%/, $list->[$index]);
|
||||||
|
} else {
|
||||||
|
$status = undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
return($status);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub selection_type {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my ($selected, $row, $index, $dn, $type, $list);
|
||||||
|
|
||||||
|
$row = $self->{'x509clist'}->get_selection->get_selected();
|
||||||
|
|
||||||
|
return undef if (not defined $row);
|
||||||
|
|
||||||
|
if ($self->{'mode'} eq 'key') {
|
||||||
|
$index = ($self->{'x509store'}->get($row))[8];
|
||||||
|
$list = $self->{'main'}->{'KEY'}->{'keylist'};
|
||||||
|
} else {
|
||||||
|
GUI::HELPERS::print_error(
|
||||||
|
_("Invalid browser mode for selection_type():"." "
|
||||||
|
.$self->{'mode'}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined $index) {
|
||||||
|
($dn, $type) = split(/\%/, $list->[$index]);
|
||||||
|
} else {
|
||||||
|
$type = undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
return($type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub ok_function {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
# is there a user defined ok_function?
|
||||||
|
if (defined $self->{'User_OK_function'}) {
|
||||||
|
$self->{'User_OK_function'}($self, selection_fname($self));
|
||||||
|
}
|
||||||
|
# otherwise do default
|
||||||
|
else {
|
||||||
|
printf STDOUT "%s\n", selection_fname($self);
|
||||||
|
$self->hide();
|
||||||
|
}
|
||||||
|
return $true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sub cancel_function {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
# is there a user defined ok_function?
|
||||||
|
if (defined $self->{'User_CANCEL_function'}) {
|
||||||
|
$self->{'User_CANCEL_function'}($self, get_listselect($self));
|
||||||
|
}
|
||||||
|
# otherwise do default
|
||||||
|
else {
|
||||||
|
$self->{'window'}->hide();
|
||||||
|
$self->{'dialog_shown'} = $false;
|
||||||
|
}
|
||||||
|
return $true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# sort the table by the clicked column
|
||||||
|
#
|
||||||
|
sub _sort_clist {
|
||||||
|
my ($clist, $col) = @_;
|
||||||
|
|
||||||
|
$clist->set_sort_column($col);
|
||||||
|
$clist->sort();
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# called on mouseclick in certlist
|
||||||
|
#
|
||||||
|
sub _show_cert_menu {
|
||||||
|
my ($clist, $self, $event) = @_;
|
||||||
|
|
||||||
|
if ((defined($event->{'type'})) &&
|
||||||
|
$event->{'button'} == 3) {
|
||||||
|
$self->{'certmenu'}->popup(
|
||||||
|
undef,
|
||||||
|
undef,
|
||||||
|
0,
|
||||||
|
$event->{'button'},
|
||||||
|
undef);
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
$true;
|
||||||
|
|
||||||
|
__END__
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
GUI::X509_browser - Perl-Gtk2 browser for X.509 certificates and requests
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
use X509_browser;
|
||||||
|
|
||||||
|
$browser=X509_browser->new($mode);
|
||||||
|
$browser->create_window($title, $oktext, $canceltext,
|
||||||
|
\&okayfunction, \&cancelfunction);
|
||||||
|
$browser->add_ca_select($cadir, @calist, $active-ca);
|
||||||
|
$browser->add_list($active-ca, $X509dir, $crlfile, $indexfile);
|
||||||
|
$browser->add_info();
|
||||||
|
my $selection = $browser->selection_fname();
|
||||||
|
$browser->hide();
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
This displays a browser for X.509v3 certificates or certification
|
||||||
|
requests (CSR) from a CA managed by TinyCA2 (or some similar
|
||||||
|
structure).
|
||||||
|
|
||||||
|
Creation of an X509_browser is done by calling B<new()>,
|
||||||
|
the argument has to be 'cert' or 'req' to display certificates
|
||||||
|
or requests.
|
||||||
|
|
||||||
|
A window can be created for this purpose using
|
||||||
|
B<create_window($title, $oktext, $canceltext, \&okfunction, \&cancelfunction)>,
|
||||||
|
all arguments are optional.
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
=item $title:
|
||||||
|
|
||||||
|
the existing Gtk2::VBox inside which the info will be
|
||||||
|
displayed.
|
||||||
|
|
||||||
|
=item $oktext:
|
||||||
|
|
||||||
|
The text to be displayed on the OK button of the dialog.
|
||||||
|
|
||||||
|
=item $canceltext:
|
||||||
|
|
||||||
|
The text to be displayed on the CANCEL button of the dialog.
|
||||||
|
|
||||||
|
=item \&okfunction:
|
||||||
|
|
||||||
|
Reference to a function that is executed on click on OK button.
|
||||||
|
This function should fetch the selected result (using
|
||||||
|
B<selection_fname()>) and also close the dialog using B<hide()>.
|
||||||
|
|
||||||
|
=item \&cancelfunction:
|
||||||
|
|
||||||
|
Reference to a function that is executed on click on CANCEL button.
|
||||||
|
This function should also close the dialog using B<hide()>.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
Further functions to get information about the selected item
|
||||||
|
exist, these are <B>selection_dn()</B>, <B>selection_status()</B>,
|
||||||
|
<B>selection_cadir()</B> and <B>selection_caname()</B>.
|
||||||
|
|
||||||
|
An existing infobox that already displays the content
|
||||||
|
of some directory can be modified by calling
|
||||||
|
<B>update()</B> with the same arguments that add_list().
|
||||||
|
|
||||||
|
An existing infobox is destroyed by calling B<destroy()>.
|
||||||
|
|
||||||
|
=cut
|
|
@ -0,0 +1,280 @@
|
||||||
|
# Copyright (c) Olaf Gellert <og@pre-secure.de> and
|
||||||
|
# Stephan Martin <sm@sm-zone.net>
|
||||||
|
#
|
||||||
|
# $Id: X509_infobox.pm,v 1.7 2006/06/28 21:50:42 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 GUI::X509_infobox;
|
||||||
|
|
||||||
|
use HELPERS;
|
||||||
|
use GUI::HELPERS;
|
||||||
|
use GUI::WORDS;
|
||||||
|
|
||||||
|
use POSIX;
|
||||||
|
|
||||||
|
my $version = "0.1";
|
||||||
|
my $true = 1;
|
||||||
|
my $false = undef;
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my $that = shift;
|
||||||
|
my $self = {};
|
||||||
|
|
||||||
|
my $class = ref($that) || $that;
|
||||||
|
|
||||||
|
$self->{'init'} = shift;
|
||||||
|
|
||||||
|
bless($self, $class);
|
||||||
|
|
||||||
|
$self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub display {
|
||||||
|
my ($self, $parent, $parsed, $mode, $title) = @_;
|
||||||
|
|
||||||
|
my ($bottombox, $textbox, $lefttable, $righttable, $leftbox, $rightbox,
|
||||||
|
@fields, $scrolled);
|
||||||
|
|
||||||
|
$self->{'root'} = $parent;
|
||||||
|
|
||||||
|
if (defined $self->{'child'}) {
|
||||||
|
$self->{'child'}->destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
# if title is given create a surrounding frame with the title
|
||||||
|
if (defined $title) {
|
||||||
|
$self->{'child'}= Gtk2::Frame->new($title);
|
||||||
|
$self->{'x509textbox'}= Gtk2::VBox->new(0,0);
|
||||||
|
$self->{'child'}->add($self->{'x509textbox'});
|
||||||
|
}
|
||||||
|
# otherwise we create the VBox directly inside the root widget
|
||||||
|
else {
|
||||||
|
$self->{'child'} = Gtk2::VBox->new(0,0);
|
||||||
|
$self->{'x509textbox'} = $self->{'child'};
|
||||||
|
}
|
||||||
|
|
||||||
|
# and pack it there
|
||||||
|
$self->{'root'}->pack_start($self->{'child'}, 1, 1, 0);
|
||||||
|
|
||||||
|
if (($mode eq 'cert') || ($mode eq 'cacert')) {
|
||||||
|
# fingerprint in the top of certtextbox
|
||||||
|
if(defined($self->{'certfingerprintmd5'})) {
|
||||||
|
$self->{'certfingerprintmd5'}->destroy();
|
||||||
|
}
|
||||||
|
$self->{'certfingerprintmd5'} = GUI::HELPERS::create_label(
|
||||||
|
_("Fingerprint (MD5)").": ".$parsed->{'FINGERPRINTMD5'},
|
||||||
|
'center', 0, 0);
|
||||||
|
$self->{'x509textbox'}->pack_start( $self->{'certfingerprintmd5'},
|
||||||
|
0, 0, 0);
|
||||||
|
|
||||||
|
if(defined($self->{'certfingerprintsha1'})) {
|
||||||
|
$self->{'certfingerprintsha1'}->destroy();
|
||||||
|
}
|
||||||
|
$self->{'certfingerprintsha1'} = GUI::HELPERS::create_label(
|
||||||
|
_("Fingerprint (SHA1)").": ".$parsed->{'FINGERPRINTSHA1'},
|
||||||
|
'center', 0, 0);
|
||||||
|
$self->{'x509textbox'}->pack_start($self->{'certfingerprintsha1'},
|
||||||
|
0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($mode eq 'cert') || ($mode eq 'cacert')) {
|
||||||
|
$bottombox = 'certbottombox';
|
||||||
|
$textbox = 'x509textbox';
|
||||||
|
$lefttable = 'certlefttable';
|
||||||
|
$leftbox = 'certleftbox';
|
||||||
|
$righttable = 'certrighttable';
|
||||||
|
$rightbox = 'certrightbox';
|
||||||
|
}else{
|
||||||
|
$bottombox = 'reqbottombox';
|
||||||
|
$textbox = 'x509textbox';
|
||||||
|
$lefttable = 'reqlefttable';
|
||||||
|
$leftbox = 'reqleftbox';
|
||||||
|
$righttable = 'reqrighttable';
|
||||||
|
$rightbox = 'reqrightbox';
|
||||||
|
}
|
||||||
|
|
||||||
|
# hbox in the bottom
|
||||||
|
if(defined($self->{$bottombox})) {
|
||||||
|
$self->{$bottombox}->destroy();
|
||||||
|
}
|
||||||
|
$self->{$bottombox} = Gtk2::HBox->new(1, 0);
|
||||||
|
$self->{$textbox}->pack_start($self->{$bottombox}, 1, 1, 5);
|
||||||
|
|
||||||
|
# vbox in the bottom/left
|
||||||
|
if(defined($self->{$lefttable})) {
|
||||||
|
$self->{$lefttable}->destroy();
|
||||||
|
}
|
||||||
|
@fields = qw( CN EMAIL O OU L ST C);
|
||||||
|
$self->{$lefttable} = _create_detail_table(\@fields, $parsed);
|
||||||
|
|
||||||
|
# the only widget i know to set shadow type :-(
|
||||||
|
$scrolled = Gtk2::ScrolledWindow->new();
|
||||||
|
$scrolled->set_shadow_type('etched-in');
|
||||||
|
$scrolled->set_policy('never', 'never');
|
||||||
|
|
||||||
|
$self->{$leftbox} = Gtk2::VBox->new(0, 0);
|
||||||
|
$self->{$bottombox}->pack_start($self->{$leftbox}, 1, 1, 0);
|
||||||
|
|
||||||
|
$self->{$leftbox}->pack_start($scrolled, 1, 1, 0);
|
||||||
|
$scrolled->add($self->{$lefttable});
|
||||||
|
|
||||||
|
# vbox in the bottom/right
|
||||||
|
if(defined($self->{$righttable})) {
|
||||||
|
$self->{$righttable}->destroy();
|
||||||
|
}
|
||||||
|
if ($mode eq "cacert") {
|
||||||
|
@fields = qw(SERIAL NOTBEFORE NOTAFTER KEYSIZE PK_ALGORITHM SIG_ALGORITHM
|
||||||
|
TYPE);
|
||||||
|
} else {
|
||||||
|
@fields = qw(STATUS SERIAL NOTBEFORE NOTAFTER KEYSIZE PK_ALGORITHM
|
||||||
|
SIG_ALGORITHM TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->{$righttable} = _create_detail_table(\@fields, $parsed);
|
||||||
|
|
||||||
|
$scrolled = Gtk2::ScrolledWindow->new();
|
||||||
|
$scrolled->set_shadow_type('etched-in');
|
||||||
|
$scrolled->set_policy('never', 'never');
|
||||||
|
|
||||||
|
$self->{$rightbox} = Gtk2::VBox->new(0, 0);
|
||||||
|
$self->{$bottombox}->pack_start($self->{$rightbox}, 1, 1, 0);
|
||||||
|
|
||||||
|
$self->{$rightbox}->pack_start($scrolled, 1, 1, 0);
|
||||||
|
$scrolled->add($self->{$righttable});
|
||||||
|
|
||||||
|
$self->{$textbox}->show_all();
|
||||||
|
|
||||||
|
$parent->show_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
sub hide {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
if (defined $self->{'child'}) {
|
||||||
|
$self->{'child'}->destroy();
|
||||||
|
undef $self->{'child'};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# create standard table with details (cert/req)
|
||||||
|
#
|
||||||
|
sub _create_detail_table {
|
||||||
|
my ($fields, $parsed) = @_;
|
||||||
|
|
||||||
|
my ($list, $store, $rows, $words, @l, $iter, $column, $renderer);
|
||||||
|
|
||||||
|
$words = GUI::WORDS->new();
|
||||||
|
|
||||||
|
$store = Gtk2::ListStore->new('Glib::String', 'Glib::String');
|
||||||
|
$list = Gtk2::TreeView->new_with_model($store);
|
||||||
|
$list->set_headers_visible(0);
|
||||||
|
$list->get_selection->set_mode('none');
|
||||||
|
|
||||||
|
$renderer = Gtk2::CellRendererText->new();
|
||||||
|
$column = Gtk2::TreeViewColumn->new_with_attributes(
|
||||||
|
'', $renderer, 'text' => 0);
|
||||||
|
$list->append_column($column);
|
||||||
|
|
||||||
|
$renderer = Gtk2::CellRendererText->new();
|
||||||
|
$column = Gtk2::TreeViewColumn->new_with_attributes(
|
||||||
|
'', $renderer, 'text' => 1);
|
||||||
|
$list->append_column($column);
|
||||||
|
|
||||||
|
|
||||||
|
foreach my $f (@{$fields}) {
|
||||||
|
if(defined($parsed->{$f})){
|
||||||
|
if(ref($parsed->{$f})) {
|
||||||
|
foreach(@{$parsed->{$f}}) {
|
||||||
|
$iter = $store->append();
|
||||||
|
$store->set($iter, 0 => $words->{$f}, 1 => $_);
|
||||||
|
# print STDERR "DEBUG: add line: @l\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
# print STDERR "DEBUG: add line: @l\n";
|
||||||
|
$iter = $store->append();
|
||||||
|
$store->set($iter, 0 => $words->{$f}, 1 => $parsed->{$f});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return($list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
1;
|
||||||
|
|
||||||
|
|
||||||
|
__END__
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
GUI::X509_infobox - show X.509 certificates and requests in a Gtk2::VBox
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
use X509_infobox;
|
||||||
|
|
||||||
|
$infobox=X509_infobox->new();
|
||||||
|
$infobox->update($parent,$parsed,$mode,$title);
|
||||||
|
$infobox->update($parent,$parsed,$mode);
|
||||||
|
$infobox->hide();
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
This displays the information of an X.509v3 certificate or
|
||||||
|
certification request (CSR) inside a given Gtk2::VBox.
|
||||||
|
|
||||||
|
Creation of an X509_infobox is done by calling B<new()>,
|
||||||
|
no arguments are required.
|
||||||
|
|
||||||
|
The infobox is shown when inserted into an already
|
||||||
|
existing Gtk2::VBox using the method B<update()>. Arguments
|
||||||
|
to update are:
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
=item $parent:
|
||||||
|
|
||||||
|
the existing Gtk2::VBox inside which the info will be
|
||||||
|
displayed.
|
||||||
|
|
||||||
|
=item $parsed:
|
||||||
|
|
||||||
|
a structure returned by OpenSSL::parsecert() or OpenSSL::parsecrl()
|
||||||
|
containing the required information.
|
||||||
|
|
||||||
|
=item $mode:
|
||||||
|
|
||||||
|
what type of information is to be displayed. Valid modes
|
||||||
|
are 'req' (certification request), 'cert' (certificate), 'key' or 'cacert'
|
||||||
|
(same as certificate but without displaying the validity information
|
||||||
|
of the cert because this cannot be decided on from the view of the
|
||||||
|
actual CA).
|
||||||
|
|
||||||
|
=item $title:
|
||||||
|
|
||||||
|
if specified, a surrounding frame with the given title
|
||||||
|
is drawn.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
An existing infobox is destroyed by calling B<hide()>.
|
||||||
|
|
||||||
|
=cut
|
|
@ -0,0 +1,393 @@
|
||||||
|
# Copyright (c) Olaf Gellert <og@pre-secure.de> and
|
||||||
|
# Stephan Martin <sm@sm-zone.net>
|
||||||
|
#
|
||||||
|
# $Id: HELPERS.pm,v 1.6 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 HELPERS;
|
||||||
|
|
||||||
|
use POSIX;
|
||||||
|
|
||||||
|
my $version = "0.1";
|
||||||
|
my $true = 1;
|
||||||
|
my $false = undef;
|
||||||
|
|
||||||
|
#
|
||||||
|
# generate filename from Subject-DN
|
||||||
|
#
|
||||||
|
sub gen_name {
|
||||||
|
my $opts = shift;
|
||||||
|
|
||||||
|
my $name = '';
|
||||||
|
|
||||||
|
foreach (qw(CN EMAIL OU O L ST C)) {
|
||||||
|
if((not defined($opts->{$_})) || ($opts->{$_} eq '')) {
|
||||||
|
$opts->{$_} = ".";
|
||||||
|
}
|
||||||
|
if($opts->{$_} ne '.' && not ref($opts->{$_})) {
|
||||||
|
$name .= $opts->{$_};
|
||||||
|
} elsif (ref($opts->{$_})) {
|
||||||
|
if(defined($opts->{$_}->[0])) {
|
||||||
|
$name .= $opts->{$_}->[0];
|
||||||
|
} else {
|
||||||
|
$name .= " ";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$name .= " ";
|
||||||
|
}
|
||||||
|
$name .= ":" if($_ ne 'C');
|
||||||
|
}
|
||||||
|
|
||||||
|
return($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# generate temporary filename
|
||||||
|
#
|
||||||
|
sub mktmp {
|
||||||
|
my $base = shift;
|
||||||
|
|
||||||
|
my @rand = ();
|
||||||
|
my $ret = '';
|
||||||
|
|
||||||
|
do {
|
||||||
|
for(my $i = 0; $i < 8; $i++) {
|
||||||
|
push(@rand, int(rand 26)+65);
|
||||||
|
}
|
||||||
|
my $end = pack("C8", @rand);
|
||||||
|
$ret = $base.$end;
|
||||||
|
} while (-e $ret);
|
||||||
|
|
||||||
|
return($ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# finished...
|
||||||
|
#
|
||||||
|
sub exit_clean {
|
||||||
|
my ($ret) = @_;
|
||||||
|
|
||||||
|
$ret = 0 unless(defined $ret);
|
||||||
|
|
||||||
|
# hack to avoid busy cursor
|
||||||
|
my $rootwin = Gtk2::Gdk->get_default_root_window();
|
||||||
|
my $cursor = Gtk2::Gdk::Cursor->new('left-ptr');
|
||||||
|
|
||||||
|
$rootwin->set_cursor($cursor);
|
||||||
|
|
||||||
|
Gtk2->main_quit();
|
||||||
|
exit($ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# split Subject DN and return hash
|
||||||
|
#
|
||||||
|
sub parse_dn {
|
||||||
|
my $dn = shift;
|
||||||
|
|
||||||
|
my (@dn, $k, $v, $tmp);
|
||||||
|
|
||||||
|
$tmp = {};
|
||||||
|
|
||||||
|
$dn =~ s/,/\//g;
|
||||||
|
|
||||||
|
@dn = split(/\//, $dn);
|
||||||
|
foreach(@dn) {
|
||||||
|
s/^\s+//;
|
||||||
|
s/\s+$//;
|
||||||
|
($k, $v) = split(/=/);
|
||||||
|
next if(not defined($k));
|
||||||
|
if($k =~ /ou/i) {
|
||||||
|
$tmp->{'OU'} or $tmp->{'OU'} = [];
|
||||||
|
push(@{$tmp->{'OU'}}, $v);
|
||||||
|
} else {
|
||||||
|
if($k =~ /emailaddress/i) {
|
||||||
|
$tmp->{'EMAIL'} = $v;
|
||||||
|
} else {
|
||||||
|
$tmp->{uc($k)} = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return($tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# parse (requested) X509 extensions and return hash
|
||||||
|
#
|
||||||
|
sub parse_extensions {
|
||||||
|
my ($lines, $mode) = @_;
|
||||||
|
|
||||||
|
my ($sep, $i, $k, $v, $tmp);
|
||||||
|
|
||||||
|
$sep = $mode eq "req"?"Requested extensions:":"X509v3 extensions:";
|
||||||
|
|
||||||
|
$tmp = {};
|
||||||
|
|
||||||
|
# skip everything before the extensions
|
||||||
|
for($i = 0; defined($lines->[$i]) && $lines->[$i] !~ /^[\s\t]*$sep$/i; $i++) {
|
||||||
|
return(undef) if not defined($lines->[$i]);
|
||||||
|
}
|
||||||
|
$i++;
|
||||||
|
|
||||||
|
while($i < @{$lines}) {
|
||||||
|
if(($lines->[$i] =~ /^[\s\t]*[^:]+:\s*$/) ||
|
||||||
|
($lines->[$i] =~ /^[\s\t]*[^:]+:\s+.+$/)) {
|
||||||
|
if($lines->[$i] =~ /^[\s\t]*Signature Algorithm/i) {
|
||||||
|
$i++;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
$k = $lines->[$i];
|
||||||
|
$k =~ s/[\s\t:]*$//g;
|
||||||
|
$k =~ s/^[\s\t]*//g;
|
||||||
|
$tmp->{$k} = [];
|
||||||
|
$i++;
|
||||||
|
while(($lines->[$i] !~ /^[\s\t].+:\s*$/) &&
|
||||||
|
($lines->[$i] !~ /^[\s\t]*[^:]+:\s+.+$/) &&
|
||||||
|
($lines->[$i] !~ /^[\s\t]*Signature Algorithm/i) &&
|
||||||
|
($i < @{$lines})) {
|
||||||
|
$v = $lines->[$i];
|
||||||
|
$v =~ s/^[\s]+//g;
|
||||||
|
$v =~ s/[\s]+$//g;
|
||||||
|
$i++;
|
||||||
|
next if $v =~ /^$/;
|
||||||
|
next if $v =~ /Signature Algorithm:/;
|
||||||
|
my @vs = split(/,/, $v);
|
||||||
|
foreach(@vs) {
|
||||||
|
$_ =~ s/^\s//;
|
||||||
|
$_ =~ s/\s$//;
|
||||||
|
push(@{$tmp->{$k}}, $_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return($tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# get last used export directory
|
||||||
|
#
|
||||||
|
sub get_export_dir {
|
||||||
|
my $main = shift;
|
||||||
|
|
||||||
|
open(EXPIN, "<$main->{'cadir'}/.exportdir") || return(undef);
|
||||||
|
my $dir = <EXPIN>;
|
||||||
|
chomp($dir);
|
||||||
|
|
||||||
|
return($dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# write last used export directory
|
||||||
|
#
|
||||||
|
sub write_export_dir {
|
||||||
|
my ($main, $dir) = @_;
|
||||||
|
|
||||||
|
$dir =~ s:/[^/]+$::;
|
||||||
|
|
||||||
|
open(EXPOUT, ">$main->{'cadir'}/.exportdir") || do {
|
||||||
|
my $t = sprintf(_("Can't write exportdir: %s, %s"),
|
||||||
|
"$main->{'cadir'}/.exportdir", $!);
|
||||||
|
GUI::HELPERS::print_warning($t);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
print EXPOUT "$dir\n";
|
||||||
|
|
||||||
|
close(EXPOUT);
|
||||||
|
|
||||||
|
return($dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# generate contents for subjectAltName
|
||||||
|
#
|
||||||
|
sub gen_subjectaltname_contents($@)
|
||||||
|
{
|
||||||
|
my $type = shift || '';
|
||||||
|
my @input = map { split/,\s*|\s+/, $_ } @_; # split on ',' and ' '
|
||||||
|
my %output = (); # uniq on the fly
|
||||||
|
|
||||||
|
if ($type) { # type given => use that one for all
|
||||||
|
foreach my $elem (@input) {
|
||||||
|
$output{$type.$elem} = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { # no type => use heuristigcs to guess type per element
|
||||||
|
foreach my $elem (@input) {
|
||||||
|
if ($elem =~ s/^(ip:|dns:)(.*)/$2/i) {
|
||||||
|
$type = uc($1);
|
||||||
|
} elsif ($elem =~ s/^(email:)(.*)/$2/i) {
|
||||||
|
$type = lc($1);
|
||||||
|
} else {
|
||||||
|
if ($elem =~ /^\d+\.\d+\.\d+\.\d+$/) { # it's an IP address
|
||||||
|
$type = 'IP:';
|
||||||
|
}
|
||||||
|
elsif ($elem =~ /^.+\@.+\.\w+$/) { # it's a mail address
|
||||||
|
$type = 'email:';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$type = 'DNS:' # otherwise it's a DNS name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$output{$type.$elem} = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(wantarray ? keys(%output) : join(', ', keys(%output)));
|
||||||
|
}
|
||||||
|
|
||||||
|
sub enc_base64 {
|
||||||
|
my $data = shift;
|
||||||
|
my $ret = MIME::Base64::encode($data, '');
|
||||||
|
$ret =~ tr/\/+/-_/;
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub dec_base64 {
|
||||||
|
my $data = shift;
|
||||||
|
$data =~ tr/-_/\/+/;
|
||||||
|
return MIME::Base64::decode($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
1
|
||||||
|
|
||||||
|
__END__
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
HELPERS - helper functions for TinyCA, doing small jobs not related to the GUI
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
use HELPERS;
|
||||||
|
|
||||||
|
$name = HELPERS::gen_name($opts);
|
||||||
|
$tmpnam = HELPERS::mktmp($base);
|
||||||
|
$dnhash = HELPERS::parse_dn($dnstring);
|
||||||
|
$exthash = HELPERS::parse_extensions($mode, $lines);
|
||||||
|
$subjaltname = HELPERS::gen_subjectaltname_contents($type, @list);
|
||||||
|
|
||||||
|
exit_clean($retcode);
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
HELPERS.pm is just a library, containing some useful functions used by other
|
||||||
|
TinyCA modules.
|
||||||
|
|
||||||
|
=head1 FUNCTIONS
|
||||||
|
|
||||||
|
=head2 HELPERS::gen_name($opts)
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
returns a string with the TinyCA filename for a certificate, request or key.
|
||||||
|
The filename is generated from the following parts of the Subject DN from the
|
||||||
|
related request or certificate if present:
|
||||||
|
|
||||||
|
CN EMAIL OU O L ST C
|
||||||
|
|
||||||
|
These parts need to be elements in the given options hash.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 HELPERS::mktmp($base)
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
returns a string, containing a uniqe filename starting with $base, which is
|
||||||
|
not existing yet.
|
||||||
|
|
||||||
|
$base needs to be an absolute path to allow HELPERS::mktmp() reliable check
|
||||||
|
that the filename is really uniqe.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 HELPERS::parse_dn($dnstring)
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
returns the reference to a hash containing all elements of the Subject DN,
|
||||||
|
given in $dnstring.
|
||||||
|
|
||||||
|
The element OU is included as an array refernce in the hash, with an array
|
||||||
|
containing all values of OU.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 HELPERS::parse_extensions($mode, $lines)
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
returns the reference to a hash containing all X509 extensions of the given
|
||||||
|
request or certificate.
|
||||||
|
|
||||||
|
The request or certificate is given in textform as an array reference
|
||||||
|
with the array containing one line per element.
|
||||||
|
|
||||||
|
$mode contains one of the strings "req" or "cert" depending on the type of the
|
||||||
|
data.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 HELPERS::exit_clean($retcode)
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
does nothing yet, than closing the Gtk application returning the exitcode
|
||||||
|
given in $retcode.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 $main->HELPERS::get_export_dir()
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
Get last used export directory.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 $main->HELPERS::write_export-dir($dir)
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
Store last used export directory
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 HELPERS::gen_subjectaltname_contents($type, @list)
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
Generate a string suitable for the use as subjhectAltname contets for OpenSSL.
|
||||||
|
|
||||||
|
If $Type is not empty create the contents of that type only,
|
||||||
|
otherwise use either the type prefix of the list elements or
|
||||||
|
the following heuristics to find the type for the appropriate elements:
|
||||||
|
|
||||||
|
If the element looks like an IP address in dotted quad notation set
|
||||||
|
then treat it as one.
|
||||||
|
If the element contains a '@' followed by a '.' and a sequence of letters
|
||||||
|
then treat the element as an email address.
|
||||||
|
In all other cases treat it as a DNS name.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
|
@ -0,0 +1,494 @@
|
||||||
|
# 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 POSIX;
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my $self = {};
|
||||||
|
my $that = shift;
|
||||||
|
my $class = ref($that) || $that;
|
||||||
|
|
||||||
|
bless($self, $class);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub key_change_passwd {
|
||||||
|
my ($self, $main, $file, $oldpass, $newpass) = @_;
|
||||||
|
my $opts = {};
|
||||||
|
my ($t, $ret, $ext);
|
||||||
|
|
||||||
|
my $inform = "DER";
|
||||||
|
my $outform = "PEM";
|
||||||
|
|
||||||
|
my($type);
|
||||||
|
|
||||||
|
# ckeck 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 RSA 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) {
|
||||||
|
$t = _("Generating key failed");
|
||||||
|
|
||||||
|
if($ext =~ /unable to load Private Key/) {
|
||||||
|
$t .= _("The password for your old CA Key is wrong");
|
||||||
|
}
|
||||||
|
GUI::HELPERS::print_warning(($t), $ext);
|
||||||
|
return($ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return($ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
1
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,777 @@
|
||||||
|
# Copyright (c) Stephan Martin <sm@sm-zone.net>
|
||||||
|
#
|
||||||
|
# $Id: REQ.pm,v 1.7 2006/06/28 21:50:42 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 REQ;
|
||||||
|
|
||||||
|
use POSIX;
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my $that = shift;
|
||||||
|
my $class = ref($that) || $that;
|
||||||
|
|
||||||
|
my $self = {};
|
||||||
|
|
||||||
|
$self->{'OpenSSL'} = shift;
|
||||||
|
|
||||||
|
bless($self, $class);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# check if all data for creating a new request is available
|
||||||
|
#
|
||||||
|
sub get_req_create {
|
||||||
|
my ($self, $main, $opts, $box) = @_;
|
||||||
|
|
||||||
|
$box->destroy() if(defined($box));
|
||||||
|
|
||||||
|
my ($name, $action, $parsed, $reqfile, $keyfile, $ca, $t);
|
||||||
|
|
||||||
|
$ca = $main->{'CA'}->{'actca'};
|
||||||
|
|
||||||
|
if(!(defined($opts)) || !(ref($opts))) {
|
||||||
|
if(defined($opts) && $opts eq "signserver") {
|
||||||
|
$opts = {};
|
||||||
|
$opts->{'sign'} = 1;
|
||||||
|
$opts->{'type'} = "server";
|
||||||
|
} elsif(defined($opts) && $opts eq "signclient") {
|
||||||
|
$opts = {};
|
||||||
|
$opts->{'sign'} = 1;
|
||||||
|
$opts->{'type'} = "client";
|
||||||
|
} elsif (defined($opts)) {
|
||||||
|
$t = sprintf(_("Strange value for 'opts': %s"), $opts);
|
||||||
|
GUI::HELPERS::print_error($t);
|
||||||
|
}
|
||||||
|
$opts->{'bits'} = 4096;
|
||||||
|
$opts->{'digest'} = 'sha1';
|
||||||
|
$opts->{'algo'} = 'rsa';
|
||||||
|
if(defined($opts) && $opts eq "sign") {
|
||||||
|
$opts->{'sign'} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$parsed = $main->{'CERT'}->parse_cert($main, 'CA');
|
||||||
|
|
||||||
|
defined($parsed) ||
|
||||||
|
GUI::HELPERS::print_error(_("Can't read CA certificate"));
|
||||||
|
|
||||||
|
# set defaults
|
||||||
|
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'};
|
||||||
|
}
|
||||||
|
my $cc = 0;
|
||||||
|
foreach my $ou (@{$parsed->{'OU'}}) {
|
||||||
|
$opts->{'OU'}->[$cc++] = $ou;
|
||||||
|
}
|
||||||
|
|
||||||
|
$main->show_req_dialog($opts);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((not defined($opts->{'CN'})) ||
|
||||||
|
($opts->{'CN'} eq "") ||
|
||||||
|
(not defined($opts->{'passwd'})) ||
|
||||||
|
($opts->{'passwd'} eq "")) {
|
||||||
|
$main->show_req_dialog($opts);
|
||||||
|
GUI::HELPERS::print_warning(
|
||||||
|
_("Please specify at least Common Name ")
|
||||||
|
._("and Password"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((not defined($opts->{'passwd2'})) ||
|
||||||
|
$opts->{'passwd'} ne $opts->{'passwd2'}) {
|
||||||
|
$main->show_req_dialog($opts);
|
||||||
|
GUI::HELPERS::print_warning(_("Passwords don't match"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$opts->{'C'} = uc($opts->{'C'});
|
||||||
|
|
||||||
|
if((defined $opts->{'C'}) &&
|
||||||
|
($opts->{'C'} ne "") &&
|
||||||
|
(length($opts->{'C'}) != 2)) {
|
||||||
|
$main->show_req_dialog($opts);
|
||||||
|
GUI::HELPERS::print_warning(
|
||||||
|
_("Country must be exact 2 letter code"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = HELPERS::gen_name($opts);
|
||||||
|
|
||||||
|
$opts->{'reqname'} = HELPERS::enc_base64($name);
|
||||||
|
|
||||||
|
$reqfile = $main->{'CA'}->{$ca}->{'dir'}."/req/".$opts->{'reqname'}.".pem";
|
||||||
|
$keyfile = $main->{'CA'}->{$ca}->{'dir'}."/keys/".$opts->{'reqname'}.".pem";
|
||||||
|
|
||||||
|
if(-s $reqfile || -s $keyfile) {
|
||||||
|
$main->show_req_overwrite_warning($opts);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->create_req($main, $opts);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# create new request and key
|
||||||
|
#
|
||||||
|
sub create_req {
|
||||||
|
my ($self, $main, $opts) = @_;
|
||||||
|
|
||||||
|
my($reqfile, $keyfile, $ca, $ret, $ext, $cadir);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 1);
|
||||||
|
|
||||||
|
$ca = $main->{'CA'}->{'actca'};
|
||||||
|
$cadir = $main->{'CA'}->{$ca}->{'dir'};
|
||||||
|
|
||||||
|
$reqfile = $cadir."/req/".$opts->{'reqname'}.".pem";
|
||||||
|
$keyfile = $cadir."/keys/".$opts->{'reqname'}.".pem";
|
||||||
|
|
||||||
|
($ret, $ext) = $self->{'OpenSSL'}->newkey(
|
||||||
|
'algo' => $opts->{'algo'},
|
||||||
|
'bits' => $opts->{'bits'},
|
||||||
|
'outfile' => $keyfile,
|
||||||
|
'pass' => $opts->{'passwd'}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (not -s $keyfile || $ret) {
|
||||||
|
unlink($keyfile);
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
GUI::HELPERS::print_warning(_("Generating key failed"), $ext);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my @dn = ( $opts->{'C'}, $opts->{'ST'}, $opts->{'L'}, $opts->{'O'} );
|
||||||
|
if(ref($opts->{'OU'})) {
|
||||||
|
foreach my $ou (@{$opts->{'OU'}}) {
|
||||||
|
push(@dn,$ou);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
push(@dn, $opts->{'OU'});
|
||||||
|
}
|
||||||
|
@dn = (@dn, $opts->{'CN'}, $opts->{'EMAIL'}, '', '');
|
||||||
|
($ret, $ext) = $self->{'OpenSSL'}->newreq(
|
||||||
|
'config' => $main->{'CA'}->{$ca}->{'cnf'},
|
||||||
|
'outfile' => $reqfile,
|
||||||
|
'keyfile' => $keyfile,
|
||||||
|
'digest' => $opts->{'digest'},
|
||||||
|
'pass' => $opts->{'passwd'},
|
||||||
|
'dn' => \@dn,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (not -s $reqfile || $ret) {
|
||||||
|
unlink($keyfile);
|
||||||
|
unlink($reqfile);
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
GUI::HELPERS::print_warning(_("Generating Request failed"), $ext);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $parsed = $self->parse_req($main, $opts->{'reqname'}, 1);
|
||||||
|
|
||||||
|
$main->{'reqbrowser'}->update($cadir."/req",
|
||||||
|
$cadir."/crl/crl.pem",
|
||||||
|
$cadir."/index.txt",
|
||||||
|
0);
|
||||||
|
|
||||||
|
$main->{'keybrowser'}->update($cadir."/keys",
|
||||||
|
$cadir."/crl/crl.pem",
|
||||||
|
$cadir."/index.txt",
|
||||||
|
0);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
|
||||||
|
if($opts->{'sign'}) {
|
||||||
|
$opts->{'reqfile'} = $reqfile;
|
||||||
|
$opts->{'passwd'} = undef; # to sign request, ca-password is needed
|
||||||
|
$self->get_sign_req($main, $opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# get name of requestfile to delete
|
||||||
|
#
|
||||||
|
sub get_del_req {
|
||||||
|
my ($self, $main) = @_;
|
||||||
|
|
||||||
|
my($reqname, $req, $reqfile, $row, $ind, $ca, $cadir);
|
||||||
|
|
||||||
|
$ca = $main->{'reqbrowser'}->selection_caname();
|
||||||
|
$cadir = $main->{'reqbrowser'}->selection_cadir();
|
||||||
|
|
||||||
|
if(not(defined($reqfile))) {
|
||||||
|
$req = $main->{'reqbrowser'}->selection_dn();
|
||||||
|
|
||||||
|
|
||||||
|
if(not defined($req)) {
|
||||||
|
GUI::HELPERS::print_info(_("Please select a Request first"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$reqname = HELPERS::enc_base64($req);
|
||||||
|
$reqfile = $cadir."/req/".$reqname.".pem";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(not -s $reqfile) {
|
||||||
|
GUI::HELPERS::print_warning(_("Request file not found"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$main->show_del_confirm($reqfile, 'req');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# now really delete the requestfile
|
||||||
|
#
|
||||||
|
sub del_req {
|
||||||
|
my ($self, $main, $file) = @_;
|
||||||
|
|
||||||
|
my ($ca, $cadir);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 1);
|
||||||
|
|
||||||
|
unlink($file);
|
||||||
|
|
||||||
|
$ca = $main->{'reqbrowser'}->selection_caname();
|
||||||
|
$cadir = $main->{'reqbrowser'}->selection_cadir();
|
||||||
|
|
||||||
|
$main->{'reqbrowser'}->update($cadir."/req",
|
||||||
|
$cadir."/crl/crl.pem",
|
||||||
|
$cadir."/index.txt",
|
||||||
|
0);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub read_reqlist {
|
||||||
|
my ($self, $reqdir, $crlfile, $indexfile, $force, $main) = @_;
|
||||||
|
|
||||||
|
my ($f, $modt, $d, $reqlist, $c, $p, $t);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 1);
|
||||||
|
|
||||||
|
$reqlist = [];
|
||||||
|
|
||||||
|
$modt = (stat($reqdir))[9];
|
||||||
|
|
||||||
|
if(defined($self->{'lastread'}) &&
|
||||||
|
$self->{'lastread'} >= $modt) {
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
opendir(DIR, $reqdir) || do {
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
GUI::HELPERS::print_warning(_("Can't open Request directory"));
|
||||||
|
return(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
while($f = readdir(DIR)) {
|
||||||
|
next if $f =~ /^\./;
|
||||||
|
$c++;
|
||||||
|
}
|
||||||
|
rewinddir(DIR);
|
||||||
|
|
||||||
|
$main->{'barbox'}->pack_start($main->{'progress'}, 0, 0, 0);
|
||||||
|
$main->{'progress'}->show();
|
||||||
|
while($f = readdir(DIR)) {
|
||||||
|
next if $f =~ /^\./;
|
||||||
|
$f =~ s/\.pem//;
|
||||||
|
$d = HELPERS::dec_base64($f);
|
||||||
|
next if not defined($d);
|
||||||
|
next if $d eq "";
|
||||||
|
push(@{$reqlist}, $d);
|
||||||
|
|
||||||
|
if(defined($main)) {
|
||||||
|
$t = sprintf(_(" Read Request: %s"), $d);
|
||||||
|
GUI::HELPERS::set_status($main, $t);
|
||||||
|
$p += 100/$c;
|
||||||
|
if($p/100 <= 1) {
|
||||||
|
$main->{'progress'}->set_fraction($p/100);
|
||||||
|
while(Gtk2->events_pending) {
|
||||||
|
Gtk2->main_iteration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
select(undef, undef, undef, 0.025);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@{$reqlist} = sort(@{$reqlist});
|
||||||
|
closedir(DIR);
|
||||||
|
|
||||||
|
delete($self->{'reqlist'});
|
||||||
|
$self->{'reqlist'} = $reqlist;
|
||||||
|
|
||||||
|
$self->{'lastread'} = time();
|
||||||
|
|
||||||
|
if(defined($main)) {
|
||||||
|
$main->{'progress'}->set_fraction(0);
|
||||||
|
$main->{'barbox'}->remove($main->{'progress'});
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(1); # got new list
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# get name of request to sign
|
||||||
|
#
|
||||||
|
sub get_sign_req {
|
||||||
|
my ($self, $main, $opts, $box) = @_;
|
||||||
|
|
||||||
|
my($time, $parsed, $ca, $cadir, $ext, $ret);
|
||||||
|
|
||||||
|
$box->destroy() if(defined($box));
|
||||||
|
|
||||||
|
$time = time();
|
||||||
|
$ca = $main->{'reqbrowser'}->selection_caname();
|
||||||
|
$cadir = $main->{'reqbrowser'}->selection_cadir();
|
||||||
|
|
||||||
|
if(not(defined($opts->{'reqfile'}))) {
|
||||||
|
$opts->{'req'} = $main->{'reqbrowser'}->selection_dn();
|
||||||
|
|
||||||
|
if(not defined($opts->{'req'})) {
|
||||||
|
GUI::HELPERS::print_info(_("Please select a Request first"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$opts->{'reqname'} = HELPERS::enc_base64($opts->{'req'});
|
||||||
|
$opts->{'reqfile'} = $cadir."/req/".$opts->{'reqname'}.".pem";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(not -s $opts->{'reqfile'}) {
|
||||||
|
GUI::HELPERS::print_warning(_("Request file not found"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((-s $cadir."/certs/".$opts->{'reqname'}.".pem") &&
|
||||||
|
(!(defined($opts->{'overwrite'})) || ($opts->{'overwrite'} ne 'true'))) {
|
||||||
|
$main->show_cert_overwrite_confirm($opts);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$parsed = $main->{'CERT'}->parse_cert($main, 'CA');
|
||||||
|
|
||||||
|
defined($parsed) ||
|
||||||
|
GUI::HELPERS::print_error(_("Can't read CA certificate"));
|
||||||
|
|
||||||
|
if(!defined($opts->{'passwd'})) {
|
||||||
|
$opts->{'days'} =
|
||||||
|
$main->{'TCONFIG'}->{$opts->{'type'}."_ca"}->{'default_days'};
|
||||||
|
|
||||||
|
if($opts->{'days'} > (($parsed->{'EXPDATE'}/86400) - ($time/86400))) {
|
||||||
|
$opts->{'days'} = int(($parsed->{'EXPDATE'}/86400) - ($time/86400));
|
||||||
|
}
|
||||||
|
|
||||||
|
$main->show_req_sign_dialog($opts);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((($time + ($opts->{'days'} * 86400)) > $parsed->{'EXPDATE'}) &&
|
||||||
|
(!(defined($opts->{'ignoredate'})) ||
|
||||||
|
$opts->{'ignoredate'} ne 'true')){
|
||||||
|
$main->show_req_date_warning($opts);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
# try to find message digest used for the request
|
||||||
|
$parsed = undef;
|
||||||
|
$parsed = $self->parse_req($main, $opts->{'reqname'}, 1);
|
||||||
|
defined($parsed) ||
|
||||||
|
GUI::HELPERS::print_error(_("Can't read Request file"));
|
||||||
|
|
||||||
|
if(defined($parsed->{'SIG_ALGORITHM'})) {
|
||||||
|
$opts->{'digest'} = $parsed->{'SIG_ALGORITHM'};
|
||||||
|
|
||||||
|
if($opts->{'digest'} =~ /^md2/) {
|
||||||
|
$opts->{'digest'} = "md2";
|
||||||
|
} elsif ($opts->{'digest'} =~ /^mdc2/) {
|
||||||
|
$opts->{'digest'} = "mdc2";
|
||||||
|
} elsif ($opts->{'digest'} =~ /^md4/) {
|
||||||
|
$opts->{'digest'} = "md4";
|
||||||
|
} elsif ($opts->{'digest'} =~ /^md5/) {
|
||||||
|
$opts->{'digest'} = "md5";
|
||||||
|
} elsif ($opts->{'digest'} =~ /^sha1/) {
|
||||||
|
$opts->{'digest'} = "sha1";
|
||||||
|
} elsif ($opts->{'digest'} =~ /^ripemd160/) {
|
||||||
|
$opts->{'digest'} = "ripemd160";
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$opts->{'digest'} = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
($ret, $ext) = $self->sign_req($main, $opts);
|
||||||
|
|
||||||
|
return($ret, $ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# now really sign the request
|
||||||
|
#
|
||||||
|
sub sign_req {
|
||||||
|
my ($self, $main, $opts) = @_;
|
||||||
|
|
||||||
|
my($serial, $certout, $certfile, $certfile2, $ca, $cadir, $ret, $t, $ext);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 1);
|
||||||
|
|
||||||
|
$ca = $main->{'reqbrowser'}->selection_caname();
|
||||||
|
$cadir = $main->{'reqbrowser'}->selection_cadir();
|
||||||
|
|
||||||
|
$serial = $cadir."/serial";
|
||||||
|
open(IN, "<$serial") || do {
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
GUI::HELPERS::print_warning(_("Can't read serial"));
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
$serial = <IN>;
|
||||||
|
chomp($serial);
|
||||||
|
close IN;
|
||||||
|
|
||||||
|
if(not defined($opts->{'nsSslServerName'})) {
|
||||||
|
$opts->{'nsSslServerName'} = 'none';
|
||||||
|
}
|
||||||
|
if(not defined($opts->{'nsRevocationUrl'})) {
|
||||||
|
$opts->{'nsRevocationUrl'} = 'none';
|
||||||
|
}
|
||||||
|
if(not defined($opts->{'nsRenewalUrl'})) {
|
||||||
|
$opts->{'nsRenewalUrl'} = 'none';
|
||||||
|
}
|
||||||
|
if(not defined($opts->{'subjectAltName'})) {
|
||||||
|
$opts->{'subjectAltName'} = 'none';
|
||||||
|
$opts->{'subjectAltNameType'} = 'none';
|
||||||
|
} else {
|
||||||
|
$opts->{'subjectAltNameType'} =
|
||||||
|
$main->{TCONFIG}->{$opts->{'type'}.'_cert'}->{'subjectAltNameType'};
|
||||||
|
}
|
||||||
|
if(not defined($opts->{'extendedKeyUsage'})) {
|
||||||
|
$opts->{'extendedKeyUsage'} = 'none';
|
||||||
|
$opts->{'extendedKeyUsageType'} = 'none';
|
||||||
|
} else {
|
||||||
|
$opts->{'extendedKeyUsageType'} =
|
||||||
|
$main->{TCONFIG}->{$opts->{'type'}.'_cert'}->{'extendedKeyUsageType'};
|
||||||
|
}
|
||||||
|
|
||||||
|
if(defined($opts->{'mode'}) && $opts->{'mode'} eq "sub") {
|
||||||
|
($ret, $ext) = $self->{'OpenSSL'}->signreq(
|
||||||
|
'mode' => $opts->{'mode'},
|
||||||
|
'config' => $main->{'CA'}->{$ca}->{'cnf'},
|
||||||
|
'reqfile' => $opts->{'reqfile'},
|
||||||
|
'keyfile' => $opts->{'keyfile'},
|
||||||
|
'cacertfile' => $opts->{'cacertfile'},
|
||||||
|
'outdir' => $opts->{'outdir'},
|
||||||
|
'days' => $opts->{'days'},
|
||||||
|
'parentpw' => $opts->{'parentpw'},
|
||||||
|
'caname' => "ca_ca",
|
||||||
|
'revocationurl' => $opts->{'nsRevocationUrl'},
|
||||||
|
'renewalurl' => $opts->{'nsRenewalUrl'},
|
||||||
|
'subjaltname' => $opts->{'subjectAltName'},
|
||||||
|
'subjaltnametype' => $opts->{'subjectAltNameType'},
|
||||||
|
'extendedkeyusage' => $opts->{'extendedKeyUsage'},
|
||||||
|
'extendedkeyusagetype' => $opts->{'extendedKeyUsageType'},
|
||||||
|
'noemaildn' => $opts->{'noemaildn'},
|
||||||
|
'digest' => $opts->{'digest'}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
($ret, $ext) = $self->{'OpenSSL'}->signreq(
|
||||||
|
'config' => $main->{'CA'}->{$ca}->{'cnf'},
|
||||||
|
'reqfile' => $opts->{'reqfile'},
|
||||||
|
'days' => $opts->{'days'},
|
||||||
|
'pass' => $opts->{'passwd'},
|
||||||
|
'caname' => $opts->{'type'}."_ca",
|
||||||
|
'sslservername' => $opts->{'nsSslServerName'},
|
||||||
|
'revocationurl' => $opts->{'nsRevocationUrl'},
|
||||||
|
'renewalurl' => $opts->{'nsRenewalUrl'},
|
||||||
|
'subjaltname' => $opts->{'subjectAltName'},
|
||||||
|
'subjaltnametype' => $opts->{'subjectAltNameType'},
|
||||||
|
'extendedkeyusage' => $opts->{'extendedKeyUsage'},
|
||||||
|
'extendedkeyusagetype' => $opts->{'extendedKeyUsageType'},
|
||||||
|
'noemaildn' => $opts->{'noemaildn'},
|
||||||
|
'digest' => $opts->{'digest'}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
|
||||||
|
if($ret eq 1) {
|
||||||
|
$t = _("Wrong CA password given\nSigning of the Request failed");
|
||||||
|
GUI::HELPERS::print_warning($t, $ext);
|
||||||
|
delete($opts->{$_}) foreach(keys(%$opts));
|
||||||
|
$opts = undef;
|
||||||
|
return;
|
||||||
|
} elsif($ret eq 2) {
|
||||||
|
$t = _("CA Key not found\nSigning of the Request failed");
|
||||||
|
GUI::HELPERS::print_warning($t, $ext);
|
||||||
|
delete($opts->{$_}) foreach(keys(%$opts));
|
||||||
|
$opts = undef;
|
||||||
|
return;
|
||||||
|
} elsif($ret eq 3) {
|
||||||
|
$t = _("Certificate already existing\nSigning of the Request failed");
|
||||||
|
GUI::HELPERS::print_warning($t, $ext);
|
||||||
|
delete($opts->{$_}) foreach(keys(%$opts));
|
||||||
|
$opts = undef;
|
||||||
|
return;
|
||||||
|
} elsif($ret eq 4) {
|
||||||
|
$t = _("Invalid IP Address given\nSigning of the Request failed");
|
||||||
|
GUI::HELPERS::print_warning($t, $ext);
|
||||||
|
delete($opts->{$_}) foreach(keys(%$opts));
|
||||||
|
$opts = undef;
|
||||||
|
return;
|
||||||
|
} elsif($ret) {
|
||||||
|
GUI::HELPERS::print_warning(
|
||||||
|
_("Signing of the Request failed"), $ext);
|
||||||
|
delete($opts->{$_}) foreach(keys(%$opts));
|
||||||
|
$opts = undef;
|
||||||
|
return($ret, $ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(defined($opts->{'mode'}) && $opts->{'mode'} eq "sub") {
|
||||||
|
$certout = $cadir."/newcerts/".$serial.".pem";
|
||||||
|
$certfile = $opts->{'outfile'};
|
||||||
|
$certfile2 = $cadir."/certs/".$opts->{'reqname'}.".pem";
|
||||||
|
} else {
|
||||||
|
$certout = $cadir."/newcerts/".$serial.".pem";
|
||||||
|
$certfile = $cadir."/certs/".$opts->{'reqname'}.".pem";
|
||||||
|
#print STDERR "DEBUG: write certificate to: ".$cadir."/certs/".$opts->{'reqname'}.".pem";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not -s $certout) {
|
||||||
|
GUI::HELPERS::print_warning(
|
||||||
|
_("Signing of the Request failed"), $ext);
|
||||||
|
delete($opts->{$_}) foreach(keys(%$opts));
|
||||||
|
$opts = undef;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
open(IN, "<$certout") || do {
|
||||||
|
GUI::HELPERS::print_warning(_("Can't read Certificate file"));
|
||||||
|
delete($opts->{$_}) foreach(keys(%$opts));
|
||||||
|
$opts = undef;
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
open(OUT, ">$certfile") || do {
|
||||||
|
GUI::HELPERS::print_warning(_("Can't write Certificate file"));
|
||||||
|
delete($opts->{$_}) foreach(keys(%$opts));
|
||||||
|
$opts = undef;
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
print OUT while(<IN>);
|
||||||
|
|
||||||
|
if(defined($opts->{'mode'}) && $opts->{'mode'} eq "sub") {
|
||||||
|
close OUT;
|
||||||
|
open(OUT, ">$certfile2") || do {
|
||||||
|
GUI::HELPERS::print_warning(_("Can't write Certificate file"));
|
||||||
|
delete($opts->{$_}) foreach(keys(%$opts));
|
||||||
|
$opts = undef;
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
seek(IN, 0, 0);
|
||||||
|
print OUT while(<IN>);
|
||||||
|
}
|
||||||
|
|
||||||
|
close IN; close OUT;
|
||||||
|
|
||||||
|
GUI::HELPERS::print_info(
|
||||||
|
_("Request signed succesfully.\nCertificate created"), $ext);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 1);
|
||||||
|
|
||||||
|
$main->{'CERT'}->reread_cert($main,
|
||||||
|
HELPERS::dec_base64($opts->{'reqname'}));
|
||||||
|
|
||||||
|
$main->{'certbrowser'}->update($cadir."/certs",
|
||||||
|
$cadir."/crl/crl.pem",
|
||||||
|
$cadir."/index.txt",
|
||||||
|
0);
|
||||||
|
|
||||||
|
delete($opts->{$_}) foreach(keys(%$opts));
|
||||||
|
$opts = undef;
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
|
||||||
|
return($ret, $ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# get informations/verifications to import request from file
|
||||||
|
#
|
||||||
|
sub get_import_req {
|
||||||
|
my ($self, $main, $opts, $box) = @_;
|
||||||
|
|
||||||
|
my ($ret, $ext, $der);
|
||||||
|
|
||||||
|
$box->destroy() if(defined($box));
|
||||||
|
|
||||||
|
my($ca, $parsed, $file, $format);
|
||||||
|
|
||||||
|
$ca = $main->{'CA'}->{'actca'};
|
||||||
|
|
||||||
|
if(not defined($opts)) {
|
||||||
|
$main->show_req_import_dialog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(not defined($opts->{'infile'})) {
|
||||||
|
$main->show_req_import_dialog();
|
||||||
|
GUI::HELPERS::print_warning(_("Please select a Request file first"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(not -s $opts->{'infile'}) {
|
||||||
|
$main->show_req_import_dialog();
|
||||||
|
GUI::HELPERS::print_warning(
|
||||||
|
_("Can't find Request file: ").$opts->{'infile'});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
open(IN, "<$opts->{'infile'}") || do {
|
||||||
|
GUI::HELPERS::print_warning(
|
||||||
|
_("Can't read Request file:").$opts->{'infile'});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
$opts->{'in'} .= $_ while(<IN>);
|
||||||
|
|
||||||
|
if($opts->{'in'} =~ /-BEGIN[\s\w]+CERTIFICATE REQUEST-/i) {
|
||||||
|
$format = "PEM";
|
||||||
|
$file = $opts->{'infile'};
|
||||||
|
} else {
|
||||||
|
$format = "DER";
|
||||||
|
}
|
||||||
|
|
||||||
|
if($format eq "DER") {
|
||||||
|
($ret, $der, $ext) = $opts->{'in'} = $self->{'OpenSSL'}->convdata(
|
||||||
|
'cmd' => 'req',
|
||||||
|
'data' => $opts->{'in'},
|
||||||
|
'inform' => 'DER',
|
||||||
|
'outform' => 'PEM'
|
||||||
|
);
|
||||||
|
|
||||||
|
if($ret) {
|
||||||
|
GUI::HELPERS::print_warning(
|
||||||
|
_("Error converting Request"), $ext);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$opts->{'tmpfile'} =
|
||||||
|
HELPERS::mktmp($self->{'OpenSSL'}->{'tmp'}."/import");
|
||||||
|
|
||||||
|
open(TMP, ">$opts->{'tmpfile'}") || do {
|
||||||
|
GUI::HELPERS::print_warning( _("Can't create temporary file: %s: %s"),
|
||||||
|
$opts->{'tmpfile'}, $!);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
print TMP $opts->{'in'};
|
||||||
|
close(TMP);
|
||||||
|
$file = $opts->{'tmpfile'};
|
||||||
|
}
|
||||||
|
|
||||||
|
$parsed = $self->{'OpenSSL'}->parsereq(
|
||||||
|
$main->{'CA'}->{$ca}->{'cnf'},
|
||||||
|
$file);
|
||||||
|
|
||||||
|
if(not defined($parsed)) {
|
||||||
|
unlink($opts->{'tmpfile'});
|
||||||
|
GUI::HELPERS::print_warning(_("Parsing Request failed"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$main->show_import_verification("req", $opts, $parsed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# import request
|
||||||
|
#
|
||||||
|
sub import_req {
|
||||||
|
my ($self, $main, $opts, $parsed, $box) = @_;
|
||||||
|
|
||||||
|
my ($ca, $cadir);
|
||||||
|
|
||||||
|
$box->destroy() if(defined($box));
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 1);
|
||||||
|
|
||||||
|
$ca = $main->{'reqbrowser'}->selection_caname();
|
||||||
|
$cadir = $main->{'reqbrowser'}->selection_cadir();
|
||||||
|
|
||||||
|
$opts->{'name'} = HELPERS::gen_name($parsed);
|
||||||
|
|
||||||
|
$opts->{'reqname'} = HELPERS::enc_base64($opts->{'name'});
|
||||||
|
|
||||||
|
$opts->{'reqfile'} = $cadir."/req/".$opts->{'reqname'}.".pem";
|
||||||
|
|
||||||
|
open(OUT, ">$opts->{'reqfile'}") || do {
|
||||||
|
unlink($opts->{'tmpfile'});
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
GUI::HELPERS::print_warning(_("Can't open output file: %s: %s"),
|
||||||
|
$opts->{'reqfile'}, $!);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
print OUT $opts->{'in'};
|
||||||
|
close OUT;
|
||||||
|
|
||||||
|
$main->{'reqbrowser'}->update($cadir."/req",
|
||||||
|
$cadir."/crl/crl.pem",
|
||||||
|
$cadir."/index.txt",
|
||||||
|
0);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub parse_req {
|
||||||
|
my ($self, $main, $name, $force) = @_;
|
||||||
|
|
||||||
|
my ($parsed, $ca, $reqfile, $req);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 1);
|
||||||
|
|
||||||
|
$ca = $main->{'CA'}->{'actca'};
|
||||||
|
|
||||||
|
$reqfile = $main->{'CA'}->{$ca}->{'dir'}."/req/".$name.".pem";
|
||||||
|
|
||||||
|
$parsed = $self->{'OpenSSL'}->parsereq($main->{'CA'}->{$ca}->{'cnf'},
|
||||||
|
$reqfile, $force);
|
||||||
|
|
||||||
|
GUI::HELPERS::set_cursor($main, 0);
|
||||||
|
|
||||||
|
return($parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
1
|
||||||
|
|
|
@ -0,0 +1,555 @@
|
||||||
|
# Copyright (c) Stephan Martin <sm@sm-zone.net>
|
||||||
|
#
|
||||||
|
# $Id: TCONFIG.pm,v 1.2 2006/06/28 21:50:42 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 TCONFIG;
|
||||||
|
|
||||||
|
use POSIX;
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my $self = {};
|
||||||
|
my $that = shift;
|
||||||
|
my $class = ref($that) || $that;
|
||||||
|
|
||||||
|
bless($self, $class);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub init_config {
|
||||||
|
my ($self, $main, $ca) = @_;
|
||||||
|
|
||||||
|
my($file, @lines, $i, $section, $l, $k, $v);
|
||||||
|
|
||||||
|
if(not defined($ca)) {
|
||||||
|
$ca = $main->{'CA'}->{'actca'};
|
||||||
|
}
|
||||||
|
if(not defined($ca)) {
|
||||||
|
GUI::HELPERS::print_warning(_("Please select a CA first"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $main->{'CA'}->{$ca}->{'cnf'};
|
||||||
|
|
||||||
|
open(IN, "<$file") || do {
|
||||||
|
GUI::HELPERS::print_warning(_("Can't open configuration"));
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
@lines = <IN>;
|
||||||
|
close IN;
|
||||||
|
chomp(@lines);
|
||||||
|
|
||||||
|
# clean old configuration
|
||||||
|
foreach $k (keys(%$self)) {
|
||||||
|
delete($self->{$k});
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach $l (@lines) {
|
||||||
|
next if $l =~ /^#/;
|
||||||
|
next if $l =~ /^$/;
|
||||||
|
next if $l =~ /^ *$/;
|
||||||
|
|
||||||
|
# find section
|
||||||
|
if($l =~ /\[\s*([^\s]+)\s*\]/) {
|
||||||
|
$section = $1;
|
||||||
|
} elsif ($l =~ /^([^\s\t]+)[\s\t]*=[\s\t]*([^\s\t]+.*)$/) {
|
||||||
|
if($section eq "ca" ||
|
||||||
|
$section eq "policy_client" ||
|
||||||
|
$section eq "policy_server" ||
|
||||||
|
$section eq "policy_ca" ||
|
||||||
|
$section eq "req" ||
|
||||||
|
$section eq "req_distinguished_name" ||
|
||||||
|
$section eq "v3_req" ||
|
||||||
|
$section eq "req_attributes") {
|
||||||
|
if(not defined($self->{$section})) {
|
||||||
|
$self->{$section} = [];
|
||||||
|
}
|
||||||
|
push(@{$self->{$section}}, $l);
|
||||||
|
} else {
|
||||||
|
$k = $1;
|
||||||
|
$v = $2;
|
||||||
|
# really ugly hack XXX
|
||||||
|
if($v =~ /ENV::(\w+)$/) {
|
||||||
|
$ENV{$1} = 'dummy';
|
||||||
|
}
|
||||||
|
if(not defined($self->{$section})) {
|
||||||
|
$self->{$section} = {};
|
||||||
|
}
|
||||||
|
$self->{$section}->{$k} = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# store nsSslServerName information
|
||||||
|
if(defined($self->{'server_cert'}->{'nsSslServerName'})) {
|
||||||
|
if($self->{'server_cert'}->{'nsSslServerName'}
|
||||||
|
=~ /ENV:/) {
|
||||||
|
$self->{'server_cert'}->{'nsSslServerName'} = 'user';
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
$self->{'server_cert'}->{'nsSslServerName'} = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
# store subjectAltName information
|
||||||
|
# ca
|
||||||
|
if(defined($self->{'v3_ca'}->{'subjectAltName'})) {
|
||||||
|
if($self->{'v3_ca'}->{'subjectAltName'} eq 'email:copy') {
|
||||||
|
$self->{'v3_ca'}->{'subjectAltName'} = 'emailcopy';
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
$self->{'v3_ca'}->{'subjectAltName'} = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
# server
|
||||||
|
if(defined($self->{'server_cert'}->{'subjectAltName'})) {
|
||||||
|
if($self->{'server_cert'}->{'subjectAltName'}
|
||||||
|
=~ /ENV:.*IP/) {
|
||||||
|
$self->{'server_cert'}->{'subjectAltNameType'} = 'ip';
|
||||||
|
$self->{'server_cert'}->{'subjectAltName'} = 'user';
|
||||||
|
}elsif($self->{'server_cert'}->{'subjectAltName'}
|
||||||
|
=~ /ENV:.*DNS/) {
|
||||||
|
$self->{'server_cert'}->{'subjectAltNameType'} = 'dns';
|
||||||
|
$self->{'server_cert'}->{'subjectAltName'} = 'user';
|
||||||
|
}elsif($self->{'server_cert'}->{'subjectAltName'}
|
||||||
|
=~ /ENV:.*RAW/) {
|
||||||
|
$self->{'server_cert'}->{'subjectAltNameType'} = 'raw';
|
||||||
|
$self->{'server_cert'}->{'subjectAltName'} = 'user';
|
||||||
|
}elsif($self->{'server_cert'}->{'subjectAltName'}
|
||||||
|
eq 'email:copy') {
|
||||||
|
$self->{'server_cert'}->{'subjectAltName'} = 'emailcopy';
|
||||||
|
$self->{'server_cert'}->{'subjectAltNameType'} = 'ip';
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
$self->{'server_cert'}->{'subjectAltNameType'} = 'ip';
|
||||||
|
$self->{'server_cert'}->{'subjectAltName'} = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
# client
|
||||||
|
if(defined($self->{'client_cert'}->{'subjectAltName'})) {
|
||||||
|
if($self->{'client_cert'}->{'subjectAltName'}
|
||||||
|
=~ /ENV:.*IP/) {
|
||||||
|
$self->{'client_cert'}->{'subjectAltNameType'} = 'ip';
|
||||||
|
$self->{'client_cert'}->{'subjectAltName'} = 'user';
|
||||||
|
}elsif($self->{'client_cert'}->{'subjectAltName'}
|
||||||
|
=~ /ENV:.*DNS/) {
|
||||||
|
$self->{'client_cert'}->{'subjectAltNameType'} = 'dns';
|
||||||
|
$self->{'client_cert'}->{'subjectAltName'} = 'user';
|
||||||
|
}elsif($self->{'client_cert'}->{'subjectAltName'}
|
||||||
|
=~ /ENV:.*EMAIL/) {
|
||||||
|
$self->{'client_cert'}->{'subjectAltNameType'} = 'mail';
|
||||||
|
$self->{'client_cert'}->{'subjectAltName'} = 'user';
|
||||||
|
}elsif($self->{'client_cert'}->{'subjectAltName'}
|
||||||
|
=~ /ENV:.*RAW/) {
|
||||||
|
$self->{'client_cert'}->{'subjectAltNameType'} = 'raw';
|
||||||
|
$self->{'client_cert'}->{'subjectAltName'} = 'user';
|
||||||
|
}elsif($self->{'client_cert'}->{'subjectAltName'}
|
||||||
|
eq 'email:copy') {
|
||||||
|
$self->{'client_cert'}->{'subjectAltName'} = 'emailcopy';
|
||||||
|
$self->{'client_cert'}->{'subjectAltNameType'} = 'ip';
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
$self->{'client_cert'}->{'subjectAltNameType'} = 'ip';
|
||||||
|
$self->{'client_cert'}->{'subjectAltName'} = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $sect ('server_cert', 'client_cert', 'v3_ca') {
|
||||||
|
# store nsRevocationUrl information
|
||||||
|
if(defined($self->{$sect}->{'nsRevocationUrl'})) {
|
||||||
|
if($self->{$sect}->{'nsRevocationUrl'}
|
||||||
|
=~ /ENV:/) {
|
||||||
|
$self->{$sect}->{'nsRevocationUrl'} = 'user';
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
$self->{$sect}->{'nsRevocationUrl'} = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
# store nsRenewalUrl information
|
||||||
|
if(defined($self->{$sect}->{'nsRenewalUrl'})) {
|
||||||
|
if($self->{$sect}->{'nsRenewalUrl'}
|
||||||
|
=~ /ENV:/) {
|
||||||
|
$self->{$sect}->{'nsRenewalUrl'} = 'user';
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
$self->{$sect}->{'nsRenewalUrl'} = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
# store extendedKeyUsage information
|
||||||
|
if(defined($self->{$sect}->{'extendedKeyUsage'})) {
|
||||||
|
if($self->{$sect}->{'extendedKeyUsage'} =~ /critical/) {
|
||||||
|
$self->{$sect}->{'extendedKeyUsageType'} = 'critical';
|
||||||
|
$self->{$sect}->{'extendedKeyUsage'} =~ s/critical\s*,\s*//;
|
||||||
|
}else {
|
||||||
|
$self->{$sect}->{'extendedKeyUsageType'} = 'noncritical';
|
||||||
|
}
|
||||||
|
if($self->{$sect}->{'extendedKeyUsage'}
|
||||||
|
=~ /ENV:/) {
|
||||||
|
$self->{$sect}->{'extendedKeyUsage'} = 'user';
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
$self->{$sect}->{'extendedKeyUsage'} = 'none';
|
||||||
|
$self->{$sect}->{'extendedKeyUsageType'} = 'noncritical';
|
||||||
|
}
|
||||||
|
|
||||||
|
# store keyUsage information
|
||||||
|
if(defined($self->{$sect}->{'keyUsage'})) {
|
||||||
|
if($self->{$sect}->{'keyUsage'} =~ /critical/) {
|
||||||
|
$self->{$sect}->{'keyUsageType'} = 'critical';
|
||||||
|
}else {
|
||||||
|
$self->{$sect}->{'keyUsageType'} = 'noncritical';
|
||||||
|
}
|
||||||
|
if($self->{$sect}->{'keyUsage'}
|
||||||
|
=~ /digitalSignature, keyEncipherment/) {
|
||||||
|
$self->{$sect}->{'keyUsage'} = 'keysig';
|
||||||
|
} elsif($self->{$sect}->{'keyUsage'}
|
||||||
|
=~ /digitalSignature/) {
|
||||||
|
$self->{$sect}->{'keyUsage'} = 'sig';
|
||||||
|
} elsif($self->{$sect}->{'keyUsage'}
|
||||||
|
=~ /keyEncipherment/) {
|
||||||
|
$self->{$sect}->{'keyUsage'} = 'key';
|
||||||
|
} elsif($self->{$sect}->{'keyUsage'}
|
||||||
|
=~ /keyCertSign, cRLSign/) {
|
||||||
|
$self->{$sect}->{'keyUsage'} = 'keyCertSign, cRLSign';
|
||||||
|
} elsif($self->{$sect}->{'keyUsage'}
|
||||||
|
=~ /keyCertSign/) {
|
||||||
|
$self->{$sect}->{'keyUsage'} = 'keyCertSign';
|
||||||
|
} elsif($self->{$sect}->{'keyUsage'}
|
||||||
|
=~ /cRLSign/) {
|
||||||
|
$self->{$sect}->{'keyUsage'} = 'cRLSign';
|
||||||
|
}else {
|
||||||
|
$self->{$sect}->{'keyUsage'} = 'none';
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
$self->{$sect}->{'keyUsage'} = 'none';
|
||||||
|
$self->{$sect}->{'keyUsageType'} = 'noncritical';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# hack to add new section to openssl.cnf, if old config
|
||||||
|
if(not defined($self->{'ca_ca'})) {
|
||||||
|
$self->{'ca_ca'} = $self->{'server_ca'};
|
||||||
|
$self->{'ca_ca'}->{'x509_extensions'} = "v3_ca";
|
||||||
|
$self->{'server_ca'}->{'x509_extensions'} = "server_cert";
|
||||||
|
|
||||||
|
$self->write_config($main, $ca);
|
||||||
|
}
|
||||||
|
if($self->{'server_ca'}->{'x509_extensions'} eq "v3_ca") {
|
||||||
|
$self->{'server_ca'}->{'x509_extensions'} = "server_cert";
|
||||||
|
$self->write_config($main, $ca);
|
||||||
|
}
|
||||||
|
|
||||||
|
# hack to add new option
|
||||||
|
if(not defined($self->{'ca_ca'}->{'unique_subject'})) {
|
||||||
|
$self->{'ca_ca'}->{'unique_subject'} = "yes";
|
||||||
|
|
||||||
|
$self->write_config($main, $ca);
|
||||||
|
}
|
||||||
|
if(not defined($self->{'server_ca'}->{'unique_subject'})) {
|
||||||
|
$self->{'server_ca'}->{'unique_subject'} = "yes";
|
||||||
|
|
||||||
|
$self->write_config($main, $ca);
|
||||||
|
}
|
||||||
|
if(not defined($self->{'client_ca'}->{'unique_subject'})) {
|
||||||
|
$self->{'client_ca'}->{'unique_subject'} = "yes";
|
||||||
|
|
||||||
|
$self->write_config($main, $ca);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub config_ca {
|
||||||
|
my ($self, $main, $ca) = @_;
|
||||||
|
|
||||||
|
my($action);
|
||||||
|
|
||||||
|
if(not defined($ca)) {
|
||||||
|
$ca = $main->{'CA'}->{'actca'};
|
||||||
|
}
|
||||||
|
if(not defined($ca)) {
|
||||||
|
GUI::HELPERS::print_warning(_("Can't get CA name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
$action = GUI::TCONFIG::show_config_ca($main, $ca);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub config_openssl {
|
||||||
|
my ($self, $main, $ca) = @_;
|
||||||
|
|
||||||
|
if(not defined($ca)) {
|
||||||
|
$ca = $main->{'CA'}->{'actca'};
|
||||||
|
}
|
||||||
|
if(not defined($ca)) {
|
||||||
|
GUI::HELPERS::print_warning(_("Can't get CA name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI::TCONFIG::show_configbox($main, $ca);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub write_config {
|
||||||
|
my ($self, $main, $ca) = @_;
|
||||||
|
|
||||||
|
my($file, @sections, $line, $sect, $key, $val, @opts);
|
||||||
|
|
||||||
|
# these sections are not configurable
|
||||||
|
@sections = qw(
|
||||||
|
ca
|
||||||
|
policy_client
|
||||||
|
policy_server
|
||||||
|
policy_ca
|
||||||
|
req
|
||||||
|
req_distinguished_name
|
||||||
|
v3_req
|
||||||
|
req_attributes
|
||||||
|
);
|
||||||
|
|
||||||
|
$file = $main->{'CA'}->{$ca}->{'cnf'};
|
||||||
|
|
||||||
|
open(OUT, ">$file") || do {
|
||||||
|
GUI::HELPERS::print_warning(_("Can't open configfile"));
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach $sect (@sections) {
|
||||||
|
print OUT "[ $sect ]\n";
|
||||||
|
foreach $line (@{$self->{$sect}}) {
|
||||||
|
print OUT "$line\n";
|
||||||
|
}
|
||||||
|
print OUT "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
# these sections are configurable
|
||||||
|
@sections = qw(
|
||||||
|
v3_ca
|
||||||
|
crl_ext
|
||||||
|
server_ca
|
||||||
|
client_ca
|
||||||
|
ca_ca
|
||||||
|
client_cert
|
||||||
|
server_cert
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach $sect (@sections) {
|
||||||
|
print OUT "[ $sect ]\n";
|
||||||
|
if($sect eq "v3_ca") {
|
||||||
|
@opts = qw(
|
||||||
|
subjectKeyIdentifier
|
||||||
|
authorityKeyIdentifier
|
||||||
|
basicConstraints
|
||||||
|
nsCertType
|
||||||
|
issuerAltName
|
||||||
|
nsComment
|
||||||
|
crlDistributionPoints
|
||||||
|
nsCaRevocationUrl
|
||||||
|
nsCaPolicyUrl
|
||||||
|
nsRevocationUrl
|
||||||
|
nsRenewalUrl
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach $key (@opts) {
|
||||||
|
if(defined($self->{$sect}->{$key}) &&
|
||||||
|
$self->{$sect}->{$key} ne '' &&
|
||||||
|
$self->{$sect}->{$key} ne 'none') {
|
||||||
|
print OUT "$key = $self->{$sect}->{$key}\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(defined($self->{$sect}->{'subjectAltName'})) {
|
||||||
|
if($self->{$sect}->{'subjectAltName'} eq 'emailcopy') {
|
||||||
|
print OUT "subjectAltName = email:copy\n";
|
||||||
|
} elsif($self->{$sect}->{'subjectAltName'} eq 'none') {
|
||||||
|
;# do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(defined($self->{$sect}->{'keyUsage'})) {
|
||||||
|
if($self->{$sect}->{'keyUsage'} eq 'keyCertSign') {
|
||||||
|
if($self->{$sect}->{'keyUsageType'} eq 'critical') {
|
||||||
|
print OUT "keyUsage = critical, keyCertSign\n";
|
||||||
|
} else {
|
||||||
|
print OUT "keyUsage = keyCertSign\n";
|
||||||
|
}
|
||||||
|
}elsif($self->{$sect}->{'keyUsage'} eq 'cRLSign') {
|
||||||
|
if($self->{$sect}->{'keyUsageType'} eq 'critical') {
|
||||||
|
print OUT "keyUsage = critical, cRLSign\n";
|
||||||
|
}else {
|
||||||
|
print OUT "keyUsage = cRLSign\n";
|
||||||
|
}
|
||||||
|
}elsif($self->{$sect}->{'keyUsage'} eq 'keyCertSign, cRLSign') {
|
||||||
|
if($self->{$sect}->{'keyUsageType'} eq 'critical') {
|
||||||
|
print OUT "keyUsage = critical, keyCertSign, cRLSign\n";
|
||||||
|
}else {
|
||||||
|
print OUT "keyUsage = keyCertSign, cRLSign\n";
|
||||||
|
}
|
||||||
|
}elsif($self->{$sect}->{'keyUsage'} eq 'none') {
|
||||||
|
;# do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elsif($sect eq "server_cert" ||
|
||||||
|
$sect eq "client_cert") {
|
||||||
|
@opts = qw(
|
||||||
|
basicConstraints
|
||||||
|
nsCertType
|
||||||
|
nsComment
|
||||||
|
subjectKeyIdentifier
|
||||||
|
authorityKeyIdentifier
|
||||||
|
issuerAltName
|
||||||
|
crlDistributionPoints
|
||||||
|
nsCaRevocationUrl
|
||||||
|
nsBaseUrl
|
||||||
|
nsCaPolicyUrl
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach $key (@opts) {
|
||||||
|
if(defined($self->{$sect}->{$key}) &&
|
||||||
|
$self->{$sect}->{$key} ne '' &&
|
||||||
|
$self->{$sect}->{$key} ne 'none') {
|
||||||
|
print OUT "$key = $self->{$sect}->{$key}\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(defined($self->{$sect}->{'nsSslServerName'})) {
|
||||||
|
if($self->{$sect}->{'nsSslServerName'} eq 'user') {
|
||||||
|
print OUT "nsSslServerName = \$ENV::NSSSLSERVERNAME\n";
|
||||||
|
} elsif($self->{$sect}->{'nsSslServerName'} eq 'none') {
|
||||||
|
;# do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(defined($self->{$sect}->{'nsRevocationUrl'})) {
|
||||||
|
if($self->{$sect}->{'nsRevocationUrl'} eq 'user') {
|
||||||
|
print OUT "nsRevocationUrl = \$ENV::NSREVOCATIONURL\n";
|
||||||
|
} elsif($self->{$sect}->{'nsRevocationUrl'} eq 'none') {
|
||||||
|
;# do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(defined($self->{$sect}->{'nsRenewalUrl'})) {
|
||||||
|
if($self->{$sect}->{'nsRenewalUrl'} eq 'user') {
|
||||||
|
print OUT "nsRenewalUrl = \$ENV::NSRENEWALURL\n";
|
||||||
|
} elsif($self->{$sect}->{'nsRenewalUrl'} eq 'none') {
|
||||||
|
;# do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(defined($self->{$sect}->{'subjectAltName'})) {
|
||||||
|
if($self->{$sect}->{'subjectAltName'} eq 'user') {
|
||||||
|
if($self->{$sect}->{'subjectAltNameType'} eq 'ip') {
|
||||||
|
print OUT "subjectAltName = \$ENV::SUBJECTALTNAMEIP\n";
|
||||||
|
} elsif($self->{$sect}->{'subjectAltNameType'} eq 'dns') {
|
||||||
|
print OUT "subjectAltName = \$ENV::SUBJECTALTNAMEDNS\n";
|
||||||
|
} elsif($self->{$sect}->{'subjectAltNameType'} eq 'mail') {
|
||||||
|
print OUT "subjectAltName = \$ENV::SUBJECTALTNAMEEMAIL\n";
|
||||||
|
} elsif($self->{$sect}->{'subjectAltNameType'} eq 'raw') {
|
||||||
|
print OUT "subjectAltName = \$ENV::SUBJECTALTNAMERAW\n";
|
||||||
|
}
|
||||||
|
} elsif($self->{$sect}->{'subjectAltName'} eq 'emailcopy') {
|
||||||
|
print OUT "subjectAltName = email:copy\n";
|
||||||
|
} elsif($self->{$sect}->{'subjectAltName'} eq 'none') {
|
||||||
|
;# do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(defined($self->{$sect}->{'keyUsage'})) {
|
||||||
|
if($self->{$sect}->{'keyUsage'} eq 'key') {
|
||||||
|
if($self->{$sect}->{'keyUsageType'} eq 'critical') {
|
||||||
|
print OUT "keyUsage = critical, keyEncipherment\n";
|
||||||
|
} else {
|
||||||
|
print OUT "keyUsage = keyEncipherment\n";
|
||||||
|
}
|
||||||
|
}elsif($self->{$sect}->{'keyUsage'} eq 'sig') {
|
||||||
|
if($self->{$sect}->{'keyUsageType'} eq 'critical') {
|
||||||
|
print OUT "keyUsage = critical, digitalSignature\n";
|
||||||
|
}else {
|
||||||
|
print OUT "keyUsage = digitalSignature\n";
|
||||||
|
}
|
||||||
|
}elsif($self->{$sect}->{'keyUsage'} eq 'keysig') {
|
||||||
|
if($self->{$sect}->{'keyUsageType'} eq 'critical') {
|
||||||
|
print OUT "keyUsage = critical, digitalSignature, keyEncipherment\n";
|
||||||
|
}else {
|
||||||
|
print OUT "keyUsage = digitalSignature, keyEncipherment\n";
|
||||||
|
}
|
||||||
|
}elsif($self->{$sect}->{'keyUsage'} eq 'none') {
|
||||||
|
;# do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(defined($self->{$sect}->{'extendedKeyUsage'})) {
|
||||||
|
if(($self->{$sect}->{'extendedKeyUsage'} ne 'none') &&
|
||||||
|
($self->{$sect}->{'extendedKeyUsage'} ne '')) {
|
||||||
|
if($self->{$sect}->{'extendedKeyUsage'} eq 'user') {
|
||||||
|
if($self->{$sect}->{'extendedKeyUsageType'} eq 'critical') {
|
||||||
|
print OUT "extendedKeyUsage = critical, \$ENV::EXTENDEDKEYUSAGE\n";
|
||||||
|
} else {
|
||||||
|
print OUT "extendedKeyUsage = \$ENV::EXTENDEDKEYUSAGE\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if($self->{$sect}->{'extendedKeyUsageType'} eq 'critical') {
|
||||||
|
print OUT "extendedKeyUsage = critical, $self->{$sect}->{'extendedKeyUsage'}\n";
|
||||||
|
} else {
|
||||||
|
print OUT "extendedKeyUsage = $self->{$sect}->{'extendedKeyUsage'}\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elsif ($self->{$sect}->{'extendedKeyUsage'} eq 'none') {
|
||||||
|
;# do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elsif(($sect eq "server_ca") ||
|
||||||
|
($sect eq "client_ca") ||
|
||||||
|
($sect eq "ca_ca")) {
|
||||||
|
@opts = qw(
|
||||||
|
dir
|
||||||
|
certs
|
||||||
|
crl_dir
|
||||||
|
database
|
||||||
|
new_certs_dir
|
||||||
|
certificate
|
||||||
|
serial
|
||||||
|
crl
|
||||||
|
private_key
|
||||||
|
RANDFILE
|
||||||
|
x509_extensions
|
||||||
|
default_days
|
||||||
|
default_crl_days
|
||||||
|
default_md
|
||||||
|
preserve
|
||||||
|
policy
|
||||||
|
unique_subject
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach $key (@opts) {
|
||||||
|
if(defined($self->{$sect}->{$key}) &&
|
||||||
|
$self->{$sect}->{$key} ne '' &&
|
||||||
|
$self->{$sect}->{$key} ne 'none') {
|
||||||
|
print OUT "$key = $self->{$sect}->{$key}\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while(($key, $val) = each(%{$self->{$sect}})) {
|
||||||
|
if(defined($val) && $val ne "") {
|
||||||
|
print OUT "$key = $val\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print OUT "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
close OUT;
|
||||||
|
|
||||||
|
# print STDERR "DEBUG: wrote config and reinit\n";
|
||||||
|
# $self->init_config($main, $ca);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
1
|
|
@ -0,0 +1,25 @@
|
||||||
|
POTFILES=$(wildcard ../lib/*.pm) $(wildcard ../lib/GUI/*.pm) ../tinyca2
|
||||||
|
CATALOGS=de.mo es.mo cs.mo fr.mo sv.mo
|
||||||
|
|
||||||
|
all: $(CATALOGS)
|
||||||
|
|
||||||
|
.po.mo:
|
||||||
|
msgfmt -o $@ $<
|
||||||
|
install -m 644 $@ ../locale/`basename $@ .mo`/LC_MESSAGES/tinyca2.mo
|
||||||
|
|
||||||
|
%.po: tinyca2.pot
|
||||||
|
msgmerge -vU $@ tinyca2.pot
|
||||||
|
|
||||||
|
tinyca2.pot: $(POTFILES)
|
||||||
|
xgettext --add-comments \
|
||||||
|
--keyword=_ \
|
||||||
|
--keyword=N_ \
|
||||||
|
--language=C \
|
||||||
|
-o tinyca2.pot \
|
||||||
|
$(POTFILES); \
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(CATALOGS)
|
||||||
|
rm -f tinyca2.pot
|
||||||
|
|
||||||
|
.SUFFIXES: .po .pot .mo
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,147 @@
|
||||||
|
[ ca ]
|
||||||
|
default_ca = server_ca
|
||||||
|
|
||||||
|
[ client_ca ]
|
||||||
|
dir = %dir%
|
||||||
|
certs = $dir/certs
|
||||||
|
crl_dir = $dir/crl
|
||||||
|
database = $dir/index.txt
|
||||||
|
new_certs_dir = $dir/newcerts
|
||||||
|
certificate = $dir/cacert.pem
|
||||||
|
serial = $dir/serial
|
||||||
|
crl = $dir/crl.pem
|
||||||
|
private_key = $dir/cacert.key
|
||||||
|
RANDFILE = $dir/.rand
|
||||||
|
x509_extensions = client_cert
|
||||||
|
default_days = 365
|
||||||
|
default_crl_days= 30
|
||||||
|
default_md = sha1
|
||||||
|
preserve = no
|
||||||
|
policy = policy_client
|
||||||
|
|
||||||
|
[ server_ca ]
|
||||||
|
dir = %dir%
|
||||||
|
certs = $dir/certs
|
||||||
|
crl_dir = $dir/crl
|
||||||
|
database = $dir/index.txt
|
||||||
|
new_certs_dir = $dir/newcerts
|
||||||
|
certificate = $dir/cacert.pem
|
||||||
|
serial = $dir/serial
|
||||||
|
crl = $dir/crl.pem
|
||||||
|
private_key = $dir/cacert.key
|
||||||
|
RANDFILE = $dir/.rand
|
||||||
|
x509_extensions = server_cert
|
||||||
|
default_days = 365
|
||||||
|
default_crl_days= 30
|
||||||
|
default_md = sha1
|
||||||
|
preserve = no
|
||||||
|
policy = policy_server
|
||||||
|
|
||||||
|
[ ca_ca ]
|
||||||
|
dir = %dir%
|
||||||
|
certs = $dir/certs
|
||||||
|
crl_dir = $dir/crl
|
||||||
|
database = $dir/index.txt
|
||||||
|
new_certs_dir = $dir/newcerts
|
||||||
|
certificate = $dir/cacert.pem
|
||||||
|
serial = $dir/serial
|
||||||
|
crl = $dir/crl.pem
|
||||||
|
private_key = $dir/cacert.key
|
||||||
|
RANDFILE = $dir/.rand
|
||||||
|
x509_extensions = v3_ca
|
||||||
|
default_days = 365
|
||||||
|
default_crl_days= 30
|
||||||
|
default_md = sha1
|
||||||
|
preserve = no
|
||||||
|
policy = policy_ca
|
||||||
|
|
||||||
|
[ policy_client ]
|
||||||
|
countryName = optional
|
||||||
|
stateOrProvinceName = optional
|
||||||
|
organizationName = optional
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
[ policy_server ]
|
||||||
|
countryName = optional
|
||||||
|
stateOrProvinceName = optional
|
||||||
|
organizationName = optional
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
[ policy_ca ]
|
||||||
|
countryName = optional
|
||||||
|
stateOrProvinceName = optional
|
||||||
|
organizationName = optional
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
[ req ]
|
||||||
|
default_bits = 4096
|
||||||
|
default_keyfile = privkey.pem
|
||||||
|
distinguished_name = req_distinguished_name
|
||||||
|
attributes = req_attributes
|
||||||
|
x509_extensions = v3_ca
|
||||||
|
string_mask = nombstr
|
||||||
|
req_extensions = v3_req
|
||||||
|
|
||||||
|
[ req_distinguished_name ]
|
||||||
|
countryName = Country Name (2 letter code)
|
||||||
|
countryName_default = AU
|
||||||
|
countryName_min = 2
|
||||||
|
countryName_max = 2
|
||||||
|
stateOrProvinceName = State or Province Name (full name)
|
||||||
|
stateOrProvinceName_default = Some-State
|
||||||
|
localityName = Locality Name (eg, city)
|
||||||
|
0.organizationName = Organization Name (eg, company)
|
||||||
|
0.organizationName_default = Internet Widgits Pty Ltd
|
||||||
|
organizationalUnitName = Organizational Unit Name (eg, section)
|
||||||
|
commonName = Common Name (eg, YOUR name)
|
||||||
|
commonName_max = 64
|
||||||
|
emailAddress = Email Address
|
||||||
|
emailAddress_max = 40
|
||||||
|
|
||||||
|
[ v3_req ]
|
||||||
|
basicConstraints = CA:FALSE
|
||||||
|
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
[ req_attributes ]
|
||||||
|
challengePassword = A challenge password
|
||||||
|
challengePassword_min = 4
|
||||||
|
challengePassword_max = 20
|
||||||
|
unstructuredName = An optional company name
|
||||||
|
|
||||||
|
[ client_cert ]
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
nsCertType = client, email, objsign
|
||||||
|
nsComment = "TinyCA Generated Certificate"
|
||||||
|
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer:always
|
||||||
|
subjectAltName=email:copy
|
||||||
|
issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
[ server_cert ]
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
nsCertType = server
|
||||||
|
nsComment = "TinyCA Generated Certificate"
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer:always
|
||||||
|
subjectAltName=email:copy
|
||||||
|
issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
[ v3_ca ]
|
||||||
|
nsComment = "TinyCA Generated Certificate"
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
basicConstraints = critical,CA:true
|
||||||
|
keyUsage = keyCertSign, cRLSign
|
||||||
|
nsCertType = sslCA, emailCA
|
||||||
|
subjectAltName=email:copy
|
||||||
|
issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
[ crl_ext ]
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
|
@ -0,0 +1,115 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
#
|
||||||
|
# $Id: tinyca2,v 1.6 2006/07/04 19:53:16 sm Exp $
|
||||||
|
#
|
||||||
|
# Copyright (c) Stephan Martin <sm@sm-zone.net>
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
BEGIN { unshift(@INC, './lib'); # put here the location of the modules
|
||||||
|
}
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use Gtk2 '-init';
|
||||||
|
|
||||||
|
use MIME::Base64;
|
||||||
|
|
||||||
|
use POSIX;
|
||||||
|
use Locale::gettext;
|
||||||
|
|
||||||
|
use OpenSSL;
|
||||||
|
use CA;
|
||||||
|
use GUI;
|
||||||
|
use HELPERS;
|
||||||
|
use GUI::TCONFIG;
|
||||||
|
use GUI::HELPERS;
|
||||||
|
use GUI::CALLBACK;
|
||||||
|
use GUI::WORDS;
|
||||||
|
use GUI::X509_infobox;
|
||||||
|
use GUI::X509_browser;
|
||||||
|
use CERT;
|
||||||
|
use REQ;
|
||||||
|
use KEY;
|
||||||
|
use TCONFIG;
|
||||||
|
|
||||||
|
setlocale(LC_MESSAGES, "");
|
||||||
|
bindtextdomain("tinyca2", "./locale/");
|
||||||
|
textdomain("tinyca2");
|
||||||
|
|
||||||
|
# https://bugs.gentoo.org/show_bug.cgi?id=78576
|
||||||
|
$ENV{XLIB_SKIP_ARGB_VISUALS}= '1';
|
||||||
|
|
||||||
|
my $init = {};
|
||||||
|
|
||||||
|
# location of openssl
|
||||||
|
$init->{'opensslbin'} = "/usr/bin/openssl";
|
||||||
|
$init->{'zipbin'} = "/usr/bin/zip";
|
||||||
|
$init->{'tarbin'} = "/bin/tar";
|
||||||
|
|
||||||
|
if(not -x $init->{'opensslbin'}) {
|
||||||
|
printf(gettext("Can't execute %s.\n"), $init->{'opensslbin'});
|
||||||
|
print gettext("Configure correct path to openssl in tinyca.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(not -x $init->{'zipbin'}) {
|
||||||
|
print gettext("zip command not found, support disabled.\n");
|
||||||
|
print gettext("Configure correct path to zip in tinyca.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(not -x $init->{'tarbin'}) {
|
||||||
|
print gettext("tar command not found, support disabled.\n");
|
||||||
|
print gettext("Configure correct path to tar in tinyca.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
# directory with the templates
|
||||||
|
$init->{'templatedir'} = "./templates";
|
||||||
|
|
||||||
|
if(not -d $init->{'templatedir'}) {
|
||||||
|
print gettext("Can't find templatedir.\n");
|
||||||
|
print gettext("Please configure correct path with templates in tinyca.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
# location for CA files
|
||||||
|
$init->{'basedir'} = $ENV{HOME}."/.TinyCA";
|
||||||
|
$init->{'exportdir'} = $ENV{HOME};
|
||||||
|
|
||||||
|
umask(0077);
|
||||||
|
|
||||||
|
# create main object and initialize CA
|
||||||
|
my $gui = GUI->new($init);
|
||||||
|
|
||||||
|
# and now run...
|
||||||
|
$gui->{'mw'}->show_all();
|
||||||
|
|
||||||
|
# decide what to do on startup
|
||||||
|
if(@{$gui->{'CA'}->{'calist'}}) {
|
||||||
|
$gui->{'CA'}->get_open_name($gui);
|
||||||
|
} else {
|
||||||
|
$gui->{'CA'}->get_ca_create($gui);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _ {
|
||||||
|
my $s = gettext(@_);
|
||||||
|
utf8::decode($s);
|
||||||
|
return($s);
|
||||||
|
}
|
||||||
|
|
||||||
|
Gtk2->main();
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Encoding=UTF-8
|
||||||
|
Type=Application
|
||||||
|
GenericName=Tool to manage a Certification Authority
|
||||||
|
Name=TinyCA2
|
||||||
|
Exec=tinyca2
|
||||||
|
|
||||||
|
Categories=Network;Security
|
||||||
|
GenericName[bg]=GenericName(tinyca.desktop): Управление на сертификационните регистри (Certification Authority)
|
||||||
|
Name[cs]=TinyCA2
|
||||||
|
GenericName[cs]=Nástroj pro správu certifikační autority
|
||||||
|
Name[de]=TinyCA2
|
||||||
|
GenericName[de]=Werkzeug zum Verwalten einer Certification Authority
|
||||||
|
Name[es]=TinyCA2
|
||||||
|
GenericName[es]=Herramienta para gestionar autoridades certificadoras
|
||||||
|
Name[fr]=TinyCA2
|
||||||
|
GenericName[fr]=Outil de gestion d'une autorité de certification
|
||||||
|
Name[hu]=TinyCA2
|
||||||
|
GenericName[hu]=CA (Certification Authority) kezelő segédeszköz
|
||||||
|
Name[it]=TinyCA2
|
||||||
|
GenericName[it]=Tool d'amministrazione per una certification authority
|
||||||
|
Name[ja]=TinyCA2
|
||||||
|
GenericName[ja]=認証局の管理ツール
|
||||||
|
Name[nb]=TinyCA2
|
||||||
|
GenericName[nb]=Administrasjonsverktøy for sertifikater
|
||||||
|
Name[nl]=TinyCA2
|
||||||
|
GenericName[nl]=Programma om een certificaat autoriteit te beheren
|
||||||
|
Name[pl]=TinyCA2
|
||||||
|
GenericName[pl]=Narzędzie do zarządzania centrum certyfikacyjnym
|
||||||
|
Name[pt_BR]=TinyCA2
|
||||||
|
GenericName[pt_BR]=Ferramenta para gerenciar uma Autoridade de Certificação
|
||||||
|
Name[sk]=TinyCA2
|
||||||
|
GenericName[sk]=Nástroj pre správu certifikačnej autority
|
||||||
|
Name[zh_CN]=TinyCA2
|
||||||
|
GenericName[zh_CN]=管理证书授权者的工具
|
||||||
|
Name[zh_TW]=TinyCA2
|
||||||
|
GenericName[zh_TW]=管理認證授權的工具
|
||||||
|
X-SuSE-translate=true
|
|
@ -0,0 +1,170 @@
|
||||||
|
# spec file for package tinyca
|
||||||
|
#
|
||||||
|
# $Id: tinyca2.spec,v 1.9 2006/07/25 20:10:54 sm Exp $
|
||||||
|
#
|
||||||
|
# Copyright (c) 2002 Stephan Martin
|
||||||
|
# This file and all modifications and additions to the pristine
|
||||||
|
# package are under the same license as the package itself.
|
||||||
|
#
|
||||||
|
|
||||||
|
%define bindir %{_bindir}
|
||||||
|
%define libdir %{_datadir}/TinyCA2/lib
|
||||||
|
%define templatesdir %{_datadir}/TinyCA2/templates
|
||||||
|
%define localedir %{_datadir}/TinyCA2/locale/
|
||||||
|
|
||||||
|
Name: tinyca2
|
||||||
|
URL: http://tinyca.sm-zone.net/
|
||||||
|
Group: Productivity/Networking/Security
|
||||||
|
License: GPL
|
||||||
|
Requires: perl perl-Gtk2 perl-MIME-Base64
|
||||||
|
Packager: Stephan Martin <sm@sm-zone.net>
|
||||||
|
Version: @version@
|
||||||
|
Release: 0
|
||||||
|
Source0: %{name}-%{version}.tar.gz
|
||||||
|
Source1: %{name}.desktop
|
||||||
|
Summary: Graphical Tool for Managing a Certification Authority
|
||||||
|
BuildArch: noarch
|
||||||
|
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||||
|
|
||||||
|
%description
|
||||||
|
TinyCA is a graphical tool written in Perl/Gtk to manage a small
|
||||||
|
Certification Authority (CA) using openssl.
|
||||||
|
|
||||||
|
TinyCA supports - creation and revocation of x509 - S/MIME
|
||||||
|
certificates.
|
||||||
|
|
||||||
|
- PKCS#10 requests.
|
||||||
|
|
||||||
|
- exporting certificates as PEM, DER, TXT, and PKCS#12.
|
||||||
|
|
||||||
|
- server certificates for use in web servers, email servers, IPsec,
|
||||||
|
and more.
|
||||||
|
|
||||||
|
- client certificates for use in web browsers, email clients, IPsec,
|
||||||
|
and more.
|
||||||
|
|
||||||
|
- creation and management of SubCAs
|
||||||
|
|
||||||
|
|
||||||
|
Authors:
|
||||||
|
--------
|
||||||
|
Stephan Martin <sm@sm-zone.net>
|
||||||
|
|
||||||
|
%prep
|
||||||
|
%setup
|
||||||
|
|
||||||
|
%build
|
||||||
|
# Configure pristine source
|
||||||
|
perl -pi -e 's:./lib:%{libdir}:g' tinyca2
|
||||||
|
perl -pi -e 's:./templates:%{templatesdir}:g' tinyca2
|
||||||
|
perl -pi -e 's:./locale:%{localedir}:g' tinyca2
|
||||||
|
make -C po
|
||||||
|
|
||||||
|
%install
|
||||||
|
[ "$RPM_BUILD_ROOT" != "/" ] && [ -d $RPM_BUILD_ROOT ] && rm -rf $RPM_BUILD_ROOT;
|
||||||
|
|
||||||
|
LANGUAGES="de es cs fr sv"
|
||||||
|
|
||||||
|
mkdir -p $RPM_BUILD_ROOT%{bindir}
|
||||||
|
mkdir -p $RPM_BUILD_ROOT%{libdir}
|
||||||
|
mkdir -p $RPM_BUILD_ROOT%{libdir}/GUI
|
||||||
|
mkdir -p $RPM_BUILD_ROOT%{templatesdir}
|
||||||
|
|
||||||
|
install -m 644 lib/*.pm $RPM_BUILD_ROOT%{libdir}
|
||||||
|
install -m 644 lib/GUI/*.pm $RPM_BUILD_ROOT%{libdir}/GUI/
|
||||||
|
install -m 644 templates/openssl.cnf $RPM_BUILD_ROOT%{templatesdir}
|
||||||
|
install -m 755 tinyca2 $RPM_BUILD_ROOT%{bindir}
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/usr/share/applications/
|
||||||
|
install -m 644 tinyca2.desktop $RPM_BUILD_ROOT/usr/share/applications/
|
||||||
|
|
||||||
|
for LANG in $LANGUAGES; do
|
||||||
|
mkdir -p $RPM_BUILD_ROOT%{localedir}/$LANG/LC_MESSAGES/
|
||||||
|
install -m 644 locale/$LANG/LC_MESSAGES/tinyca2.mo %{buildroot}%{localedir}/$LANG/LC_MESSAGES/
|
||||||
|
done
|
||||||
|
|
||||||
|
%clean
|
||||||
|
rm -rf %{buildroot}
|
||||||
|
|
||||||
|
%files
|
||||||
|
%defattr(-,root,root)
|
||||||
|
%doc CHANGES
|
||||||
|
%dir %{_datadir}/TinyCA2
|
||||||
|
%{bindir}/tinyca2
|
||||||
|
%{_datadir}/TinyCA2/*
|
||||||
|
%{_datadir}/applications/*
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* Sun Dec 5 2004 - sm@sm-zone.net
|
||||||
|
- import functioins added
|
||||||
|
* Fri Aug 13 2004 - sm@sm-zone.net
|
||||||
|
- czech translation
|
||||||
|
* Sun Jun 13 2004 - sm@sm-zone.net
|
||||||
|
- gui polishing
|
||||||
|
- code cleanup
|
||||||
|
- some usability improvements
|
||||||
|
* Wed Jun 2 2004 - sm@sm-zone.net
|
||||||
|
- gui polishing
|
||||||
|
- GUI module splitted to several files
|
||||||
|
* Fri Oct 3 2003 - sm@sm-zone.net
|
||||||
|
- added a lot of configuration options
|
||||||
|
- correctly import/show details of requests without extensions
|
||||||
|
(thanks to James.Leavitt@anywaregroup.com)
|
||||||
|
* Mon Sep 1 2003 - sm@sm-zone.net
|
||||||
|
- added renewal of certificates
|
||||||
|
* Wed Aug 13 2003 - sm@sm-zone.net
|
||||||
|
- rewite, now using perl-Gtk
|
||||||
|
* Sat Jul 5 2003 - sm@sm-zone.net
|
||||||
|
- added german translation
|
||||||
|
* Tue Jul 1 2003 - sm@sm-zone.net
|
||||||
|
- convert index.txt if openssl changed from 0.9.6x to 0.9.7x
|
||||||
|
* Fri Jun 27 2003 - sm@sm-zone.net
|
||||||
|
- added export into zip-file
|
||||||
|
thanks to ludwig.nussel@suse.de
|
||||||
|
* Mon Jun 23 2003 - sm@sm-zone.net
|
||||||
|
- some tiny usability improvements
|
||||||
|
thanks to ludwig.nussel@suse.de again
|
||||||
|
* Thu Jun 19 2003 - sm@sm-zone.net
|
||||||
|
- some usability improvements
|
||||||
|
thanks to ludwig.nussel@suse.de
|
||||||
|
- some more configuration options
|
||||||
|
* Fri Oct 4 2002 - sm@sm-zone.net
|
||||||
|
- Fixed bug exporting keys in PEM format
|
||||||
|
- Fixed possible empty lines in cert/key/reqlist
|
||||||
|
thanks to waldemar.mertke@gmx.de
|
||||||
|
* Fri Sep 27 2002 - sm@sm-zone.net
|
||||||
|
- fixed some minor bugs and typos (e.g. concerning openssl 0.9.7)
|
||||||
|
thanks to iebgener@yahoo.com and waldemar.mertke@gmx.de
|
||||||
|
* Wed Aug 21 2002 - sm@sm-zone.net
|
||||||
|
- fixed revocation
|
||||||
|
- added some colors
|
||||||
|
- thanks to curly@e-card.bg
|
||||||
|
* Sun Aug 18 2002 - sm@sm-zone.net
|
||||||
|
- new version 0.4.0
|
||||||
|
- works independent of OpenCA modules now
|
||||||
|
- some enhancements to functionality (e.g. export of key without
|
||||||
|
passwd)
|
||||||
|
- some smaller bugfixes in usability
|
||||||
|
- new specfile (thanks to oron@actcom.co.il)
|
||||||
|
* Thu Jun 6 2002 - Oron Peled <oron@actcom.co.il>
|
||||||
|
- Cleaned .spec file
|
||||||
|
* Mon Jun 3 2002 - sm@sm-zone.net
|
||||||
|
- fixed wrong templatedir when creating new CA
|
||||||
|
* Sun Jun 2 2002 - sm@sm-zone.net
|
||||||
|
- fixed some minor bugs and typos
|
||||||
|
* Sat May 11 2002 - sm@sm-zone.net
|
||||||
|
- Added parser for x509 extensions
|
||||||
|
* Fri May 03 2002 - sm@sm-zone.net
|
||||||
|
- added possibility to view requests/certificates
|
||||||
|
* Thu Apr 18 2002 - sm@sm-zone.net
|
||||||
|
- added configuration
|
||||||
|
* Sun Apr 7 2002 - sm@sm-zone.net
|
||||||
|
- improved usability
|
||||||
|
* Sun Mar 31 2002 - sm@sm-zone.net
|
||||||
|
- added function to delete ca
|
||||||
|
* Sat Mar 30 2002 - sm@sm-zone.net
|
||||||
|
- allow import of pkcs#10 requests
|
||||||
|
* Thu Mar 21 2002 - sm@sm-zone.et
|
||||||
|
- use different listboxes
|
||||||
|
* Mon Mar 18 2002 - sm@sm-zone.net
|
||||||
|
- initial package
|
||||||
|
|
Loading…
Reference in New Issue