Imported former upstream version 0.7.5

master
Thomas Hooge 8 years ago
commit e136e7cbbf
  1. 212
      CHANGES
  2. 30
      INSTALL
  3. 9
      install.sh
  4. 1402
      lib/CA.pm
  5. 713
      lib/CERT.pm
  6. 3105
      lib/GUI.pm
  7. 173
      lib/GUI/CALLBACK.pm
  8. 479
      lib/GUI/HELPERS.pm
  9. 1502
      lib/GUI/TCONFIG.pm
  10. 112
      lib/GUI/WORDS.pm
  11. 879
      lib/GUI/X509_browser.pm
  12. 280
      lib/GUI/X509_infobox.pm
  13. 393
      lib/HELPERS.pm
  14. 494
      lib/KEY.pm
  15. 1079
      lib/OpenSSL.pm
  16. 777
      lib/REQ.pm
  17. 555
      lib/TCONFIG.pm
  18. 25
      po/Makefile
  19. 2003
      po/cs.po
  20. 1980
      po/de.po
  21. 2010
      po/es.po
  22. 1999
      po/fr.po
  23. 2158
      po/sv.po
  24. 1918
      po/tinyca2.pot
  25. 147
      templates/openssl.cnf
  26. 115
      tinyca2
  27. 38
      tinyca2.desktop
  28. 170
      tinyca2.spec

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

File diff suppressed because it is too large Load Diff

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

2003
po/cs.po

File diff suppressed because it is too large Load Diff

1980
po/de.po

File diff suppressed because it is too large Load Diff

2010
po/es.po

File diff suppressed because it is too large Load Diff

1999
po/fr.po

File diff suppressed because it is too large Load Diff

2158
po/sv.po

File diff suppressed because it is too large Load Diff

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