#!/usr/bin/perl
#
# --- BEGIN COPYRIGHT BLOCK ---
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation;
# version 2.1 of the License.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#
# Copyright (C) 2007 Red Hat, Inc.
# All rights reserved.
# --- END COPYRIGHT BLOCK ---
#
# wizard -
# Fedora Certificate System - Token Processing System configuration wizard
# This script is run as a 'mod_perl' CGI. Configure mod_perl by adding
# the following to /etc/httpd/conf.d/perl.conf
#
# PerlModule ModPerl::Registry
# PerlModule Apache::compat
# PerlModule RHCS::TPS::Wizard
# PerlSetEnv RHCS_DOCROOT /u/sparkins/t/cs_tip/certsystem/prj/common/ui
#
# SetHandler perl-script
# PerlHandler RHCS::TPS::Wizard
# Order deny,allow
# Allow from all
#
# Note: The Velocity parser is not very helpful when it comes to
# errors right now. Here are some common errors, and what they mean:
#
# ERROR:
# [Mon Apr 03 13:57:33 2006] [error] [client 172.16.24.26]
# Can't use string ("0") as an ARRAY ref while "strict refs"
# in use at /usr/lib/perl5/site_perl/5.8.5/Template/Velocity.pm
# line 423.\n, referer: http://chico/wizard?p=2
# MEANING
# This probably means that your *.vm file refers to an array
# variable in a foreach statement that is not defined
# Check your foreach array variables.
use warnings;
use ModPerl::Registry;
use Template::Velocity;
use Getopt::Std;
use Data::Dumper;
use CGI::Carp qw(fatalsToBrowser);
use CGI;
use APR::Const -compile => qw(:error SUCCESS);
use PKI::TPS::GlobalVar;
use PKI::TPS::WelcomePanel;
use PKI::TPS::SecurityDomainPanel;
use PKI::TPS::DisplayCertChainPanel;
use PKI::TPS::SubsystemTypePanel;
use PKI::TPS::CAInfoPanel;
use PKI::TPS::TKSInfoPanel;
use PKI::TPS::DRMInfoPanel;
use PKI::TPS::DisplayCertChain2Panel;
use PKI::TPS::AdminAuthPanel;
use PKI::TPS::AgentAuthPanel;
use PKI::TPS::AuthDBPanel;
use PKI::TPS::DatabasePanel;
use PKI::TPS::ModulePanel;
use PKI::TPS::SizePanel;
use PKI::TPS::NamePanel;
use PKI::TPS::ConfigHSMLoginPanel;
use PKI::TPS::CertRequestPanel;
use PKI::TPS::AdminPanel;
use PKI::TPS::ImportAdminCertPanel;
use PKI::TPS::DonePanel;
use PKI::TPS::Config;
use PKI::TPS::Common qw(yes no r);
package PKI::TPS::Wizard;
$PKI::TPS::Wizard::VERSION = '1.00';
# read configuration file
my $flavor = "pki";
$flavor =~ s/\n//g;
my $pkiroot = $ENV{PKI_ROOT};
my $config = PKI::TPS::Config->new();
$config->load_file("$pkiroot/conf/CS.cfg");
# read password cache file
my $pwdconf = PKI::TPS::Config->new();
$pwdconf->load_file("$pkiroot/conf/pwcache.conf");
# SELinux disallows performing a "chmod" on this file
if( $^O ne "linux" ) {
system( "chmod 00660 $pkiroot/conf/pwcache.conf" );
}
# create cfg debug log
my $logfile = $config->get("service.instanceDir") . "/logs/debug";
system( "touch $logfile" );
system( "chmod 00640 $logfile" );
open( DEBUG, ">>" . $logfile ) ||
warn( "Could not open '" . $logfile . "': $!" );
# apache server
our $debug;
my $STATUS_OK = 0; # Apache 2 needs this to be zero
my $STATUS_ERROR = 2;
my $STATUS_REDIRECT = 3;
&debug_log("TPS wizard: starting up");
my $docroot = $ENV{PKI_DOCROOT};
if (! $docroot) {
&debug_log("TPS wizard: ERROR: PKI_DOCROOT is null");
return 0;
}
our $parser = new Template::Velocity($docroot);
our $symbol;
our @certtags;
makepanels();
&debug_log("TPS wizard: start up complete");
1;
sub debug_log
{
my ($msg) = @_;
my $date = `date`;
chomp($date);
if( -w $logfile ) {
print DEBUG "$date - $msg\n";
}
}
# initializes entries in parser's global symbol table for panels
sub makepanels
{
#REAL PANELS BELOW
my $welcome = new PKI::TPS::WelcomePanel();
my $securitydomain = new PKI::TPS::SecurityDomainPanel();
my $displaycertchain = new PKI::TPS::DisplayCertChainPanel();
my $subsystem = new PKI::TPS::SubsystemTypePanel();
my $cainfopanel = new PKI::TPS::CAInfoPanel();
# my $displaycertchain2 = new PKI::TPS::DisplayCertChain2Panel();
my $tksinfopanel = new PKI::TPS::TKSInfoPanel();
my $drminfopanel = new PKI::TPS::DRMInfoPanel();
my $authdbpanel = new PKI::TPS::AuthDBPanel();
my $databasepanel = new PKI::TPS::DatabasePanel();
my $modulepanel = new PKI::TPS::ModulePanel();
my $confighsmloginpanel = new PKI::TPS::ConfigHSMLoginPanel();
my $sizepanel = new PKI::TPS::SizePanel();
my $namepanel = new PKI::TPS::NamePanel();
my $certrequestpanel = new PKI::TPS::CertRequestPanel();
my $adminpanel = new PKI::TPS::AdminPanel();
my $importadmincertpanel = new PKI::TPS::ImportAdminCertPanel();
my $donepanel = new PKI::TPS::DonePanel();
$symbol{panels} = [
$welcome, # com.netscape.cms.servlet.csadmin.WelcomePanel
$modulepanel, # com.netscape.cms.servlet.csadmin.ModulePanel
$confighsmloginpanel, # com.netscape.cms.servlet.csadmin.ConfigHSMLoginPanel
$securitydomain, # com.netscape.cms.servlet.csadmin.SecurityDomainPanel
$displaycertchain, # com.netscape.cms.servlet.csadmin.DisplayCertChainPanel
$subsystem, # com.netscape.cms.servlet.csadmin.CreateSubsystemPanel
$cainfopanel, # com.netscape.cms.servlet.csadmin.CAInfoPanel
# $displaycertchain2, # com.netscape.cms.servlet.csadmin.DisplayCertChain2Panel
$tksinfopanel, # com.netscape.cms.servlet.csadmin.TKSInfoPanel
$drminfopanel, # com.netscape.cms.servlet.csadmin.DRMInfoPanel
$authdbpanel, # com.netscape.cms.servlet.csadmin.DatabasePanel
$databasepanel, # com.netscape.cms.servlet.csadmin.DatabasePanel
$sizepanel, # com.netscape.cms.servlet.csadmin.SizePanel
$namepanel, # com.netscape.cms.servlet.csadmin.NamePanel
$certrequestpanel, # com.netscape.cms.servlet.csadmin.CertRequestPanel
$adminpanel, # com.netscape.cms.servlet.csadmin.AdminPanel
$importadmincertpanel, # com.netscape.cms.servlet.csadmin.ImportAdminCertPanel
$donepanel, # com.netscape.cms.servlet.csadmin.DonePanel
];
};
sub render_panel
{
my ($panelnum, $q) = @_;
$symbol{errorString} = "";
my $currentpanel;
if ($q->param('op') && $q->param('op') eq "next") {
$currentpanel = $symbol{panels}[$panelnum];
# validate variables for panel
if ($currentpanel->{validate}) {
$currentpanel->{validate}($q);
}
# execute current panel
my $status = "0";
if ($currentpanel->{update}) {
$status = $currentpanel->{update}($q);
&debug_log("TPS wizard: update returns status '" .
$status . "'");
if ($status == $STATUS_REDIRECT) {
return $STATUS_REDIRECT;
}
}
&debug_log("TPS wizard: about to find out about sub panel");
if ($status eq "1") {
if ($currentpanel->{hasSubPanel} && &{$currentpanel->{hasSubPanel}}($q)) {
&debug_log("TPS wizard: has sub panel");
$panelnum = $panelnum + 2;
} elsif ($currentpanel->{isSubPanel} && &{$currentpanel->{isSubPanel}}($q)) {
&debug_log("TPS wizard: is sub panel");
$panelnum = $panelnum - 1;
} else {
&debug_log("TPS wizard: no sub panel and is not subpanel");
$panelnum = $panelnum + 1;
}
}
} elsif ($q->param('op') && $q->param('op') eq "back") {
$panelnum = $panelnum - 1;
#check if this a subpanel, if so, go back to it's parent.
#only handles one-deep at this point
my $panel = $symbol{panels}[$panelnum];
if (&{$panel->{isSubPanel}}($q)) {
$panelnum = $panelnum - 1;
}
} elsif ($q->param('op') && $q->param('op') eq "apply") {
&debug_log("TPS wizard: update : apply button pressed");
$currentpanel = $symbol{panels}[$panelnum];
# validate variables for panel
if ($currentpanel->{validate}) {
$currentpanel->{validate}($q);
}
# execute current panel
if ($currentpanel->{update}) {
my $status = $currentpanel->{update}($q);
&debug_log("TPS wizard: update returns status '" .
$status . "'");
if ($status == $STATUS_REDIRECT) {
return $STATUS_REDIRECT;
}
}
}
&debug_log("TPS wizard: after looking into about sub panel");
# advance to next panel
$currentpanel = $symbol{panels}[$panelnum];
# initialize symbol table values
$symbol{showApplyButton} = "false";
# fill in variables for new panel
if ($currentpanel->{panelvars}) {
$Data::Dumper::Indent = 1;
# The '&debug_log("q=".Dumper($q));' call must be commented out to fix
# Bugzilla Bug #249923: Incorrect file permissions on
# various files and/or directories
# &debug_log("q=".Dumper($q));
$currentpanel->{panelvars}($q);
}
$symbol{panel} = "tps/admin/console/config/".$currentpanel->{vmfile};
#wizard.vm:
$symbol{name} = "Token Processing System";
$symbol{title} = $currentpanel->{getName}();
if ($panelnum == 0) {
$symbol{firstpanel} = "1";
} else {
$symbol{firstpanel} = "0";
}
if ($panelnum == 16) {
$symbol{lastpanel} = "1";
} else {
$symbol{lastpanel} = "0";
}
$symbol{p} = $panelnum;
$symbol{subpanelno} = $panelnum+1;
$symbol{productversion} = $::config->get("preop.product.version");
$symbol{csstate} = "1";
# $symbol{urls} = [ "cert1", "cert2" ]; #createsubsystem
# $symbol{urls_size} = 2;
# $symbol{instanceId} = "tps";
# $symbol{errorString} = "";
#modulepanel
# $symbol{certs} = [ ];
# $symbol{reqscerts} = [ ];
$symbol{ppcerts} = [ ];
return $STATUS_OK;
}
sub dbg {
my $msg = shift;
$::symbol{dbg} .= "$msg\n";
}
sub handler {
my $r = shift;
*::symbol = \%symbol;
*::s = \$s;
*::config = \$config;
*::pwdconf = \$pwdconf;
&debug_log("TPS wizard: in handler");
if ($#ARGV == -1) {
$r->send_http_header('text/html');
}
my $q = new CGI;
# check cookie
my $cookie = $q->cookie('pin');
my $pin = $::config->get("preop.pin");
if ($cookie ne $pin) {
print $q->redirect("login");
return;
}
# output http parameters
&debug_log("TPS wizard: uri='" . $ENV{REQUEST_URI} . "'");
my @pnames = $q->param();
foreach $pn (@pnames) {
# added this facility so that password can be hidden,
# all sensitive parameters should be prefixed with
# __ (double underscores); however, in the event that
# a security parameter slips through, we perform multiple
# additional checks to insure that it is NOT displayed
if( $pn =~ /^__/ ||
$pn =~ /password$/ ||
$pn =~ /passwd$/ ||
$pn =~ /pwd$/ ||
$pn =~ /admin_password_again/i ||
$pn =~ /directoryManagerPwd/i ||
$pn =~ /bindpassword/i ||
$pn =~ /bindpwd/i ||
$pn =~ /passwd/i ||
$pn =~ /password/i ||
$pn =~ /pin/i ||
$pn =~ /pwd/i ||
$pn =~ /pwdagain/i ||
$pn =~ /uPasswd/i ) {
&debug_log("TPS wizard: http parameter name='" . $pn . "' value='(sensitive)'");
} else {
&debug_log("TPS wizard: http parameter name='" . $pn . "' value='" . $q->param($pn) . "'");
}
}
my $panelnum = $q->param('p');
if (!defined($panelnum) || $panelnum eq "") {
# Apache fails to pick up the p parameter after
# redirecting from the security domain. This is
# a quick hack to solve the issue.
if ($ENV{'QUERY_STRING'} ne "") {
$ENV{'QUERY_STRING'} =~ /p=([0-9]+)&/;
$panelnum = $1;
}
}
use subs qw(debug);
*debug = \&Template::Velocity::Executor::debug;
$::symbol{dbg} = "";
&debug_log("TPS wizard: before argparsing");
if ($#ARGV == -1) {
$Data::Dumper::Maxdepth = 7;
$startfile = "tps/admin/console/config/wizard.vm";
}
&debug_log("TPS wizard: setting up test objects");
#initialize from config file
my $certlist = $::config->get("preop.cert.list");
if ($certlist eq "") {
$certlist = "sslserver,subsystem";
}
@certtags = split(/,/, $certlist);
$numtags = @certtags;
if ($numtags eq 0) {
@certtags = ("sslserver", "subsystem");
}
&debug_log("TPS wizard: found $numtags certtags");
if (! $panelnum) {
$panelnum = 0;
}
my $status = render_panel($panelnum, $q);
if ($status == 3) {
$r->header_out(Location => $symbol{redirect});
$r->status(301);
$r->send_http_header();
return;
}
use Data::Dumper;
&debug_log("TPS wizard: executing file $startfile");
foreach $q (sort keys %symbol) {
&debug_log("TPS wizard:/config/wizard?p=9&SecToken=NSS%20Generic%20Crypto%20Services sym{$q}=".$symbol{$q});
}
my $result;
if ($q->param('xml') && $q->param('xml') eq "true") {
$r->send_http_header('text/xml');
$result = "";
foreach $s (sort keys %symbol) {
if ($s =~ /^__/) {
next;
}
$result .= "<" . $s . ">";
my $v = $symbol{$s};
$result .= &get_xml($s, $v);
$result .= "" . $s . ">";
}
$result .= "";
} else {
$result = $parser->execute_file($startfile);
if (!defined $result) {
die("Couldn't execute template file: $docroot/$startfile");
}
}
print "$result\n";
return $STATUS_OK;
}
sub escape_xml
{
my ($v) = @_;
$v =~ s/\"/"/g;
$v =~ s/\'/'/g;
$v =~ s/\&/&/g;
$v =~ s/</g;
$v =~ s/>/>/g;
return $v;
}
sub get_xml
{
my ($s, $v) = @_;
my $result;
if (ref($v) eq "HASH") {
foreach my $xkey (keys %$v) {
$result .= "<" . $xkey . ">";
$result .= &get_xml($xkey, $v{$xkey});
# $result .= "-" . ref($xkey);
$result .= "" . $xkey . ">";
}
} elsif (ref($v) eq "PKI::TPS::CertInfo") {
my $certinfo = $v;
$result .= "";
$result .= "" . $certinfo->get_dn() ."";
$result .= "" . $certinfo->get_cert_tag() . "";
$result .= "" . $certinfo->get_user_friendly_name() .
"";
$result .= "";
} elsif (ref($v) eq "PKI::TPS::ReqCertInfo") {
my $reqcertinfo = $v;
$result .= "";
$result .= "" . $reqcertinfo->get_user_friendly_name() ."";
$result .= "" . $reqcertinfo->get_request() ."";
$result .= "" . $reqcertinfo->get_cert() ."";
$result .= "" . &escape_xml($reqcertinfo->get_cert_pp()) ."";
$result .= "" . $reqcertinfo->get_cert_tag() ."";
$result .= "" . $reqcertinfo->get_cert_tag() ."";
$result .= "";
} elsif (ref($v) eq "ARRAY") {
my $pos = 0;
foreach my $item (@$v) {
$result .= "";
$result .= &get_xml("p" . $pos, $item);
# $result .= "-" . ref($item);
$result .= "";
$pos++;
}
} else {
$result .= &escape_xml($v);
}
return $result;
}
1;