|
|
|
# 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);
|
|
|
|
if ($text eq _("VALID")) {
|
|
|
|
$color = 'green';
|
|
|
|
} elsif ($text eq _("EXPIRING")) {
|
|
|
|
$color = 'orange';
|
|
|
|
} else {
|
|
|
|
$color = '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
|