# Copyright (c) Stephan Martin # # $Id: GUI.pm,v 1.34 2006/07/25 20:10:54 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; use POSIX; use Gtk2::SimpleMenu; my $false=undef; my $true=1; # This hash maps our internal MD names to the displayed digest names. # Maybe it should live in a crypto-related file instead of a UI-related file? my %md_algorithms = ( 'sha256' => 'SHA-256', 'md5' => 'ins.MD5', # n/a 'md2' => 'MD2', # n/a 'mdc2' => 'MDC2', 'md4' => 'ins.MD4', 'ripemd160' => 'RIPEMD-160', # 'sha' => 'SHA', 'sha1' => 'ins.SHA-1', 'sha384' => 'SHA-384', 'sha512' => 'SHA-512', ); my %bit_lengths = ( '1024' => '1024', '2048' => '2048', '4096' => '4096' ); # # create the main object # sub new { my $that = shift; my $class = ref($that) || $that; my $self = {}; $self->{'init'} = shift; bless($self, $class); my ($section, $x, $y, $w, $h); $self->{'version'} = '0.7.6'; $self->{'words'} = GUI::WORDS->new(); $self->{'exportdir'} = $self->{'init'}->{'exportdir'}; $self->{'basedir'} = $self->{'init'}->{'basedir'}; $self->{'tmpdir'} = $self->{'basedir'}."/tmp"; $self->{'init'}->{'tmpdir'} = $self->{'basedir'}."/tmp"; # initialize CA object $self->{'CA'} = CA->new($self->{'init'}); # initialize OpenSSL object $self->{'OpenSSL'} = OpenSSL->new($self->{'init'}->{'opensslbin'}, $self->{'tmpdir'}); # initialize CERT object $self->{'CERT'} = CERT->new($self->{'OpenSSL'}); # initialize KEY object $self->{'KEY'} = KEY->new(); # initialize REQ object $self->{'REQ'} = REQ->new($self->{'OpenSSL'}); # initialize CONFIG object $self->{'TCONFIG'} = TCONFIG->new(); # initialize fonts and styles $self->{'fontfix'} = Gtk2::Pango::FontDescription->from_string( "Courier 10" ); # Gtk::Rc->parse_string( #'style "default" #{ # fontset = "-*-helvetica-medium-r-normal--11-*,-*-fixed-medium-r-normal--11-*" #} #widget_class "*" style "default"'); # $self->{'stylered'} = Gtk2::Style->new(); # $self->{'stylered'}->fg('normal', Gtk2::Gdk::Color->parse('red')); # $self->{'stylegreen'} = Gtk2::Style->new(); # $self->{'stylegreen'}->fg('normal', Gtk2::Gdk::Color->parse('green')); # initialize main window $self->{'mw'} = Gtk2::Window->new("toplevel"); $self->{'mw'}->set_title("TinyCA2 Management $self->{'version'}"); $self->{'mw'}->set_icon_from_file("./icons/tinyca.png"); $self->{'mw'}->set_resizable(1); $section = $self->{'init'}->{'cfg'}->{window}; if(defined($section->{x}) && defined($section->{y})) { # save position for later use after show_all() $self->{'posx'} = $section->{x}; $self->{'posy'} = $section->{y}; } $w = $section->{w} // 850; $h = $section->{h} // 600; main::printd("Sizing window to $w,$h"); $self->{'mw'}->set_default_size($w, $h); $self->{'mw'}->signal_connect( 'delete_event', sub { HELPERS::exit_clean(0) }); $self->{'busycursor'} = Gtk2::Gdk::Cursor->new('watch'); $self->{'cursor'} = Gtk2::Gdk::Cursor->new('left-ptr'); $self->{'rootwin'} = Gtk2::Gdk->get_default_root_window(); # split window horizontal to add menu, toolbar and notebook $self->{'mvb'} = Gtk2::VBox->new(); $self->{'mw'}->add($self->{'mvb'}); $self->create_menu(); $self->{'mvb'}->pack_start($self->{'menu'}->{'widget'} , 0, 0, 0); $self->create_toolbar('startup'); $self->{'mvb'}->pack_start($self->{'toolbar'}, 0, 0, 0); $self->create_nb(); $self->{'mvb'}->pack_start($self->{'nb'}, 1, 1, 0); $self->create_bar(); $self->{'mvb'}->pack_start($self->{'barbox'}, 0, 0, 0); $self->{'rootwin'}->set_cursor($self->{'cursor'}); $self; } # # create/update the main frame with the notebooks # sub create_mframe { my ($self, $force) = @_; my($parsed, $calabel, $caframe, $rows, $table, @fields, $text, @childs, $label, $cert_export, $cert_revoke, $cert_delete, $certlabel, $certlistwin, @certtitles, @keytitles, $keylabel, $keylistwin, $reqlistwin, @reqtitles, $reqlabel, $ind, $column, $ca, $cadir); if ((defined($self->{'CA'}->{'actca'})) && ($self->{'CA'}->{'actca'} ne "")) { $ca = $self->{'CA'}->{'actca'}; } else { return; } $cadir = $self->{'CA'}->{'cadir'}; $parsed = $self->{'CERT'}->parse_cert( $self, 'CA'); defined($parsed) || GUI::HELPERS::print_error( _("Can't read CA certificate")); ### notebooktab for ca information if(not defined($self->{'cabox'})) { $self->{'cabox'} = Gtk2::VBox->new(0, 0); $calabel = GUI::HELPERS::create_label(_("CA"), 'left', 1, 0); $self->{'nb'}->insert_page($self->{'cabox'}, $calabel, 0); } else { $self->{'nb'}->hide(); $self->{'nb'}->remove_page(0); $self->{'cabox'}->destroy(); $self->{'cabox'} = Gtk2::VBox->new(0, 0); $calabel = GUI::HELPERS::create_label(_("CA"), 'left', 1, 0); $self->{'nb'}->insert_page($self->{'cabox'}, $calabel, 0); } # frame for CA informations $self->{'cainfobox'} = GUI::X509_infobox->new(); $self->{'cainfobox'}->display($self->{'cabox'}, $parsed, 'cacert', _("CA Information")); ### notebooktab for certificates # delete old instance, force reinitialisation if (defined($self->{'certbox'}) && $force) { $self->{'certbox'}->destroy(); delete($self->{'certbox'}); $self->{'certbox'} = undef; delete($self->{'certbrowser'}->{'OpenSSL'}); $self->{'certbrowser'}->{'OpenSSL'} = undef; delete($self->{'certbrowser'}); $self->{'certbrowser'} = undef; } if(not defined($self->{'certbox'})) { $self->{'certbox'} = Gtk2::VBox->new(0, 0); $certlabel = GUI::HELPERS::create_label( _("Certificates"), 'left', 1, 0); $self->{'nb'}->insert_page($self->{'certbox'}, $certlabel, 1); if (not defined ($self->{'certbrowser'})) { $self->{'certbrowser'}=GUI::X509_browser->new($self, 'cert'); $self->{'certbrowser'}->set_window($self->{'certbox'}); $self->{'certbrowser'}->add_list($ca, $cadir."/certs", $cadir."/crl/crl.pem", $cadir."/index.txt"); $self->{'certbrowser'}->add_info(); # create popup menu if(not defined($self->{'certmenu'})) { _create_cert_menu($self); } $self->{'certbrowser'}->{'x509clist'}->signal_connect( 'button_release_event', sub { _show_popup_menu($self, 'cert', @_) }); $self->{'certbrowser'}->{'x509clist'}->signal_connect( 'button_press_event', sub { _show_details_wrapper($self, 'cert', @_)}); # $self->{'certbrowser'}->destroy(); } else { $self->{'certbrowser'}->update($cadir."/certs", $cadir."/crl/crl.pem", $cadir."/index.txt"); } } else { $self->{'certbrowser'}->update($cadir."/certs", $cadir."/crl/crl.pem", $cadir."/index.txt"); } ### notebooktab for keys (split info and buttons) @keytitles = (_("Common Name"), _("eMail Address"), _("Organizational Unit"), _("Organization"), _("Location"), _("State"), _("Country"), _("Type")); # delete old instance, force reinitialisation if (defined($self->{'keybox'}) && $force) { $self->{'keybox'}->destroy(); delete($self->{'keybox'}); $self->{'keybox'} = undef; delete($self->{'keybrowser'}->{'OpenSSL'}); $self->{'keybrowser'}->{'OpenSSL'} = undef; delete($self->{'keybrowser'}); $self->{'keybrowser'} = undef; } if(not defined($self->{'keybox'})) { $self->{'keybox'} = Gtk2::VBox->new(0, 0); $keylabel = GUI::HELPERS::create_label( _("Keys"), 'left', 1, 0); $self->{'nb'}->insert_page($self->{'keybox'}, $keylabel, 2); if (not defined ($self->{'keybrowser'})) { $self->{'keybrowser'}=GUI::X509_browser->new($self, 'key'); $self->{'keybrowser'}->set_window($self->{'keybox'}); $self->{'keybrowser'}->add_list($ca, $cadir."/keys", $cadir."/crl/crl.pem", $cadir."/index.txt"); # create popup menu if(not defined($self->{'keymenu'})) { _create_key_menu($self); } $self->{'keybrowser'}->{'x509clist'}->signal_connect( 'button_release_event', sub { _show_popup_menu($self, 'key', @_) }); } else { $self->{'keybrowser'}->update($cadir."/keys", $cadir."/crl/crl.pem", $cadir."/index.txt"); } } # delete old instance, force reinitialisation if (defined($self->{'reqbox'}) && $force) { $self->{'reqbox'}->destroy(); delete($self->{'reqbox'}); $self->{'reqbox'} = undef; delete($self->{'reqbrowser'}->{'OpenSSL'}); $self->{'reqbrowser'}->{'OpenSSL'} = undef; delete($self->{'reqbrowser'}); $self->{'reqbrowser'} = undef; } ### notebooktab for requests (split info and buttons) if(not defined($self->{'reqbox'})) { $self->{'reqbox'} = Gtk2::VBox->new(0, 0); $reqlabel = GUI::HELPERS::create_label( _("Requests"), 'left', 1, 0); $self->{'nb'}->insert_page($self->{'reqbox'}, $reqlabel, 3); if (not defined ($self->{'reqbrowser'})) { $self->{'reqbrowser'}=GUI::X509_browser->new($self, 'req'); $self->{'reqbrowser'}->set_window($self->{'reqbox'}); $self->{'reqbrowser'}->add_list($ca, $cadir."/req", $cadir."/crl/crl.pem", $cadir."/index.txt"); $self->{'reqbrowser'}->add_info(); # create popup menu if(not defined($self->{'reqmenu'})) { _create_req_menu($self); } $self->{'reqbrowser'}->{'x509clist'}->signal_connect( 'button_release_event', sub { _show_popup_menu($self, 'req', @_) }); $self->{'reqbrowser'}->{'x509clist'}->signal_connect( 'button_press_event', sub { _show_details_wrapper($self, 'req', @_)}); } else { $self->{'reqbrowser'}->update($cadir."/req", $cadir."/crl/crl.pem", $cadir."/index.txt"); } } else { $self->{'reqbrowser'}->update($cadir."/req", $cadir."/crl/crl.pem", $cadir."/index.txt"); } $self->{'nb'}->show_all(); $self->{'nb'}->signal_connect_after('switch-page' => sub { _act_toolbar($self->{'nb'}, $self) }); $self->{'nb'}->set_current_page(1); return; } # # create empty notebook, add to main window and configure # sub create_nb { my $self = shift; $self->{'nb'} = Gtk2::Notebook->new(); $self->{'nb'}->set_tab_pos('top'); return; } # # create the applicationbar # sub create_bar { my $self = shift; $self->{'barbox'} = Gtk2::HBox->new(); $self->{'bar'} = Gtk2::Statusbar->new(); $self->{'progress'} = Gtk2::ProgressBar->new(); $self->{'barbox'}->pack_start($self->{'bar'}, 1, 1, 0); GUI::HELPERS::set_status($self, _(" Watch out...")); return; } # # keep toolbar in sync with notebook # sub _act_toolbar { my ($nb, $self) = @_; my $page_num = $nb->get_current_page(); my $mode = 'startup'; my $t; if(defined($self->{'CA'}->{'actca'})) { if ($page_num == 0) { $mode = 'ca'; $t = _(" Actual CA: %s"); } elsif ($page_num == 1) { $mode = 'cert'; $t = _(" Actual CA: %s - Certificates"); } elsif ($page_num == 2) { $mode = 'key'; $t = _(" Actual CA: %s - Keys"); } elsif ($page_num == 3) { $mode = 'req'; $t = _(" Actual CA: %s - Requests"); } if(defined($self->{'CA'}->{'actca'})) { $t = sprintf($t, $self->{'CA'}->{'actca'}); GUI::HELPERS::set_status($self, $t); } } $self->create_toolbar($mode); } # # create the toolbar # sub create_toolbar { my ($self, $mode) = @_; my ($icon, $mask, $iconw, $button, @children, $c, $ca); $ca = $self->{'CA'}->{'actca'}; if(not defined($self->{'separator'})) { $self->{'separator'} = Gtk2::SeparatorToolItem->new(); } if(defined($self->{'toolbar'})) { @children = $self->{'toolbar'}->get_children(); for(my $i = 6; $i < @children; $i++) { $c = $children[$i]; $c->destroy(); } } else { $self->{'toolbar'} = Gtk2::Toolbar->new(); $self->{'tooltips'} = Gtk2::Tooltips->new(); $self->{'toolbar'}->set_orientation('horizontal'); $self->{'toolbar'}->set_icon_size('small-toolbar'); ## Buttons for all toolbars $self->{'toolbar'} = Gtk2::Toolbar->new(); $self->{'toolbar'}->set_orientation('horizontal'); $button = Gtk2::ToolButton->new_from_stock('gtk-quit'); $self->{'toolbar'}->insert($button, -1); $button->signal_connect('clicked', sub { Gtk2->main_quit() }); $button->set_tooltip($self->{'tooltips'}, _("Exit TinyCA"), ""); $button = Gtk2::ToolButton->new_from_stock('gtk-open'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Open CA")); $button->set_tooltip($self->{'tooltips'}, _("Open other CA"), ""); $button->signal_connect('clicked', sub { $self->{'CA'}->get_open_name($self)}); $button = Gtk2::ToolButton->new_from_stock('gtk-new'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("New CA")); $button->set_tooltip($self->{'tooltips'}, _("Create new CA"), ""); $button->signal_connect('clicked', sub { $self->{'CA'}->get_ca_create($self)}); $button = Gtk2::ToolButton->new_from_stock('gtk-convert'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Import CA")); $button->set_tooltip($self->{'tooltips'}, _("Import CA"), ""); $button->signal_connect('clicked', sub { $self->{'CA'}->get_ca_import($self)}); $button = Gtk2::ToolButton->new_from_stock('gtk-delete'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Delete CA")); $button->set_tooltip($self->{'tooltips'}, _("Delete CA"), ""); $button->signal_connect('clicked', sub { $self->{'CA'}->get_ca_delete($self)}); $self->{'toolbar'}->insert($self->{'separator'}, -1); } if($mode eq 'ca') { $button = Gtk2::ToolButton->new_from_stock('gtk-find'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Details")); $button->set_tooltip($self->{'tooltips'}, _("Show certificate details"), ""); $button->signal_connect('clicked', sub { $self->show_details('CA') }); $button = Gtk2::ToolButton->new_from_stock('gtk-find-and-replace'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("History")); $button->set_tooltip($self->{'tooltips'}, _("Show history"), ""); $button->signal_connect('clicked', sub { $self->show_history() }); $button = Gtk2::ToolButton->new_from_stock('gtk-new'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Sub CA")); $button->set_tooltip($self->{'tooltips'}, _("Create new sub CA"), ""); $button->signal_connect('clicked', sub { $self->{'CA'}->get_ca_create($self, undef, undef, "sub")}); $button = Gtk2::ToolButton->new_from_stock('gtk-save'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Export CA")); $button->set_tooltip($self->{'tooltips'}, _("Export CA certificate"), ""); $button->signal_connect('clicked', sub { $self->{'CA'}->export_ca_cert($self)}); $button = Gtk2::ToolButton->new_from_stock('gtk-save'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Export CRL")); $button->set_tooltip($self->{'tooltips'}, _("Export certificate revocation list"), ""); $button->signal_connect('clicked', sub { $self->{'CA'}->export_crl($self)}); if(-s $self->{'CA'}->{$ca}->{'dir'}."/cachain.pem") { $button = Gtk2::ToolButton->new_from_stock('gtk-save'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Export Chain")); $button->set_tooltip($self->{'tooltips'}, _("Export Chain"), ""); $button->signal_connect('clicked', sub { $self->{'CA'}->export_ca_chain($self)}); } } elsif($mode eq 'cert') { $button = Gtk2::ToolButton->new_from_stock('gtk-find'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Details")); $button->set_tooltip($self->{'tooltips'}, _("Show certificate details"), ""); $button->signal_connect('clicked', sub { $self->show_details('cert') }); $button = Gtk2::ToolButton->new_from_stock('gtk-find'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("View")); $button->set_tooltip($self->{'tooltips'}, _("View certificate raw data"), ""); $button->signal_connect('clicked', sub { $self->show_text('cert') }); if(not(defined($self->{'newcertmenu'}))) { _create_create_cert_menu($self); } $button = Gtk2::ToolButton->new_from_stock('gtk-new'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("New")); $button->set_tooltip($self->{'tooltips'}, _("Create new certificate request"), ""); $button->signal_connect('clicked' => sub { $self->{'newcertmenu'}->popup( undef, undef, undef, undef, 1, 0) }); $button = Gtk2::ToolButton->new_from_stock('gtk-save'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Export")); $button->set_tooltip($self->{'tooltips'}, _("Export certificate"), ""); $button->signal_connect('clicked', sub { $self->{'CERT'}->get_export_cert($self) }); $button = Gtk2::ToolButton->new_from_stock('gtk-stop'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Revoke")); $button->set_tooltip($self->{'tooltips'}, _("Revoke certificate"), ""); $button->signal_connect('clicked', sub { $self->{'CERT'}->get_revoke_cert($self) }); if(not defined($self->{'renewcertmenu'})) { _create_renew_cert_menu($self); } $button = Gtk2::ToolButton->new_from_stock('gtk-refresh'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Renew")); $button->set_tooltip($self->{'tooltips'}, _("Renew certificate"), ""); $button->signal_connect('clicked' => sub { $self->{'renewcertmenu'}->popup( undef, undef, undef, undef, 1, 0) }); $button = Gtk2::ToolButton->new_from_stock('gtk-delete'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Delete")); $button->set_tooltip($self->{'tooltips'}, _("Delete certificate"), ""); $button->signal_connect('clicked', sub { $self->{'CERT'}->get_del_cert($self) }); } elsif($mode eq 'key') { $button = Gtk2::ToolButton->new_from_stock('gtk-revert-to-saved'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Import")); $button->set_tooltip($self->{'tooltips'}, _("Import key"), ""); $button->signal_connect('clicked', sub { $self->{'KEY'}->get_import_key($self) }); $button = Gtk2::ToolButton->new_from_stock('gtk-save'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Export")); $button->set_tooltip($self->{'tooltips'}, _("Export key"), ""); $button->signal_connect('clicked', sub { $self->{'KEY'}->get_export_key($self) }); $button = Gtk2::ToolButton->new_from_stock('gtk-delete'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Delete")); $button->set_tooltip($self->{'tooltips'}, _("Delete key"), ""); $button->signal_connect('clicked', sub { $self->{'KEY'}->get_del_key($self) }); } elsif($mode eq 'req') { $button = Gtk2::ToolButton->new_from_stock('gtk-find'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Details")); $button->set_tooltip($self->{'tooltips'}, _("Show request details"), ""); $button->signal_connect('clicked', sub { $self->show_details('req') }); $button = Gtk2::ToolButton->new_from_stock('gtk-find'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("View")); $button->set_tooltip($self->{'tooltips'}, _("View request raw data"), ""); $button->signal_connect('clicked', sub { $self->show_text('req') }); $button = Gtk2::ToolButton->new_from_stock('gtk-new'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("New")); $button->set_tooltip($self->{'tooltips'}, _("New request"), ""); $button->signal_connect('clicked', sub { $self->{'REQ'}->get_req_create($self) }); $button = Gtk2::ToolButton->new_from_stock('gtk-revert-to-saved'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Import")); $button->set_tooltip($self->{'tooltips'}, _("Import request"), ""); $button->signal_connect('clicked', sub { $self->{'REQ'}->get_import_req($self) }); if(not(defined($self->{'reqsignmenu'}))) { _create_sign_req_menu($self); } $button = Gtk2::ToolButton->new_from_stock('gtk-properties'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Sign")); $button->set_tooltip($self->{'tooltips'}, _("Sign request"), ""); $button->signal_connect('clicked' => sub { $self->{'reqsignmenu'}->popup( undef, undef, undef, undef, 1, 0) }); $button = Gtk2::ToolButton->new_from_stock('gtk-delete'); $self->{'toolbar'}->insert($button, -1); $button->set_label(_("Delete")); $button->set_tooltip($self->{'tooltips'}, _("Delete request"), ""); $button->signal_connect('clicked', sub { $self->{'REQ'}->get_del_req($self) }); } $self->{'toolbar'}->set_icon_size('small-toolbar'); $self->{'toolbar'}->show_all(); return; } # # create the menubar # sub create_menu { my $self = shift; my $menu_tree = [ _("_CA") => { item_type => '', children => [ _("_Open CA") => { callback => sub { $self->{'CA'}->get_open_name($self) }, item_type => '', extra_data => 'gtk-open' }, _("_New CA") => { callback => sub { $self->{'CA'}->get_ca_create($self)}, item_type => '', extra_data => 'gtk-new' }, _("_Delete CA") => { callback => sub { $self->{'CA'}->get_ca_delete($self)}, item_type => '', extra_data => 'gtk-delete' }, Separator => { item_type => '', }, _("_Exit") => { callback => sub { Gtk2->main_quit() }, item_type => '', extra_data => 'gtk-close' } ], }, _("_Preferences") => { item_type => '', children => [ _("View") => { callback => sub { $self->show_cfg_dialog($self) }, item_type => '', extra_data => 'gtk-info' }, Separator => { item_type => '', }, _("OpenSSL _Configuration") => { callback => sub{ $self->{'TCONFIG'}->config_openssl($self) }, item_type => '', extra_data => 'gtk-preferences' } ], }, _("_Help") => { item_type => '', children => [ _("_Help") => { callback => sub{ $self->show_help() }, item_type => '', extra_data => 'gtk-help' }, _("_About TinyCA") => { callback => sub { $self->about($self) }, item_type => '', extra_data => 'gtk-about' } ], } ]; $self->{'menu'} = Gtk2::SimpleMenu->new(menu_tree => $menu_tree); return; } # # pop-up to display request/cert as TXT # sub show_text { my ($self, $mode) = @_; my($parsed, $t, $box, $label, $text, $vscrollbar, $name, $button_ok, $status, $scrolled, $ca, $buffer); $ca = $self->{'CA'}->{'actca'}; if($mode eq 'req') { $name = $self->{'reqbrowser'}->selection_dn(); } elsif($mode eq 'cert') { $name = $self->{'certbrowser'}->selection_dn(); } else { GUI::HELPERS::print_error( _("Invalid mode for show_text():")." ".$mode); return; } if((not defined $name) && ($mode eq 'req')) { GUI::HELPERS::print_info(_("Please select a Request first")); return; }elsif((not defined $name) && ($mode eq 'cert')) { GUI::HELPERS::print_info(_("Please select a certificate first")); return; } if($mode eq 'cert') { $status = $self->{'certbrowser'}->selection_status(); } $name = HELPERS::enc_base64($name); if($mode eq 'req') { $parsed = $self->{'REQ'}->parse_req( $self, $name); } elsif($mode eq 'cert') { $parsed = $self->{'CERT'}->parse_cert( $self, $name); } defined($parsed) || GUI::HELPERS::print_error(_("Can't read file")); $t = $mode eq 'req'?_("Request"):_("Certificate"); $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->signal_connect('clicked', sub { $box->destroy() }); $button_ok->can_default(1); $box = GUI::HELPERS::dialog_box($t, $t, $button_ok); $box->set_default_size(550, 440); $button_ok->grab_default(); $scrolled = Gtk2::ScrolledWindow->new(undef, undef); $scrolled->set_policy('automatic', 'automatic'); $scrolled->set_shadow_type('etched-in'); $box->vbox->pack_start($scrolled, 1, 1, 0); $buffer = Gtk2::TextBuffer->new(); $buffer->set_text($parsed->{'TEXT'}); $text = Gtk2::TextView->new_with_buffer($buffer); $text->set_editable(0); $text->set_wrap_mode('none'); $text->modify_font($self->{'fontfix'}); $scrolled->add($text); $box->show_all(); return; } # # completeley sick, but needed for doubleclick # sub _show_details_wrapper { my ($self, $mode, $list, $event) = @_; return(0) if($event->type() ne '2button-press'); show_details($self, $mode); return(1); } # # called on rightclick in [key|cert|reqlist] # sub _show_popup_menu { my ($self, $mode, $list, $event) = @_; my $t; if ($event->button() == 3) { if($mode eq 'cert') { $self->{'certmenu'}->popup(undef, undef, undef, undef, 3, 0); } elsif ($mode eq 'req') { $self->{'reqmenu'}->popup(undef, undef, undef, undef, 3, 0); } elsif ($mode eq 'key') { $self->{'keymenu'}->popup(undef, undef, undef, undef, 3, 0); } else { $t = sprintf( _("Invalid mode for _show_popup_menu(): %s"), $mode); GUI::HELPERS::print_error($t); } return(1); } return(0); } # # show request/certificate informations and extensions # sub show_details { my ($self, $mode) = @_; my($name, $status, $parsed, $row, $ind, $label, $table, $tree, $box, $button_ok, $t, @fields, $ca); $ca = $self->{'CA'}->{'actca'}; if($mode eq 'req') { $name = $self->{'reqbrowser'}->selection_dn(); } elsif($mode eq 'cert') { $name = $self->{'certbrowser'}->selection_dn(); } elsif($mode eq 'CA') { $name = 'CA'; } else { GUI::HELPERS::print_error( _("Invalid mode for show_details():")." ".$mode); return; } if((not defined $name) && ($mode eq 'req')) { GUI::HELPERS::print_info(_("Please select a Request first")); return; }elsif((not defined $name) && ($mode eq 'cert')) { GUI::HELPERS::print_info(_("Please select a Certificate first")); return; } if($mode eq 'cert') { $status = $self->{'certbrowser'}->selection_status(); } $name = HELPERS::enc_base64($name) if($name ne 'CA'); if($mode eq 'req') { $parsed = $self->{'REQ'}->parse_req( $self, $name); } elsif($mode eq 'cert' || $mode eq 'CA') { $parsed = $self->{'CERT'}->parse_cert( $self, $name); } defined($parsed) || GUI::HELPERS::print_error(_("Can't read file")); $t = $mode eq 'req'?_("Request Details"):_("Certificate Details"); $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->can_default(1); $button_ok->signal_connect('clicked', sub { $box->destroy() }); $box = GUI::HELPERS::dialog_box($t, $t, $button_ok); $box->set_default_size(700, 400); $button_ok->grab_default(); $mode = 'cert' if($mode eq 'CA'); $tree = $self->create_detail_tree($parsed, $mode); $box->vbox->add($tree); $box->show_all(); $tree->{'tree'}->columns_autosize(); } # # pop-up to verify import # sub show_import_verification { my ($self, $mode, $opts, $parsed) = @_; my($box, $button_ok, $button_cancel, $label, $rows, $tree, $t); $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->can_default(1); if($mode eq "req") { $button_ok->signal_connect('clicked', sub { $self->{'REQ'}->import_req($self, $opts, $parsed, $box) }); } elsif($mode eq "cacert") { $button_ok->signal_connect('clicked', sub { $self->{'CA'}->import_ca($self, $opts, $box) }); } $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $box->destroy() }); if($mode eq "req") { $t = _("Import Request"); } elsif($mode eq "cacert") { $t = _("Import CA Certificate"); } $box = GUI::HELPERS::dialog_box( $t, $t, $button_ok, $button_cancel); $box->set_default_size(700, 400); $button_ok->grab_default(); if($mode eq "req") { $t = _("Do you want to import the following Certificate Request?"); } elsif($mode eq "cacert") { $t = _("Do you want to import the following CA Certificate?"); } $label = GUI::HELPERS::create_label($t, 'center', 1, 0); $box->vbox->pack_start($label, 0, 0, 0); $tree = $self->create_detail_tree($parsed, $mode); $box->vbox->pack_start($tree, 1, 1, 0); $box->show_all(); return; } # # create tree with details (cert/req) # sub create_detail_tree { my ($self, $parsed, $mode) = @_; # print STDERR "DEBUG: create_detail_tree called with mode $mode\n"; my ($tree, $tree_scrolled, $t, $root, $store, $piter, $citer, $column, $ind, $nsext); $tree_scrolled = Gtk2::ScrolledWindow->new(undef, undef); $tree_scrolled->set_policy('automatic', 'automatic'); $tree_scrolled->set_shadow_type('etched-in'); $store = Gtk2::TreeStore->new('Glib::String','Glib::String'); $tree = Gtk2::TreeView->new_with_model($store); $tree->get_selection->set_mode('none'); $tree->set_headers_visible(0); $tree_scrolled->{'tree'} = $tree; my @titles = ("", ""); $ind = 0; foreach my $title (@titles) { $column = Gtk2::TreeViewColumn->new_with_attributes( $title, Gtk2::CellRendererText->new(), 'text' => $ind); $tree->append_column($column); $ind++; } $tree_scrolled->add_with_viewport($tree); $t = $mode eq 'req'?_("Request Details"):_("Certificate Details"); if (defined $parsed->{'CN'}) { $t .= " - $parsed->{'CN'}"; } $root = $store->append(undef); $store->set($root, 0 => $t); # Information about Subject DN $t = _("Subject DN").":"; $piter = $store->append($root); $store->set($piter, 0 => $t); for my $l (qw(CN EMAIL O OU C ST L)) { if(defined($parsed->{$l})) { if($l eq "OU") { foreach my $ou (@{$parsed->{'OU'}}) { $citer = $store->append($piter); $store->set($citer, 0 => $self->{'words'}{$l}, 1 => $ou); } } else { $citer = $store->append($piter); $store->set($citer, 0 => $self->{'words'}{$l}, 1 => $parsed->{$l}); } } } if($mode ne "req") { # Information about Issuer $t = _("Issuer").":"; $piter = $store->append($root); $store->set($piter, 0 => $t); for my $l (qw(CN EMAIL O OU C ST L)) { if(defined($parsed->{'ISSUERDN'}->{$l})) { if($l eq "OU") { foreach my $ou (@{$parsed->{'ISSUERDN'}->{'OU'}}) { $citer = $store->append($piter); $store->set($citer, 0 => $self->{'words'}{$l}, 1 => $ou); } } else { $citer = $store->append($piter); $store->set($citer, 0 => $self->{'words'}{$l}, 1 => $parsed->{'ISSUERDN'}->{$l}); } } } } if($mode ne "req") { # Information about Validity $t = _("Validity").":"; $piter = $store->append($root); $store->set($piter, 0 => $t); for my $l (qw(STATUS NOTBEFORE NOTAFTER)) { if(defined($parsed->{$l})) { $citer = $store->append($piter); $store->set($citer, 0 => $self->{'words'}{$l}, 1 => $parsed->{$l}); } } } # Information about Key/Certificate $t = $mode eq 'req'?_("Key/Request Details:"):_("Key/Certificate Details:"); $piter = $store->append($root); $store->set($piter, 0 => $t); for my $l (qw(STATUS SERIAL KEYSIZE PK_ALGORITHM SIG_ALGORITHM TYPE)) { if(defined($parsed->{$l})) { $citer = $store->append($piter); $store->set($citer, 0 => $self->{'words'}{$l}, 1 => $parsed->{$l}); } } if($mode ne "req") { # Fingerprints $t = _("Fingerprints").":"; $piter = $store->append($root); $store->set($piter, 0 => $t); for my $l (qw(FINGERPRINTMD5 FINGERPRINTSHA1 FINGERPRINTSHA256 FINGERPRINTSHA384 FINGERPRINTSHA512)) { if(defined($parsed->{$l})) { $citer = $store->append($piter); $store->set($citer, 0 => $self->{'words'}{$l}, 1 => $parsed->{$l}); } } } # Information about Key/Certificate if(keys(%{$parsed->{'EXT'}})) { $t = $mode eq 'req'?_("Requested X.509 Extensions"):_("X.509v3 Extensions"); $piter = $store->append($root); $store->set($piter, 0 => $t); while(my ($key, $val) = each(%{$parsed->{'EXT'}})) { if($key =~ /^netscape/i) { $nsext = 1; next; } # print STDERR "DEBUG: print key: >$key< val: >$val->[0]<\n"; $citer = $store->append($piter); $store->set($citer, 0 => $key, 1 => $val->[0]); if(@{$val} > 1) { for(my $i = 1; $val->[$i]; $i++) { $citer = $store->append($piter); $store->set($citer, 0 => $key, 1 => $val->[$i]); } } } if($nsext) { $t = $mode eq 'req'?_("Requested Netscape Extensions"):_("Netscape Extensions"); $piter = $store->append($root); $store->set($piter, 0 => $t); while(my ($key, $val) = each(%{$parsed->{'EXT'}})) { if($key !~ /^netscape/i) { next; } $citer = $store->append($piter); $store->set($citer, 0 => $key, 1 => $val->[0]); if(@{$val} > 1) { for(my $i = 1; $val->[$i]; $i++) { $t = [$key, $val->[$i]]; $citer = $store->append($piter); $store->set($citer, 0 => $key, 1 => $val->[$i]); } } } } } $tree->expand_to_path(Gtk2::TreePath->new_first()); return($tree_scrolled); } # # get name for open/delete a CA # sub show_select_ca_dialog { my ($self, $action, $opts)= @_; my ($box, $button_ok, $button_cancel, $label, $scrolled, $list, $model, $name, $t, $store, $column, $iter); if($action eq 'open') { $t = _("Open CA"); }elsif($action eq 'delete') { $t = _("Delete CA"); }else { GUI::HELPERS::print_error(_("Invalid action given: ").$action); return; } $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->can_default(1); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $box->destroy() }); $button_ok->signal_connect('clicked', sub { $iter = $list->get_selection->get_selected(); if(defined($iter)) { $name = $store->get($iter); if($action eq 'open') { $opts->{'name'} = $name; $self->{'CA'}->open_ca($self, $opts, $box); }elsif($action eq 'delete') { $self->{'CA'}->delete_ca($self, $name, $box); }else { GUI::HELPERS::print_error( _("Invalid action for show_select_ca_dialog(): ").$action); } } } ); $box = GUI::HELPERS::dialog_box($t, $t, $button_ok, $button_cancel); $box->set_default_size(240,320); $button_ok->grab_default(); $scrolled = Gtk2::ScrolledWindow->new(undef, undef); $scrolled->set_policy('automatic', 'automatic' ); $scrolled->set_shadow_type('etched-in'); $box->vbox->add($scrolled); $store = Gtk2::ListStore->new('Glib::String'); $list = Gtk2::TreeView->new_with_model ($store); $list->get_selection->set_mode('single'); $scrolled->add_with_viewport($list); $column = Gtk2::TreeViewColumn->new_with_attributes( _("Available CAs"), Gtk2::CellRendererText->new(), 'text' => 0); $list->append_column($column); foreach(@{$self->{'CA'}->{'calist'}}) { next if (not defined $_ ); $iter = $store->append(); $store->set($iter, 0, $_); } # activate doubleclick in the list $list->signal_connect('button_press_event', sub { if($_[1]->type() eq '2button-press') { $iter = $list->get_selection->get_selected(); if($iter) { $name = $store->get($iter); if($action eq 'open') { $opts->{'name'} = $name; $self->{'CA'}->open_ca($self, $opts, $box); }elsif($action eq 'delete') { $self->{'CA'}->delete_ca($self, $name, $box); }else { GUI::HELPERS::print_error( _("Invalid action for show_select_ca_dialog(): ").$action); } } return(1); } return(0); } ); $button_ok->grab_default(); $box->show_all(); } # # get data for creating a new request # sub show_req_dialog { my ($self, $opts) = @_; my ($box, $button_ok, $button_cancel, $reqtable, $radiobox, $key1, $key2, $key3, $key4, $key5, $entry, $label); $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->can_default(1); $button_ok->signal_connect('clicked', sub { $self->{'REQ'}->get_req_create($self, $opts, $box) }); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $box->destroy() }); $box = GUI::HELPERS::dialog_box( $self->{'CA'}->{'actca'} . ': ' . _("Create Request") , _("Create a new Certificate Request"), $button_ok, $button_cancel); # table for request data my $cc=0; my $ous = 1; if(defined($opts->{'OU'}) and ref($opts->{'OU'}) eq 'ARRAY') { $ous = @{$opts->{'OU'}} - 1; } $reqtable = Gtk2::Table->new(1, 13 + $ous, 0); $reqtable->set_col_spacing(0, 7); $box->vbox->add($reqtable); $entry = GUI::HELPERS::entry_to_table( _("Common Name (eg, your Name,"), \$opts->{'CN'}, $reqtable, 0, 1); $entry->grab_focus(); $label = GUI::HELPERS::create_label( _("your eMail Address"), 'right', 0, 0); $reqtable->attach_defaults($label, 0, 1, 2, 3); $label = GUI::HELPERS::create_label( _("or the Servers Name)"), 'right', 0, 0); $reqtable->attach_defaults($label, 0, 1, 3, 4); $entry = GUI::HELPERS::entry_to_table( _("eMail Address").":", \$opts->{'EMAIL'}, $reqtable, 4, 1); $entry = GUI::HELPERS::entry_to_table( _("Password (protect your private Key):"), \$opts->{'passwd'}, $reqtable, 5, 0); $entry = GUI::HELPERS::entry_to_table( _("Password (confirmation):"), \$opts->{'passwd2'}, $reqtable, 6, 0); $entry = GUI::HELPERS::entry_to_table( _("Country Name (2 letter code):"), \$opts->{'C'}, $reqtable, 7, 1); $entry = GUI::HELPERS::entry_to_table( _("State or Province Name:"), \$opts->{'ST'}, $reqtable, 8, 1); $entry = GUI::HELPERS::entry_to_table( _("Locality Name (eg. city):"), \$opts->{'L'}, $reqtable, 9, 1); $entry = GUI::HELPERS::entry_to_table( _("Organization Name (eg. company):"), \$opts->{'O'}, $reqtable, 10, 1); if(defined($opts->{'OU'}) and ref($opts->{'OU'}) eq 'ARRAY') { foreach my $ou (@{$opts->{'OU'}}) { $entry = GUI::HELPERS::entry_to_table( _("Organizational Unit Name (eg. section):"), \$ou, $reqtable, 11 + $cc++, 1); } } else { $entry = GUI::HELPERS::entry_to_table( _("Organizational Unit Name (eg. section):"), \$opts->{'OU'}, $reqtable, 11, 1); } $label = GUI::HELPERS::create_label( _("Keylength").":", 'left', 0, 0); $reqtable->attach_defaults($label, 0, 1, 13, 14); $radiobox = Gtk2::HBox->new(0, 0); # use config if present main::printd("preparing radiobox for type " . $self->{'CA'}->{'cfg'}->{global}{default_req_type}); if ($self->{'CA'}->{'cfg'}->{global}{default_req_type} eq 'user') { $opts->{'bits'} = $self->{'CA'}->{'cfg'}->{user}{default_bits} // \$opts->{'bits'}; } elsif ($self->{'CA'}->{'cfg'}->{global}{default_req_type} eq 'server') { $opts->{'bits'} = $self->{'CA'}->{'cfg'}->{server}{default_bits}// \$opts->{'bits'}; } _fill_radiobox($radiobox, \$opts->{'bits'}, %bit_lengths); $reqtable->attach_defaults($radiobox, 1, 2, 13, 14); $label = GUI::HELPERS::create_label( _("Digest").":", 'left', 0, 0); $reqtable->attach_defaults($label, 0, 1, 15, 16); $radiobox = Gtk2::HBox->new(0, 0); _fill_radiobox($radiobox, \$opts->{'digest'}, %md_algorithms); $reqtable->attach_defaults($radiobox, 1, 2, 15, 16); $label = GUI::HELPERS::create_label(_("Algorithm").":", 'left', 0, 0); $reqtable->attach_defaults($label, 0, 1, 16, 17); $radiobox = Gtk2::HBox->new(0, 0); _fill_radiobox($radiobox, \$opts->{'algo'}, 'rsa' => 'RSA', 'dsa' => 'DSA'); $reqtable->attach_defaults($radiobox, 1, 2, 16, 17); $box->show_all(); return; } # # get data for revoking a certificate # sub show_cert_revoke_dialog { my ($self, $opts) = @_; my ($box, $button_ok, $button_cancel, $table, $entry, $t, $label, $combo, @combostrings); $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->signal_connect('clicked', sub { $self->{'CERT'}->get_revoke_cert($self, $opts, $box) }); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $box->destroy() }); $box = GUI::HELPERS::dialog_box( $self->{'CA'}->{'actca'} . ': ' . _("Revoke Certificate"), _("Revoke Certificate"), $button_ok, $button_cancel); # small table for data $table = Gtk2::Table->new(1, 2, 0); $table->set_col_spacing(0, 10); $box->vbox->add($table); $entry = GUI::HELPERS::entry_to_table( _("CA Password:"), \$opts->{'passwd'}, $table, 0, 0); $entry->grab_focus(); if($self->{'OpenSSL'}->{'version'} !~ /^0\.9\.[0-6][a-z]?$/) { # OpenSSL < 0.9.7 was not able to handle revocation reasons $label = GUI::HELPERS::create_label( _("Revocation Reason:"), 'left', 0, 0); $table->attach_defaults($label, 0, 1, 1, 2); $combo = Gtk2::Combo->new(); @combostrings = qw( unspecified keyCompromise CACompromise affiliationChanged superseded cessationOfOperation certificateHold); $combo->set_popdown_strings(@combostrings); $combo->set_use_arrows(1); $combo->set_value_in_list(1, 0); $combo->entry->signal_connect('changed' => sub{GUI::CALLBACK::entry_to_var( $combo, $combo->entry, \$opts->{'reason'}, undef, undef)}); $table->attach_defaults($combo, 1, 2, 1, 2); } $box->show_all(); return; } # # get data for exporting a crl # sub show_crl_export_dialog { my ($self, $opts) = @_; my ($box, $button_ok, $button_cancel, $button, $label, $format1, $format2, $format3, $table, $entry, $fileentry, $hbox); $button_ok = Gtk2::Button->new_from_stock('gtk-save'); $button_ok->signal_connect('clicked' => sub { $self->{'CA'}->export_crl($self, $opts, $box) }); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $box->destroy() }); $box = GUI::HELPERS::dialog_box( $self->{'CA'}->{'actca'} . ': ' . _("Export CRL"), _("Export Revocation List to File"), $button_ok, $button_cancel); # small table for file selection $table = Gtk2::Table->new(3, 3, 0); $table->set_col_spacing(0, 10); $box->vbox->add($table); $label = GUI::HELPERS::create_label(_("File:"), 'left', 0, 0); $table->attach_defaults($label, 0, 1, 0, 1); $fileentry = Gtk2::Entry->new(); $table->attach_defaults($fileentry, 1, 2, 0, 1); $fileentry->set_text($opts->{'outfile'}) if(defined($opts->{'outfile'})); $fileentry->signal_connect( 'changed' => sub{GUI::CALLBACK::entry_to_var( $fileentry, $fileentry, \$opts->{'outfile'})}); $fileentry->grab_focus(); $button = Gtk2::Button->new(_("Browse...")); $button->signal_connect('clicked' => sub{GUI::HELPERS::browse_file( _("Export CA Certificate"), $fileentry, 'save')}); $table->attach_defaults($button, 2, 3, 0, 1); $entry = GUI::HELPERS::entry_to_table(_("CA Password:"), \$opts->{'passwd'}, $table, 1, 0); $entry->grab_focus(); $entry = GUI::HELPERS::entry_to_table(_("Valid for (Days):"), \$opts->{'days'}, $table, 2, 1); $label = GUI::HELPERS::create_label( _("Export Format:"), 'left', 0, 0); $box->vbox->add($label); $hbox = Gtk2::HBox->new(0, 0); $box->vbox->add($hbox); $format1 = Gtk2::RadioButton->new(undef, _("PEM")); $format1->set_active(1) if(defined($opts->{'format'}) && $opts->{'format'} eq 'PEM'); $format1->signal_connect('toggled' => sub{GUI::CALLBACK::toggle_to_var($format1, \$opts->{'format'}, 'PEM', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry)}); $hbox->add($format1); $format2 = Gtk2::RadioButton->new($format1, _("DER")); $format2->set_active(1) if(defined($opts->{'format'}) && $opts->{'format'} eq 'DER'); $format2->signal_connect('toggled' => sub{GUI::CALLBACK::toggle_to_var($format2, \$opts->{'format'}, 'DER', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry)}); $hbox->add($format2); $format3 = Gtk2::RadioButton->new($format1, _("TXT")); $format3->set_active(1) if(defined($opts->{'format'}) && $opts->{'format'} eq 'TXT'); $format3->signal_connect('toggled' => sub{ GUI::CALLBACK::toggle_to_var($format3, \$opts->{'format'}, 'TXT', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry)}); $hbox->add($format3); $box->show_all(); return; } # # get data for exporting a ca certificate chain # sub show_ca_chain_export_dialog { my ($self, $opts) = @_; my ($box, $button_ok, $button_cancel, $button, $label, $format1, $format2, $format3, $table, $fileentry, $hbox); $button_ok = Gtk2::Button->new_from_stock('gtk-save'); $button_ok->signal_connect('clicked', sub { $self->{'CA'}->export_ca_chain($self, $opts, $box) }); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $box->destroy() }); $box = GUI::HELPERS::dialog_box( $self->{'CA'}->{'actca'} . ': ' . _("Export CA Certificate Chain"), _("Export CA Certificate Chain to File"), $button_ok, $button_cancel); # small table for file selection $table = Gtk2::Table->new(1, 3, 0); $box->vbox->add($table); $label = GUI::HELPERS::create_label(_("File:"), 'left', 0, 0); $table->attach_defaults($label, 0, 1, 0, 1); $fileentry = Gtk2::Entry->new(); $table->attach_defaults($fileentry, 1, 2, 0, 1); $fileentry->set_text($opts->{'outfile'}) if(defined($opts->{'outfile'})); $fileentry->signal_connect( 'changed' => sub { GUI::CALLBACK::entry_to_var( $fileentry, $fileentry, \$opts->{'outfile'}) }); $fileentry->grab_focus(); $button = Gtk2::Button->new(_("Browse...")); $button->signal_connect('clicked' => sub{GUI::HELPERS::browse_file( _("Export CA Certificate Chain"), $fileentry, 'save')}); $table->attach_defaults($button, 2, 3, 0, 1); $box->show_all(); return; } # # get data for exporting a ca certificate # sub show_ca_export_dialog { my ($self, $opts) = @_; my ($box, $button_ok, $button_cancel, $label, $format1, $format2, $format3, $table, $entry, $fileentry, $hbox, $button); $button_ok = Gtk2::Button->new_from_stock('gtk-save'); $button_ok->signal_connect('clicked', sub { $self->{'CA'}->export_ca_cert($self, $opts, $box) }); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $box->destroy() }); $box = GUI::HELPERS::dialog_box( $self->{'CA'}->{'actca'} . ': ' . _("Export CA Certificate"), _("Export CA Certificate to File"), $button_ok, $button_cancel); # small table for file selection $table = Gtk2::Table->new(1, 3, 0); $table->set_col_spacing(0, 10); $box->vbox->add($table); $label = GUI::HELPERS::create_label(_("File:"), 'left', 0, 0); $table->attach_defaults($label, 0, 1, 0, 1); $fileentry = Gtk2::Entry->new(); $table->attach_defaults($fileentry, 1, 2, 0, 1); $fileentry->set_text($opts->{'outfile'}) if(defined($opts->{'outfile'})); $fileentry->signal_connect('changed' => sub{GUI::CALLBACK::entry_to_var( $fileentry, $fileentry, \$opts->{'outfile'})}); $fileentry->grab_focus(); $button = Gtk2::Button->new(_("Browse...")); $button->signal_connect('clicked' => sub{GUI::HELPERS::browse_file( _("Export CA Certificate"), $fileentry, 'save')}); $table->attach_defaults($button, 2, 3, 0, 1); $label = GUI::HELPERS::create_label( _("Export Format:"), 'left', 0, 0); $box->vbox->add($label); $hbox = Gtk2::HBox->new(0, 0); $box->vbox->add($hbox); $format1 = Gtk2::RadioButton->new(undef, _("PEM")); $format1->set_active(1) if(defined($opts->{'format'}) && $opts->{'format'} eq 'PEM'); $format1->signal_connect_after('toggled' => sub{GUI::CALLBACK::toggle_to_var($format1, \$opts->{'format'}, 'PEM', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry)}); $hbox->add($format1); $format2 = Gtk2::RadioButton->new($format1, _("DER")); $format2->set_active(1) if(defined($opts->{'format'}) && $opts->{'format'} eq 'DER'); $format2->signal_connect_after('toggled' => sub{GUI::CALLBACK::toggle_to_var($format2, \$opts->{'format'}, 'DER', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry)}); $hbox->add($format2); $format3 = Gtk2::RadioButton->new($format1, _("TXT")); $format3->set_active(1) if(defined($opts->{'format'}) && $opts->{'format'} eq 'TXT'); $format3->signal_connect_after('toggled' => sub{GUI::CALLBACK::toggle_to_var($format3, \$opts->{'format'}, 'TXT', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry)}); $hbox->add($format3); $box->show_all(); return; } # # get filename for importing keys # sub show_key_import_dialog { my ($self, $opts) = @_; my ($box, $button_ok, $button_cancel, $button, $entry, $table, $label); my ($t, $fileentry); $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->signal_connect('clicked', sub { $self->{'KEY'}->get_import_key($self, $opts, $box) }); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $box->destroy() }); $box = GUI::HELPERS::dialog_box( $self->{'CA'}->{'actca'} . ': ' . _("Import Key"), _("Import Key"), $button_ok, $button_cancel); $box->set_default_size(640, -1); # small table for file selection $table = Gtk2::Table->new(1, 3, 0); $table->set_col_spacing(0, 10); $box->vbox->add($table); $label = GUI::HELPERS::create_label(_("File:"), 'left', 0, 0); $table->attach($label, 0, 1, 0, 1, 'fill', 'fill', 0, 0); $t = _("Select key file"); $fileentry = Gtk2::Entry->new(); $fileentry->set_text($opts->{'infile'}) if(defined($opts->{'infile'})); $fileentry->signal_connect( 'changed', sub{ GUI::CALLBACK::entry_to_var( $fileentry, $fileentry, \$opts->{'infile'})}); $table->attach_defaults($fileentry, 1, 2, 0, 1); $button = Gtk2::Button->new(_("Browse...")); $button->signal_connect('clicked' => sub{GUI::HELPERS::browse_file( $t, $fileentry, 'key')}); $table->attach($button, 2, 3, 0, 1, 'fill', 'fill', 0, 0); $label = GUI::HELPERS::create_label(_("Metadata"), 'left', 0, 1); $box->vbox->add($label); $table = Gtk2::Table->new(1, 5, 0); $table->set_col_spacing(0, 7); $box->vbox->add($table); $entry = GUI::HELPERS::entry_to_table( _("Common Name"), \$opts->{'CN'}, $table, 0, 1); $entry = GUI::HELPERS::entry_to_table( _("eMail Address").":", \$opts->{'EMAIL'}, $table, 1, 1); $entry = GUI::HELPERS::entry_to_table( _("Country Name (2 letter code):"), \$opts->{'C'}, $table, 2, 1); $entry = GUI::HELPERS::entry_to_table( _("State or Province Name:"), \$opts->{'ST'}, $table, 3, 1); $entry = GUI::HELPERS::entry_to_table( _("Locality Name (eg. city):"), \$opts->{'L'}, $table, 4, 1); $entry = GUI::HELPERS::entry_to_table( _("Organization Name (eg. company):"), \$opts->{'O'}, $table, 5, 1); $entry = GUI::HELPERS::entry_to_table( _("Organizational Unit Name (eg. section):"), \$opts->{'OU'}, $table, 6, 1); # Hint: We don't need the password for import $box->show_all(); return; } # # get password for exporting keys # sub show_key_nopasswd_dialog { my ($self, $opts) = @_; my ($box, $button_ok, $button_cancel, $label, $table, $entry); $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->signal_connect('clicked', sub { $self->{'KEY'}->get_export_key($self, $opts, $box) }); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $box->destroy() }); $box = GUI::HELPERS::dialog_box( $self->{'CA'}->{'actca'} . ': ' . _("Export Key without Passphrase"), _("Export Key without Passphrase"), $button_ok, $button_cancel); $label = GUI::HELPERS::create_label( _("I hope you know what you\'re doing?"), 'center', 1, 0); $box->vbox->add($label); $label = GUI::HELPERS::create_label( _("The Key Passphrase is needed for decryption of the Key"), 'center', 1, 0); $box->vbox->add($label); # small table for data $table = Gtk2::Table->new(1, 2, 0); $table->set_col_spacing(0, 10); $box->vbox->add($table); $entry = GUI::HELPERS::entry_to_table(_("Password:"), \$opts->{'passwd'}, $table, 0, 0); $entry->grab_focus(); $box->show_all(); return; } # # get filename for importing a request # sub show_req_import_dialog { my $self = shift; my $opts = {}; my($box, $button_ok, $button_cancel, $button, $entry, $table, $label); $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->signal_connect('clicked', sub { $self->{'REQ'}->get_import_req($self, $opts, $box) }); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $box->destroy() }); $box = GUI::HELPERS::dialog_box( $self->{'CA'}->{'actca'} . ': ' . _("Import Request"), _("Import Request from File"), $button_ok, $button_cancel); # small table for data $table = Gtk2::Table->new(2, 3, 0); $table->set_col_spacing(0, 10); $box->vbox->add($table); $label = GUI::HELPERS::create_label(_("File:"), 'left', 0, 0); $table->attach_defaults($label, 0, 1, 0, 1); $entry = Gtk2::Entry->new(); $table->attach_defaults($entry, 1, 2, 0, 1); $entry->signal_connect( 'changed' => sub{ GUI::CALLBACK::entry_to_var($entry, $entry, \$opts->{'infile'})}); $entry->grab_focus(); $button = Gtk2::Button->new(_("Browse...")); $button->signal_connect('clicked' => sub{GUI::HELPERS::browse_file( _("Import Request from File"), $entry, 'open')}); $table->attach_defaults($button, 2, 3, 0, 1); $box->show_all(); return; } # # get data for exporting a certificate # sub show_export_dialog { my ($self, $opts, $mode) = @_; my ($box, $button_ok, $button_cancel, $button, $label, $table, $entry, $fileentry, $format1, $format2, $format3, $format4, $format5, $format6, $passbox, $pass1, $pass2, $title, $text, $t, $incbox, $inc1, $inc2, $fpbox, $incfp1, $incfp2); if($mode eq 'cert') { $title = _("Export Certificate"); } elsif($mode eq 'key') { $title = _("Export Key"); } else { GUI::HELPERS::print_error( _("Invalid mode for show_export_dialog(): ").$mode); return; } $button_ok = Gtk2::Button->new_from_stock('gtk-save'); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); if($mode eq 'cert') { $button_ok->signal_connect('clicked', sub { $self->{'CERT'}->get_export_cert($self, $opts, $box) }); } else { $button_ok->signal_connect('clicked', sub { $self->{'KEY'}->get_export_key($self, $opts, $box) }); } $button_cancel->signal_connect('clicked', sub { $box->destroy() }); if($mode eq 'cert') { $text = _("Export Certificate to File"); } else { $text = _("Export Key to File"); } $box = GUI::HELPERS::dialog_box($title, $text, $button_ok, $button_cancel); $box->set_default_size(640, -1); # small table for file selection $table = Gtk2::Table->new(1, 3, 0); $table->set_col_spacing(0, 10); $box->vbox->add($table); $label = GUI::HELPERS::create_label(_("File:"), 'left', 0, 0); $table->attach($label, 0, 1, 0, 1, 'fill', 'fill', 0, 0); if($mode eq 'cert') { $t = _("Export Certificate"); }else { $t = _("Export Key"); } $fileentry = Gtk2::Entry->new(); $table->attach_defaults($fileentry, 1, 2, 0, 1); $fileentry->set_text($opts->{'outfile'}) if(defined($opts->{'outfile'})); $fileentry->signal_connect( 'changed', sub{ GUI::CALLBACK::entry_to_var( $fileentry, $fileentry, \$opts->{'outfile'})}); $fileentry->grab_focus(); $button = Gtk2::Button->new(_("Browse...")); $button->signal_connect('clicked' => sub{GUI::HELPERS::browse_file( $t, $fileentry, 'save')}); $table->attach($button, 2, 3, 0, 1, 'fill', 'fill', 0, 0); $label = GUI::HELPERS::create_label( _("Export Format:"), 'center', 0, 0); $box->vbox->add($label); if($mode eq 'cert') { $t = _("PEM (Certificate)"); }else { $t = _("PEM (Key)"); } $format1 = Gtk2::RadioButton->new(undef, $t); $format1->set_active(1) if(defined($opts->{'format'}) && $opts->{'format'} eq 'PEM'); $box->vbox->add($format1); if($mode eq 'cert') { $t = _("DER (Certificate)"); }else { $t = _("DER (Key without Passphrase)"); } $format2 = Gtk2::RadioButton->new($format1, $t); $format2->set_active(1) if(defined($opts->{'format'}) && $opts->{'format'} eq 'DER'); $box->vbox->add($format2); $t = _("PKCS#12 (Certificate & Key)"); $format3 = Gtk2::RadioButton->new($format1, $t); $format3->set_active(1) if(defined($opts->{'format'}) && $opts->{'format'} eq 'P12'); $box->vbox->add($format3); $t = _("Zip (Certificate & Key)"); $format4 = Gtk2::RadioButton->new($format1, $t); $format4->set_active(1) if(defined($opts->{'format'}) && $opts->{'format'} eq 'ZIP'); $box->vbox->add($format4); if(not -x $self->{'init'}->{'zipbin'}) { $format4->set_sensitive(0); } $t = _("Tar (Certificate & Key)"); $format5 = Gtk2::RadioButton->new($format1, $t); $format5->set_active(1) if(defined($opts->{'format'}) && $opts->{'format'} eq 'TAR'); $box->vbox->add($format5); if(not -x $self->{'init'}->{'tarbin'}) { $format5->set_sensitive(0); } if($mode eq 'cert') { $format6 = Gtk2::RadioButton->new( $format1, _("TXT (Certificate)")); $format6->set_active(1) if(defined($opts->{'format'}) && $opts->{'format'} eq 'TXT'); $box->vbox->add($format6); } else { # no password for PEM key $label = GUI::HELPERS::create_label( _("Without Passphrase (PEM/PKCS#12)"), 'left', 0, 0); $box->vbox->add($label); $passbox = Gtk2::HBox->new(0, 0); $box->vbox->add($passbox); $pass1 = Gtk2::RadioButton->new(undef, _("Yes")); $pass1->set_active(1) if(defined($opts->{'nopass'}) && $opts->{'nopass'} == 1); $passbox->add($pass1); $pass2 = Gtk2::RadioButton->new($pass1, _("No")); $pass2->set_active(1) if(defined($opts->{'nopass'}) && $opts->{'nopass'} == 0); $passbox->add($pass2); } # add key/certificate if($mode eq 'cert') { $label = GUI::HELPERS::create_label( _("Include Key (PEM)"), 'left', 0, 0); $box->vbox->add($label); } else { $label = GUI::HELPERS::create_label( _("Include Certificate (PEM)"), 'left', 0, 0); $box->vbox->add($label); } $incbox = Gtk2::HBox->new(0, 0); $box->vbox->add($incbox); $inc1 = Gtk2::RadioButton->new(undef, _("Yes")); $inc1->set_active(1) if(defined($opts->{'include'}) && $opts->{'include'} == 1); $incbox->add($inc1); $inc2 = Gtk2::RadioButton->new($inc1, _("No")); $inc2->set_active(1) if(defined($opts->{'include'}) && $opts->{'include'} == 0); $incbox->add($inc2); # add fingerprint if($mode eq 'cert') { $label = GUI::HELPERS::create_label( _("Include Fingerprint (PEM)"), 'left', 0, 0); $box->vbox->add($label); $fpbox = Gtk2::HBox->new(0, 0); $box->vbox->add($fpbox); $incfp1 = Gtk2::RadioButton->new(undef, _("Yes")); $incfp1->set_active(1) if(defined($opts->{'incfp'}) && $opts->{'incfp'} == 1); $fpbox->add($incfp1); $incfp2 = Gtk2::RadioButton->new($incfp1, _("No")); $incfp2->set_active(1) if(defined($opts->{'incfp'}) && $opts->{'incfp'} == 0); $fpbox->add($incfp2); } if($mode eq 'cert') { $format1->signal_connect('toggled' => sub{ GUI::CALLBACK::toggle_to_var($format1, \$opts->{'format'}, 'PEM', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry)}); $format2->signal_connect('toggled' => sub{ &GUI::CALLBACK::toggle_to_var($format2, \$opts->{'format'}, 'DER', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry)}); $format3->signal_connect('toggled' => sub{ GUI::CALLBACK::toggle_to_var($format3, \$opts->{'format'}, 'P12', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry)}); $format4->signal_connect('toggled' => sub{ GUI::CALLBACK::toggle_to_var($format4, \$opts->{'format'}, 'ZIP', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry)}); $format5->signal_connect('toggled' => sub{ GUI::CALLBACK::toggle_to_var($format5, \$opts->{'format'}, 'TAR', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry)}); $format6->signal_connect('toggled' => sub{ GUI::CALLBACK::toggle_to_var($format6, \$opts->{'format'}, 'TXT', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry)}); $inc1->signal_connect('toggled' => sub { GUI::CALLBACK::toggle_to_var($incfp1, \$opts->{'include'}, 1)}); $inc2->signal_connect('toggled' => sub { GUI::CALLBACK::toggle_to_var($incfp2, \$opts->{'include'}, 0)}); $incfp1->signal_connect('toggled' => sub { GUI::CALLBACK::toggle_to_var($incfp1, \$opts->{'incfp'}, 1)}); $incfp2->signal_connect('toggled' => sub { GUI::CALLBACK::toggle_to_var($incfp2, \$opts->{'incfp'}, 0)}); }else { $format1->signal_connect('toggled' => sub{ GUI::CALLBACK::toggle_to_var($format1, \$opts->{'format'}, 'PEM', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry, $pass1, $pass2)}); $format2->signal_connect('toggled' => sub{ &GUI::CALLBACK::toggle_to_var($format2, \$opts->{'format'}, 'DER', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry, $pass1, $pass2)}); $format3->signal_connect('toggled' => sub{ GUI::CALLBACK::toggle_to_var($format3, \$opts->{'format'}, 'P12', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry, $pass1, $pass2)}); $format4->signal_connect('toggled' => sub{ GUI::CALLBACK::toggle_to_var($format4, \$opts->{'format'}, 'ZIP', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry, $pass1, $pass2)}); $format5->signal_connect('toggled' => sub{ GUI::CALLBACK::toggle_to_var($format5, \$opts->{'format'}, 'TAR', \$opts->{'outfile'}, \$opts->{'format'}, $fileentry, $pass1, $pass2)}); $pass1->signal_connect('toggled' => sub { GUI::CALLBACK::toggle_to_var($pass1, \$opts->{'nopass'}, 1)}); $pass2->signal_connect('toggled' => sub { GUI::CALLBACK::toggle_to_var($pass2, \$opts->{'nopass'}, 0)}); $inc1->signal_connect('toggled' => sub { GUI::CALLBACK::toggle_to_var($inc1, \$opts->{'include'}, 1)}); $inc2->signal_connect('toggled' => sub { GUI::CALLBACK::toggle_to_var($inc2, \$opts->{'include'}, 0)}); } $box->show_all(); return; } # # get export passwd for pkcs#12 # sub show_p12_export_dialog { my ($self, $opts, $mode) = @_; my ($box, $label, $table, $entry, $button_ok, $button_cancel, $radiobox, $includeca1, $includeca2, $passbox, $pass1, $pass2); $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); if($mode eq 'key') { $button_ok->signal_connect('clicked', sub { $self->{'KEY'}->get_export_key($self, $opts, $box) }); } elsif($mode eq 'cert') { $button_ok->signal_connect('clicked', sub { $self->{'CERT'}->get_export_cert($self, $opts, $box) }); } $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $box->destroy() }); $box = GUI::HELPERS::dialog_box( $self->{'CA'}->{'actca'} . ': ' . _("Export to PKCS#12"), _("Export to PKCS#12"), $button_ok, $button_cancel); # small table for storage name $table = Gtk2::Table->new(2, 2, 0); $box->vbox->add($table); $entry = GUI::HELPERS::entry_to_table(_("Key Password:"), \$opts->{'passwd'}, $table, 0, 0); $entry->grab_focus(); $entry = GUI::HELPERS::entry_to_table(_("Export Password:"), \$opts->{'p12passwd'}, $table, 1, 0); $entry = GUI::HELPERS::entry_to_table(_("Friendly Name:"), \$opts->{'friendlyname'}, $table, 2, 1); $label = GUI::HELPERS::create_label( _("Without Passphrase"), 'left', 0, 0); $box->vbox->add($label); $passbox = Gtk2::HBox->new(0, 0); $box->vbox->add($passbox); $pass1 = Gtk2::RadioButton->new(undef, _("Yes")); $pass1->signal_connect_after('toggled' => sub { GUI::CALLBACK::toggle_to_var( $pass1, \$opts->{'nopass'}, 1) }); $passbox->add($pass1); $pass2 = Gtk2::RadioButton->new($pass1, _("No")); $pass2->signal_connect_after('toggled' => sub { GUI::CALLBACK::toggle_to_var( $pass2, \$opts->{'nopass'}, 0) }); $passbox->add($pass2); if((defined($opts->{'nopass'})) && ($opts->{'nopass'} == 1)) { $pass1->set_active(1); } else { $pass2->set_active(1); } $label = GUI::HELPERS::create_label( _("Add CA Certificate to PKCS#12 structure"), 'left', 0, 0); $box->vbox->add($label); $radiobox = Gtk2::HBox->new(0, 0); $box->vbox->add($radiobox); $includeca1 = Gtk2::RadioButton->new(undef, _("Yes")); $includeca1->signal_connect('toggled' => sub { GUI::CALLBACK::toggle_to_var( $includeca1, \$opts->{'includeca'}, 1) }); $radiobox->add($includeca1); $includeca2 = Gtk2::RadioButton->new($includeca1, _("No")); $includeca2->signal_connect('toggled' => sub { GUI::CALLBACK::toggle_to_var( $includeca2, \$opts->{'includeca'}, 0) }); $radiobox->add($includeca2); if(defined($opts->{'includeca'}) && $opts->{'includeca'} == 1) { $includeca1->set_active(1); } else { $includeca2->set_active(1); } $box->show_all(); return; } # # get data for signing a request # sub show_req_sign_dialog { my ($self, $opts) = @_; my($box, $button_ok, $button_cancel, $entry, $table, $t, $rows, $key1, $key2, $radiobox, $label); $rows = 0; $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->signal_connect('clicked', sub { $self->{'REQ'}->get_sign_req($self, $opts, $box) }); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $box->destroy() }); $box = GUI::HELPERS::dialog_box( $self->{'CA'}->{'actca'} . ': ' . _("Sign Request"), _("Sign Request/Create Certificate"), $button_ok, $button_cancel); # small table for data $table = Gtk2::Table->new(2, 2, 0); $table->set_col_spacing(0, 10); $box->vbox->add($table); $entry = GUI::HELPERS::entry_to_table(_("CA Password:"), \$opts->{'passwd'}, $table, $rows, 0); $rows++; $entry->grab_focus(); $entry = GUI::HELPERS::entry_to_table(_("Valid for (Days):"), \$opts->{'days'}, $table, $rows, 1); $rows++; # print STDERR "DEBUG: got type: $opts->{'type'}\n"; if($opts->{'type'} eq 'server') { if(defined($self->{'TCONFIG'}->{'server_cert'}->{'subjectAltName'}) && $self->{'TCONFIG'}->{'server_cert'}->{'subjectAltName'} eq 'user') { if($self->{'TCONFIG'}->{'server_cert'}->{'subjectAltNameType'} eq 'ip'){ $t = _("Subject alternative name (IP Address):"); }elsif($self->{TCONFIG}->{'server_cert'}->{'subjectAltNameType'} eq 'dns'){ $t = _("Subject alternative name (DNS Name):"); }elsif($self->{TCONFIG}->{'server_cert'}->{'subjectAltNameType'} eq 'raw'){ $t = _("Subject alternative name (raw):"); } $entry = GUI::HELPERS::entry_to_table($t, \$opts->{'subjectAltName'}, $table, $rows, 1); $rows++; } if(defined($self->{'TCONFIG'}->{'server_cert'}->{'extendedKeyUsage'}) && $self->{'TCONFIG'}->{'server_cert'}->{'extendedKeyUsage'} eq 'user') { $t = _("Extended Key Usage:"); $entry = GUI::HELPERS::entry_to_table($t, \$opts->{'extendedKeyUsage'}, $table, $rows, 1); $rows++; } if(defined($self->{'TCONFIG'}->{'server_cert'}->{'nsSslServerName'}) && $self->{'TCONFIG'}->{'server_cert'}->{'nsSslServerName'} eq 'user') { $t = _("Netscape SSL Server Name:"); $entry = GUI::HELPERS::entry_to_table($t, \$opts->{'nsSslServerName'}, $table, $rows, 1); $rows++; } if(defined($self->{'TCONFIG'}->{'server_cert'}->{'nsRevocationUrl'}) && $self->{'TCONFIG'}->{'server_cert'}->{'nsRevocationUrl'} eq 'user') { $t = _("Netscape Revocation URL:"); $entry = GUI::HELPERS::entry_to_table($t, \$opts->{'nsRevocationUrl'}, $table, $rows, 1); $rows++; } if(defined($self->{'TCONFIG'}->{'server_cert'}->{'nsRenewalUrl'}) && $self->{'TCONFIG'}->{'server_cert'}->{'nsRenewalUrl'} eq 'user') { $t = _("Netscape Renewal URL:"); $entry = GUI::HELPERS::entry_to_table($t, \$opts->{'nsRenewalUrl'}, $table, $rows, 1); $rows++; } }elsif($opts->{'type'} eq 'client') { if(defined($self->{'TCONFIG'}->{'client_cert'}->{'subjectAltName'}) && $self->{'TCONFIG'}->{'client_cert'}->{'subjectAltName'} eq 'user') { if($self->{'TCONFIG'}->{'client_cert'}->{'subjectAltNameType'} eq 'ip'){ $t = _("Subject alternative name (IP Address):"); }elsif($self->{TCONFIG}->{'client_cert'}->{'subjectAltNameType'} eq 'dns'){ $t = _("Subject alternative name (DNS Name):"); }elsif($self->{TCONFIG}->{'client_cert'}->{'subjectAltNameType'} eq 'mail'){ $t = _("Subject alternative name (eMail Address):"); }elsif($self->{TCONFIG}->{'client_cert'}->{'subjectAltNameType'} eq 'raw'){ $t = _("Subject alternative name (raw):"); } $entry = GUI::HELPERS::entry_to_table($t, \$opts->{'subjectAltName'}, $table, $rows, 1); $rows++; } if(defined($self->{'TCONFIG'}->{'client_cert'}->{'extendedKeyUsage'}) && $self->{'TCONFIG'}->{'client_cert'}->{'extendedKeyUsage'} eq 'user') { $t = _("Extended Key Usage:"); $entry = GUI::HELPERS::entry_to_table($t, \$opts->{'extendedKeyUsage'}, $table, $rows, 1); $rows++; } if(defined($self->{'TCONFIG'}->{'client_cert'}->{'nsRevocationUrl'}) && $self->{'TCONFIG'}->{'client_cert'}->{'nsRevocationUrl'} eq 'user') { $t = _("Netscape Revocation URL:"); $entry = GUI::HELPERS::entry_to_table($t, \$opts->{'nsRevocationUrl'}, $table, $rows, 1); $rows++; } if(defined($self->{'TCONFIG'}->{'client_cert'}->{'nsRenewalUrl'}) && $self->{'TCONFIG'}->{'client_cert'}->{'nsRenewalUrl'} eq 'user') { $t = _("Netscape Renewal URL:"); $entry = GUI::HELPERS::entry_to_table($t, \$opts->{'nsRenewalUrl'}, $table, $rows, 1); $rows++; } } # OpenSSL < 0.9.7 was not able to dynamically handle mailadresses in DNs if($self->{'OpenSSL'}->{'version'} !~ /^0\.9\.[0-6][a-z]?$/) { $radiobox = Gtk2::HBox->new(0, 0); $key1 = Gtk2::RadioButton->new(undef, _("Yes")); $key1->signal_connect('toggled' => sub{GUI::CALLBACK::toggle_to_var($key1, \$opts->{'noemaildn'}, 0)}); $radiobox->add($key1); $key2 = Gtk2::RadioButton->new($key1, _("No")); $key2->signal_connect('toggled' => sub{GUI::CALLBACK::toggle_to_var($key2, \$opts->{'noemaildn'}, 1)}); $radiobox->add($key2); # For server set default to 'no' if($opts->{'type'} eq 'server') { $key2->set_active(1); }else{ $key1->set_active(1); } $label = GUI::HELPERS::create_label( _("Add eMail Address to Subject DN:"), 'left', 0, 0); $table->attach_defaults($label, 0, 1, $rows, $rows+1); $table->attach_defaults($radiobox, 1, 2, $rows, $rows+1); } $box->show_all(); return; } # # get data for creating a new CA # sub show_ca_dialog { my ($self, $opts, $mode) = @_; my ($box, $button_ok, $button_cancel, $label, $table, $entry, $catable, $pwtable, $radiobox, $key1, $key2, $key3, $key4, $key5); $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->can_default(1); $button_ok->signal_connect('clicked', sub { $self->{'CA'}->get_ca_create($self, $opts, $box, $mode) }); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $box->destroy() }); if(defined($mode) && $mode eq "sub") { $box = GUI::HELPERS::dialog_box( _("Create CA"), _("Create a new Sub CA"), $button_ok, $button_cancel); } else { $box = GUI::HELPERS::dialog_box( _("Create CA"), _("Create a new CA"), $button_ok, $button_cancel); } $button_ok->grab_default(); if(defined($mode) && $mode eq "sub") { # small table for ca-password $pwtable = Gtk2::Table->new(1, 2, 0); $pwtable->set_col_spacing(0, 10); $box->vbox->add($pwtable); $entry = GUI::HELPERS::entry_to_table( _("CA Password (for creating the new CA):"), \$opts->{'parentpw'}, $pwtable, 0, 0); $entry->grab_focus(); } # small table for storage name $table = Gtk2::Table->new(1, 2, 0); $table->set_col_spacing(0, 10); $box->vbox->add($table); $entry = GUI::HELPERS::entry_to_table( _("Name (for local storage):"), \$opts->{'name'}, $table, 0, 1); if(not defined($mode)) { $entry->grab_focus(); } $label = GUI::HELPERS::create_label( _("Data for CA Certificate"), 'left', 0, 0); $box->vbox->add($label); # table for ca data $catable = Gtk2::Table->new(1, 13, 0); $catable->set_col_spacing(0, 10); $box->vbox->add($catable); $entry = GUI::HELPERS::entry_to_table( _("Common Name (for the CA):"), \$opts->{'CN'}, $catable, 0, 1); $entry = GUI::HELPERS::entry_to_table( _("Country Name (2 letter code):"), \$opts->{'C'}, $catable, 1, 1); $entry = GUI::HELPERS::entry_to_table( _("Password (needed for signing):"), \$opts->{'passwd'}, $catable, 2, 0); $entry = GUI::HELPERS::entry_to_table( _("Password (confirmation):"), \$opts->{'passwd2'}, $catable, 3, 0); $entry = GUI::HELPERS::entry_to_table( _("State or Province Name:"), \$opts->{'ST'}, $catable, 4, 1); $entry = GUI::HELPERS::entry_to_table( _("Locality Name (eg. city):"), \$opts->{'L'}, $catable, 5, 1); $entry = GUI::HELPERS::entry_to_table( _("Organization Name (eg. company):"), \$opts->{'O'}, $catable, 6, 1); $entry = GUI::HELPERS::entry_to_table( _("Organizational Unit Name (eg. section):"), \$opts->{'OU'}->[0], $catable, 7, 1); $entry = GUI::HELPERS::entry_to_table( _("eMail Address").":", \$opts->{'EMAIL'}, $catable, 8, 1); $entry = GUI::HELPERS::entry_to_table( _("Valid for (Days):"), \$opts->{'days'}, $catable, 9, 1); $label = GUI::HELPERS::create_label( _("Keylength").":", 'left', 0, 0); $catable->attach_defaults($label, 0, 1, 10, 11); $radiobox = Gtk2::HBox->new(0, 0); $key1 = Gtk2::RadioButton->new(undef, '1024'); $key1->signal_connect('toggled' => sub { GUI::CALLBACK::toggle_to_var($key1, \$opts->{'bits'}, 1024)}); $radiobox->add($key1); $key2 = Gtk2::RadioButton->new($key1, '2048'); $key2->signal_connect('toggled' => sub { GUI::CALLBACK::toggle_to_var($key2, \$opts->{'bits'}, 2048)}); $radiobox->add($key2); $key3 = Gtk2::RadioButton->new($key1, '4096'); $key3->signal_connect('toggled' => sub { GUI::CALLBACK::toggle_to_var($key3, \$opts->{'bits'}, 4096)}); $radiobox->add($key3); # set default if(defined($opts->{'bits'}) && $opts->{'bits'} == 1024) { $key1->set_active(1); } elsif (defined($opts->{'bits'}) && $opts->{'bits'} == 2048) { $key2->set_active(1); } elsif (defined($opts->{'bits'}) && $opts->{'bits'} == 4096) { $key3->set_active(1); } $catable->attach_defaults($radiobox, 1, 2, 10, 11); $label = GUI::HELPERS::create_label(_("Digest").":", 'left', 0, 0); $catable->attach_defaults($label, 0, 1, 15, 16); $radiobox = Gtk2::HBox->new(0, 0); &_fill_radiobox($radiobox, \$opts->{'digest'}, %md_algorithms); $catable->attach_defaults($radiobox, 1, 2, 15, 16); $box->show_all(); return; } # # get data for importing a new CA # sub show_ca_import_dialog { my ($self, $opts) = @_; my ($box, $button, $button_ok, $button_cancel, $label, $table, $filetable, $pwtable, $entry, $certentry, $keyentry, $direntry, $indexentry); $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->can_default(1); $button_ok->signal_connect('clicked', sub { $self->{'CA'}->get_ca_import($self, $opts, $box) }); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $box->destroy() }); $box = GUI::HELPERS::dialog_box( _("Import CA"), _("Import an existing CA into TinyCA"), $button_ok, $button_cancel); $button_ok->grab_default(); # small table for old ca-password $pwtable = Gtk2::Table->new(1, 2, 0); $pwtable->set_col_spacing(0, 10); $box->vbox->add($pwtable); $entry = GUI::HELPERS::entry_to_table( _("Password of the private CA key (Needed for import):"), \$opts->{'passwd'}, $pwtable, 0, 0); $entry->grab_focus(); # small table for storage name and new passwords $table = Gtk2::Table->new(1, 2, 0); $table->set_col_spacing(0, 10); $box->vbox->add($table); $entry = GUI::HELPERS::entry_to_table( _("Name (for local storage):"), \$opts->{'name'}, $table, 0, 1); $entry = GUI::HELPERS::entry_to_table( _("New password for the CA:"), \$opts->{'newpasswd'}, $table, 1, 0); $entry = GUI::HELPERS::entry_to_table( _("Confirm password:"), \$opts->{'newpasswd2'}, $table, 2, 0); # table for file selection dialogs $label = GUI::HELPERS::create_label( _("Files/Directories to import"), 'center', 0, 1); $box->vbox->add($label); $filetable = Gtk2::Table->new(1, 3, 0); $box->vbox->add($filetable); # CA certificate $label = GUI::HELPERS::create_label( _("CA Certificate (PEM/DER):"), 'left', 0, 0); $filetable->attach_defaults($label, 0, 1, 0, 1); $certentry = Gtk2::Entry->new(); $filetable->attach_defaults($certentry, 1, 2, 0, 1); $certentry->set_text($opts->{'cacertfile'}) if(defined($opts->{'cacertfile'})); $certentry->signal_connect( 'changed' => sub { GUI::CALLBACK::entry_to_var( $certentry, $certentry, \$opts->{'cacertfile'}) }); $button = Gtk2::Button->new(_("Browse...")); $button->signal_connect('clicked' => sub{ GUI::HELPERS::browse_file( _("Import CA Certificate"), $certentry, 'open') }); $filetable->attach_defaults($button, 2, 3, 0, 1); # CA private key $label = GUI::HELPERS::create_label( _("CA private key (PEM/DER):"), 'left', 0, 0); $filetable->attach_defaults($label, 0, 1, 1, 2); $keyentry = Gtk2::Entry->new(); $filetable->attach_defaults($keyentry, 1, 2, 1, 2); $keyentry->set_text($opts->{'cakeyfile'}) if(defined($opts->{'cakeyfile'})); $keyentry->signal_connect( 'changed' => sub { GUI::CALLBACK::entry_to_var( $keyentry, $keyentry, \$opts->{'cakeyfile'}) }); $button = Gtk2::Button->new(_("Browse...")); $button->signal_connect('clicked' => sub{ GUI::HELPERS::browse_file( _("Import CA private Key"), $keyentry, 'open') }); $filetable->attach_defaults($button, 2, 3, 1, 2); # Index file $label = GUI::HELPERS::create_label( _("OpenSSL Index File (index.txt):"), 'left', 0, 0); $filetable->attach_defaults($label, 0, 1, 2, 3); $indexentry = Gtk2::Entry->new(); $filetable->attach_defaults($indexentry, 1, 2, 2, 3); $indexentry->set_text($opts->{'indexfile'}) if(defined($opts->{'indexfile'})); $indexentry->signal_connect( 'changed' => sub { GUI::CALLBACK::entry_to_var( $indexentry, $indexentry, \$opts->{'indexfile'}) }); $button = Gtk2::Button->new(_("Browse...")); $button->signal_connect('clicked' => sub{ GUI::HELPERS::browse_file( _("Import Index File"), $indexentry, 'open') }); $filetable->attach_defaults($button, 2, 3, 2, 3); # certificate directory $label = GUI::HELPERS::create_label( _("Directory containing certificates (PEM/DER):"), 'left', 0, 0); $filetable->attach_defaults($label, 0, 1, 3, 4); $direntry = Gtk2::Entry->new(); $filetable->attach_defaults($direntry, 1, 2, 3, 4); $direntry->set_text($opts->{'certdir'}) if(defined($opts->{'certdir'})); $direntry->signal_connect( 'changed' => sub { GUI::CALLBACK::entry_to_var( $direntry, $direntry, \$opts->{'certdir'}) }); $button = Gtk2::Button->new(_("Browse...")); $button->signal_connect('clicked' => sub{ GUI::HELPERS::browse_file( _("Import Certificates from directory"), $direntry, 'open') }); $filetable->attach_defaults($button, 2, 3, 3, 4); $box->show_all(); return; } # # Configuration display dialog # sub show_cfg_dialog { my $self = shift; my $main = shift; my ($box, $button, $table, $label); $box = Gtk2::Dialog->new(_("Preferences"), undef, ["destroy-with-parent"]); $box->signal_connect(response => sub { $box->destroy }); $label = Gtk2::Label->new("base directory:".$main->{'init'}->{'basedir'}); $box->vbox->add($label); $label = Gtk2::Label->new("export directory:".$main->{'init'}->{'exportdir'}); $box->vbox->add($label); $label = Gtk2::Label->new("openssl binary:".$main->{'init'}->{'opensslbin'}); $box->vbox->add($label); $label = Gtk2::Label->new("zip binary:".$main->{'init'}->{'zipbin'}); $box->vbox->add($label); $label = Gtk2::Label->new("tar binary:".$main->{'init'}->{'tarbin'}); $box->vbox->add($label); $button = Gtk2::Button->new_from_stock('gtk-ok'); $box->add_action_widget($button, 0); $button->can_default(1); $button->grab_default(); $box->show_all(); } # # subroutines for pop-up boxes # sub show_help { my $self = shift; GUI::HELPERS::print_info(_("You are kidding, are you??")); return; } # # About dialog # sub about { my $self = shift; my $main = shift; my ($aboutdialog, $href, $label); $aboutdialog = Gtk2::AboutDialog->new(); $aboutdialog->set_program_name("TinyCA2"); $aboutdialog->set_version($main->{'version'}); $aboutdialog->set_comments("using OpenSSL version " . $main->{'OpenSSL'}->get_version()); $aboutdialog->set_copyright("2002-2006 Stephan Martin\n 2020 Thomas Hooge"); $aboutdialog->set_license("GNU Public License (GPL)"); $aboutdialog->set_website("https://www.hoogi.de/tinyca/"); $aboutdialog->set_authors( "Stephan Martin "."\n". "Thomas Hooge "); $aboutdialog->set_translator_credits( _("Czech: Robert Wolf ")."\n". _("Swedish: Daniel Nylander ")."\n". _("Spanish: Ramon Pons Vivanco ")."\n". _("French: Thibault Le Meur ")); $aboutdialog->show_all(); $aboutdialog->run; $aboutdialog->destroy; return; } # # get confirmation for deleting a request # sub show_del_confirm { my ($self, $file, $type) = @_; my($t, $button_ok, $button_cancel, $box); if($type eq 'req') { $t = _("Do you really want to delete the selected Request?"); }elsif($type eq 'key') { $t = _("Do you really want to delete the selected Key?"); }elsif($type eq 'cert') { $t = _("Do you really want to delete the selected Certificate?"); }else{ GUI::HELPERS::print_error("Invalid type in show_del_confirm(): ".$type); } $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); if($type eq 'req') { $button_ok->signal_connect('clicked', sub { $self->{'REQ'}->del_req($self, $file); $box->destroy() }); }elsif($type eq 'key') { $button_ok->signal_connect('clicked', sub { $self->{'KEY'}->del_key($self, $file); $box->destroy() }); }elsif($type eq 'cert') { $button_ok->signal_connect('clicked', sub { $self->{'CERT'}->del_cert($self, $file); $box->destroy() }); } $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $box->destroy(); return }); $box = Gtk2::MessageDialog->new( undef, [qw/destroy-with-parent modal/], 'question', 'none', $t); $box->add_action_widget($button_ok, 0); $box->add_action_widget($button_cancel, 1); $box->show_all(); } # # show warning - overwrite key # sub show_req_overwrite_warning { my ($self, $opts) = @_; my ($box, $actionarea, $button_ok, $button_cancel, $label); $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->signal_connect('clicked' => sub { $self->{'REQ'}->create_req($self, $opts); $box->destroy() }); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->can_default(1); $button_cancel->signal_connect('clicked', sub { $box->destroy() }); $box = GUI::HELPERS::dialog_box( $self->{'CA'}->{'actca'} . ': ' . _("Overwrite Request/Key"), _("Overwrite Request/Key"), $button_ok, $button_cancel); $button_cancel->grab_default(); $label = GUI::HELPERS::create_label( _("The Key or the Request is already existing!"), 'center', 1, 0); $box->vbox->add($label); $label = GUI::HELPERS::create_label( _("You won't be able to sign this Request"), 'center', 1, 0); $box->vbox->add($label); $label = GUI::HELPERS::create_label( _("if the corresponding certificate is still valid"), 'center', 1, 0); $box->vbox->add($label); $box->show_all(); return; } # # show warning - certificate expiration date # sub show_req_date_warning { my ($self, $opts) = @_; my ($box, $button_ok, $button_cancel, $t); $t = _("The certificate will be valid longer than its CA!"); $t .= "\n"; $t .= _("This may cause problems with some software!!"); $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->signal_connect('clicked', sub { $opts->{'ignoredate'} = 'true'; $self->{'REQ'}->get_sign_req($self, $opts, $box); }); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $self->show_req_sign_dialog($opts); $box->destroy(); }); $button_cancel->can_default(1); $box = GUI::HELPERS::dialog_box( _("Expirationdate Warning"), $t, $button_ok, $button_cancel); $button_cancel->grab_default(); $box->show_all(); } # # show CA history # sub show_history { my $self = shift; my ($box, $button_ok, @index, $list, $list_scrolled, $store, @titles, $column, $t, $iter, $dn, $state, $expdate, $revdate, $renderer); @index = $self->{'OpenSSL'}->read_index($self->{'CA'}->{'cadir'}."/index.txt"); $list_scrolled = Gtk2::ScrolledWindow->new(undef, undef); $list_scrolled->set_policy('automatic', 'automatic'); $list_scrolled->set_shadow_type('etched-in'); $store = Gtk2::ListStore->new( 'Glib::String', # common name 'Glib::String', # status 'Glib::String', # serial 'Glib::String', # expiration 'Glib::String', # revocation 'Glib::String' # reason ); $list = Gtk2::TreeView->new_with_model($store); $list->get_selection->set_mode('none'); @titles = ( _("Serial"), _("Common Name"), _("Status"), _("Expiration Date"), _("Revocation Date"), _("Revocation Reason") ); 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 == 2) { $column->set_cell_data_func ($renderer, sub { my ($column, $cell, $model, $iter) = @_; my $text = $model->get($iter, 2); my $color = $text eq _("VALID")?'green':'red'; $cell->set (text => $text, foreground => $color); }); } $list->append_column($column); } foreach my $tmp (@index) { $iter = $store->append(); $dn = HELPERS::parse_dn($tmp->{'DN'}); if($tmp->{'STATUS'} eq 'V') { $state = _("VALID"); } elsif($tmp->{'STATUS'} eq 'E') { $state = _("EXPIRED"); } elsif($tmp->{'STATUS'} eq 'R') { $state = _("REVOKED"); } $expdate = strftime("%F", localtime($tmp->{'EXPDATE'})); if(defined($tmp->{'REVDATE'})) { $revdate = strftime("%F", localtime($tmp->{'REVDATE'})); } else { $revdate = ''; } $store->set($iter, 0 => $tmp->{'SERIAL'}, 1 => $dn->{'CN'}, 2 => $state, 3 => $expdate, 4 => $revdate, 5 => $tmp->{'REVREASON'} ); } $list_scrolled->add_with_viewport($list); $t = _("CA History"); $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->can_default(1); $button_ok->signal_connect('clicked', sub { $box->destroy() }); $box = GUI::HELPERS::dialog_box($t, $t, $button_ok); $box->set_default_size(700, 400); $button_ok->grab_default(); $box->vbox->add($list_scrolled); $box->show_all(); } # # get confirmation for overwriting certificate # sub show_cert_overwrite_confirm { my ($self, $opts) = @_; my($box, $button_ok, $button_cancel, $label); $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->signal_connect('clicked', sub { $opts->{'overwrite'} = 'true'; $self->{'REQ'}->get_sign_req($self, $opts, $box) }); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->can_default(1); $button_cancel->signal_connect('clicked', sub { $box->destroy() }); $box = GUI::HELPERS::dialog_box( $self->{'CA'}->{'actca'} . ': ' . _("Overwrite Certificate"), _("Overwrite Certificate"), $button_ok, $button_cancel); $button_cancel->grab_default(); $label = GUI::HELPERS::create_label( _("There seems to be a certificate with the same Subject already."), 'center', 1, 0); $box->vbox->add($label); $label = GUI::HELPERS::create_label( _("Creating a new one (overwrite) will fail if it\'s not revoked or expired!"), 'center', 1, 0); $box->vbox->add($label); $label = GUI::HELPERS::create_label( _("Really try to overwrite the Certificate?"), 'center', 1, 0); $box->vbox->add($label); $box->show_all(); return; } # # ask if the CA shall be converted # sub show_ca_convert_dialog { my ($self, $opts) = @_; my($box, $label, $button_ok, $button_cancel, $t); $button_ok = Gtk2::Button->new_from_stock('gtk-ok'); $button_ok->signal_connect('clicked', sub { $opts->{'doconv'} = 1; $self->{'CA'}->open_ca($self, $opts, $box) } ); $button_ok->can_default(1); $button_cancel = Gtk2::Button->new_from_stock('gtk-cancel'); $button_cancel->signal_connect('clicked', sub { $opts->{'noconv'} = 1; $self->{'CA'}->open_ca($self, $opts, $box) } ); $box = GUI::HELPERS::dialog_box( $self->{'CA'}->{'actca'} . ': ' . _("Convert CA"), _("Convert CA"), $button_ok, $button_cancel); $button_ok->grab_default(); $label = GUI::HELPERS::create_label(' ', 'center', 0, 0); $box->vbox->pack_start($label, 0, 0, 0); $t = _("This CA seems to be created with openssl 0.9.6x. And it seems like you have switched to openssl 0.9.7x."); $label = GUI::HELPERS::create_label($t, 'center', 1, 0); $box->vbox->add($label); $label = GUI::HELPERS::create_label(' ', 'center', 0, 0); $box->vbox->pack_start($label, 0, 0, 0); $t = _("You won't be able to revoke the existing certificates without converting the index file of this CA to the new format."); $label = GUI::HELPERS::create_label($t, 'center', 1, 0); $box->vbox->add($label); $label = GUI::HELPERS::create_label(' ', 'center', 0, 0); $box->vbox->pack_start($label, 0, 0, 0); $t = _("Attention: it will not be easy to switch back, this has to be done manually"); $label = GUI::HELPERS::create_label($t, 'center', 1, 0); $box->vbox->add($label); $box->show_all(); return; } # # create popup menu for keys # sub _create_key_menu { my $self = shift; my ($item, $image); $self->{'keymenu'} = Gtk2::Menu->new(); $item = Gtk2::ImageMenuItem->new( _("Export Key")); $item->signal_connect(activate => sub { $self->{'KEY'}->get_export_key($self) }); $image = Gtk2::Image->new_from_stock('gtk-save', 'menu'); $item->set_image($image); $self->{'keymenu'}->insert($item, -1); $item = Gtk2::ImageMenuItem->new( _("Delete Key")); $item->signal_connect(activate => sub { $self->{'KEY'}->get_del_key($self) }); $image = Gtk2::Image->new_from_stock('gtk-delete', 'menu'); $item->set_image($image); $self->{'keymenu'}->insert($item, -1); $self->{'keymenu'}->show_all(); return; } # # create popup menus for certificates # sub _create_cert_menu { my $self = shift; my ($item, $image); $self->{'certmenu'} = Gtk2::Menu->new(); $item = Gtk2::ImageMenuItem->new( _("Certificate Details")); $item->signal_connect(activate => sub { $self->show_details('cert') }); $image = Gtk2::Image->new_from_stock('gtk-new', 'menu'); $item->set_image($image); $self->{'certmenu'}->insert($item, -1); $item = Gtk2::ImageMenuItem->new( _("View Certificate")); $item->signal_connect(activate => sub { $self->show_text('cert') }); $image = Gtk2::Image->new_from_stock('gtk-find', 'menu'); $item->set_image($image); $self->{'certmenu'}->insert($item, -1); $item = Gtk2::ImageMenuItem->new( _("Export Certificate")); $item->signal_connect(activate => sub { $self->{'CERT'}->get_export_cert($self) }); $image = Gtk2::Image->new_from_stock('gtk-save', 'menu'); $item->set_image($image); $self->{'certmenu'}->insert($item, -1); $item = Gtk2::ImageMenuItem->new( _("Revoke Certificate")); $item->signal_connect(activate => sub { $self->{'CERT'}->get_revoke_cert($self) }); $image = Gtk2::Image->new_from_stock('gtk-stop', 'menu'); $item->set_image($image); $self->{'certmenu'}->insert($item, -1); $item = Gtk2::ImageMenuItem->new( _("Renew Certificate")); $item->signal_connect(activate => sub { $self->{'renewcertmenu'}->popup( undef, undef, undef, undef, 1, 0) }); $image = Gtk2::Image->new_from_stock('gtk-refresh', 'menu'); $item->set_image($image); $self->{'certmenu'}->insert($item, -1); $item = Gtk2::ImageMenuItem->new( _("Delete Certificate")); $item->signal_connect(activate => sub { $self->{'CERT'}->get_del_cert($self) }); $image = Gtk2::Image->new_from_stock('gtk-delete', 'menu'); $item->set_image($image); $self->{'certmenu'}->insert($item, -1); $self->{'certmenu'}->show_all(); return; } # # create popup menus for creating certificates # sub _create_create_cert_menu { my $self = shift; my ($item); $self->{'newcertmenu'} = Gtk2::Menu->new(); $item = Gtk2::MenuItem->new( _("Create Key and Certificate (Server)")); $item->signal_connect(activate => sub { $self->{'REQ'}->get_req_create($self, "signserver") }); $self->{'newcertmenu'}->insert($item, 0); $item = Gtk2::MenuItem->new( _("Create Key and Certificate (Client)")); $item->signal_connect(activate => sub { $self->{'REQ'}->get_req_create($self, "signclient") }); $self->{'newcertmenu'}->insert($item, 1); $self->{'newcertmenu'}->show_all(); return; } # # create popup menus for sign request button # sub _create_renew_cert_menu { my $self = shift; my ($item, $opts); $self->{'renewcertmenu'} = Gtk2::Menu->new(); $item = Gtk2::MenuItem->new( _("Renew Certificate (Server)")); $item->signal_connect(activate => sub { $opts->{'type'} = 'server'; $self->{'CERT'}->get_renew_cert($self, $opts) }); $self->{'renewcertmenu'}->insert($item, 0); $item = Gtk2::MenuItem->new( _("Renew Certificate (Client)")); $item->signal_connect(activate => sub { $opts->{'type'} = 'client'; $self->{'CERT'}->get_renew_cert($self, $opts) }); $self->{'renewcertmenu'}->insert($item, 1); $self->{'renewcertmenu'}->show_all(); return; } # # create popup menus for sign request button # sub _create_sign_req_menu { my $self = shift; my ($item, $opts); $self->{'reqsignmenu'} = Gtk2::Menu->new(); $item = Gtk2::MenuItem->new( _("Sign Request (Server)")); $item->signal_connect(activate => sub { $opts->{'type'} = 'server'; $self->{'REQ'}->get_sign_req($self, $opts) }); $self->{'reqsignmenu'}->insert($item, 0); $item = Gtk2::MenuItem->new( _("Sign Request (Client)")); $item->signal_connect(activate => sub { $opts->{'type'} = 'client'; $self->{'REQ'}->get_sign_req($self, $opts) }); $self->{'reqsignmenu'}->insert($item, 1); $self->{'reqsignmenu'}->show_all(); return; } # # create popup menus for requests # sub _create_req_menu { my $self = shift; my ($item, $opts, $image); $self->{'reqmenu'} = Gtk2::Menu->new(); $item = Gtk2::ImageMenuItem->new( _("Request Details")); $item->signal_connect(activate => sub { $self->show_details('req') }); $image = Gtk2::Image->new_from_stock('gtk-find', 'menu'); $item->set_image($image); $self->{'reqmenu'}->insert($item, -1); $item = Gtk2::ImageMenuItem->new( _("View Request")); $item->signal_connect(activate => sub { $self->show_text('req') }); $image = Gtk2::Image->new_from_stock('gtk-find', 'menu'); $item->set_image($image); $self->{'reqmenu'}->insert($item, -1); $item = Gtk2::ImageMenuItem->new( _("New Request")); $item->signal_connect(activate => sub { $self->{'REQ'}->get_req_create($self) }); $image = Gtk2::Image->new_from_stock('gtk-new', 'menu'); $item->set_image($image); $self->{'reqmenu'}->insert($item, -1); $item = Gtk2::ImageMenuItem->new( _("Import Request")); $item->signal_connect(activate => sub { $self->{'REQ'}->get_import_req($self) }); $image = Gtk2::Image->new_from_stock('gtk-revert-to-saved', 'menu'); $item->set_image($image); $self->{'reqmenu'}->insert($item, -1); $item = Gtk2::ImageMenuItem->new( _("Sign Request")); $item->signal_connect(activate => sub { $self->{'reqsignmenu'}->popup( undef, undef, undef, undef, 1, 0) }); $image = Gtk2::Image->new_from_stock('gtk-properties', 'menu'); $item->set_image($image); $self->{'reqmenu'}->insert($item, -1); $item = Gtk2::ImageMenuItem->new( _("Delete Request")); $item->signal_connect(activate => sub { $self->{'REQ'}->get_del_req($self) }); $image = Gtk2::Image->new_from_stock('gtk-delete', 'menu'); $item->set_image($image); $self->{'reqmenu'}->insert($item, -1); $self->{'reqmenu'}->show_all(); return; } sub _fill_radiobox { my($radiobox, $var, %values) = @_; my($active_key, $previous_key, $value); $active_key = undef; $previous_key = undef; for $value (sort keys %values) { my $display_name = $values{$value}; my $key = Gtk2::RadioButton->new($previous_key, $display_name); #$key->set_active(1) if(defined($$var) && $$var eq $value); $active_key = $key if(defined($$var) && $$var eq $value); $key->signal_connect('toggled' => sub{GUI::CALLBACK::toggle_to_var($key, $var, $value)}); $radiobox->add($key); $previous_key = $key; } $active_key->set_active(1) if ($active_key); } 1