From a4682ceae6774956461edd03b2485bbacea445f4 Mon Sep 17 00:00:00 2001 From: mharmsen Date: Tue, 4 Oct 2011 01:17:41 +0000 Subject: Bugzilla Bug #688225 - (dogtagIPAv2.1) TRACKER: of the Dogtag fixes for freeIPA 2.1 git-svn-id: svn+ssh://svn.fedorahosted.org/svn/pki/tags/IPA_v2_RHEL_6_2_20111003@2252 c9f7a03b-bd48-0410-a16d-cbbf54688b0b --- pki/base/setup/CMakeLists.txt | 29 + pki/base/setup/LICENSE | 291 ++++ pki/base/setup/build.xml | 313 ++++ pki/base/setup/pki-setup-proxy | 499 ++++++ pki/base/setup/pkicommon.pm | 3561 ++++++++++++++++++++++++++++++++++++++++ pki/base/setup/pkicreate | 3343 +++++++++++++++++++++++++++++++++++++ pki/base/setup/pkiremove | 649 ++++++++ 7 files changed, 8685 insertions(+) create mode 100644 pki/base/setup/CMakeLists.txt create mode 100644 pki/base/setup/LICENSE create mode 100644 pki/base/setup/build.xml create mode 100644 pki/base/setup/pki-setup-proxy create mode 100755 pki/base/setup/pkicommon.pm create mode 100755 pki/base/setup/pkicreate create mode 100755 pki/base/setup/pkiremove (limited to 'pki/base/setup') diff --git a/pki/base/setup/CMakeLists.txt b/pki/base/setup/CMakeLists.txt new file mode 100644 index 000000000..d8d36f6f8 --- /dev/null +++ b/pki/base/setup/CMakeLists.txt @@ -0,0 +1,29 @@ +project(setup) + +install( + FILES + pkicreate + pkiremove + pki-setup-proxy + DESTINATION + ${BIN_INSTALL_DIR} + PERMISSIONS + OWNER_EXECUTE OWNER_WRITE OWNER_READ + GROUP_EXECUTE GROUP_READ + WORLD_EXECUTE WORLD_READ +) + +install( + FILES + pkicommon.pm + DESTINATION + ${DATA_INSTALL_DIR}/scripts/ + PERMISSIONS + OWNER_EXECUTE OWNER_WRITE OWNER_READ + GROUP_EXECUTE GROUP_READ + WORLD_EXECUTE WORLD_READ +) + +# install empty directories +install(CODE "file(MAKE_DIRECTORY \$ENV{DESTDIR}${VAR_INSTALL_DIR}/lock/pki)") +install(CODE "file(MAKE_DIRECTORY \$ENV{DESTDIR}${VAR_INSTALL_DIR}/run/pki)") diff --git a/pki/base/setup/LICENSE b/pki/base/setup/LICENSE new file mode 100644 index 000000000..e281f4362 --- /dev/null +++ b/pki/base/setup/LICENSE @@ -0,0 +1,291 @@ +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; version 2 of the License. + +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-1307 USA. + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. diff --git a/pki/base/setup/build.xml b/pki/base/setup/build.xml new file mode 100644 index 000000000..4d446b9af --- /dev/null +++ b/pki/base/setup/build.xml @@ -0,0 +1,313 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pki/base/setup/pki-setup-proxy b/pki/base/setup/pki-setup-proxy new file mode 100644 index 000000000..0222eab46 --- /dev/null +++ b/pki/base/setup/pki-setup-proxy @@ -0,0 +1,499 @@ +#!/usr/bin/perl +# +# --- BEGIN COPYRIGHT BLOCK --- +# 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; version 2 of the License. +# +# 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., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2011 Red Hat, Inc. +# All rights reserved. +# --- END COPYRIGHT BLOCK --- +# +use strict; +use warnings; + +use File::Copy; +use Sys::Hostname; +use Getopt::Long qw(GetOptions); +use File::Slurp qw(read_file write_file); + +use lib "/usr/share/pki/scripts"; +use pkicommon; + +############################################################## +# This script is used to convert an existing instance from a +# non-proxy port configuration to a proxy port configuration. +# +# Sample Invocation (for CA): +# +# ./pki-setup-proxy -pki_instance_root=/var/lib +# -pki_instance_name=pki-ca +# -subsystem_type=ca +# -ajp_redirect_port=9444 +# -ajp_port=9447 +# -proxy_secure_port=443 +# -proxy_unsecure_port=80 +# -unsecure_port=9080 +# -user=pkiuser +# -group=pkiuser +# -verbose +# +############################################################## + +############################################################## +# Command-Line Variables +############################################################## + +my $ARGS = ($#ARGV + 1); + +############################################################## +# Local Variables +############################################################## + +# Command-line variables (mandatory) +my $pki_instance_root = undef; +my $pki_instance_name = undef; +my $subsystem_type = undef; + +# Command-line variables (optional) +my $ajp_port = -1; +my $ajp_redirect_port = -1; +my $proxy_secure_port = -1; +my $proxy_unsecure_port = -1; +my $unsecure_port = -1; +my $pki_user = $PKI_USER; +my $pki_group = $PKI_GROUP; + +# Base subsystem directory paths +my $pki_subsystem_conf_path = undef; + +# Base instance directory paths +my $pki_instance_path = undef; +my $pki_instance_conf_path = undef; +my $pki_instance_webxml_path = undef; +my $pki_instance_profile_select_path = undef; + +#proxy defaults +my $PROXY_SECURE_PORT_DEFAULT = "443"; +my $PROXY_UNSECURE_PORT_DEFAULT = "80"; +my $UNSECURE_PORT_DEFAULT = "9080"; +my $AJP_PORT_DEFAULT = "9447"; +my $AJP_REDIRECT_PORT_DEFAULT = "9444"; + +sub usage +{ + print STDOUT <<'EOF'; +############################################################################### +### USAGE: CA, KRA, OCSP, or TKS subsystem proxy setup ### +############################################################################### + +pki-proxy-setup \ + -pki_instance_root= # Instance root directory + # destination + + -pki_instance_name= # Unique PKI subsystem + # instance name + + -subsystem_type= # Subsystem type + # [ca | kra | ocsp | tks] + + [-ajp_port=] # AJP port, default 9447 + + [-ajp_redirect_port=] # AJP redirect port, + # default 9444 + + [-proxy_secure_port=] # Proxy secure port, + # default 443 + + [-proxy_unsecure_port=] # Proxy unsecure port, + # default 80 + + [-unsecure_port=] # UnSecure port, + # default 9080 + + [-user=] # User ownership, + # default pkiuser + + [-group=] # Group ownership + # default pkiuser + + [-verbose] # Print out liberal info + # Specify multiple times + # to increase verbosity. + + [-help] # Print out this screen +EOF + +} + +sub pki_instance_already_exists +{ + my ($name) = @_; + my $result = 0; + my $instance = ""; + + $instance = "/etc/sysconfig/pki" + . "/" . $subsystem_type + . "/" . $name; + + if (-e $instance) { + $result = 1; + } + + return $result; +} + +# no args +# return 1 - success, or +# return 0 - failure +sub parse_arguments +{ + my $l_proxy_secure_port = -1; + my $l_proxy_unsecure_port = -1; + my $l_unsecure_port = -1; + my $l_ajp_port = -1; + my $l_ajp_redirect_port = -1; + my $show_help = 0; + my $username = undef; + my $groupname = undef; + + my $result = GetOptions("help" => \$show_help, + "pki_instance_root=s" => \$pki_instance_root, + "pki_instance_name=s" => \$pki_instance_name, + "subsystem_type=s" => \$subsystem_type, + "ajp_port:i" => \$l_ajp_port, + "ajp_redirect_port:i" => \$l_ajp_redirect_port, + "proxy_secure_port:i" => \$l_proxy_secure_port, + "proxy_unsecure_port:i" => \$l_proxy_unsecure_port, + "unsecure_port:i" => \$l_unsecure_port, + "user=s" => \$username, + "group=s" => \$groupname, + "verbose+" => \$verbose); + + ## Optional "-help" option - no "mandatory" options are required + if ($show_help) { + usage(); + return 0; + } + + ## Mandatory "-pki_instance_root=s" option + if (!$pki_instance_root) { + usage(); + emit("Must have value for -pki_instance_root!\n", "error"); + return 0; + } + + # Remove all trailing directory separators ('/') + $pki_instance_root =~ s/\/+$//; + + ## Mandatory "-subsystem_type=s" option + if ($subsystem_type ne $CA && + $subsystem_type ne $KRA && + $subsystem_type ne $OCSP && + $subsystem_type ne $TKS && + $subsystem_type ne $RA && + $subsystem_type ne $TPS) { + usage(); + emit("Illegal value => $subsystem_type : for -subsystem_type!\n", + "error"); + return 0; + } + + if ($subsystem_type eq $RA || + $subsystem_type eq $TPS) { + usage(); + emit("Illegal value => $subsystem_type : for -subsystem_type!\n" . + "Proxy configuration is not yet supported for TPS and RA subsystems", + "error"); + return 0; + } + + ## Mandatory "-pki_instance_name=s" option + if (!$pki_instance_name) { + usage(); + emit("Must have value for -pki_instance_name!\n", "error"); + return 0; + } + + if (! pki_instance_already_exists($pki_instance_name)) { + usage(); + emit("An instance named $pki_instance_name " + . "does not exist; please try again.\n", "error"); + return 0; + } + + $pki_instance_path = "${pki_instance_root}/${pki_instance_name}"; + + # Capture installation information in a log file, always overwrite this file. + # When modifying an instance it's a fatal error if the logfile + # cannot be created. + my $logfile = "/var/log/${pki_instance_name}-proxy-setup.log"; + if (!open_logfile($logfile, $default_file_permissions)) { + emit("can not create logfile ($logfile)", "error"); + return 0; + } + + printf(STDOUT "Capturing configuration information in %s\n", $logfile); + + emit("Parsing setup_proxy arguments ...\n"); + if ($verbose) { + emit(" verbose mode ENABLED (level=$verbose)\n"); + } + + if ($username) { + $pki_user = $username; + } + emit(" user $pki_user\n"); + + if ($groupname) { + $pki_group = $groupname; + } + emit(" group $pki_group\n"); + + $proxy_secure_port = ($l_proxy_secure_port >= 0) ? $l_proxy_secure_port : + $PROXY_SECURE_PORT_DEFAULT; + emit(" proxy_secure_port $proxy_secure_port\n"); + + $proxy_unsecure_port = ($l_proxy_unsecure_port >= 0) ? $l_proxy_unsecure_port : + $PROXY_UNSECURE_PORT_DEFAULT; + emit(" proxy_unsecure_port $proxy_unsecure_port\n"); + + $unsecure_port = ($l_unsecure_port >= 0) ? $l_unsecure_port : + $UNSECURE_PORT_DEFAULT; + emit(" unsecure_port $unsecure_port\n"); + + $ajp_port = ($l_ajp_port >= 0) ? $l_ajp_port : $AJP_PORT_DEFAULT; + emit(" ajp_port $ajp_port\n"); + + $ajp_redirect_port = ($l_ajp_redirect_port >= 0) ? $l_ajp_redirect_port : + $AJP_REDIRECT_PORT_DEFAULT; + emit(" ajp_redirect_port $ajp_redirect_port\n"); + + return 1; +} + +# no args +# no return +sub initialize_paths +{ + $pki_instance_conf_path = "${pki_instance_path}/conf"; + $pki_subsystem_conf_path = "/usr/share/pki/${subsystem_type}/conf"; + $pki_instance_webxml_path = "${pki_instance_path}/webapps/${subsystem_type}" . + "/WEB-INF/web.xml"; + $pki_instance_profile_select_path = "${pki_instance_path}/webapps/" . + "${subsystem_type}/ee/${subsystem_type}/" . + "ProfileSelect.template"; +} + +# no args +# no return +sub update_server_xml +{ + my $server_xml = "${pki_instance_conf_path}/server.xml"; + + my $new_match = < + +EOF + my $old_match = < + +EOF + my $new_ajp = < + +EOF + + my $data = read_file $server_xml; + $data =~ s/$old_match/$new_ajp/; + $data =~ s/$new_match/$new_ajp/; + + # back up existing server.xml + copy_file($server_xml, $server_xml . ".pre-proxy.$$", + $default_file_permissions, $pki_user, $pki_group); + write_file($server_xml, $data); + set_file_props($server_xml, $default_file_permissions, + $pki_user, $pki_group); + +} + +# no args +# no return +sub update_proxy_conf +{ + my $template_file = "${pki_subsystem_conf_path}/proxy.conf"; + my $server_file = "${pki_instance_conf_path}/proxy.conf"; + + #backup, just in case there already was a file + copy_file($server_file, $server_file . ".pre-proxy.$$", + $default_file_permissions, $pki_user, $pki_group); + + my $data = read_file $template_file; + my $host = hostname; + $data =~ s/\[PKI_MACHINE_NAME\]/$host/g; + $data =~ s/\[PKI_AJP_PORT\]/$ajp_port/g; + + write_file($server_file, $data); + set_file_props($server_file, $default_file_permissions, + $pki_user, $pki_group); + +} + +# no args +# no return +sub update_web_xml +{ + my $data = read_file $pki_instance_webxml_path; + + my $commented_proxy_stanza = < + proxy_port + + +--> +EOF + my $proxy_stanza = < + proxy_port + $proxy_secure_port + +EOF + + my $commented_proxy_stanza_2 = < + proxy_port + + + + proxy_http_port + + +--> +EOF + my $proxy_stanza_2 = < + proxy_port + $proxy_secure_port + + + proxy_http_port + $proxy_unsecure_port + +EOF + + my $ee_filter_head = < + EERequestFilter + com.netscape.cms.servlet.filter.EERequestFilter + + http_port + $unsecure_port + + + https_port + $proxy_secure_port + +EOF + + my $active_stanza = < + active +EOF + + if ($data =~ /$commented_proxy_stanza/) { + $data =~ s/$commented_proxy_stanza/$proxy_stanza/g; + $data =~ s/$commented_proxy_stanza_2/$proxy_stanza_2/g; + } else { + $data =~ s/$active_stanza/${proxy_stanza}${active_stanza}/g; + $data =~ s/${ee_filter_head}${proxy_stanza}${active_stanza}/${ee_filter_head}${proxy_stanza_2}${active_stanza}/; + } + + # backup old file + copy_file($pki_instance_webxml_path, $pki_instance_webxml_path . ".pre_proxy", + $default_file_permissions, $pki_user, $pki_group); + + write_file($pki_instance_webxml_path, $data); + set_file_props($pki_instance_webxml_path, $default_file_permissions, + $pki_user, $pki_group); +} + +# no args +# no return +sub update_cs_cfg +{ + my $cs_cfg = "${pki_instance_conf_path}/CS.cfg"; + my $data = read_file $cs_cfg; + + $data =~ s/proxy.securePort=[\d]*\n//g; + $data =~ s/proxy.unsecurePort=[\d]*\n//g; + chomp($data); + $data .= "\nproxy.securePort=$proxy_secure_port" . + "\nproxy.unsecurePort=$proxy_unsecure_port\n"; + + # backup old file + copy_file($cs_cfg, $cs_cfg . ".pre-proxy.$$", + $default_file_permissions, $pki_user, $pki_group); + + write_file($cs_cfg, $data); + set_file_props($cs_cfg, $default_file_permissions, + $pki_user, $pki_group); +} + +# no args +# no return +sub update_profile_select_template +{ + my $template_file = $pki_instance_profile_select_path; + my $data = read_file $template_file; + + my $host = hostname; + $data =~ s/https:\/\/$host:\d*\/ca\/eeca/https:\/\/$host:$proxy_secure_port\/ca\/eeca/; + + # backup old file + copy_file($template_file, $template_file . ".pre-proxy.$$", + $default_file_permissions, $pki_user, $pki_group); + + write_file($template_file, $data); + set_file_props($template_file, $default_file_permissions, + $pki_user, $pki_group); +} + +###################################### +# Main program +##################################### + +sub main +{ + my $parse_result = parse_arguments(); + if (!$parse_result) { + close_logfile(); + exit 255; + } + + initialize_paths(); + update_server_xml(); + update_proxy_conf(); + update_web_xml(); + update_cs_cfg(); + update_profile_select_template(); + parse_selinux_ports(); + add_selinux_port("pki_${subsystem_type}_port_t", $ajp_port); +} + +main(); +exit 0; diff --git a/pki/base/setup/pkicommon.pm b/pki/base/setup/pkicommon.pm new file mode 100755 index 000000000..108860c28 --- /dev/null +++ b/pki/base/setup/pkicommon.pm @@ -0,0 +1,3561 @@ +#!/usr/bin/perl +# +# --- BEGIN COPYRIGHT BLOCK --- +# 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; version 2 of the License. +# +# 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., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2007-2010 Red Hat, Inc. +# All rights reserved. +# --- END COPYRIGHT BLOCK --- +# + +package pkicommon; +use strict; +use warnings; + +use Exporter; +our @ISA = qw(Exporter); +our @EXPORT = qw( + $lib_prefix $obj_ext $path_sep $tmp_dir + $pki_flavor $pki_registry_path + $verbose $dry_run $hostname $default_hardware_platform + $default_system_binaries $default_lockdir $default_system_libraries $default_system_user_binaries + $default_system_user_libraries + $default_java_path $default_pki_java_path $default_system_jni_java_path @default_jar_path + $default_security_libraries $default_certutil_command + $default_ldapmodify_command $default_modutil_command + $default_dir_permissions $default_exe_permissions $default_file_permissions + $default_initscripts_path $default_registry_path + $ROOTUID $MAX_WELL_KNOWN_PORT $MAX_RESERVED_PORT $MAX_REGISTERED_PORT $MAX_DYNAMIC_PORT + $FILE_PREFIX $FTP_PREFIX $HTTP_PREFIX $HTTPS_PREFIX $LDAP_PREFIX $LDAPS_PREFIX + $PKI_USER $PKI_GROUP $PKI_UID $PKI_GID + $CA $KRA $OCSP $TKS $RA $TPS + $CA_INITSCRIPT $KRA_INITSCRIPT $OCSP_INITSCRIPT + $TKS_INITSCRIPT $RA_INITSCRIPT $TPS_INITSCRIPT + $install_info_basename $cleanup_basename %installation_info + $semanage $restorecon $SELINUX_PORT_UNDEFINED $SELINUX_PORT_DEFINED $SELINUX_PORT_WRONGLY_DEFINED + + add_install_info remove_install_info get_install_description + format_install_info get_install_info_description + parse_install_info parse_old_cleanup read_old_cleanup + read_install_info read_install_info_from_dir write_install_info_to_dir uninstall + is_Windows is_Linux is_Fedora is_RHEL is_RHEL4 setup_platform_dependent_parameters + set_library_path get_library_path + check_for_root_UID user_disallows_shell + user_exists create_user + group_exists create_group user_is_a_member_of_group add_user_as_a_member_of_group + get_UID_from_username + get_FQDN check_for_valid_url_prefix + AreConnectorPortsValid IsLocalPortAvailable IsServerReachable + get_time_stamp generate_random generate_random_string password_quality_checker + LDAP_add LDAP_modify + certutil_create_databases certutil_delete_cert certutil_generate_CSR + certutil_generate_self_signed_cert certutil_import_cert + certutil_print_cert certutil_list_certs modutil_add_token + open_logfile get_logfile_path close_logfile + prompt printFile emit + is_path_valid is_name_valid entity_type entity_exists + file_exists is_file_empty create_empty_file create_file copy_file remove_file + set_permissions set_owner_group set_file_props + get_directory_files normalize_path + directory_exists is_directory_empty create_directory copy_directory remove_directory + set_owner_group_on_directory_contents + symlink_exists create_symlink remove_symlink set_owner_group_on_symlink + run_command get_cs_cfg get_registry_initscript_name + register_pki_instance_with_chkconfig deregister_pki_instance_with_chkconfig + find_jar + check_selinux_port parse_selinux_ports add_selinux_port add_selinux_file_context + ); + + +use File::Slurp qw(read_file write_file); + +############################################################## +# This file contains shared data and subroutines for +# the "pkicreate" and "pkiremove" Perl scripts. +############################################################## + + +############################################################## +# Perl Version +############################################################## + +my $MINIMUM_PERL_VERSION = "5.006001"; + +my $perl_version_error_message = "ERROR: Using Perl version $] ...\n" + . " Must use Perl version " + . "$MINIMUM_PERL_VERSION or later to " + . "run this script!\n"; + +die $perl_version_error_message if $] < $MINIMUM_PERL_VERSION; + + +############################################################## +# Execution Check +############################################################## + +# Check to insure that this script's original +# invocation directory has not been deleted! +my $cwd = `/bin/pwd`; +chomp $cwd; +if (!$cwd) { + emit("Cannot invoke '$0' from non-existent directory!\n", "error"); + exit 255; +} + + +############################################################## +# Environment Variables +############################################################## + +# untaint called subroutines +if (($^O ne 'Windows_NT') && ($^O ne 'MSWin32')) { + $> = $<; # set effective user ID to real UID + $) = $(; # set effective group ID to real GID + $ENV{'PATH'} = '/bin:/usr/bin'; + $ENV{'ENV'} = '' if !defined($ENV{'ENV'}); +} + + +############################################################## +# Perl Modules +############################################################## + +use Sys::Hostname; +use FileHandle; +use Socket; +use File::Copy; +use File::Basename; +use File::Path qw(make_path remove_tree); + +############################################################## +# Global Variables +############################################################## + +# Platform-dependent parameters +our $lib_prefix = undef; +our $obj_ext = undef; +our $path_sep = undef; +our $tmp_dir = undef; + +# Whether or not to do verbose mode +our $verbose = 0; + +# Controls whether actions are executed (dry_run == false) +# or if actions are only reported (dry_run == true). +our $dry_run = 0; + +our $hostname = undef; + +# selinux structures +our %selinux_ports = (); + +############################################################## +# Shared Default Values +############################################################## + +our $pki_flavor = undef; +our $pki_registry_path = undef; + +our $default_hardware_platform = undef; +our $default_system_binaries = undef; +our $default_lockdir = undef; +our $default_system_libraries = undef; +our $default_system_user_binaries = undef; +our $default_system_user_libraries = undef; +our $default_java_path = undef; +our $default_pki_java_path = undef; +our $default_system_jni_java_path = undef; +our @default_jar_path = undef; +our $default_security_libraries = undef; +our $default_certutil_command = undef; +our $default_ldapmodify_command = undef; +our $default_modutil_command = undef; +our $default_initscripts_path = undef; +our $default_registry_path = undef; + +our $default_dir_permissions = 00770; +our $default_exe_permissions = 00770; +our $default_file_permissions = 00660; + +our $semanage = "/usr/sbin/semanage"; +our $restorecon = "/sbin/restorecon"; +our $SELINUX_PORT_UNDEFINED = 0; +our $SELINUX_PORT_DEFINED = 1; +our $SELINUX_PORT_WRONGLY_DEFINED = 2; + + + +# Use a local variable to denote IPv6 +my $is_IPv6 = 0; + +# Compute "hardware platform" of Operating System +if ($^O eq "linux") { + $pki_flavor = "pki"; + $default_registry_path = "/etc/sysconfig"; + $pki_registry_path = "$default_registry_path/$pki_flavor"; + $default_initscripts_path = "/etc/rc.d/init.d"; + $default_lockdir = "/var/lock/$pki_flavor"; + $default_hardware_platform = `uname -i`; + $default_hardware_platform =~ s/\s+$//g; + chomp($default_hardware_platform); + if ($default_hardware_platform eq "i386") { + # 32-bit Linux + $default_system_binaries = "/bin"; + $default_system_libraries = "/lib"; + $default_system_user_binaries = "/usr/bin"; + $default_system_user_libraries = "/usr/lib"; + $default_java_path = "/usr/share/java"; + $default_pki_java_path = "/usr/share/java/pki"; + $default_system_jni_java_path = "/usr/lib/java"; + } elsif ($default_hardware_platform eq "x86_64") { + # 64-bit Linux + $default_system_binaries = "/bin"; + $default_system_libraries = "/lib64"; + $default_system_user_binaries = "/usr/bin"; + $default_system_user_libraries = "/usr/lib64"; + $default_java_path = "/usr/share/java"; + $default_pki_java_path = "/usr/share/java/pki"; + $default_system_jni_java_path = "/usr/lib/java"; + } else { + emit("Unsupported '$^O' hardware platform '$default_hardware_platform'!", "error"); + exit 255; + } + + @default_jar_path = ($default_pki_java_path, $default_java_path, $default_system_jni_java_path); + + # Retrieve hostname + if (defined($ENV{'PKI_HOSTNAME'})) { + # IPv6: Retrieve hostname from environment variable + $hostname = $ENV{'PKI_HOSTNAME'}; + $is_IPv6 = 1; + } else { + # IPv4: Retrieve hostname using Sys::Hostname + $hostname = hostname; + } +} else { + emit("Unsupported platform '$^O'!\n", "error"); + exit 255; +} + + +$default_security_libraries = "$default_system_user_libraries/dirsec"; + +$default_certutil_command = "$default_system_user_binaries/certutil"; +$default_ldapmodify_command = "$default_system_user_binaries/ldapmodify"; +$default_modutil_command = "$default_system_user_binaries/modutil"; + + +############################################################## +# Global Constants +############################################################## + +our $ROOTUID = 0; + +our $MAX_WELL_KNOWN_PORT = 511; # well-known ports = 0 through 511 +our $MAX_RESERVED_PORT = 1023; # reserved ports = 512 through 1023 +our $MAX_REGISTERED_PORT = 49151; # registered ports = 1024 through 49151 +our $MAX_DYNAMIC_PORT = 65535; # dynamic/private ports = 49152 through 65535 + +our $FILE_PREFIX = "file://"; +our $FTP_PREFIX = "ftp://"; +our $HTTP_PREFIX = "http://"; +our $HTTPS_PREFIX = "https://"; +our $LDAP_PREFIX = "ldap://"; +our $LDAPS_PREFIX = "ldaps://"; + +# Identity values +our $PKI_USER = "pkiuser"; +our $PKI_GROUP = "pkiuser"; +our $PKI_UID = 17; +our $PKI_GID = 17; + +# Subsystem names +our $CA = "ca"; +our $KRA = "kra"; +our $OCSP = "ocsp"; +our $TKS = "tks"; +our $RA = "ra"; +our $TPS = "tps"; + +# Subsystem init scripts +our $CA_INITSCRIPT = "pki-cad"; +our $KRA_INITSCRIPT = "pki-krad"; +our $OCSP_INITSCRIPT = "pki-ocspd"; +our $TKS_INITSCRIPT = "pki-tksd"; +our $RA_INITSCRIPT = "pki-rad"; +our $TPS_INITSCRIPT = "pki-tpsd"; + + +############################################################## +# Local Variables +############################################################## + +# "identity" parameters +my $fqdn = undef; + +# "logging" parameters +my $logfd = undef; +my $logfile_path = undef; + + + +############################################################## +# Routines & data structures used to track & +# manage installation information +############################################################## + +# Basename of the installation info file. +our $install_info_basename = "install_info"; + +# Basename of the old clean up file. +our $cleanup_basename = ".cleanup.dat"; + +# Global hash table of installation actions +# Each filesystem path which is modified during installation +# is entered into this table as a key. The value associated +# with the key is an anonymous hash table of key/value pairs, +# e.g. the installation metadata associated with the path. +# This table should not be directly modified, rather use +# the utility subroutines which know how to operate on +# on an installation info table. The utility routines can +# operate on any installation table, but default to using +# this single global table. +our %installation_info = (); + +# Table to validate an installation type +my %valid_install_types = ('file' => 1, + 'symlink' => 1, + 'dir' => 1); + +# Table to validate a install action +my %valid_install_action = ('create' => 1, + 'move' => 1, + 'remove' => 1); + +# Table to validate an uninstall action +my %valid_uninstall_action = ('remove' => 1, + 'preserve' => 1); + +# Capture information about items modified during installation +# +# add_install_info(path, [type='file'], [uninstall_action='remove], +# [install_action='create]) +# +# path the path name of the object +# type what kind of object +# (file, symlink, dir) +# uninstall_action - during uninstall what should be done +# (remove, preserve) +# install_action what was done during install +# (create, move, remove) +# +# The data structure used to capture the information is a hash +# table whose keys are path names and whose value is a hash +# table of key/value attributes belonging to the path object. +sub add_install_info { + my ($path, $type, $uninstall_action, $install_action) = @_; + my ($install_info) = \%installation_info; + $type = 'file' unless defined($type); + $uninstall_action = 'remove' unless defined($uninstall_action); + $install_action = 'create' unless defined($install_action); + my $info; + + die "invalid install type ($type) for path ($path)" + if (!exists($valid_install_types{$type})); + + die "invalid uninstall action ($uninstall_action) for path ($path)" + if (!exists($valid_uninstall_action{$uninstall_action})); + + die "invalid install action ($install_action) for path ($path)" + if (!exists($valid_install_action{$install_action})); + + if (exists($install_info->{$path})) { + $info = $install_info->{$path}; + } else { + $install_info->{$path} = $info = {}; + } + + $info->{'type'} = $type; + $info->{'install_action'} = $install_action; + $info->{'uninstall_action'} = $uninstall_action; +} + +# Removes the install info for the given path. +# Used primarily after an error occurs. +sub remove_install_info { + my ($path) = @_; + my ($install_info) = \%installation_info; + + delete $install_info->{$path}; +} + +# return text description of installed files and directories +sub get_install_description +{ + my ($install_info) = \%installation_info; + + return get_install_info_description($install_info); +} + +# Given a hash of installation information format it into text. +# Each path name is in brackets at the beginning of a line +# followed by the path's attributes, which is an indented line of +# key = value, for each attribute +# +# The formatted text is referred to as a "Installation Manifest". +# +# returns formatted text +# +# Example: +# +# [/etc/pki-ca] +# install_action = create +# type = dir +# uninstall_action = remove +# [/etc/pki-ca/CS.cfg] +# install_action = create +# type = file +# uninstall_action = remove +# +sub format_install_info +{ + my ($install_info) = @_; + my ($text, @paths, $path, $info, @key_names, $key, $value); + + $text = ""; + @paths = sort(keys %$install_info); + foreach $path (@paths) { + $info = $install_info->{$path}; + $text .= sprintf("[%s]\n", $path); + @key_names = sort(keys %$info); + foreach $key (@key_names) { + $value = $info->{$key}; + $text .= sprintf(" %s = %s\n", $key, $value); + } + } + return $text; +} + +# Given a hash of installation information format it into +# into friendly description of what was installed. +# +# Brief Example: +# +# Installed Files: +# /etc/pki-ca/CS.cfg +# /var/log/pki-ca-install.log +# Installed Directories: +# /etc/pki-ca +# /var/log/pki-ca +# Installed Symbolic Links: +# /var/lib/pki-ca/logs +# Removed Items: +# /etc/pki-ca/noise +# +sub get_install_info_description +{ + my ($install_info) = @_; + my ($text, @paths, @filtered_paths, $path); + + $text = ''; + @paths = sort(keys %$install_info); + + @filtered_paths = grep {my ($info) = $install_info->{$_}; + $info->{'type'} eq 'file' && + $info->{'install_action'} ne 'remove'} @paths; + if (@filtered_paths) { + $text .= "Installed Files:\n"; + foreach $path (@filtered_paths) { + $text .= " ${path}\n"; + } + } + + @filtered_paths = grep {my ($info) = $install_info->{$_}; + $info->{'type'} eq 'dir' && + $info->{'install_action'} ne 'remove'} @paths; + if (@filtered_paths) { + $text .= "Installed Directories:\n"; + foreach $path (@filtered_paths) { + $text .= " ${path}\n"; + } + } + + @filtered_paths = grep {my ($info) = $install_info->{$_}; + $info->{'type'} eq 'symlink' && + $info->{'install_action'} ne 'remove'} @paths; + if (@filtered_paths) { + $text .= "Installed Symbolic Links:\n"; + foreach $path (@filtered_paths) { + $text .= " ${path}\n"; + } + } + + @filtered_paths = grep {my ($info) = $install_info->{$_}; + $info->{'install_action'} eq 'remove'} @paths; + if (@filtered_paths) { + $text .= "Removed Items:\n"; + foreach $path (@filtered_paths) { + $text .= " ${path}\n"; + } + } + + return $text; + +} + +# Given text as formatted by format_install_info() parse it into +# a install info hash table where each key is a path name and whose +# value is a hash table of key/value pairs. +# +# E.g. this routine parses an "Installation Manifest". +# +# Returns pointer to an install info hash table +sub parse_install_info +{ + my ($text) = @_; + my ($install_info, @lines, $line, $line_num, $path, $info, $key, $value); + + $install_info = {}; + @lines = split(/\n/, $text); + $line_num = 0; + $path = undef; + $info = undef; + + foreach $line (@lines) { + $line_num++; + $line =~ s/#.*//; # nuke comments + $line =~ s/\s+$//; # strip trailing whitespace + next if !$line; # skip blank lines + + # Look for quoted path at beginning of line + if ($line =~ /^\s*\[(.+)\]\s*$/) { + $path = $1; + $info = {}; + $install_info->{$path} = $info; + next; + } + + if (defined($path)) { + # Look for key = value in section, must be preceded by whitespace + undef($key); + if ($line =~ /^\s+(\w+)\s*=\s*(.*)/) { + # quoted name followed by a colon followed by an action + $key = $1; + $value = $2; + $info->{$key} = $value; + } + } + } + return $install_info; +} + +# Formerly the installation info was written as an ini style +# file, a section for files and a section for directories. +# Everything in the file was meant to be removed upon uninstall. +# +# Returns an install info style hash table (see parse_install_info) +sub parse_old_cleanup +{ + my ($text) = @_; + my ($install_info, @lines, $line, $section, $info, $path); + + $install_info = {}; + @lines = split(/\n/, $text); + + foreach $line (@lines) { + $line =~ s/#.*//; # nuke comments + $line =~ s/^\s+//; # strip leading whitespace + $line =~ s/\s+$//; # strip trailing whitespace + next if !$line; # skip blank lines + + # Look for section markers + if ($line =~ /^\s*\[\s*(\w+)\s*\]\s*$/) { + $section = $1; + next; + } + + # Must be path name + $path = $line; + $info = {}; + $install_info->{$path} = $info; + $info->{'uninstall_action'} = 'remove'; + if ($section eq 'files') { + $info->{'type'} = 'file'; + } elsif ($section eq 'directories') { + $info->{'type'} = 'dir'; + } else { + die "unknown cleanup section = \"$section\"\n"; + } + } + return $install_info; +} + +# Get the contents of the old cleanup file +sub read_old_cleanup +{ + my ($path) = @_; + my ($text); + + $text = read_file($path); + return parse_old_cleanup($text); +} + +# Get the contents of an install info file +sub read_install_info +{ + my ($path) = @_; + my ($text); + + $text = read_file($path); + return parse_install_info($text); +} + +# Get the contents of installation info from a directory. +# Supports both the new install info format and the older +# cleanup format. First checks for the presence of the newer +# install info format file, if that's absent reads the older +# cleanup format but returns it as the new install info hash table. +sub read_install_info_from_dir +{ + my ($dir) = @_; + my ($path); + + $path = "${dir}/${install_info_basename}"; + if (-e $path) { + return read_install_info($path); + } + + $path = "${dir}/${cleanup_basename}"; + if (-e $path) { + return read_old_cleanup($path); + } + + return undef; +} + +# Give an install info hash table writes it formated as a +# "Installation Manifest" into specified directory under +# the name $install_info_basename +# +# Returns pathname of manifest if successful, undef otherwise. +sub write_install_info_to_dir +{ + my ($dir, $install_info) = @_; + my ($path, $formatted); + + if (! defined($dir)) { + emit("Cannot write installation manifest, directory unspecified", "error"); + return undef; + } + + if (! defined($install_info_basename)) { + emit("Cannot write installation manifest, file basename unspecified", "error"); + return undef; + } + + if (! -e $dir) { + emit("Cannot write installation manifest, directory ($dir) does not exist", "error"); + return undef; + } + + if (! -d $dir) { + emit("Cannot write installation manifest, directory ($dir) is not a directory", "error"); + return undef; + } + + if (! -w $dir) { + emit("Cannot write installation manifest, directory ($dir) is not writable", "error"); + return undef; + } + + $path = "${dir}/${install_info_basename}"; + $formatted = format_install_info($install_info); + write_file($path, \$formatted); + + return $path; +} + +# Given an Installation Manifest (e.g. install_info) remove the items in +# the manifest marked for removal. +# +# 1) Remove all files and symlinks we created. +# +# 2) Attempt to remove all directories we created, even if they are non-empty. +# +sub uninstall +{ + my ($install_info) = @_; + my ($result, @paths, @filtered_paths, $path, @dirs); + + $result = 1; + + @paths = sort(keys %$install_info); + + # Get a list of files marked for removal. + @filtered_paths = grep {my ($info) = $install_info->{$_}; + ($info->{'type'} eq 'file' || $info->{'type'} eq 'symlink') && + $info->{'install_action'} ne 'remove' && + $info->{'uninstall_action'} eq 'remove'} @paths; + # Remove the files + if (@filtered_paths) { + foreach $path (@filtered_paths) { + $result = 0 if !remove_file($path); + } + } + + # Get a list of directories marked for removal. + @filtered_paths = grep {my ($info) = $install_info->{$_}; + $info->{'type'} eq 'dir' && + $info->{'uninstall_action'} eq 'remove'} @paths; + + # We need to removed directories starting at the deepest level + # and progressively work upward, otherwise the directory might + # not be empty. To accomplish this we sort the directory array + # based on the number of path components. + + # Primary sort by number of path components, longest first. + # When the number of path components is the same the secondary sort + # is lexical string comparision. + @dirs = sort {my ($r, @a, @b); + @a = split("/", $a); + @b = split("/", $b); + $r = @b <=> @a; + $r == 0 ? $a cmp $b : $r} @filtered_paths; + + foreach $path (@dirs) { + $result = 0 if !remove_directory($path, 1); + } + + return $result; +} + +############################################################## +# Generic "platform" Subroutines +############################################################## + +# no args +# return 1 - true, or +# return 0 - false +sub is_Windows +{ + if (($^O eq "Windows_NT") || ($^O eq "MSWin32")) { + return 1; + } + + return 0; +} + + +# no args +# return 1 - true, or +# return 0 - false +sub is_Linux +{ + if ($^O eq "linux") { + return 1; + } + + return 0; +} + + +# no args +# return 1 - true, or +# return 0 - false +sub is_Fedora +{ + if (is_Linux() && (-e "/etc/fedora-release")) { + return 1; + } + + return 0; +} + + +# no args +# return 1 - true, or +# return 0 - false +sub is_RHEL { + if ((! is_Fedora()) && (-e "/etc/redhat-release")) { + return 1; + } + + return 0; +} + + +# no args +# return 1 - true, or +# return 0 - false +sub is_RHEL4 { + if (is_RHEL()) { + my $releasefd = new FileHandle; + if ($releasefd->open("< /etc/redhat-release")) { + while (defined(my $line = <$releasefd>)) { + if ($line =~ /Nahant/i) { + return 1; + } + } + } + } + + return 0; +} + + +# no args +# no return value +sub setup_platform_dependent_parameters +{ + # Setup path separators, et. al., based upon platform + if (is_Windows()) { + $lib_prefix = ""; + $obj_ext = ".dll"; + $path_sep = ";"; + $tmp_dir = "c:\\temp"; + } elsif ($^O eq "hpux") { + $lib_prefix = "lib"; + $obj_ext = ".sl"; + $path_sep = ":"; + $tmp_dir = "/tmp"; + } else { + $lib_prefix = "lib"; + $obj_ext = ".so"; + $path_sep = ":"; + $tmp_dir = "/tmp"; + } + + return; +} + + +# Takes an array reference containing a list of paths. +# Any item in the list which is undefined will be ignored. +# no return value +sub set_library_path +{ + my ($paths) = @_; + my ($path); + + $path = join($path_sep, grep(defined($_), @$paths)); + + if (is_Windows()) { + $ENV{'PATH'} = $path; + } elsif ($^O eq "hpux") { + $ENV{'SHLIB_PATH'} = $path; + } else { + $ENV{'LD_LIBRARY_PATH'} = $path; + } + + return; +} + + +# no args +# return Library Path Environment variable +sub get_library_path +{ + if (is_Windows()) { + return $ENV{'PATH'}; + } elsif ($^O eq "hpux") { + return $ENV{'SHLIB_PATH'}; + } else { + return $ENV{'LD_LIBRARY_PATH'}; + } +} + + +############################################################## +# Generic "identity" Subroutines +############################################################## + +# no args +# return 1 - success, or +# return 0 - failure +sub check_for_root_UID +{ + my $result = 0; + + # On Linux/UNIX, insure that this script is being run as "root"; + # First check the "Real" UID, and then check the "Effective" UID. + if (!is_Windows()) { + if (($< != $ROOTUID) && + ($> != $ROOTUID)) { + emit("This script must be run as root!\n", "error"); + $result = 0; + } else { + # Success -- running script as root + $result = 1; + } + } else { + emit("Root UID makes no sense on Windows machines!\n", "error"); + $result = 0; + } + + return $result; +} + + +# return 1 - exists, or +# return 0 - DOES NOT exist +sub user_exists +{ + my ($username) = @_; + + return defined(getpwnam($username)); +} + + +# Return 1 if success, 0 if failure +sub create_user +{ + my ($username, $groupname) = @_; + my $command; + + emit(sprintf("create_user(%s)\n", join(", ", @_)), "debug"); + + return 1 if $dry_run; + + if (($username eq $PKI_USER) && + ($groupname eq $PKI_GROUP)) { + # Attempt to create $PKI_USER with $PKI_UID + emit("create_user(): Adding default PKI user '$username' " + . "(uid=$PKI_UID) to '/etc/passwd'.\n", "debug"); + if ($^O eq "linux") { + $command = "/usr/sbin/useradd " + . "-g $groupname " + . "-d /usr/share/pki " + . "-s /sbin/nologin " + . "-c 'Certificate System' " + . "-u $PKI_UID " + . "-r " + . $username; + } elsif ($^O eq "solaris") { + $command = "/usr/sbin/useradd " + . "-g $groupname " + . "-d /usr/share/pki " + . "-s /bin/false " + . "-c 'Certificate System' " + . "-u $PKI_UID " + . $username; + } else { + $command = "/usr/sbin/useradd " + . "-g $groupname " + . "-d /usr/share/pki " + . "-s '' " + . "-c 'Certificate System' " + . "-u $PKI_UID " + . $username; + } + } else { + # Attempt to create $username with random UID + emit("create_user(): Adding default PKI user '$username' " + . "(uid=random) to '/etc/passwd'.\n", "debug"); + if ($^O eq "linux") { + $command = "/usr/sbin/useradd " + . "-g $groupname " + . "-d /usr/share/pki " + . "-s /sbin/nologin " + . "-c 'Certificate System' " + . $username; + } elsif ($^O eq "solaris") { + $command = "/usr/sbin/useradd " + . "-g $groupname " + . "-d /usr/share/pki " + . "-s /bin/false " + . "-c 'Certificate System' " + . $username; + } else { + $command = "/usr/sbin/useradd " + . "-g $groupname " + . "-d /usr/share/pki " + . "-s '' " + . "-c 'Certificate System' " + . $username; + } + } + + return 0 if !run_command($command); + return user_exists($username); +} + + +# return 1 - exists, or +# return 0 - DOES NOT exist +sub group_exists +{ + my ($groupname) = @_; + + return defined(getgrnam($groupname)); +} + + +# Return 1 if success, 0 if failure +sub create_group +{ + my ($groupname) = @_; + my $command; + + emit(sprintf("create_group(%s)\n", join(", ", @_)), "debug"); + + return 1 if $dry_run; + + if ($groupname eq $PKI_GROUP) { + # Attempt to create $PKI_GROUP with $PKI_GID + emit("Adding default PKI group '$groupname' " + . "(gid=$PKI_GID) to '/etc/group'.\n", "debug"); + if ($^O eq "linux") { + $command = "/usr/sbin/groupadd " + . "-g $PKI_GID " + . "-r " + . $groupname; + } elsif ($^O eq "solaris") { + $command = "/usr/sbin/groupadd " + . "-g $PKI_GID " + . $groupname; + } else { + $command = "/usr/sbin/groupadd " + . "-g $PKI_GID " + . $groupname; + } + } else { + # Attempt to create $groupname with random GID + emit("Adding default PKI group '$groupname' " + . "(gid=random) to '/etc/group'.\n", "debug"); + if ($^O eq "linux") { + $command = "/usr/sbin/groupadd " + . $groupname; + } elsif ($^O eq "solaris") { + $command = "/usr/sbin/groupadd " + . $groupname; + } else { + $command = "/usr/sbin/groupadd " + . $groupname; + } + } + + return 0 if !run_command($command); + return group_exists($groupname); +} + + +# return 1 - disallows shell, or +# return 0 - allows shell +sub user_disallows_shell +{ + my ($username) = @_; + + my $result = 0; + my $sans_shell = ""; + + if ($^O eq "linux") { + $sans_shell="/sbin/nologin"; + $result = 0; + } elsif ($^O eq "solaris") { + $sans_shell="/bin/false"; + $result = 0; + } else { + $sans_shell=""; + return 1; + } + + if (!user_exists($username)) { + return $result; + } + + my ($name, $passwd, $uid, $gid, $quota, + $comment, $gcos, $dir, $shell, $expire) = getpwnam($username); + + if (!$shell) { + $result = 1; + } elsif ($shell eq $sans_shell) { + $result = 1; + } else { + # issue a warning and continue + emit("WARNING: Potential security hole - user '$username' is\n" + . " using '$shell' instead of '$sans_shell'!\n", "warning"); + } + + return $result; +} + + +# return 1 - is a member, or +# return 0 - is NOT a member +sub user_is_a_member_of_group +{ + my ($username, $groupname) = @_; + + return 0 if !user_exists($username); + return 0 if !group_exists($groupname); + + # The members list returned by getgrname may not contain the user's primary group. + # This is OS dependent and is typically the case when the primary gid is a + # "user private group". Therefore testing the group member list is insufficient, + # we must also test the primary group. + my ($pw_name, $pw_passwd, $pw_uid, $pw_gid) = getpwnam($username); + if (defined $pw_gid) { + my $primary_groupname = getgrgid($pw_gid); + + return 1 if $primary_groupname eq $groupname; + } + + # Now get the list of users in the specified group + # and test to see if the specified user is in that list. + my ($gr_name, $gr_passwd, $gr_gid, $gr_members) = getgrnam($groupname); + for my $member (split(' ', $gr_members)) { + return 1 if $member eq $username; + } + + return 0; +} + + +# return 1 - success, or +# return 0 - failure +sub add_user_as_a_member_of_group +{ + my ($username, $groupname) = @_; + + my $command = ""; + my $result = 0; + + emit(sprintf("add_user_as_a_member_of_group(%s)\n", join(", ", @_)), "debug"); + + return 1 if $dry_run; + + return 0 if !user_exists($username); + return 0 if !group_exists($groupname); + return 1 if user_is_a_member_of_group($username, $groupname); + + # Attempt to add user to be a member of group + emit("Adding user '$username' to be a member of group " + . "'$groupname'.\n", "debug"); + if ($^O eq "linux") { + $command = "/usr/sbin/usermod " + . "-G $groupname " + . $username; + } elsif ($^O eq "solaris") { + $command = "/usr/sbin/usermod " + . "-G $groupname " + . $username; + } else { + $command = "/usr/sbin/usermod " + . "-G $groupname " + . $username; + } + + return 0 if !run_command($command); + return user_is_a_member_of_group($username, $groupname); +} + + +# return UID, or +# return (-1) - user is not in password file +sub get_UID_from_username +{ + my ($username) = @_; + + my ($name, $passwd, $uid) = getpwnam($username); + + return $uid if defined($uid); + return (-1); + } + + +# Return fully-qualified domain name (FQDN) given +# either a hostname or an IP address +sub get_FQDN +{ + my ($addr) = @_; + + if (!$is_IPv6) { + if ($addr !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) { + # Retrieve FQDN via a "mnemonic" hostname + ($fqdn) = gethostbyname($addr); + } else { + # Retrieve FQDN via a "4-tuple" IP address + $fqdn = gethostbyaddr(pack('C4', $1, $2, $3, $4), 2); + } + } else { + # IPv6: Don't rely upon "Socket6.pm" being present! + $fqdn = $addr; + } + + return($fqdn); +} + + +############################################################## +# Generic "availability" Subroutines +############################################################## + +# return 1 - URL prefix is known (success) +# return 0 - URL prefix is unknown (failure) +sub check_for_valid_url_prefix +{ + my ($url_prefix) = @_; + + if (($url_prefix eq $FILE_PREFIX) || + ($url_prefix eq $FTP_PREFIX) || + ($url_prefix eq $HTTP_PREFIX) || + ($url_prefix eq $HTTPS_PREFIX) || + ($url_prefix eq $LDAP_PREFIX) || + ($url_prefix eq $LDAPS_PREFIX)) { + return 1; + } + + return 0; +} + +# return 1 - ports are valid (success) +# return 0 - ports have a conflict (failure) +sub AreConnectorPortsValid +{ + # parse parameters + my ($secure_port, $unsecure_port, $agent_secure_port, + $ee_secure_port, $admin_secure_port, $proxy_secure_port, + $proxy_unsecure_port, $ajp_port) = @_; + + + if ($secure_port == -1 && $agent_secure_port == -1) + { + return 0; + } + + if ($secure_port >= 0 && $agent_secure_port >= 0) + { + return 0; + } + + if ($secure_port >= 0) + { + if ($secure_port == $unsecure_port) + { + return 0; + } + return 1; + } + + if (!portsUnique($agent_secure_port,$ee_secure_port, $admin_secure_port, $proxy_secure_port, + $proxy_unsecure_port, $ajp_port)) { + return 0; + } + + return 1; + +} + +#return 1 - if non-negative ports are uique +#return 0 - otherwise (failure) +sub portsUnique +{ + my @ports = sort @_; + my $last_port = -1; + for my $port (@ports) { + next if ($port < 0); + if ($port == $last_port) { + return 0; + } + $last_port = $port; + } + return 1; +} + +# return 1 - port is available (success) +# return 0 - port is unavailable; report an error (failure) +sub IsLocalPortAvailable +{ + # parse parameters + my ($user, $port) = @_; + + # On Linux/UNIX, check well-known/reserved ports + if (!is_Windows()) { + my $uid = -1; + + # retrieve the UID given the username + $uid = get_UID_from_username($user); + if ($uid == -1) { + emit("User '$user' is NOT in the password file!\n", "error"); + return 0; + } + + # insure that well-known ports cannot be used by a non-root user + if (($port <= $MAX_WELL_KNOWN_PORT) && ($uid != $ROOTUID)) { + emit("User '$user' is not allowed to bind to well-known " + . "port $port!\n", "error"); + return 0; + } + + # insure that reserved ports cannot be used by a non-root user + if (($port <= $MAX_RESERVED_PORT) && ($uid != $ROOTUID)) { + emit("User '$user' is not allowed to bind to reserved " + . "port $port!\n", "error"); + return 0; + } + + # insure that the user has not specified a port greater than + # the number of dynamic/private ports + if ($port > $MAX_DYNAMIC_PORT) { + emit("User '$user' is not allowed to bind to a " + . "port greater than $MAX_DYNAMIC_PORT!\n", "error"); + return 0; + } + + # if the user has specified a port greater than the number + # of registered ports, issue a warning and continue + if ($port > $MAX_REGISTERED_PORT) { + emit("WARNING: User '$user' is binding to port $port; use of " + . "a dynamic/private port is discouraged!\n", "warning"); + } + } + + # initialize local variables + my $rv = 0; + my $status = "AVAILABLE"; + + # make a local TCP server socket + my $proto = getprotobyname('tcp'); + socket(SERVER, PF_INET, SOCK_STREAM, $proto); + + # create a local server socket address + my $server_address = sockaddr_in($port, INADDR_ANY); + + # attempt to bind this local server socket + # to this local server socket address + bind(SERVER, $server_address) or $status = $!; + + # identify the status of this attempt to bind + if ($status eq "AVAILABLE") { + # this port is inactive + $rv = 1; + } elsif ($status eq "Address already in use") { + emit("Unable to bind to local port $port : $status\n", "error"); + $rv = 0; + } else { + emit("Unable to bind to local port $port : $status\n", "error"); + $rv = 0; + } + + # close local server socket + close(SERVER); + + # return result + return $rv; +} + + +# return 2 - warn that server is unreachable (continue) +# return 1 - server is reachable (success) +# return 0 - server is unreachable; report an error (failure) +sub IsServerReachable +{ + # parse parameters + my ($prefix, $host, $port) = @_; + + # check the validity of the prefix + my $result = 0; + + $result = check_for_valid_url_prefix($prefix); + if (!$result) { + emit("Specified unknown url prefix '$prefix'!\n", "error"); + return $result; + } + + # create a URL from the passed-in parameters + my $url = $prefix . $host . ":" . $port; + + # initialize the state of the Server referred to by this URL + my $rv = 0; + my $status = "ACTIVE"; + + # retrieve the remote host IP address + my $iaddr = inet_aton($host) or $status = $!; + if ($status ne "ACTIVE") { + emit("Unable to contact the Server at '$url' ($status)", "error"); + return $rv; + } + + # create a remote server socket address + my $server_address = sockaddr_in($port, $iaddr); + + # make a local TCP client socket + my $proto = getprotobyname('tcp'); + socket(CLIENT, PF_INET, SOCK_STREAM, $proto); + + # attempt to connect this local client socket + # to the remote server socket address + connect(CLIENT, $server_address) or $status = $!; + + # identify the status of this connection + if ($status eq "ACTIVE") { + # this '$host:$port' is reachable + $rv = 1; + } else { + emit("WARNING: Unable to contact the Server at '$url' ($status)", "warning"); + } + + # close local client socket + close(CLIENT); + + # return result + return $rv; +} + + +############################################################## +# Generic "time" Subroutines +############################################################## + +# no args +# return time stamp +sub get_time_stamp +{ + my ($sec, $min, $hour, $mday, + $mon, $year, $wday, $yday, $isdst) = localtime(time); + + my $stamp = sprintf "%4d-%02d-%02d %02d:%02d:%02d", + $year+1900, $mon+1, $mday, $hour, $min, $sec; + + return $stamp; +} + + +############################################################## +# Generic "random" Subroutines +############################################################## + +# return random number between low & high +sub generate_random +{ + my ($low, $high) = @_; + + my $number = 0; + + if ($low >= $high || $low < 0 || $high < 0) { + return -1; + } + + $number = int(rand($high -$low +1)) + $low; + + return $number; +} + + +# return random string of specified length +sub generate_random_string +{ + my ($length_of_randomstring) = @_; + + my @chars=('a'..'z','A'..'Z','0'..'9'); + my $random_string; + + foreach (1..$length_of_randomstring) { + $random_string .= $chars[rand @chars]; + } + + return $random_string; +} + + +############################################################## +# Generic "password" Subroutines +############################################################## + +# return 1 - success +# return 0 - failure; report an error +sub password_quality_checker +{ + my ($password) = @_; + my ($i, $letter); + + # Test #1: $password MUST be > 8 characters + if (length($password) < 8) { + print("\n"); + print("Password entered is less than 8 characters. Try again.\n"); + return 0; + } + + + # Test #2: $password MUST contain at least one non-alphabetic character + my @alphabet = ("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", + "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", + "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", + "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", + "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", + "y", "z"); + + my $non_alphabetic_characters = 0; + for ($i = 0; $i < length($password); $i++) { + # always reset character type + my $found_alphabetic_character = 0; + + # extract the next character from the $password + my $character = substr($password, $i, 1); + + # check to see if this character is "alphabetic" + for $letter (@alphabet) { + if ($character eq $letter) { + $found_alphabetic_character = 1; + last; + } + } + + # keep a count of "non-alphabetic" characters + if ($found_alphabetic_character == 0) { + $non_alphabetic_characters++; + } + } + + # pass Test #2 if the $password contains any "non-alphabetic" characters + if ($non_alphabetic_characters > 0) { + return 1; + } else { + print("\n"); + print("Password entered contains 0 non-alphabetic characters. " + . "Try again.\n"); + return 0; + } +} + + +############################################################## +# Generic "LDAP" Subroutines +############################################################## + +# hostname - LDAP server name or IP address (default: localhost) +# port - LDAP server TCP port number (default: 389) +# password - bind passwd (for simple authentication) +# file - read modifications from file (default: standard input) +# no return value +sub LDAP_add +{ + my ($tokendb_hostname, $tokendb_port, $tokendb_password, $file) = @_; + + my $command = ""; + + my $original_library_path = get_library_path(); + + emit(sprintf("LDAP_add(%s)\n", join(", ", @_)), "debug"); + + return if $dry_run; + + set_library_path([$default_security_libraries, + $default_system_user_libraries, + $default_system_libraries, + $original_library_path]); + + $command = "$default_ldapmodify_command " + . "-h '$tokendb_hostname' " + . "-p '$tokendb_port' " + . "-D 'cn=directory manager' " + . "-w '$tokendb_password' " + . "-a " + . "-f '$file'"; + + system($command); + + set_library_path([$original_library_path]); + + return; +} + + +# hostname - LDAP server name or IP address (default: localhost) +# port - LDAP server TCP port number (default: 389) +# password - bind passwd (for simple authentication) +# file - read modifications from file (default: standard input) +# no return value +sub LDAP_modify +{ + my ($tokendb_hostname, $tokendb_port, $tokendb_password, $file) = @_; + + my $command = ""; + + my $original_library_path = get_library_path(); + + emit(sprintf("LDAP_modify(%s)\n", join(", ", @_)), "debug"); + + return if $dry_run; + + set_library_path([$default_security_libraries, + $default_system_user_libraries, + $default_system_libraries, + $original_library_path]); + + $command = "$default_ldapmodify_command " + . "-h '$tokendb_hostname' " + . "-p '$tokendb_port' " + . "-D 'cn=directory manager' " + . "-w '$tokendb_password' " + . "-f '$file'"; + + system($command); + + set_library_path([$original_library_path]); + + return; +} + + +############################################################## +# Generic "Security Databases" Subroutines +############################################################## + +# instance path - Security databases directory (default is ~/.netscape) +# password file - Specify the password file +# no return value +sub certutil_create_databases +{ + my ($instance_path, $pwdfile) = @_; + + my $command = ""; + + my $original_library_path = get_library_path(); + + emit(sprintf("certutil_create_databases(%s)\n", join(", ", @_)), "debug"); + + return if $dry_run; + + set_library_path([$default_security_libraries, + $default_system_user_libraries, + $default_system_libraries, + $original_library_path]); + + if (!$pwdfile) { + $command = "$default_certutil_command " + . "-N " + . "-d $instance_path"; + } else { + $command = "$default_certutil_command " + . "-N " + . "-d $instance_path " + . "-f $pwdfile"; + } + + system($command); + + set_library_path([$original_library_path]); + + return; +} + + +# instance path - Security databases directory (default is ~/.netscape) +# token - Name of token in which to look for cert (default is internal, +# use "all" to look for cert on all tokens) +# nickname - The nickname of the cert to delete +# no return value +sub certutil_delete_cert +{ + my ($instance_path, $token, $nickname) = @_; + + my $command = ""; + + my $original_library_path = get_library_path(); + + emit(sprintf("certutil_delete_cert(%s)\n", join(", ", @_)), "debug"); + + return if $dry_run; + + set_library_path([$default_security_libraries, + $default_system_user_libraries, + $default_system_libraries, + $original_library_path]); + + $command = "$default_certutil_command " + . "-D " + . "-d $instance_path " + . "-h '$token' " + . "-n '$nickname'"; + + system($command); + + set_library_path([$original_library_path]); + + return; +} + + +# instance path - Security databases directory (default is ~/.netscape) +# token - Name of token in which to generate key (default is internal) +# subject - Specify the subject name (using RFC1485) +# password file - Specify the password file +# no return value +sub certutil_generate_CSR +{ + my ($instance_path, $token, $subject, $pwdfile) = @_; + + my $command = ""; + + my $original_library_path = get_library_path(); + + emit(sprintf("certutil_generate_CSR(%s)\n", join(", ", @_)), "debug"); + + return if $dry_run; + + set_library_path([$default_security_libraries, + $default_system_user_libraries, + $default_system_libraries, + $original_library_path]); + + if (!$pwdfile) { + $command = "$default_certutil_command " + . "-R " + . "-d $instance_path " + . "-h '$token' " + . "-s '$subject' " + . "-a"; + } else { + $command = "$default_certutil_command " + . "-R " + . "-d $instance_path " + . "-h '$token' " + . "-s '$subject' " + . "-a " + . "-f $pwdfile"; + } + + system($command); + + set_library_path([$original_library_path]); + + return; +} + + +# instance path - Security databases directory (default is ~/.netscape) +# token - Name of token in which to store the certificate +# (default is internal) +# serial number - Cert serial number +# validity period - Months valid (default is 3) +# subject - Specify the subject name (using RFC1485) +# issuer name - The nickname of the issuer cert +# nickname - Specify the nickname of the server certificate +# trust args - Set the certificate trust attributes: +# p valid peer +# P trusted peer (implies p) +# c valid CA +# T trusted CA to issue client certs (implies c) +# C trusted CA to issue server certs (implies c) +# u user cert +# w send warning +# g make step-up cert +# noise file - Specify the noise file to be used +# (to introduce randomness during key generation) +# password file - Specify the password file +# no return value +sub certutil_generate_self_signed_cert +{ + my ($instance_path, $token, $serial_number, $validity_period, + $subject, $issuer_name, $nickname, $trustargs, $noise_file, + $pwdfile) = @_; + + my $command = ""; + + my $original_library_path = get_library_path(); + + emit(sprintf("certutil_generate_self_signed_cert(%s)\n", join(", ", @_)), "debug"); + + return if $dry_run; + + set_library_path([$default_security_libraries, + $default_system_user_libraries, + $default_system_libraries, + $original_library_path]); + + if (!$pwdfile) { + $command = "$default_certutil_command " + . "-S " + . "-d $instance_path " + . "-h '$token' " + . "-m $serial_number " + . "-v $validity_period " + . "-x " + . "-s '$subject' " + . "-c '$issuer_name' " + . "-n '$nickname' " + . "-t '$trustargs' " + . "-z $noise_file " + . "> /dev/null " + . "2>&1"; + } else { + $command = "$default_certutil_command " + . "-S " + . "-d $instance_path " + . "-h '$token' " + . "-f $pwdfile " + . "-m $serial_number " + . "-v $validity_period " + . "-x " + . "-s '$subject' " + . "-c '$issuer_name' " + . "-n '$nickname' " + . "-t '$trustargs' " + . "-z $noise_file " + . "> /dev/null " + . "2>&1"; + } + + system($command); + + set_library_path([$original_library_path]); + + return; +} + + +# instance path - Security databases directory (default is ~/.netscape) +# token - Name of token in which to store the certificate +# (default is internal) +# nickname - Specify the nickname of the server certificate +# trust args - Set the certificate trust attributes: +# p valid peer +# P trusted peer (implies p) +# c valid CA +# T trusted CA to issue client certs (implies c) +# C trusted CA to issue server certs (implies c) +# u user cert +# w send warning +# g make step-up cert +# (e. g. - Server Cert 'u,u,u', CA Cert 'CT,CT,CT') +# cert - The certificate encoded in ASCII (RFC1113) +# no return value +sub certutil_import_cert +{ + my ($instance_path, $token, $nickname, $trustargs, $cert) = @_; + + my $original_library_path = get_library_path(); + + emit(sprintf("certutil_import_cert(%s)\n", join(", ", @_)), "debug"); + + return if $dry_run; + + set_library_path([$default_security_libraries, + $default_system_user_libraries, + $default_system_libraries, + $original_library_path]); + + open(F, + "|$default_certutil_command " + . "-A " + . "-d $instance_path " + . "-h '$token' " + . "-n '$nickname' " + . "-t '$trustargs' " + . "-a"); + print(F $cert); + close(F); + + set_library_path([$original_library_path]); + + return; +} + + +# instance path - Security databases directory (default is ~/.netscape) +# token - Name of token in which to look for cert (default is internal, +# use "all" to look for cert on all tokens) +# nickname - Pretty print named cert (list all if unspecified) +# no return value +sub certutil_print_cert +{ + my ($instance_path, $token, $nickname) = @_; + + my $command = ""; + + my $original_library_path = get_library_path(); + + emit(sprintf("certutil_print_cert(%s)\n", join(", ", @_)), "debug"); + + return if $dry_run; + + set_library_path([$default_security_libraries, + $default_system_user_libraries, + $default_system_libraries, + $original_library_path]); + + if ($token) { + # Raidzilla Bug #57616 - certutil is not being consistent, nickname + # requires token name for no reason. + $command = "$default_certutil_command " + . "-L " + . "-d $instance_path " + . "-h '$token' " + . "-n '$token:$nickname'"; + } else { + $command = "$default_certutil_command " + . "-L " + . "-d $instance_path " + . "-h '$token' " + . "-n '$nickname'"; + } + + system($command); + + set_library_path([$original_library_path]); + + return; +} + + +# no return value +# instance path - Security databases directory (default is ~/.netscape) +# token - Name of token in which to look for certs (default is internal, +# use "all" to list certs on all tokens) +sub certutil_list_certs +{ + my ($instance_path, $token) = @_; + + my $command = ""; + + my $original_library_path = get_library_path(); + + emit(sprintf("certutil_list_certs(%s)\n", join(", ", @_)), "debug"); + + return if $dry_run; + + set_library_path([$default_security_libraries, + $default_system_user_libraries, + $default_system_libraries, + $original_library_path]); + + $command = "$default_certutil_command " + . "-L " + . "-d $instance_path " + . "-h '$token'"; + + system($command); + + set_library_path([$original_library_path]); + + return; +} + + +# instance path - Security databases directory (default is ~/.netscape) +# token - Add the named token to the module database +# library - The name of the file (.so or .dll) containing the +# implementation of PKCS #11 +# no return value +sub modutil_add_token +{ + my ($instance_path, $token, $library) = @_; + + my $command = ""; + + my $original_library_path = get_library_path(); + + emit(sprintf("modutil_add_token(%s)\n", join(", ", @_)), "debug"); + + return if $dry_run; + + set_library_path([$default_security_libraries, + $default_system_user_libraries, + $default_system_libraries, + $original_library_path]); + + $command = "$default_modutil_command " + . "-force " + . "-dbdir $instance_path " + . "-add $token " + . "-libfile $library " + . "-nocertdb"; + + system("$command > /dev/null 2>&1"); + + set_library_path([$original_library_path]); + + return; +} + + +############################################################## +# Generic "logging" Subroutines +############################################################## + +# Return 1 if success, 0 if failure +sub open_logfile +{ + my ($path, $permissions, $owner, $group) = @_; + + + $logfd = FileHandle->new("> $path"); + + if (defined($logfd)) { + $logfile_path = $path; + } else { + return 0; + } + + if (defined($permissions)) { + return 0 if !set_permissions($logfile_path, $permissions); + } + + if (defined($owner) && defined($group)) { + return 0 if !set_owner_group($logfile_path, $owner, $group); + } + + return 1; +} + +# no return value +sub get_logfile_path +{ + return $logfile_path; +} + +# no return value +sub close_logfile +{ + if (defined($logfd)) { + $logfd->close(); + } + + $logfd = undef; + return; +} + + +############################################################## +# Generic "response" Subroutines +############################################################## + +# return answer +sub prompt +{ + my ($promptStr) = @_; + + my $answer = ""; + + print(STDOUT "$promptStr "); + + $| = 1; + $answer = ; + + chomp $answer; + + print(STDOUT "\n"); + + return $answer; +} + + +############################################################## +# Generic "reply" Subroutines +############################################################## + +# no return value +sub printFile +{ + my ($fileHandle) = @_; + + while (<$fileHandle>) { + my $line = $_; + chomp($line); + print(STDOUT "$line\n"); + } + + return; +} + + +# no return value +sub emit +{ + my ($string, $type) = @_; + + my $force_emit = 0; + my $log_entry = ""; + + $type = "debug" if !defined($type); + + if ($type eq "error" || $type eq "warning" || $type eq "info") { + $force_emit = 1; + } + + return if !$string; + + chomp($string); + my $stamp = get_time_stamp(); + + if ($verbose || $force_emit) { + # print to stdout + if ($type ne "log") { + print(STDERR "[$type] $string\n"); + } + } + + # If a log file exists, write all types + # ("debug", "error", "info", or "log") + # to this specified log file + if (defined($logfd)) { + $log_entry = "[$stamp] [$type] $string\n"; + $logfd->print($log_entry); + } + + return; +} + + +############################################################## +# Generic "validity" Subroutines +############################################################## + +# return 1 - valid, or +# return 0 - invalid +sub is_path_valid +{ + my ($path) = @_; + + my @pathname = split("/", $path); + + shift @pathname unless $pathname[0]; + + my $valid = 0; + my $split_path; + + foreach $split_path (@pathname) { + chomp($split_path); + + if (!($split_path !~ /^[-_.a-zA-Z0-9\[\]]+$/)) { + $valid = 1; + } else { + $valid = 0; + last; + } + } + + return $valid; +} + + +# return 1 - valid, or +# return 0 - invalid +sub is_name_valid +{ + my ($name) = @_; + + my $result = 0; + + if (!($name !~ /^[-_.a-zA-Z0-9]+$/)) { + $result = 1; + } + + return $result; +} + + +############################################################## +# Generic "entity" Subroutines +############################################################## + +# return type of entity +sub entity_type +{ + my ($entity) = @_; + + if (-b $entity) { + return "block special file"; + } elsif (-c $entity) { + return "character special file"; + } elsif (-d $entity) { + return "directory"; + } elsif (-f $entity) { + if (-B $entity) { + return "binary file"; + } elsif (-T $entity) { + return "text file"; + } else { + return "plain file"; + } + } elsif (-l $entity) { + return "symbolic link"; + } elsif (-p $entity) { + return "named pipe"; + } elsif (-S $entity) { + return "socket"; + } + + return "UNKNOWN"; +} + + +# return 1 - exists, or +# return 0 - DOES NOT exist +sub entity_exists +{ + my ($entity) = @_; + + my $result = 0; + + if (-e $entity) { + my $type = entity_type($entity); + $result = 1; + } + + return $result; +} + + +############################################################## +# Generic "file" Subroutines +############################################################## + +# return 1 - exists, or +# return 0 - DOES NOT exist +sub file_exists +{ + my ($file) = @_; + + my $result = 0; + + if (-f $file) { + $result = 1; + } elsif (-e $file) { + my $type = entity_type($file); + emit("File $file DOES NOT exist because $file is a $type!\n", + "error"); + $result = 0; + } + + + return $result; +} + + +# return 1 - empty, or +# return 0 - NOT empty +sub is_file_empty +{ + my ($file) = @_; + + my $result = 0; + + if (-z $file) { + $result = 1; + } + + return $result; +} + + +# Return 1 if success, 0 if failure +sub create_empty_file +{ + my ($path, $permissions, $owner, $group, $uninstall_action) = @_; + + $uninstall_action = 'remove' unless defined($uninstall_action); + + emit(sprintf("create_empty_file(%s, %s, %s, %s, %s)\n", + $path, + defined($permissions) ? sprintf("%o", $permissions) : "", + $owner, $group, $uninstall_action), "debug"); + + add_install_info($path, 'file', $uninstall_action); + + if (!$dry_run) { + if (!open(FILE, "> $path")) { + emit("Cannot create empty file \"$path\" ($!)", 'error'); + return 0; + } + close(FILE); + } + + if (defined($permissions)) { + return 0 if !set_permissions($path, $permissions); + } + + if (defined($owner) && defined($group)) { + return 0 if !set_owner_group($path, $owner, $group); + } + + return 1; +} + + +# Return 1 if success, 0 if failure +sub create_file +{ + my ($path, $contents, $permissions, $owner, $group, $uninstall_action) = @_; + + $uninstall_action = 'remove' unless defined($uninstall_action); + + emit(sprintf("create_file(%s, %s, %s, %s, %s)\n", + $path, + defined($permissions) ? sprintf("%o", $permissions) : "", + $owner, $group, $uninstall_action), "debug"); + + add_install_info($path, 'file', $uninstall_action); + + if (!$dry_run) { + if (!open(FILE, "> $path")) { + emit("could not create file \"$path\" ($!)\n", 'error'); + return 0; + } + print(FILE $contents); + close(FILE); + } + + if (defined($permissions)) { + return 0 if !set_permissions($path, $permissions); + } + + if (defined($owner) && defined($group)) { + return 0 if !set_owner_group($path, $owner, $group); + } + + return 1; +} + + +# Return 1 if success, 0 if failure +sub copy_file +{ + my ($src_path, $dst_path, $permissions, $owner, $group, $uninstall_action) = @_; + + $uninstall_action = 'remove' unless defined($uninstall_action); + + emit(sprintf("copy_file(%s, %s, %s, %s, %s, %s)\n", + $src_path, $dst_path, + defined($permissions) ? sprintf("%o", $permissions) : "", + $owner, $group, $uninstall_action), "debug"); + + add_install_info($dst_path, 'file', $uninstall_action); + + if (!is_path_valid($src_path)) { + emit("copy_file(): illegal src path => \"$src_path\".\n", + "error"); + remove_install_info($dst_path); + return 0; + } + + if (!is_path_valid($dst_path)) { + emit("copy_file(): illegal dst path => \"$dst_path\".\n", + "error"); + remove_install_info($dst_path); + return 0; + } + + if (!$dry_run) { + if (!copy($src_path, $dst_path)) { + emit("copy_file(): \"$src_path\" => \"$dst_path\" ($!)\n", "error"); + remove_install_info($dst_path); + return 0; + } + } + + if (defined($permissions)) { + return 0 if !set_permissions($dst_path, $permissions); + } + + if (defined($owner) && defined($group)) { + return 0 if !set_owner_group($dst_path, $owner, $group); + } + + return 1; +} + + +# Return 1 if success, 0 if failure +sub remove_file +{ + my ($path) = @_; + my $result = 0; + + emit(sprintf("remove_file(%s)\n", join(", ", @_)), "debug"); + + add_install_info($path, 'file', 'remove', 'remove'); + + return 1 if $dry_run; + + if (!unlink($path)) { + emit("remove_file(): failed to remove file \"$path\" ($!)\n", "error"); + return 0; + } + + return 1; + } + +# set_permissions(path_glob, permissions) +# Return 1 if success, 0 if failure +sub set_permissions +{ + my ($path_glob, $permissions) = @_; + my (@paths, $errstr, $result, $count); + + $errstr = undef; + $count = 0; + $result = 1; + + emit(sprintf("set_permissions(%s, %s)\n", + $path_glob, + defined($permissions) ? sprintf("%o", $permissions) : ""), "debug"); + + return 1 if $dry_run; + + @paths = glob($path_glob); + + if (($count = chmod($permissions, @paths)) != @paths) { + $errstr = "$!"; + $result = 0; + emit(sprintf("failed to set permission (%o) on \"%s\" => (%s), %d out of %d failed, \"%s\"\n", + $permissions, $path_glob, "@paths", @paths - $count, @paths+0, $errstr), 'error'); + } + return $result; + } + +# set_owner_group(path_glob, owner, group) +# Return 1 if success, 0 if failure +sub set_owner_group +{ + my ($path_glob, $owner, $group) = @_; + my (@paths, $errstr, $result, $count); + my ($uid, $gid); + + $errstr = undef; + $count = 0; + $result = 1; + + emit(sprintf("set_owner_group(%s)\n", join(", ", @_)), "debug"); + + return 1 if $dry_run; + + $uid = getpwnam($owner); + $gid = getgrnam($group); + @paths = glob($path_glob); + + if (($count = chown($uid, $gid, @paths)) != @paths) { + $errstr = "$!"; + $result = 0; + emit(sprintf("failed to set ownership (%s) on \"%s\" => (%s), %d out of %d failed, \"%s\"\n", + "${owner}:${group}", $path_glob, "@paths", @paths - $count, @paths+0, $errstr), 'error'); + } + return $result; +} + +# set_file_props(path_glob, permissions, owner, group) +# Return 1 if success, 0 if failure +sub set_file_props +{ + my ($path_glob, $permissions, $owner, $group) = @_; + my (@paths, $tmp_result, $result); + + $result = 1; + + emit(sprintf("set_file_props(%s %s %s %s)\n", + $path_glob, + defined($permissions) ? sprintf("%o", $permissions) : "", + $owner, $group), "debug"); + + return 1 if $dry_run; + + $tmp_result = set_permissions($path_glob, $permissions); + $result = 0 if !$tmp_result; + + $tmp_result = set_owner_group($path_glob, $owner, $group); + $result = 0 if !$tmp_result; + + return $result; + } + + + +############################################################## +# Generic "directory" Subroutines +############################################################## + +# Callback for walk_dir(), see walk_dir() for documentation +sub walk_callback { + my ($dir, $basename, $is_dir, $prune, $opts) = @_; + + if ($is_dir) { + my ($include_dirs, $mark_dir, $add_to_list, $regexp, $regexps); + + # Don't descend into directories unless recursive. + $$prune = ! $opts->{'recursive'}; + + # If include filter is provided, basename must match + # at least one regexp in filter list. + if (defined($regexps = $opts->{'dir_includes'})) { + $add_to_list = 0; + for $regexp (@$regexps) { + if ($basename =~ /$regexp/) { + $add_to_list = 1; + last; + } + } + } else { + $add_to_list = 1; + } + + if (!$add_to_list) { + $$prune = 1; + return; + } + + # If exclude filter is provided, basename cannot match + # any regexp in filter list. + if (defined($regexps = $opts->{'dir_excludes'})) { + for $regexp (@$regexps) { + if ($basename =~ /$regexp/) { + $add_to_list = 0; + last; + } + } + } + + if (!$add_to_list) { + $$prune = 1; + return; + } + + # Are we collecting directories? + $include_dirs = $opts->{'include_dirs'} // 0; + return if ! $include_dirs; + + if ($opts->{'mark_dir'}) { + push(@{$opts->{'file_list'}}, "${dir}/${basename}/"); + } else { + push(@{$opts->{'file_list'}}, "${dir}/${basename}"); + } + } + else { + my ($include_files, $add_to_list, $regexp, $regexps); + + # If include filter is provided, basename must match + # at least one regexp in filter list. + if (defined($regexps = $opts->{'file_includes'})) { + $add_to_list = 0; + for $regexp (@$regexps) { + if ($basename =~ /$regexp/) { + $add_to_list = 1; + last; + } + } + } else { + $add_to_list = 1; + } + + return if !$add_to_list; + + # If exclude filter is provided, basename cannot match + # any regexp in filter list. + if (defined($regexps = $opts->{'file_excludes'})) { + for $regexp (@$regexps) { + if ($basename =~ /$regexp/) { + $add_to_list = 0; + last; + } + } + } + + return if !$add_to_list; + + # Are we collecting files? + $include_files = $opts->{'include_files'} // 0; + return if ! $include_files; + + push(@{$opts->{'file_list'}}, "${dir}/${basename}"); + } +} + +# Walk directory structure invoking a callback on each +# item found. Optionally prune traversal. +# +# walk_dir($dir, $callback, $prune, $user_data) +# +# dir Path of directory to examine. +# callback Pointer to callback function. +# prune Pointer to boolean variable. +# Callback can set to avoid descending into a directory. +# Ignored for non-directory callback invocations. +# opts Hash table of key/value pairs which controls execution and +# can be used to pass user values to the walk callback. +# See get_directory_files() for definitions. +# +# The signature of the callback is: +# +# callback($dir, $basename, $is_dir, $prune, $user_data) +# +# dir Current directory path. +# basename Entry in directory. +# is_dir Boolean, true if basename is a directory +# prune Pointer to boolean variable. +# Callback can set to avoid descending into a directory. +# Ignored for non-directory callback invocations. +# opts Hash table of key/value pairs which controls execution and +# can be used to pass user values to the walk callback. +# See get_directory_files() for definitions. +# +sub walk_dir { + my ($dir, $callback, $prune, $opts) = @_; + my ($basename); + + # Get the list of files in the current directory. + opendir(DIR, $dir) || (warn "Can't open $dir: $!\n", return); + my (@entries) = sort readdir(DIR); + closedir(DIR); + + foreach $basename (@entries) { + next if $basename eq '.'; + next if $basename eq '..'; + $$prune = 0; + + my $path = "${dir}/${basename}"; + if ((-d $path) && + ((! $opts->{'preserve_links'}) || (! -l $path))) { # yes it is a directory + &$callback($dir, $basename, 1, $prune, $opts); + if (!$$prune) { + walk_dir($path, $callback, $prune, $opts); + } + } + else { # not a directory + &$callback($dir, $basename, 0, $prune, $opts); + last if $$prune; + } + } +} + +# Given a directory path return a sorted array of it's contents. +# The opts parameter is a hash of key/value pairs which controls +# execution and can be used to pass user values to the walk callback. +# +# The options are: +# +# strip_dir (default = false) +# If true strip the leading $dir from returned paths, +# otherwise preserve $dir in each returned path. +# recursive (default = true) +# If true then recusively descend into each directory, +# otherwise just examine the starting directory +# preserve_links (default = true) +# If true symbolic links are preserved. +# If false symbolic links are traversed. +# include_dirs (default = false) +# If true include directories in the returned array, +# otherwise directories are omitted. +# include_files (default = true) +# If true include files in the returned array, +# otherwise files are omitted. +# mark_dir (default = false) +# If true paths which are directories (include_dirs must be true) +# are indicated by a trailing slash, otherwise the basename of +# the directory is left bare. +# +# Filtering +# +# You may specify a set of include/exclude filters on both directories and +# files. An entry will be added to the returned list if it's in the include +# list and not in the exclude list. If either the include or exclude list +# is undefined it has no effect. Each filter is an array of regular +# expressions. The basename (directory entry) is tested against the regular +# expression. For the include filter the basename must match at least one +# of the regular expressions. For the exclude filter if the basename +# matches any of the regular expressions it will be excluded. +# +# In addition if the traversal is recursive and a directory is excluded via +# filtering then that directory is not descended into during the recursive +# traversal. +# +# dir_includes (default = undef) +# Array of regular expressions. If defined a directory must match at +# least one regular expression in the array to be included. +# dir_excludes (default = undef) +# Array of regular expressions. If defined a directory will be excluded +# if it matches any regular expression in the array. +# file_includes (default = undef) +# Array of regular expressions. If defined a file must match at +# least one regular expression in the array to be included. +# file_excludes (default = undef) +# Array of regular expressions. If defined a file will be excluded +# if it matches any regular expression in the array. +# +sub get_directory_files +{ + my ($dir, $opts) = @_; + my ($strip_dir, $mark_dir, $recursive, $preserve_links, $include_dirs, $include_files); + my ($dir_includes, $dir_excludes, $file_includes, $file_excludes); + my ($files, $prune, $pat); + + $strip_dir = $opts->{'strip_dir'} // 0; + $mark_dir = $opts->{'mark_dir'} // 0; + $recursive = $opts->{'recursive'} // 1; + $preserve_links = $opts->{'preserve_links'} // 1; + $include_dirs = $opts->{'include_dirs'} // 0; + $include_files = $opts->{'include_files'} // 1; + $dir_includes = $opts->{'dir_includes'} // undef; + $dir_excludes = $opts->{'dir_excludes'} // undef; + $file_includes = $opts->{'file_includes'} // undef; + $file_excludes = $opts->{'file_excludes'} // undef; + + $files = []; + $prune = 0; + + walk_dir($dir, \&walk_callback, \$prune, + {'file_list' => $files, + 'mark_dir' => $mark_dir, + 'recursive' => $recursive, + 'preserve_links' => $preserve_links, + 'include_dirs' => $include_dirs, + 'include_files' => $include_files, + 'dir_includes' => $dir_includes, + 'dir_excludes' => $dir_excludes, + 'file_includes' => $file_includes, + 'file_excludes' => $file_excludes, + }); + + if ($strip_dir) { + $pat = "^${dir}/"; + map {s/$pat//; $_} @$files; + } + + return $files; +} + +# Normalize paths such that: +# Multiple slashes are collapsed into one slash +# Trailing slash is stripped. +# Strip "." path components. +# Strip previous path component for ".." +# Returns normalized path. +sub normalize_path +{ + my ($path) = @_; + my (@src_components, @dst_components, $component, $leading_slash, $new_path); + + $leading_slash = $path =~ m!^/! ? "/" : ""; + + @src_components = split("/", $path); + + foreach $component (@src_components) { + next if !$component; + next if $component eq "."; + if ($component eq "..") { + die "no directory component to pop \"..\" for in \"$path\"" if !@dst_components; + pop @dst_components; + next; + } + push @dst_components, $component; + } + + $new_path = join("/", @dst_components); + + return $leading_slash . $new_path; +} + +# return 1 - exists, or +# return 0 - DOES NOT exist +sub directory_exists +{ + my ($dir) = @_; + + my $result = 0; + + if (-d $dir) { + $result = 1; + } elsif (-e $dir) { + my $type = entity_type($dir); + emit("Directory $dir DOES NOT exist because $dir is a $type!\n", + "error"); + $result = 0; + } + + return $result; +} + + +# return 1 - empty, or +# return 0 - NOT empty +sub is_directory_empty +{ + my ($dir) = @_; + + my $empty = 1; + my $entity = ""; + + if (!directory_exists($dir)) { + return 1; + } + + opendir(DIR, $dir); + while (defined($entity = readdir(DIR)) && ($empty == 1)) { + if ($entity ne "." && $entity ne "..") { + # NOTE: This is not necessarily an error! + # + # my $type = entity_type("$dir/$entity"); + # emit(" Found $type $entity in directory $dir.\n", + # "debug"); + + $empty = 0; + } + } + closedir(DIR); + + return $empty; +} + + +# Return 1 if success, 0 if failure +sub create_directory +{ + my ($dir, $permissions, $owner, $group, $uninstall_action) = @_; + my $result = 1; + my $errors; + + $uninstall_action = 'remove' unless defined($uninstall_action); + + emit(sprintf("create_directory(%s, %s, %s, %s, %s)\n", + $dir, + defined($permissions) ? sprintf("%o", $permissions) : "", + $owner, $group, $uninstall_action), "debug"); + + add_install_info($dir, 'dir', $uninstall_action); + + return 1 if $dry_run; + + if (!directory_exists($dir)) { + make_path($dir, {error => \$errors}); + if (@$errors) { + my ($error, $path, $errstr); + $result = 0; + for $error (@$errors) { + ($path, $errstr) = %$error; + if ($path eq '') { + emit("create_directory(): dir=\"$dir\" \"$errstr\"\n", "error"); +} + else { + remove_install_info($path); + emit("create_directory(): dir=\"$dir\" path=\"$path\" \"$errstr\"\n", "error"); + } + } + } + } + + if ($result) { + if (defined($permissions)) { + return 0 if !set_permissions($dir, $permissions); + } + + if (defined($owner) && defined($group)) { + return 0 if !set_owner_group($dir, $owner, $group); + } + } + + return $result; +} + +# Return 1 if success, 0 if failure +sub copy_directory +{ + my ($src_dir_path, $dst_dir_path, + $dir_permissions, $file_permissions, + $owner, $group, $uninstall_action) = @_; + my($result); + my ($files, $sub_dirs, $path, $src_path, $dst_path); + + $uninstall_action = 'remove' unless defined($uninstall_action); + $result = 1; + + $src_dir_path = normalize_path($src_dir_path); + $dst_dir_path = normalize_path($dst_dir_path); + + emit(sprintf("copy_directory(%s, %s, %s, %s, %s, %s, %s)\n", + $src_dir_path, $dst_dir_path, + defined($dir_permissions) ? sprintf("%o", $dir_permissions) : "", + defined($dir_permissions) ? sprintf("%o", $dir_permissions) : "", + $owner, $group, $uninstall_action), "debug"); + + if (!is_path_valid($src_dir_path)) { + emit("copy_directory(): illegal src path => $src_dir_path.\n", + "error"); + return 0; + } + + if (!is_path_valid($dst_dir_path)) { + emit("copy_directory(): illegal dst path ($dst_dir_path)\n", "error"); + return 0; + } + + if (!directory_exists($src_dir_path)) { + # Take the case where this directory does not exist + # Just return true + emit("copy_directory(): non-existent src path ($src_dir_path)\n", "error"); + return 1; + } + + # Get list of directories under the src dir + $sub_dirs = get_directory_files($src_dir_path, + {'strip_dir' => 1, 'include_dirs' => 1, 'include_files' => 0}); + + # Get list of files under the src dir + $files = get_directory_files($src_dir_path, + {'strip_dir' => 1, 'include_dirs' => 0, 'include_files' => 1}); + + # Assure each destination directory exists + return 0 if !create_directory($dst_dir_path, + $dir_permissions, $owner, $group, $uninstall_action); + for $path (@$sub_dirs) { + $dst_path = "${dst_dir_path}/${path}"; + return 0 if !create_directory($dst_path, $dir_permissions, + $owner, $group, $uninstall_action); + } + + # Copy each file + for $path (@$files) { + $src_path = "${src_dir_path}/${path}"; + $dst_path = "${dst_dir_path}/${path}"; + + # Emulate cp's behavior with respect to symbolic links, + # symbolic links are NOT followed when copying recursively. + # During recursive copies symbolic links are recreated. + if (-l $src_path) { # src is a symbolic link + if (!copy_symlink($src_path, $dst_path, + $owner, $group, $uninstall_action)) { + $result = 0; + } + } else { # src is not a symbolic link + if (!copy_file($src_path, $dst_path, + $file_permissions, $owner, $group, $uninstall_action)) { + $result = 0; + } + } + } + + if (!$result) { + emit("copy_directory(): failed $src_dir_path => $dst_dir_path.\n", + "error"); + } + + return $result; +} + + +# Removes given directory. By default only the directory is removed and +# only if it is empty. To remove the directory and all of it's contents +# you must provide the $remove_contents parameter and set it to true, +# it defaults to false. +# +# Return 1 if success, 0 if failure +sub remove_directory +{ + my($dir, $remove_contents) = @_; + my($errors, $result); + + emit(sprintf("remove_directory(%s)\n", join(", ", @_)), "debug"); + + $remove_contents = 0 unless defined($remove_contents); + $result = 1; + + add_install_info($dir, 'dir', 'remove', 'remove'); + + return 1 if $dry_run; + + if (!is_path_valid($dir)) { + emit("remove_directory(): specified invalid directory $dir.\n", + "error"); + return 0; + } + + if ($dir eq "/") { + emit("remove_directory(): don't even think about removing root!.\n", + "error"); + return 0; + } + + if (!directory_exists($dir)) { + return 1; + } + + if ($remove_contents) { + remove_tree($dir, {error => \$errors}); + if (@$errors) { + my($error, $path, $errstr); + $result = 0; + for $error (@$errors) { + ($path, $errstr) = %$error; + if ($path eq '') { + emit("remove_directory(): tree=\"$dir\" ($errstr)\n", "error"); + } + else { + emit("remove_directory(): tree=\"$dir\" path=\"$path\" ($errstr)\n", "error"); + } + } + } + } else { + if (!rmdir($dir)) { + $result = 0; + emit("remove_directory(): dir=\"$dir\" ($!) \n", "error"); + } + } + + return $result; +} + + +# Return 1 if success, 0 if failure +sub set_owner_group_on_directory_contents +{ + my ($dir, $owner, $group, $recursive) = @_; + my ($result, $paths, $path); + + $recursive = $recursive // 1; + $result = 1; + + emit(sprintf("set_owner_group_on_directory_contents(%s)\n", join(", ", @_)), "debug"); + + return 1 if $dry_run; + + if (!$dir || !directory_exists($dir)) { + emit("set_owner_group_on_directory_contents(): invalid directory specified.\n", + "error"); + return 0; + } + + if (!$owner || !$group) { + emit("set_owner_group_on_directory_contents(): directory $dir needs a user and group!\n", + "error"); + return 0; + } + + $paths = get_directory_files($dir, {'recursive' => $recursive, + 'include_dirs' => 1}); + + for $path (@$paths) { + $result = 0 if !set_owner_group($path, $owner, $group); + } + + return $result; +} + + +############################################################## +# Generic "symbolic link" Subroutines +############################################################## + +# return 1 - exists, or +# return 0 - DOES NOT exist +sub symlink_exists +{ + my ($symlink) = @_; + + my $result = 0; + + if (-l $symlink) { + $result = 1; + } elsif (-e $symlink) { + my $type = entity_type($symlink); + emit("Symbolic link $symlink DOES NOT exist because $symlink " + . "is a $type!\n", + "error"); + $result = 0; + } + + + return $result; +} + + +# Return 1 if success, 0 if failure +sub create_symlink +{ + my ($symlink, $dst_path, $owner, $group, $uninstall_action) = @_; + + $uninstall_action = 'remove' unless defined($uninstall_action); + + emit(sprintf("create_symlink(%s)\n", join(", ", @_)), "debug"); + + add_install_info($symlink, 'symlink', $uninstall_action); + + return 1 if $dry_run; + + if (symlink_exists($symlink)) { + # delete symbolic link so that we can recreate link for upgrades + if (unlink($symlink) != 1) { + emit("create_symlink(): could not remove existing link \"$symlink\"\n", 'error'); + remove_install_info($symlink); + return 0; + } + } + + if (!is_path_valid($symlink)) { + emit("create_symlink(): invalid path \"$symlink\"\n", "error"); + remove_install_info($symlink); + return 0; + } + + if (!is_path_valid($dst_path) || !entity_exists($dst_path)) { + emit("create_symlink(): illegal dst path \"$dst_path\"\n", "error"); + remove_install_info($symlink); + return 0; + } + + if (!symlink($dst_path, $symlink)) { + emit("create_symlink(): failed \"$symlink\" => \"$dst_path\" ($!)\n", "error"); + remove_install_info($symlink); + return 0; + } + + if (defined($owner) && defined($group)) { + # The Perl Lchown package implements lchown, but it's not currently available + # as an RPM so use a system command instead. :-( + return 0 if !set_owner_group_on_symlink($symlink, $owner, $group); + } + return 1; +} + +# Return 1 if success, 0 if failure +sub copy_symlink +{ + my ($src_path, $dst_path, $owner, $group, $uninstall_action) = @_; + my ($target); + + $uninstall_action = 'remove' unless defined($uninstall_action); + + emit(sprintf("copy_symlink(%s)\n", join(", ", @_)), "debug"); + + add_install_info($dst_path, 'symlink', $uninstall_action); + + if (!is_path_valid($src_path)) { + emit("copy_symlink(): illegal src path => \"$src_path\".\n", + "error"); + remove_install_info($dst_path); + return 0; + } + + if (!is_path_valid($dst_path)) { + emit("copy_symlink(): illegal dst path => \"$dst_path\".\n", + "error"); + remove_install_info($dst_path); + return 0; + } + + if (! -l $src_path) { + emit("copy_symlink(): $src_path is not a symbolic link\n"); + return 0; + } + + return 1 if $dry_run; + + $target = readlink($src_path); + + if (!symlink($target, $dst_path)) { + emit("could not symbolically link $target dst_path", "error"); + remove_install_info($dst_path); + return 0; + } + + if (defined($owner) && defined($group)) { + return 0 if !set_owner_group_on_symlink($dst_path, $owner, $group); + } + + return 1; +} + + +# Return 1 if success, 0 if failure +sub remove_symlink +{ + my ($symlink) = @_; + my $result = 0; + + emit(sprintf("remove_symlink(%s)\n", join(", ", @_)), "debug"); + + add_install_info($symlink, 'symlink', 'remove', 'remove'); + + return 1 if $dry_run; + + if (!$symlink) { + # symlink is NULL + return 1; + } + + if (!symlink_exists($symlink)) { + return 1; + } + + if (unlink($symlink) != 1) { + emit("remove_symlink(): failed \"$symlink\" ($!)\n", "error"); + return 0; + } + + return 1; +} + + +# Return 1 if success, 0 if failure +sub set_owner_group_on_symlink +{ + my ($symlink, $owner, $group) = @_; + + emit(sprintf("set_owner_group_on_symlink(%s)\n", join(", ", @_)), "debug"); + + return 1 if $dry_run; + + if (!$symlink || !symlink_exists($symlink)) { + emit("set_owner_group_on_symlink(): invalid symbolic link specified \"$symlink\"\n", + "error"); + return 1; + } + + if (!$owner || !$group) { + emit("set_owner_group_on_symlink(): symbolic link \"$symlink\" needs a user and group!\n", + "error"); + return 0; + } + + # The Perl Lchown package implements lchown, but it's not currently available + # as an RPM so use a system command instead. :-( + return run_command("chown --no-dereference ${owner}:${group} $symlink"); +} + + +############################################################## +# Generic "chkconfig" Subroutines (Linux ONLY) +############################################################## + +if ($^O eq "linux") { + # Return 1 if success, 0 if failure + sub register_pki_instance_with_chkconfig + { + my ($pki_instance_name) = @_; + my ($command, $exit_status, $result); + + $result = 1; + $command = "/sbin/chkconfig --add $pki_instance_name"; + if (run_command($command)) { + emit("Registered '$pki_instance_name' with '/sbin/chkconfig'.\n"); + } else { + $result = 0; + emit("Failed to register '$pki_instance_name' with '/sbin/chkconfig'.\n", 'error'); + } + return $result; + } + + # Return 1 if success, 0 if failure + sub deregister_pki_instance_with_chkconfig + { + my ($pki_instance_name) = @_; + my ($command, $exit_status, $result); + + $result = 1; + $command = "/sbin/chkconfig --del $pki_instance_name"; + if (run_command($command)) { + emit("Registered '$pki_instance_name' with '/sbin/chkconfig'.\n"); + } else { + $result = 0; + emit("Failed to deregister '$pki_instance_name' with '/sbin/chkconfig'.\n", 'error'); + } + return $result; + } +} + +############################################################## +# Generic Subprocess Subroutines +############################################################## + +# Runs the supplied command in a sub-shell. The command is subject +# to shell interpretation. +# +# WARNING: Do not supply shell IO redirection in the command. +# +# Return 1 if success, 0 if failure +# +# The critical aspect of running a command is determining if the +# command succeeded or failed. The proper way to determine this is by +# checking exit status of command. Perl's subprocess mechansims are +# less than ideal. In simplicity you would want to run the subprocess, +# indpendently capture stdout & stderr, wait for termination and then +# get the exit status. However most of the mechanisms discard +# stderr. The advantages & disadvantages of each approach is nicely +# documented here: +# +# http://blog.0x1fff.com/2009/09/howto-execute-system-commands-in-perl.html +# +# Ideally we would like to capture stdout and stderr +# independently. The best way to do this is with Perl's IPC::Cmd +# package which is part of the standard Perl distribution (whose +# installation may be optional on a given system. RPM can detect our +# use of this package and force it's installation as a +# dependency). One disadvantage of IPC::Cmd is that it does not return +# the actual exit status, just an indication if it was non-zero or not +# (e.g. success). If we chose to use IPC::Cmd at a future date the +# implementation would look like this: +# +# # Note: IPC::Cmd is in the perl-IPC-Cmd RPM +# use IPC::Cmd qw[run]; +# +# my ($success, $error_code, $full_buf, $stdout_buf, $stderr_buf) = +# run(command => $cmd, verbose => 0); +# +# if (!$success) { +# my ($err_msg); +# +# $err_msg = join("", @$stderr_buf); +# chomp($err_msg); +# +# emit(sprintf("FAILED run_command(\"%s\"), output=\"%s\"\n", +# $cmd, $err_msg), "error"); +# +# return 0; +# } +# +sub run_command +{ + my ($cmd) = @_; + my ($output, $wait_status, $exit_status); + + emit(sprintf("run_command(%s)\n", join(", ", @_)), "debug"); + + return 1 if $dry_run; + + # Perl backtick only captures stdout. + # stderr goes to the existing stderr file descriptor, probably the console. + # Capture stderr along with stdout via shell redirection (e.g. 2>&1) + + $output = `$cmd 2>&1`; + $wait_status = $?; + + # The low order 8 bits of the status is the terminating signal + # for the process, the actual exit status is obtained by + # shifting the low order 8 bits out. + $exit_status = $wait_status >> 8; + + if ($exit_status != 0) { + chomp($output); + emit(sprintf("FAILED run_command(\"%s\"), exit status=%d output=\"%s\"\n", + $cmd, $exit_status, $output), "error"); + return 0; + } + + return 1; +} + +############################################################## +# Generic Java Subroutines +############################################################## + +# Given a jar's base name locate it in the file system +# using standard Java jar path for this system. +# Return the path to the jar if found, undef otherwise. +sub find_jar +{ + my($jar_name) = @_; + my($jar_dir, $jar_path); + + for $jar_dir (@default_jar_path) { + $jar_path = "$jar_dir/$jar_name"; + if (-e $jar_path) { + return $jar_path; + } + } + return undef; +} + +############################################################## +# Generic PKI Subroutines +############################################################## + +# Get parameter value(s) from CS.cfg file +# +# get_cs_cfg(config_path, search) +# +# There are 3 ways the parameters can be returned, as a string, as a +# set of variables, or as a hash table depending on the search +# parameter type. +# +# If search is string then the parameter value is returned as a string +# if it was found, otherwise if it wasn't found then undef is +# returned. +# +# If search is a reference to a hash then each key in the hash will be +# searched for and the key's value will be used as a reference to +# assign the value of the parameter to. If the key was not found then +# the reference will be assigned the value of undef. +# +# If search is reference to an array then every parameter in the +# array will be searched for and a hash will be returned with a key +# for every parameter found, the key's value is the parameter value. +# +# Examples: +# +# my ($subsystem_type, $uri, $table); +# +# # Get a single string: $subsystem_type is assigned the string "CA" +# $subsystem_type = get_cs_cfg("/etc/pki-ca/CS.cfg", "cs.type"); +# +# # Assign a set of variables: $subsystem_type and $uri are assigned +# get_cs_cfg($config_path, {"cs.type" => \$subsystem_type, +# "ee.interface.uri" => \$uri}); +# +# # Get a lookup table: +# $table = get_cs_cfg("/etc/pki-ca/CS.cfg", ["cs.type", "ee.interface.uri"]); +# # returns the hash: +# # {"cs.type" => "CA", +# # "ee.interface.uri" => "ca/ee/ca"} +# +sub get_cs_cfg +{ + my ($config_path, $search) = @_; + my ($text, $key, $value, $num_found); + + $text = read_file($config_path); + + if (ref($search) eq "HASH") { + my $num_found = 0; + while (my ($key, $ref) = each(%$search)) { + if ($text =~ /^\s*\Q$key\E\s*=\s*(.*)/m) { + $value = $1; + $$ref = $value; + $num_found += 1; + } else { + $$ref = undef; + } + } + return $num_found; + } elsif (ref($search) eq "ARRAY") { + my $result = {}; + my $keys = $search; + + foreach $key (@$keys) { + if ($text =~ /^\s*\Q$key\E\s*=\s*(.*)/m) { + $value = $1; + $result->{$key} = $value; + } + } + + return $result; + + } else { + my $result = undef; + $key = $search; + + if ($text =~ /^\s*\Q$key\E\s*=\s*(.*)/m) { + $value = $1; + $result = $value; + } + + return $result; + + } +} + +sub get_registry_initscript_name +{ + my ($subsystem_type) = @_; + my ($pki_initscript); + + if ($subsystem_type eq $CA) { + $pki_initscript = $CA_INITSCRIPT; + } elsif($subsystem_type eq $KRA) { + $pki_initscript = $KRA_INITSCRIPT; + } elsif($subsystem_type eq $OCSP) { + $pki_initscript = $OCSP_INITSCRIPT; + } elsif($subsystem_type eq $RA) { + $pki_initscript = $RA_INITSCRIPT; + } elsif($subsystem_type eq $TKS) { + $pki_initscript = $TKS_INITSCRIPT; + } elsif($subsystem_type eq $TPS) { + $pki_initscript = $TPS_INITSCRIPT; + } else { + die "unknown subsystem type \"$subsystem_type\""; + } + +} + +####################################### +# Generic selinux routines +####################################### + +sub check_selinux_port +{ + my ($setype, $seport) = @_; + + return $SELINUX_PORT_UNDEFINED if $dry_run; + + if (defined $selinux_ports{$seport}) { + if ($selinux_ports{$seport} eq $setype) { + return $SELINUX_PORT_DEFINED; + } else { + return $SELINUX_PORT_WRONGLY_DEFINED; + } + } else { + return $SELINUX_PORT_UNDEFINED; + } +} + +sub parse_selinux_ports +{ + open SM, '/usr/sbin/semanage port -l |grep tcp |sed \'s/tcp/___/g\'|sed \'s/\s//g\'|'; + while () { + chomp($_); + my ($type, $portstr) = split /___/, $_; + my @ports = split /,/, $portstr; + foreach my $port (@ports) { + if ($port =~ /(.*)-(.*)/) { + for (my $count = $1; $count <= $2; $count++) { + $selinux_ports{$count} = $type; + } + } else { + $selinux_ports{$port} = $type; + } + } + } + close(SM); +} + +sub add_selinux_port +{ + my ($setype, $seport, $cmds_ref) = @_; + my $status = check_selinux_port($setype, $seport); + + if ($status == $SELINUX_PORT_UNDEFINED) { + if ($cmds_ref) { + $$cmds_ref .= "port -a -t $setype -p tcp $seport\n"; + } else { + my $cmd = "$semanage port -a -t $setype -p tcp $seport\n"; + if (! run_command($cmd)) { + emit("Failed to set selinux context for $seport", "error"); + } + } + + } elsif ($status == $SELINUX_PORT_WRONGLY_DEFINED) { + emit("Failed setting selinux context $setype for $seport. " . + "Port already defined otherwise.\n", "error"); + } +} + +sub add_selinux_file_context +{ + my ($fcontext, $fname, $ftype, $cmds_ref) = @_; + my ($result); + + emit(sprintf("add_selinux_file_context(%s)\n", join(", ", @_)), "debug"); + + #check if fcontext has already been set + my $tmp = `$semanage fcontext -l -n |grep $fname |grep ":$fcontext:" | wc -l`; + chomp $tmp; + if ($tmp ne "0") { + emit("selinux fcontext for $fname already defined\n", "debug"); + return; + } + + if ($ftype eq "f") { + $$cmds_ref .= "fcontext -a -t $fcontext -f -- $fname\n"; + } else { + $$cmds_ref .= "fcontext -a -t $fcontext $fname\n"; + } +} + +1; diff --git a/pki/base/setup/pkicreate b/pki/base/setup/pkicreate new file mode 100755 index 000000000..a9070947c --- /dev/null +++ b/pki/base/setup/pkicreate @@ -0,0 +1,3343 @@ +#!/usr/bin/perl +# +# --- BEGIN COPYRIGHT BLOCK --- +# 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; version 2 of the License. +# +# 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., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2007-2010 Red Hat, Inc. +# All rights reserved. +# --- END COPYRIGHT BLOCK --- +# + +use strict; +use warnings; + +use File::Slurp qw(read_file write_file); +use Getopt::Long qw(GetOptions); + +############################################################## +# This script is used to create a new instance of a +# subsystem within a PKI installation. +# +# Sample Invocation (for CA): +# +# ./pkicreate -pki_instance_root=/var/lib +# -pki_instance_name=pki-ca +# -subsystem_type=ca +# -agent_secure_port=9443 +# -ee_secure_port=9444 +# -ee_secure_client_auth_port=9446 +# -admin_secure_port=9445 +# -unsecure_port=9180 +# -tomcat_server_port=9701 +# -user=pkiuser +# -group=pkiuser +# -redirect conf=/etc/pki-ca +# -redirect logs=/var/log/pki-ca +# -verbose +# +############################################################## + + +############################################################## +# Execution Check +############################################################## + +# Disallow 'others' the ability to 'write' to new files +umask 00002; + +# Check to insure that this script's original +# invocation directory has not been deleted! +my $cwd = `/bin/pwd`; +chomp $cwd; +if (!$cwd) { + emit("Cannot invoke '$0' from non-existent directory!\n", "error"); + exit 255; +} + + +############################################################## +# Environment Variables +############################################################## + +# option to not run this script. +if (defined($ENV{'DONT_RUN_PKICREATE'})) { + if ($ENV{'DONT_RUN_PKICREATE'} == 1) { + emit("Env. variable DONT_RUN_PKICREATE is set. Exiting.\n", "error"); + exit 0; + } +} + +# untaint called subroutines +if (($^O ne 'Windows_NT') && ($^O ne 'MSWin32')) { + $> = $<; # set effective user ID to real UID + $) = $(; # set effective group ID to real GID + $ENV{'PATH'} = '/bin:/usr/bin'; + $ENV{'ENV'} = '' if !defined($ENV{'ENV'}); +} + + +############################################################## +# Command-Line Variables +############################################################## + +my $ARGS = ($#ARGV + 1); + + +############################################################## +# Shared Common Perl Data and Subroutines +############################################################## + +use lib "/usr/share/pki/scripts"; +use pkicommon; + +# Establish path to scripts +my $pki_subsystem_common_area = "/usr/share/$pki_flavor"; + +# make -w happy by suppressing warnings of Global variables used only once +my $suppress = ""; +$suppress = $hostname; +$suppress = $obj_ext; +$suppress = $tmp_dir; +$suppress = $default_security_libraries; +$suppress = $default_system_libraries; +$suppress = $lib_prefix; +$suppress = $PKI_USER; +$suppress = $PKI_GROUP; +$suppress = $install_info_basename; + +############################################################## +# Local Constants +############################################################## + +# Base subsystem directory names +my $applets_base_subsystem_dir = "applets"; # TPS +my $cgibin_base_subsystem_dir = "cgi-bin"; # TPS (Apache) +my $conf_base_subsystem_dir = "conf"; # CA, KRA, OCSP, TKS, RA, TPS +my $docroot_base_subsystem_dir = "docroot"; # RA, TPS (Apache) +my $emails_base_subsystem_dir = "emails"; # CA +my $lib_base_subsystem_dir = "lib"; # RA, TPS +my $profiles_base_subsystem_dir = "profiles"; # CA, KRA, OCSP, TKS +my $samples_base_subsystem_dir = "samples"; # TPS +my $scripts_base_subsystem_dir = "scripts"; # RA, TPS +my $webapps_base_subsystem_dir = "webapps"; # CA, KRA, OCSP, TKS + +# Base instance directory names +my $alias_base_instance_dir = "alias"; # CA, KRA, OCSP, TKS, RA, TPS +my $bin_base_instance_dir = "bin"; # TPS +my $cgibin_base_instance_dir = "cgi-bin"; # TPS (Apache) +my $conf_base_instance_dir = "conf"; # CA, KRA, OCSP, TKS, RA, TPS +my $docroot_base_instance_dir = "docroot"; # RA, TPS (Apache) +my $emails_base_instance_dir = "emails"; # CA +my $lib_base_instance_dir = "lib"; # RA, TPS +my $logs_base_instance_dir = "logs"; # CA, KRA, OCSP, TKS, RA, TPS +my $profiles_base_instance_dir = "profiles"; # CA, KRA, OCSP, TKS +my $scripts_base_instance_dir = "scripts"; # RA, TPS +my $tomcat_instance_common_lib_dir = "common/lib"; # CA, KRA, OCSP, TKS (Tomcat) +my $shared_base_instance_dir = "shared"; # CA, KRA, OCSP, TKS (Tomcat) +my $temp_base_instance_dir = "temp"; # CA, KRA, OCSP, TKS (Tomcat) +my $webapps_base_instance_dir = "webapps"; # CA, KRA, OCSP, TKS +my $work_base_instance_dir = "work"; # CA, KRA, OCSP, TKS (Tomcat) + +# Base instance symbolic link names +my $common_base_instance_symlink = "common"; # CA, KRA, OCSP, TKS +my $conf_base_instance_symlink = "conf"; # CA, KRA, OCSP, TKS, RA, TPS +my $logs_base_instance_symlink = "logs"; # CA, KRA, OCSP, TKS, RA, TPS +my $run_base_instance_symlink = "run"; # RA, TPS + +# Base names +my $cgi_home_base_name = "home/index.cgi"; # TPS +my $cgi_demo_base_name = "demo/index.cgi"; # TPS +my $cgi_so_base_name = "so/index.cgi"; # TPS +my $cgi_so_enroll_name = "so/enroll.cgi"; # TPS +my $cgi_sow_dir_name = "sow"; # TPS +my $cgi_sow_cfg_pl_name = "sow/cfg.pl"; # TPS +my $addAgents_ldif_base_name = "addAgents.ldif"; # TPS +my $addIndexes_ldif_base_name = "addIndexes.ldif"; # TPS +my $addTokens_ldif_base_name = "addTokens.ldif"; # TPS +my $addVLVIndexes_ldif_base_name = "addVLVIndexes.ldif"; # TPS +my $nss_pcache_base_name = "nss_pcache"; # RA, TPS +my $pki_subsystem_jar_base_name = undef; # CA, KRA, OCSP, TKS + +my $pki_certsrv_jar_base_name = "pki-certsrv.jar"; # CA, KRA, OCSP, TKS +my $pki_cms_jar_base_name = "pki-cms.jar"; # CA, KRA, OCSP, TKS +my $pki_cmsbundle_jar_base_name = "pki-cmsbundle.jar"; # CA, KRA, OCSP, TKS +my $pki_cmscore_jar_base_name = "pki-cmscore.jar"; # CA, KRA, OCSP, TKS +my $pki_cmsutil_jar_base_name = "pki-cmsutil.jar"; # CA, KRA, OCSP, TKS +my $commons_collections_jar_base_name = undef; # CA, KRA, OCSP, TKS +my $commons_lang_jar_base_name = undef; # CA, KRA, OCSP, TKS +my $commons_logging_jar_base_name = undef; # CA, KRA, OCSP, TKS +my $jss_jar_base_name = "jss4.jar"; # CA, KRA, OCSP, TKS +my $ldapjdk_jar_base_name = "ldapjdk.jar"; # CA, KRA, OCSP, TKS +my $pki_nsutil_jar_base_name = "pki-nsutil.jar"; # CA, KRA, OCSP, TKS +my $osutil_jar_base_name = "osutil.jar"; # CA, KRA, OCSP, TKS +my $symkey_jar_base_name = "symkey.jar"; # CA, KRA, OCSP, TKS +my $tomcatjss_jar_base_name = "tomcatjss.jar"; # CA, KRA, OCSP, TKS +my $velocity_jar_base_name = "velocity.jar"; # CA, KRA, OCSP, TKS +my $xerces_jar_base_name = "xerces-j2.jar"; # CA, KRA, OCSP, TKS + +my $apache_commons_collections_jar_base_name = "apache-commons-collections.jar"; +my $jakarta_commons_collections_jar_base_name = "jakarta-commons-collections.jar"; +my $apache_commons_logging_jar_base_name = "apache-commons-logging.jar"; +my $jakarta_commons_logging_jar_base_name = "jakarta-commons-logging.jar"; +my $apache_commons_lang_jar_base_name = "apache-commons-lang.jar"; +my $jakarta_commons_lang_jar_base_name = "jakarta-commons-lang.jar"; +my $xml_commons_apis_jar_base_name = "xml-commons-apis.jar"; +my $xml_commons_resolver_jar_base_name = "xml-commons-resolver.jar"; + +my $conf_base_name = "conf"; # CA, KRA, OCSP, TKS, +my $catalina_properties_base_name = "catalina.properties"; # CA, KRA, OCSP, TKS + +my $httpd_conf_base_name = "httpd.conf"; # RA, TPS +my $index_jsp_base_name = "index.jsp"; # CA, KRA, OCSP, TKS + # RA, TPS +my $magic_base_name = "magic"; # RA, TPS +my $mime_types_base_name = "mime.types"; # RA, TPS +my $noise_base_name = "noise"; # CA, KRA, OCSP, TKS, + # RA, TPS +my $nss_conf_base_name = "nss.conf"; # RA, TPS +my $perl_conf_base_name = "perl.conf"; # RA, TPS +my $password_conf_base_name = "password.conf"; # CA, KRA, OCSP, TKS, + # RA, TPS +my $pfile_base_name = "pfile"; # CA, KRA, OCSP, TKS, + # RA, TPS +my $pwcache_conf_base_name = "pwcache.conf"; # RA, TPS +my $pki_cfg_base_name = "CS.cfg"; # CA, KRA, OCSP, TKS, + # RA, TPS +my $schemaMods_ldif_base_name = "schemaMods.ldif"; # RA, TPS +my $server_xml_base_name = "server.xml"; # CA, KRA, OCSP, TKS +my $servercertnick_conf_base_name = "serverCertNick.conf"; # CA, KRA, OCSP, TKS +my $tomcat6_conf_base_name = "tomcat6.conf"; # CA, KRA, OCSP, TKS +my $velocity_prop_base_name = "velocity.properties"; # CA, KRA, OCSP, TKS +my $web_xml_base_name = "web.xml"; # CA, KRA, OCSP, TKS +my $profile_select_base_name = "ProfileSelect.template"; # CA +my $proxy_conf_base_name = "proxy.conf"; # CA + +my $registry_template_base_name = "registry_instance"; # CA, KRA, OCSP, TKS, RA, TPS +my $pki_apache_initscript_base_name = "pki_apache_initscript"; # RA, TPS + +# Subdirectory names +my $perl_base_instance_symlink = "perl"; # RA, TPS +my $perl_base_subsystem_dir = "perl"; # RA, TPS +my $signed_audit_base_instance_dir = "signedAudit"; # CA, KRA, OCSP, TKS, TPS +my $webapps_root_base_instance_dir = "ROOT"; # CA, KRA, OCSP, TKS +my $webapps_root_base_subsystem_dir = "ROOT"; # CA, KRA, OCSP, TKS +my $webinf_base_instance_dir = "WEB-INF"; # CA, KRA, OCSP, TKS + +# Defaults +my $default_apache_pids_path = "/var/run/pki"; +my $default_tomcat_pids_path = "/var/run"; +my $default_tomcat_lib_path = "/usr/share/tomcat6/lib"; +my $default_security_token = "internal"; +my $default_nfast_group = "nfast"; + +# Default PKI user and group to give to PKI installed files +my $pki_user = $PKI_USER; +my $pki_group = $PKI_GROUP; + +# PKI creation constants +my $db_password_low = 100000000000; +my $db_password_high = 999999999999; + +# Template slot constants (RA, TPS) +my $HTTPD_CONF = "HTTPD_CONF"; +my $LIB_PREFIX = "LIB_PREFIX"; +my $NSS_CONF = "NSS_CONF"; +my $OBJ_EXT = "OBJ_EXT"; +my $PORT = "PORT"; +my $PROCESS_ID = "PROCESS_ID"; +my $SECURE_PORT = "SECURE_PORT"; +my $NON_CLIENTAUTH_SECURE_PORT = "NON_CLIENTAUTH_SECURE_PORT"; +my $SECURITY_LIBRARIES = "SECURITY_LIBRARIES"; +my $SERVER_NAME = "SERVER_NAME"; +my $SERVER_ROOT = "SERVER_ROOT"; +my $SYSTEM_LIBRARIES = "SYSTEM_LIBRARIES"; +my $SYSTEM_USER_LIBRARIES = "SYSTEM_USER_LIBRARIES"; +my $TMP_DIR = "TMP_DIR"; +my $TPS_DIR = "TPS_DIR"; +my $FORTITUDE_APACHE = "FORTITUDE_APACHE"; +my $FORTITUDE_DIR = "FORTITUDE_DIR"; +my $FORTITUDE_MODULE = "FORTITUDE_MODULE"; +my $FORTITUDE_LIB_DIR = "FORTITUDE_LIB_DIR"; +my $FORTITUDE_AUTH_MODULES = "FORTITUDE_AUTH_MODULES"; +my $FORTITUDE_NSS_MODULES = "FORTITUDE_NSS_MODULES"; +my $REQUIRE_CFG_PL = "REQUIRE_CFG_PL"; +my $PKI_PIDDIR = "PKI_PIDDIR"; +my $PKI_LOCKDIR = "PKI_LOCKDIR"; + +# Template slot constants (CA, KRA, OCSP, TKS, RA, TPS) +my $PKI_INSTANCE_ID_SLOT = "PKI_INSTANCE_ID"; +my $PKI_REGISTRY_FILE_SLOT = "PKI_REGISTRY_FILE"; + +# Template slot constants (CA, KRA, OCSP, TKS) +my $INSTALL_TIME = "INSTALL_TIME"; +my $PKI_AGENT_CLIENTAUTH_SLOT = "PKI_AGENT_CLIENTAUTH"; +my $PKI_CERT_DB_PASSWORD_SLOT = "PKI_CERT_DB_PASSWORD"; +my $PKI_CFG_PATH_NAME_SLOT = "PKI_CFG_PATH_NAME"; +my $PKI_GROUP_SLOT = "PKI_GROUP"; +my $PKI_INSTANCE_PATH_SLOT = "PKI_INSTANCE_PATH"; +my $PKI_INSTANCE_ROOT_SLOT = "PKI_INSTANCE_ROOT"; +my $PKI_MACHINE_NAME_SLOT = "PKI_MACHINE_NAME"; +my $PKI_RANDOM_NUMBER_SLOT = "PKI_RANDOM_NUMBER"; +my $PKI_SECURE_PORT_SLOT = "PKI_SECURE_PORT"; +my $PKI_EE_SECURE_PORT_SLOT = "PKI_EE_SECURE_PORT"; +my $PKI_EE_SECURE_CLIENT_AUTH_PORT_SLOT = "PKI_EE_SECURE_CLIENT_AUTH_PORT"; +my $PKI_EE_SECURE_CLIENT_AUTH_PORT_UI_SLOT = "PKI_EE_SECURE_CLIENT_AUTH_PORT_UI"; +my $PKI_AGENT_SECURE_PORT_SLOT = "PKI_AGENT_SECURE_PORT"; +my $PKI_ADMIN_SECURE_PORT_SLOT = "PKI_ADMIN_SECURE_PORT"; +my $PKI_SERVER_XML_CONF = "PKI_SERVER_XML_CONF"; +my $PKI_SUBSYSTEM_TYPE_SLOT = "PKI_SUBSYSTEM_TYPE"; +my $PKI_UNSECURE_PORT_SLOT = "PKI_UNSECURE_PORT"; +my $PKI_USER_SLOT = "PKI_USER"; +my $TOMCAT_SERVER_PORT_SLOT = "TOMCAT_SERVER_PORT"; +my $TOMCAT_PIDFILE = "TOMCAT_PIDFILE"; +my $TOMCAT_CFG = "TOMCAT_CFG"; +my $TOMCAT_SSL_OPTIONS = "TOMCAT_SSL_OPTIONS"; +my $TOMCAT_SSL2_CIPHERS = "TOMCAT_SSL2_CIPHERS"; +my $TOMCAT_SSL3_CIPHERS = "TOMCAT_SSL3_CIPHERS"; +my $TOMCAT_TLS3_CIPHERS = "TOMCAT_TLS3_CIPHERS"; +my $TOMCAT_INSTANCE_COMMON_LIB = "TOMCAT_INSTANCE_COMMON_LIB"; +my $TOMCAT_LOG_DIR = "TOMCAT_LOG_DIR"; +my $PKI_INSTANCE_INITSCRIPT = "PKI_INSTANCE_INITSCRIPT"; +my $PKI_FLAVOR_SLOT = "PKI_FLAVOR"; +my $PKI_UNSECURE_PORT_CONNECTOR_NAME_SLOT = "PKI_UNSECURE_PORT_CONNECTOR_NAME"; +my $PKI_SECURE_PORT_CONNECTOR_NAME_SLOT = "PKI_SECURE_PORT_CONNECTOR_NAME"; +my $PKI_ADMIN_SECURE_PORT_CONNECTOR_NAME_SLOT = "PKI_ADMIN_SECURE_PORT_CONNECTOR_NAME"; +my $PKI_EE_SECURE_PORT_CONNECTOR_NAME_SLOT = "PKI_EE_SECURE_PORT_CONNECTOR_NAME"; +my $PKI_EE_SECURE_CLIENT_AUTH_PORT_CONNECTOR_NAME_SLOT = "PKI_EE_SECURE_CLIENT_AUTH_PORT_CONNECTOR_NAME"; +my $PKI_UNSECURE_PORT_COMMENT_SERVER_SLOT = "PKI_UNSECURE_PORT_SERVER_COMMENT"; +my $PKI_SECURE_PORT_COMMENT_SERVER_SLOT = "PKI_SECURE_PORT_SERVER_COMMENT"; +my $PKI_ADMIN_SECURE_PORT_COMMENT_SERVER_SLOT = "PKI_ADMIN_SECURE_PORT_SERVER_COMMENT"; +my $PKI_EE_SECURE_PORT_COMMENT_SERVER_SLOT = "PKI_EE_SECURE_PORT_SERVER_COMMENT"; +my $PKI_EE_SECURE_CLIENT_AUTH_PORT_COMMENT_SERVER_SLOT = "PKI_EE_SECURE_CLIENT_AUTH_PORT_SERVER_COMMENT"; +my $PKI_OPEN_SEPARATE_PORTS_COMMENT_SERVER_SLOT = "PKI_OPEN_SEPARATE_PORTS_SERVER_COMMENT"; +my $PKI_CLOSE_SEPARATE_PORTS_COMMENT_SERVER_SLOT = "PKI_CLOSE_SEPARATE_PORTS_SERVER_COMMENT"; +my $PKI_OPEN_SEPARATE_PORTS_COMMENT_WEB_SLOT = "PKI_OPEN_SEPARATE_PORTS_WEB_COMMENT"; +my $PKI_CLOSE_SEPARATE_PORTS_COMMENT_WEB_SLOT = "PKI_CLOSE_SEPARATE_PORTS_WEB_COMMENT"; +my $PKI_OPEN_AJP_PORT_COMMENT_SLOT = "PKI_OPEN_AJP_PORT_COMMENT"; +my $PKI_CLOSE_AJP_PORT_COMMENT_SLOT = "PKI_CLOSE_AJP_PORT_COMMENT"; +my $PKI_OPEN_ENABLE_PROXY_COMMENT_SLOT = "PKI_OPEN_ENABLE_PROXY_COMMENT"; +my $PKI_CLOSE_ENABLE_PROXY_COMMENT_SLOT = "PKI_CLOSE_ENABLE_PROXY_COMMENT"; +my $PKI_AJP_REDIRECT_PORT_SLOT = "PKI_AJP_REDIRECT_PORT"; +my $PKI_AJP_PORT_SLOT = "PKI_AJP_PORT"; +my $PROXY_SECURE_PORT_SLOT = "PKI_PROXY_SECURE_PORT"; +my $PROXY_UNSECURE_PORT_SLOT = "PKI_PROXY_UNSECURE_PORT"; +my $PKI_UNSECURE_PORT_NAME = "Unsecure"; +my $PKI_AGENT_SECURE_PORT_NAME = "Agent"; +my $PKI_ADMIN_SECURE_PORT_NAME = "Admin"; +my $PKI_EE_SECURE_PORT_NAME = "EE"; +my $PKI_EE_SECURE_CLIENT_AUTH_PORT_NAME = "EEClientAuth"; +my $PKI_SECURE_PORT_NAME = "Secure"; +my $PKI_UNUSED_SECURE_PORT_NAME = "Unused"; +my $PKI_UNSECURE_SEPARATE_PORTS_COMMENT = ""; +my $PKI_AGENT_SECURE_SEPARATE_PORTS_COMMENT = ""; +my $PKI_ADMIN_SECURE_SEPARATE_PORTS_COMMENT = ""; +my $PKI_EE_SECURE_SEPARATE_PORTS_COMMENT = ""; +my $PKI_EE_SECURE_CLIENT_AUTH_SEPARATE_PORTS_COMMENT = ""; +my $PKI_UNSECURE_SHARED_PORTS_COMMENT = ""; +my $PKI_SECURE_SHARED_PORTS_COMMENT = ""; +my $PKI_OPEN_COMMENT = ""; +my $PKI_WEBAPPS_NAME = "PKI_WEBAPPS_NAME"; + +#proxy defaults +my $PROXY_SECURE_PORT_DEFAULT = "443"; +my $PROXY_UNSECURE_PORT_DEFAULT = "80"; +my $AJP_PORT_DEFAULT = "9447"; + +############################################################## +# Local Data Structures +############################################################## + +# Useful pki references +my %redirects = (); +my %supported_sec_modules_hash = (); + +############################################################## +# Local Variables +############################################################## + +# Command-line variables (mandatory) +my $pki_instance_root = undef; +my $pki_instance_name = undef; +my $subsystem_type = undef; +my $secure_port = -1; +my $non_clientauth_secure_port = -1; +my $unsecure_port = -1; +my $tomcat_server_port = -1; + +# Command-line variables (optional) +my $agent_secure_port = -1; +my $ee_secure_port = -1; +my $ee_secure_client_auth_port = -1; +my $admin_secure_port = -1; +my $proxy_secure_port = -1; +my $proxy_unsecure_port = -1; +my $ajp_port = -1; +my $enable_proxy = undef; +my $username = undef; +my $groupname = undef; +my $redirected_conf_path = undef; +my $redirected_logs_path = undef; + +# Base subsystem directory paths +my $pki_subsystem_path = undef; # CA, KRA, OCSP, TKS, RA, TPS +my $applets_subsystem_path = undef; # TPS +my $bin_subsystem_path = undef; # TPS +my $cgibin_subsystem_path = undef; # TPS (Apache) +my $conf_subsystem_path = undef; # CA, KRA, OCSP, TKS, RA, TPS +my $docroot_subsystem_path = undef; # RA, TPS (Apache) +my $emails_subsystem_path = undef; # CA +my $lib_subsystem_path = undef; # RA, TPS +my $profiles_subsystem_path = undef; # CA, KRA, OCSP, TKS +my $samples_subsystem_path = undef; # TPS +my $scripts_subsystem_path = undef; # RA, TPS +my $webapps_subsystem_path = undef; # CA, KRA, OCSP, TKS +my $common_ui_subsystem_path = undef; # CA, KRA, OCSP, TKS, RA, TPS +my $ui_subsystem_path = undef; # CA, KRA, OCSP, TKS, RA, TPS + +# Base instance directory paths +my $pki_instance_path = undef; # CA, KRA, OCSP, TKS, RA, TPS +my $alias_instance_path = undef; # CA, KRA, OCSP, TKS, RA, TPS +my $bin_instance_path = undef; # TPS +my $cgibin_instance_path = undef; # TPS (Apache) +my $conf_instance_path = undef; # CA, KRA, OCSP, TKS, RA, TPS +my $docroot_instance_path = undef; # RA, TPS (Apache) +my $emails_instance_path = undef; # CA +my $lib_instance_path = undef; # RA, TPS +my $logs_instance_path = undef; # CA, KRA, OCSP, TKS, RA, TPS +my $profiles_instance_path = undef; # CA, KRA, OCSP, TKS +my $scripts_instance_path = undef; # CA, KRA, OCSP, TKS, RA, TPS +my $tomcat_instance_common_lib_path = undef; # CA, KRA, OCSP, TKS (Tomcat) +my $shared_instance_path = undef; # CA, KRA, OCSP, TKS (Tomcat) +my $temp_instance_path = undef; # CA, KRA, OCSP, TKS (Tomcat) +my $webapps_instance_path = undef; # CA, KRA, OCSP, TKS +my $webapps_subsystem_instance_path = undef; # CA, KRA, OCSP, TKS +my $work_instance_path = undef; # CA, KRA, OCSP, TKS (Tomcat) +my $pki_piddir_path = undef; # RA, TPS +my $pki_lockdir_path = undef; # RA, TPS + +# Base instance symbolic link paths +my $conf_instance_symlink_path = undef; # CA, KRA, OCSP, TKS, RA, TPS +my $logs_instance_symlink_path = undef; # CA, KRA, OCSP, TKS, RA, TPS +my $run_instance_symlink_path = undef; # RA, TPS + +# Subdirectory paths +my $cgi_home_instance_file_path = undef; # TPS +my $cgi_home_subsystem_file_path = undef; # TPS +my $cgi_demo_instance_file_path = undef; # TPS +my $cgi_demo_subsystem_file_path = undef; # TPS +my $cgi_so_instance_file_path = undef; # TPS +my $cgi_so_subsystem_file_path = undef; # TPS +my $cgi_so_instance_enroll_file_path = undef; # TPS +my $cgi_so_subsystem_enroll_file_path = undef; # TPS +my $cgi_sow_instance_file_path = undef; # TPS +my $cgi_sow_subsystem_file_path = undef; # TPS +my $cgi_sow_instance_cgi_file_path = undef; # TPS +my $cgi_sow_subsystem_cgi_file_path = undef; # TPS +my $cgi_sow_instance_cfg_pl_path = undef; # TPS +my $addAgents_ldif_instance_file_path = undef; # TPS +my $addAgents_ldif_subsystem_file_path = undef; # TPS +my $addIndexes_ldif_instance_file_path = undef; # TPS +my $addIndexes_ldif_subsystem_file_path = undef; # TPS +my $addTokens_ldif_instance_file_path = undef; # TPS +my $addTokens_ldif_subsystem_file_path = undef; # TPS +my $addVLVIndexes_ldif_instance_file_path = undef; # TPS +my $addVLVIndexes_ldif_subsystem_file_path = undef; # TPS +my $pki_certsrv_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $pki_certsrv_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $pki_cms_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $pki_cms_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $pki_cmsbundle_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $pki_cmsbundle_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $pki_cmscore_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $pki_cmscore_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $pki_cmsutil_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $pki_cmsutil_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $commons_collections_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $commons_collections_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $commons_lang_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $commons_lang_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $commons_logging_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $commons_logging_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $jss_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $jss_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $ldapjdk_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $ldapjdk_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $pki_nsutil_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $pki_nsutil_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $osutil_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $osutil_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $symkey_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $symkey_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $tomcatjss_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $tomcatjss_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $velocity_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $velocity_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $xerces_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $xerces_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $xml_commons_apis_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $xml_commons_apis_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $xml_commons_resolver_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $xml_commons_resolver_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $httpd_conf_instance_file_path = undef; # RA, TPS +my $httpd_conf_subsystem_file_path = undef; # RA, TPS +my $index_jsp_instance_file_path = undef; # CA, KRA, OCSP, TKS +my $index_jsp_subsystem_file_path = undef; # CA, KRA, OCSP, TKS +my $magic_instance_file_path = undef; # RA, TPS +my $magic_subsystem_file_path = undef; # RA, TPS +my $mime_types_instance_file_path = undef; # RA, TPS +my $mime_types_subsystem_file_path = undef; # RA, TPS +my $noise_instance_file_path = undef; # CA, KRA, OCSP, TKS, RA, TPS +my $nss_conf_instance_file_path = undef; # RA, TPS +my $nss_conf_subsystem_file_path = undef; # RA, TPS +my $nss_pcache_instance_file_path = undef; # RA, TPS +my $nss_pcache_subsystem_file_path = undef; # RA, TPS +my $perl_conf_instance_file_path = undef; # RA, TPS +my $perl_conf_subsystem_file_path = undef; # RA, TPS +my $password_conf_instance_file_path = undef; # CA, KRA, OCSP, TKS, RA, TPS +my $perl_instance_symlink_path = undef; # RA, TPS +my $perl_subsystem_path = undef; # RA, TPS +my $pfile_instance_file_path = undef; # CA, KRA, OCSP, TKS, RA, TPS +my $pwcache_conf_instance_file_path = undef; # RA, TPS +my $pki_cfg_subsystem_file_path = undef; # CA, KRA, OCSP, TKS, RA, TPS +my $pki_cfg_instance_file_path = undef; # CA, KRA, OCSP, TKS, RA, TPS +my $pki_apache_initscript_file_path = undef; # RA, TPS +my $schemaMods_ldif_instance_file_path = undef; # RA, TPS +my $schemaMods_ldif_subsystem_file_path = undef; # RA, TPS +my $server_xml_instance_file_path = undef; # CA, KRA, OCSP, TKS +my $server_xml_subsystem_file_path = undef; # CA, KRA, OCSP, TKS +my $servercertnick_conf_instance_file_path = undef; # CA, KRA, OCSP, TKS +my $servercertnick_conf_subsystem_file_path = undef; # CA, KRA, OCSP, TKS +my $pki_subsystem_jar_file_path = undef; # CA, KRA, OCSP, TKS +my $pki_subsystem_jar_symlink_path = undef; # CA, KRA, OCSP, TKS +my $tomcat6_conf_subsystem_file_path = undef; # CA, KRA, OCSP, TKS +my $tomcat6_conf_instance_file_path = undef; # CA, KRA, OCSP, TKS +my $tomcat6_instance_pid_file_path = undef; # CA, KRA, OCSP, TKS +my $velocity_prop_instance_file_path = undef; # CA, KRA, OCSP, TKS +my $velocity_prop_subsystem_file_path = undef; # CA, KRA, OCSP, TKS +my $web_xml_instance_file_path = undef; # CA, KRA, OCSP, TKS +my $web_xml_subsystem_file_path = undef; # CA, KRA, OCSP, TKS +my $catalina_properties_instance_file_path = undef; # CA, KRA, OCSP, TKS +my $catalina_properties_subsystem_file_path = undef; # CA, KRA, OCSP, TKS +my $webapps_root_instance_path = undef; # CA, KRA, OCSP, TKS +my $webapps_root_subsystem_path = undef; # CA, KRA, OCSP, TKS +my $webinf_instance_path = undef; # CA, KRA, OCSP, TKS +my $webinf_lib_instance_path = undef; # CA, KRA, OCSP, TKS +my $webinf_subsystem_path = undef; # CA, KRA, OCSP, TKS +my $profile_select_template_subsystem_file_path = undef; #CA +my $profile_select_template_instance_file_path = undef; #CA +my $proxy_conf_subsystem_file_path = undef; #CA +my $proxy_conf_instance_file_path = undef; #CA + +# PKI init script variables +my $pki_registry_initscript = undef; # CA, KRA, OCSP, TKS, RA, TPS +my $pki_registry_initscript_command = undef; # CA, KRA, OCSP, TKS, RA, TPS + +# PKI registry variables +my $pki_registry_subsystem_path = undef; # CA, KRA, OCSP, TKS RA, TPS +my $pki_registry_subsystem_file_path = undef; # CA, KRA, OCSP, TKS RA, TPS +my $pki_registry_instance_file_path = undef; # CA, KRA, OCSP, TKS RA, TPS + +# PKI creation variables +my $host = undef; +my $db_password = undef; +my $random = undef; + +# Linux specific variables +my $setup_base_subsystem_dir = "setup"; +my $setup_subsystem_path = undef; +my $setup_config_instance_file_path = undef; +my $setup_config_subsystem_file_path = undef; +my $setup_config_area = undef; +my $setup_config_name = undef; +my $tomcat6_initscript_path = undef; +my $tomcat6_instance_config_path = undef; +my $root_user = undef; +my $root_group = undef; +my $pki_instance_initscript_path = undef; + + +############################################################## +# Platform-Dependent Data Initialization +############################################################## + +if ($^O eq "linux") { + # Linux required desktop files + $setup_config_area = "/usr/share/applications"; + $setup_config_name = "config.desktop"; + + # Linux init scripts + $tomcat6_initscript_path = "${default_initscripts_path}/tomcat6"; + + # Tomcat instance config directory + $tomcat6_instance_config_path = "/etc/sysconfig"; + + # Superuser and group to give to PKI installed files + $root_user = "root"; + $root_group = "root"; +} else { + emit("Unsupported platform '$^O'!\n", "error"); + exit 255; +} + + +############################################################## +# Local Data Initialization +############################################################## + +# Initialize Java-specific variables +if ($^O eq "linux") { + if ($default_hardware_platform eq "i386") { + # 32-bit Linux + + # Supported hardware token PKCS #11 modules + %supported_sec_modules_hash = ("lunasa" => "/usr/lunasa/lib/libCryptoki2.so", + "nfast" => "/opt/nfast/toolkits/pkcs11/libcknfast.so"); + } elsif ($default_hardware_platform eq "x86_64") { + # 64-bit Linux + + # Supported hardware token PKCS #11 modules + %supported_sec_modules_hash = ("lunasa" => "/usr/lunasa/lib/libCryptoki2_64.so", + "nfast" => "/opt/nfast/toolkits/pkcs11/libcknfast.so"); + } else { + emit("Unsupported '$^O' hardware platform '$default_hardware_platform'!\n", "error"); + exit 255; + } +} else { + emit("Unsupported platform '$^O'!\n", "error"); + exit 255; +} + +############################################################## +# PKI Instance Creation Subroutines +############################################################## + +# no args +# no return value +sub usage +{ + print STDOUT <<'EOF'; +############################################################################### +### USAGE: CA, KRA, OCSP, or TKS subsystem instance creation (Tomcat) ### +############################################################################### + +pkicreate -pki_instance_root= # Instance root directory + # destination + + -pki_instance_name= # Unique PKI subsystem + # instance name + + -subsystem_type= # Subsystem type + # [ca | kra | ocsp | tks] + + ##################################################################### + ### SELECT separate secure ports for AGENT, EE, and ADMIN: ### + ##################################################################### + + -agent_secure_port= # Agent secure port + + -ee_secure_port= # EE secure port + + -admin_secure_port= # Admin secure port + + ##################################################################### + ### ... and a client auth EE port, required for CAs only ### + ##################################################################### + + -ee_secure_client_auth_port= + # EE secure client authentication port + + ##################################################################### + ### OR SELECT a single secure port shared by AGENT,EE and ADMIN ### + ##################################################################### + + -secure_port= # Secure port + # (shared by Agent, + # EE, and Admin) + + ##################################################################### + ### END secure port SELECTION ### + ##################################################################### + + -unsecure_port= # Unsecure port + + -tomcat_server_port= # Unique port for each + # Tomcat instance + + ##################################################################### + ### proxy configuration ### + ### if -enable_proxy is set, ajp_port, proxy_secure_port, and ### + ### proxy_unsecure_port are also set. ### + ##################################################################### + + [-enable_proxy] #enable proxy configuration + [-ajp_port=] #AJP port, default 9447 + + [-proxy_secure_port=] # Proxy secure port, + # default 443 + + [-proxy_unsecure_port=] # Proxy unsecure port, + # default 80 + + ##################################################################### + ### END proxy configuration ### + ##################################################################### + + [-user=] # User ownership + # (must ALSO specify + # group ownership) + # + # [Default=pkiuser] + + [-group=] # Group ownership + # (must ALSO specify + # user ownership) + # + # [Default=pkiuser] + + [-redirect conf=] # Redirection of + # 'conf' directory + + [-redirect logs=] # Redirection of + # 'logs' directory + + [-verbose] # Print out liberal info + # during 'pkicreate'. + # Specify multiple times + # to increase verbosity. + + [-dry_run] # Do not perform any actions. + # Just report what would have + # been done. + + [-help] # Print out this screen + + +############################################################################### +### USAGE: RA or TPS subsystem instance creation (Apache) ### +############################################################################### + +pkicreate -pki_instance_root= # Instance root directory + # destination + + -pki_instance_name= # Unique PKI subsystem + # instance name + + -subsystem_type= # Subsystem type + # [ra | tps] + + -secure_port= # Secure port + # (clientauth) + # for each + # Apache instance + + -non_clientauth_secure_port= + + # Secure port + # (non-clientauth) + # for each + # Apache instance + + -unsecure_port= # Unsecure port + + [-user=] # User ownership + # (must ALSO specify + # group ownership) + # + # [Default=pkiuser] + + [-group=] # Group ownership + # (must ALSO specify + # user ownership) + # + # [Default=pkiuser] + + [-redirect conf=] # Redirection of + # 'conf' directory + + [-redirect logs=] # Redirection of + # 'logs' directory + + [-verbose] # Print out liberal info + # during 'pkicreate'. + # Specify multiple times + # to increase verbosity. + + [-dry_run] # Do not perform any actions. + # Just report what would have + # been done. + + [-help] # Print out this screen + + +############################################################################### +### EXAMPLES: ### +### PKI (Tomcat) subsystem instance creation of a CA ### +### PKI (Tomcat) subsystem instance creation of a Subordinate CA ### +### PKI (Tomcat) subsystem instance creation of a KRA ### +### PKI (Tomcat) subsystem instance creation of an OCSP ### +### PKI (Tomcat) subsystem instance creation of a TKS ### +### PKI (Apache) subsystem instance creation of an RA ### +### PKI (Apache) subsystem instance creation of a TPS ### +### PKI (Apache) subsystem instance creation of a second TPS ### +############################################################################### + +pkicreate -pki_instance_root=/var/lib \ + -pki_instance_name=pki-ca \ + -subsystem_type=ca \ + -agent_secure_port=9443 \ + -ee_secure_port=9444 \ + -ee_secure_client_auth_port=9446 \ + -admin_secure_port=9445 \ + -unsecure_port=9180 \ + -tomcat_server_port=9701 \ + -user=pkiuser \ + -group=pkiuser \ + -redirect conf=/etc/pki-ca \ + -redirect logs=/var/log/pki-ca \ + -verbose + +pkicreate -pki_instance_root=/var/lib \ + -pki_instance_name=pki-subca \ + -subsystem_type=ca \ + -agent_secure_port=9543 \ + -ee_secure_port=9544 \ + -ee_secure_client_auth_port=9546 \ + -admin_secure_port=9545 \ + -unsecure_port=9580 \ + -tomcat_server_port=9801 \ + -user=pkiuser \ + -group=pkiuser \ + -redirect conf=/etc/pki-subca \ + -redirect logs=/var/log/pki-subca \ + -verbose + +pkicreate -pki_instance_root=/var/lib \ + -pki_instance_name=pki-kra \ + -subsystem_type=kra \ + -agent_secure_port=10443 \ + -ee_secure_port=10444 \ + -admin_secure_port=10445 \ + -unsecure_port=10180 \ + -tomcat_server_port=10701 \ + -user=pkiuser \ + -group=pkiuser \ + -redirect conf=/etc/pki-kra \ + -redirect logs=/var/log/pki-kra \ + -verbose + +pkicreate -pki_instance_root=/var/lib \ + -pki_instance_name=pki-ocsp \ + -subsystem_type=ocsp \ + -agent_secure_port=11443 \ + -ee_secure_port=11444 \ + -admin_secure_port=11445 \ + -unsecure_port=11180 \ + -tomcat_server_port=11701 \ + -user=pkiuser \ + -group=pkiuser \ + -redirect conf=/etc/pki-ocsp \ + -redirect logs=/var/log/pki-ocsp \ + -verbose + +pkicreate -pki_instance_root=/var/lib \ + -pki_instance_name=pki-tks \ + -subsystem_type=tks \ + -agent_secure_port=13443 \ + -ee_secure_port=13444 \ + -admin_secure_port=13445 \ + -unsecure_port=13180 \ + -tomcat_server_port=13701 \ + -user=pkiuser \ + -group=pkiuser \ + -redirect conf=/etc/pki-tks \ + -redirect logs=/var/log/pki-tks \ + -verbose + +pkicreate -pki_instance_root=/var/lib \ + -pki_instance_name=pki-ra \ + -subsystem_type=ra \ + -secure_port=12889 \ + -non_clientauth_secure_port=12890 \ + -unsecure_port=12888 \ + -user=pkiuser \ + -group=pkiuser \ + -redirect conf=/etc/pki-ra \ + -redirect logs=/var/log/pki-ra \ + -verbose + +pkicreate -pki_instance_root=/var/lib \ + -pki_instance_name=pki-tps \ + -subsystem_type=tps \ + -secure_port=7889 \ + -non_clientauth_secure_port=7890 \ + -unsecure_port=7888 \ + -user=pkiuser \ + -group=pkiuser \ + -redirect conf=/etc/pki-tps \ + -redirect logs=/var/log/pki-tps \ + -verbose + +pkicreate -pki_instance_root=/var/lib \ + -pki_instance_name=pki-tps1 \ + -subsystem_type=tps \ + -secure_port=7989 \ + -non_clientauth_secure_port=7990 \ + -unsecure_port=7988 \ + -user=pkiuser \ + -group=pkiuser \ + -redirect conf=/etc/pki-tps1 \ + -redirect logs=/var/log/pki-tps1 \ + -verbose + +IMPORTANT: Must be run as root! +EOF + + return; +} + + +# arg0 instance name +# return 1 - exists, or +# return 0 - DOES NOT exist +sub pki_instance_already_exists +{ + my ($name) = @_; + my $result = 0; + my $instance = ""; + + $instance = $pki_registry_path + . "/" . $subsystem_type + . "/" . $name; + + if (-e $instance) { + $result = 1; + } + + return $result; +} + + +# no args +# return 1 - success, or +# return 0 - failure +sub parse_arguments +{ + my $l_secure_port = -1; + my $l_non_clientauth_secure_port = -1; + my $l_unsecure_port = -1; + my $l_tomcat_server_port = -1; + my $l_agent_secure_port = -1; + my $l_ee_secure_port = -1; + my $l_ee_secure_client_auth_port = -1; + my $l_admin_secure_port = -1; + my $l_proxy_secure_port = -1; + my $l_proxy_unsecure_port = -1; + my $l_ajp_port = -1; + my $show_help = 0; + + my $result = GetOptions("help" => \$show_help, + "pki_instance_root=s" => \$pki_instance_root, + "pki_instance_name=s" => \$pki_instance_name, + "subsystem_type=s" => \$subsystem_type, + "secure_port:i" => \$l_secure_port, + "non_clientauth_secure_port:i" => \$l_non_clientauth_secure_port, + "unsecure_port:i" => \$l_unsecure_port, + "agent_secure_port:i" => \$l_agent_secure_port, + "ee_secure_port:i" => \$l_ee_secure_port, + "ee_secure_client_auth_port:i" => \$l_ee_secure_client_auth_port, + "admin_secure_port:i" => \$l_admin_secure_port, + "tomcat_server_port:i" => \$l_tomcat_server_port, + "proxy_secure_port:i" => \$l_proxy_secure_port, + "proxy_unsecure_port:i" => \$l_proxy_unsecure_port, + "ajp_port:i" => \$l_ajp_port, + "enable_proxy" => \$enable_proxy, + "user=s" => \$username, + "group=s" => \$groupname, + "verbose+" => \$verbose, + "dry_run" => \$dry_run, + "redirect=s" => \%redirects); + + + ## Optional "-help" option - no "mandatory" options are required + if ($show_help) { + usage(); + return 0; + } + + + ## Mandatory "-pki_instance_root=s" option + if (!$pki_instance_root) { + usage(); + emit("Must have value for -pki_instance_root!\n", "error"); + return 0; + } + + if ($pki_instance_root eq "/") { + usage(); + emit("Don't even think about making root the pki_instance_root! " + . "Try again.\n", "error"); + return 0; + } + + # Remove all trailing directory separators ('/') + $pki_instance_root =~ s/\/+$//; + + if (!is_path_valid($pki_instance_root)) { + usage(); + emit("Target directory $pki_instance_root is not a " + . "legal directory try again.\n", + "error"); + return 0; + } + + ## Mandatory "-subsystem_type=s" option + if ($subsystem_type ne $CA && + $subsystem_type ne $KRA && + $subsystem_type ne $OCSP && + $subsystem_type ne $TKS && + $subsystem_type ne $RA && + $subsystem_type ne $TPS) { + usage(); + emit("Illegal value => $subsystem_type : for -subsystem_type!\n", + "error"); + return 0; + } + + $pki_subsystem_path = $pki_subsystem_common_area + . "/" . $subsystem_type; + + if (!(-d $pki_subsystem_path)) { + usage(); + emit("$pki_subsystem_path not present. " + . "Please install the corresponding subsystem RPM first!\n", + "error"); + return 0; + } else { + emit(" subsystem_type $subsystem_type\n"); + } + + + ## Mandatory "-pki_instance_name=s" option + if (!$pki_instance_name) { + usage(); + emit("Must have value for -pki_instance_name!\n", "error"); + return 0; + } + + if (!is_name_valid($pki_instance_name)) { + usage(); + emit("Illegal Value => $pki_instance_name for -pki_instance_name!\n", + "error"); + return 0; + } + + if (pki_instance_already_exists($pki_instance_name) && !$dry_run) { + usage(); + emit("An instance named $pki_instance_name " + . "already exists; please try again.\n", "error"); + return 0; + } + + $pki_instance_path = "${pki_instance_root}/${pki_instance_name}"; + + if (directory_exists($pki_instance_path) && !$dry_run) { + usage(); + emit("Target directory $pki_instance_path " + . "already exists; clean up and " + . "try again.\n", "error"); + return 0; + } + + # Capture installation information in a log file, always overwrite this file. + # When creating an instance it's a fatal error if the logfile + # cannot be created. + my $logfile = "/var/log/${pki_instance_name}-install.log"; + if (!open_logfile($logfile, $default_file_permissions)) { + emit("can not create logfile ($logfile)", "error"); + return 0; + } + + add_install_info($logfile, 'file', 'preserve'); + + printf(STDOUT "Capturing installation information in %s\n", $logfile); + + emit("Parsing PKI creation arguments ...\n"); + + if ($verbose) { + emit(" verbose mode ENABLED (level=$verbose)\n"); + } + + if ($dry_run) { + emit(" dry run mode ENABLED, system will not be modified\n"); + print STDOUT "dry run mode ENABLED, system will not be modified\n"; + } + + emit(" pki_instance_root $pki_instance_root\n"); + emit(" pki_instance_name $pki_instance_name\n"); + + ## Mandatory "-secure_port=" option + if ($l_secure_port >= 0) { + $secure_port = $l_secure_port; + + emit(" secure_port $secure_port\n"); + } else { + if ($l_agent_secure_port == -1) + { + usage(); + emit("Must include value for secure_port!\n", "error"); + return 0; + } + } + + ## Mandatory "-non_clientauth_secure_port=" + ## option/exclusion + if (($subsystem_type eq $RA || $subsystem_type eq $TPS)) { + if ($l_non_clientauth_secure_port >= 0) { + $non_clientauth_secure_port = $l_non_clientauth_secure_port; + + emit(" non_clientauth_secure_port " + . "$non_clientauth_secure_port\n"); + } else { + if ($l_non_clientauth_secure_port == -1) + { + usage(); + emit("Must include value for non_clientauth_secure_port!\n", + "error"); + return 0; + } + } + + if ($l_agent_secure_port > 0 || + $l_ee_secure_port > 0 || + $l_ee_secure_client_auth_port > 0 || + $l_admin_secure_port > 0) { + usage(); + emit("Must NOT include values for any agent|admin|ee ports!\n", + "error"); + return 0; + } + } else { + ## Mandatory EXCLUSION for CA, KRA, OCSP, and TKS subsystems + if ($l_non_clientauth_secure_port != -1) { + usage(); + emit("Must NOT include value for non_clientauth_secure_port!\n", + "error"); + return 0; + } + } + + ## Mandatory "-unsecure_port=" option + if ($l_unsecure_port >= 0) { + $unsecure_port = $l_unsecure_port; + + emit(" unsecure_port $unsecure_port\n"); + } else { + usage(); + emit("Must include value for unsecure_port!\n", "error"); + return 0; + } + + ## Mandatory "-tomcat_server_port=" option/exclusion + if (!($subsystem_type eq $RA || $subsystem_type eq $TPS)) { + ## Mandatory OPTION for CA, KRA, OCSP, and TKS subsystems + if ($l_tomcat_server_port < 0) { + usage(); + emit("Must include value for tomcat_server_port!\n", "error"); + return 0; + } + + $tomcat_server_port = $l_tomcat_server_port; + + emit(" tomcat_server_port $tomcat_server_port\n"); + } else { + ## Mandatory EXCLUSION for RA and TPS subsystems + if ($l_tomcat_server_port != -1) { + usage(); + emit("Must NOT include value for tomcat_server_port!\n", + "error"); + return 0; + } + } + + if ($l_agent_secure_port >= 0) { + $agent_secure_port = $l_agent_secure_port; + + emit(" agent_secure_port $agent_secure_port\n"); + + } + + ## Mandatory ee_secure_port if "-agent_secure_port" is given + + if ($l_ee_secure_port >= 0) { + $ee_secure_port = $l_ee_secure_port; + + emit(" ee_secure_port $ee_secure_port\n"); + + } else { + if ($agent_secure_port >= 0) { + emit("Must include value for ee_secure_port if agent_secure_port is given!\n"); + } + } + + ## Mandatory ee_secure_client_auth_port if "-agent_secure_port" is given, and CA subsystem + + if ($l_ee_secure_client_auth_port >= 0) { + $ee_secure_client_auth_port = $l_ee_secure_client_auth_port; + + emit(" ee_secure_client_auth_port $ee_secure_client_auth_port\n"); + + } else { + if (($agent_secure_port >= 0) && ($subsystem_type eq $CA)) { + usage(); + emit("For CAs, must include value for ee_secure_client_auth_port if agent_secure_port is given!\n"); + return 0; + } + } + + ## Mandatory admin_secure_port if "-agent_secure_port" is given + + if ($l_admin_secure_port >= 0) { + $admin_secure_port = $l_admin_secure_port; + + emit(" admin_secure_port $admin_secure_port\n"); + + } else { + if ($agent_secure_port >= 0) { + emit("Must include value for admin_secure_port if agent_secure_port is given!\n"); + } + } + + if ($enable_proxy) { + + $proxy_secure_port = ($l_proxy_secure_port >= 0) ? $l_proxy_secure_port : + $PROXY_SECURE_PORT_DEFAULT; + emit(" proxy_secure_port $proxy_secure_port\n"); + + $proxy_unsecure_port = ($l_proxy_unsecure_port >= 0) ? $l_proxy_unsecure_port : + $PROXY_UNSECURE_PORT_DEFAULT; + emit(" proxy_unsecure_port $proxy_unsecure_port\n"); + + $ajp_port = ($l_ajp_port >= 0) ? $l_ajp_port : $AJP_PORT_DEFAULT; + emit(" ajp_port $ajp_port\n"); + } + + if (!AreConnectorPortsValid($secure_port,$unsecure_port,$agent_secure_port, + $ee_secure_port,$ee_secure_client_auth_port, $admin_secure_port, + $proxy_secure_port, $proxy_unsecure_port)) + { + usage(); + emit("Invalid port numbers submitted!\n","error"); + return 0; + } + + + ## Optional "-group=" option + if ($groupname) { + if (!$username) { + usage(); + emit("Must ALSO specify user ownership using -user!\n", + "error"); + return 0; + } + + if (!group_exists($groupname)) { + if (!create_group($groupname)) { + usage(); + emit("Unable to create group '$groupname' on this machine!\n", + "error"); + return 0; + } + } + + # Overwrite default value of $pki_group with user-specified $groupname + $pki_group = $groupname; + } + + + # At this point in time, ALWAYS check that $pki_group exists! + if (!group_exists($pki_group)) { + if (!create_group($pki_group)) { + usage(); + emit("Unable to create group '$pki_group' on this machine!\n", + "error"); + return 0; + } + } + + + ## Optional "-user=" option + if ($username) { + if (!$groupname) { + usage(); + emit("Must ALSO specify group ownership using -group!\n", + "error"); + return 0; + } + + if (!user_exists($username)) { + if (!create_user($username, $groupname)) { + usage(); + emit("Unable to create user '$username' on this machine!\n", + "error"); + return 0; + } + } + + # Overwrite default value of $pki_user with user-specified $username + $pki_user = $username; + } + + + # At this point in time, ALWAYS check that $pki_user exists! + if (!user_exists($pki_user)) { + if (!create_user($pki_user, $pki_group)) { + usage(); + emit("Unable to create user '$pki_user' on this machine!\n", + "error"); + return 0; + } + } + + + # At this point in time, ALWAYS check that shell access for $pki_user is + # disallowed; for now, simply notify the user performing the installation + # and continue + if (!user_disallows_shell($pki_user)) { + emit("Please contact your system administrator " + . "to disallow shell access for '$pki_user'!\n"); + } + + + # At this point in time, ALWAYS check that $pki_user + # is a valid member of $pki_group + # + # NOTE: Uncomment the following code to enforce a strict policy of + # requiring $pki_user to be a member of $pki_group . . . + # + # if (!user_is_a_member_of_group($pki_user, $pki_group)) { + # usage(); + # emit("The user '$pki_user' is NOT a member of group '$pki_group'!\n", + # "error"); + # return 0; + # } + + + # At this point in time, ALWAYS attempt to add $pki_user as a + # valid member of $default_nfast_group (presuming one exists) + if (group_exists($default_nfast_group)) { + # Ignore failures as this should be considered a 'benign' error + if (add_user_as_a_member_of_group($pki_user, + $default_nfast_group)) { + emit("User '$pki_user' is a member of group " + . "'$default_nfast_group'.\n"); + } + } + + + ## Optional "-redirect = ..." option + while (my ($key, $value) = each(%redirects)) { + if (!is_path_valid($value)) { + usage(); + emit("Illegal redirect directory value: key=$key value=" + . "$value\n", "error"); + return 0; + } + + if ($key eq "conf") { + $redirected_conf_path = $value; + emit("setting conf_path $redirected_conf_path\n"); + } elsif ($key eq "logs") { + $redirected_logs_path = $value; + emit("setting logs_path $redirected_logs_path\n"); + } else { + usage(); + emit("Illegal redirect directory key: key=$key value=" + . "$value\n", "error"); + return 0; + } + + emit("redirect $key => $value\n"); + } + + ## selinux warning + if (($pki_instance_root ne "/var/lib") && ($^O eq "linux")) { + print STDOUT <<"EOF"; +WARNING: This utility will attempt to relabel the selinux context of the +$pki_instance_path directory and the files within it +as pki_$subsystem_type _var_lib_t + +Depending on the location of pki_instance_root and the selinux rules +currently in place on the system, this may not succeed. In that case, the +directory may have to be manually relabeled, or selinux will have to be run +in permissive mode. + +It is therefore recommended that the default setting of /var/lib be used +for pki_instance_root. +EOF + +ASK_CONTINUE_NONSTD_INSTANCE_ROOT: + + my $confirm = prompt("You have chosen the following value for pki_instance_root instead: " + . $pki_instance_root + . "\nDo you wish to proceed with this value (Y/N)?"); + + if ($confirm eq "N" || $confirm eq "n") { + return 0; + } elsif ($confirm ne "Y" && $confirm ne "y") { + goto ASK_CONTINUE_NONSTD_INSTANCE_ROOT; + } + } + + return 1; +} + + +# Return 1 if success, 0 if failure +sub initialize_subsystem_paths +{ + ## Initialize subsystem directory paths (subsystem independent) + $conf_subsystem_path = $pki_subsystem_path + . "/" . $conf_base_subsystem_dir; + $setup_subsystem_path = $pki_subsystem_path + . "/" . $setup_base_subsystem_dir; + + $pki_registry_subsystem_path = $pki_registry_path + . "/" . $subsystem_type; + $pki_registry_subsystem_file_path = $setup_subsystem_path + . "/" . $registry_template_base_name; + + + ## Initialize subsystem directory paths (CA subsystems) + if ($subsystem_type eq $CA) { + $emails_subsystem_path = $pki_subsystem_path + . "/" . $emails_base_subsystem_dir; + } + + + $common_ui_subsystem_path = $pki_subsystem_common_area . "/" . + "common-ui"; + $ui_subsystem_path = $pki_subsystem_path . "-ui"; + + ## Initialize subsystem directory paths (RA, TPS subsystems) + if ($subsystem_type eq $RA || $subsystem_type eq $TPS) { + if ($subsystem_type eq $TPS) { + $applets_subsystem_path = $pki_subsystem_path + . "/" . $applets_base_subsystem_dir; + $bin_subsystem_path = $default_system_user_libraries + . "/" . $pki_flavor + . "/" . $subsystem_type; + $samples_subsystem_path = $pki_subsystem_path + . "/" . $samples_base_subsystem_dir; + } + + $lib_subsystem_path = $pki_subsystem_path + . "/" . $lib_base_subsystem_dir; + $scripts_subsystem_path = $pki_subsystem_path + . "/" . $scripts_base_subsystem_dir; + + # Apache Specific + if ($subsystem_type eq $TPS) { + $cgibin_subsystem_path = $pki_subsystem_path + . "/" . $cgibin_base_subsystem_dir; + } + + # Apache Specific + $docroot_subsystem_path = $pki_subsystem_path + . "/" . $docroot_base_subsystem_dir; + } else { + + ## Initialize subsystem directory paths (CA, KRA, OCSP, TKS subsystems) + + $profiles_subsystem_path = $pki_subsystem_path + . "/" . $profiles_base_subsystem_dir; + $webapps_subsystem_path = $pki_subsystem_path + . "/" . $webapps_base_subsystem_dir; + } + + return 1; +} + + +# Return 1 if success, 0 if failure +sub initialize_instance_paths +{ + ## Initialize instance directory paths (instance independent) + $alias_instance_path = $pki_instance_path + . "/" . $alias_base_instance_dir; + $conf_instance_path = $pki_instance_path + . "/" . $conf_base_instance_dir; + $logs_instance_path = $pki_instance_path + . "/" . $logs_base_instance_dir; + + + ## Initialize the pki registry instance + $pki_registry_instance_file_path = $pki_registry_subsystem_path + . "/" . $pki_instance_name; + + ## Initialize path to per instance init script + $pki_instance_initscript_path = $pki_instance_path + . "/" . $pki_instance_name; + + ## Initialize tomcat6 instance conf + $tomcat6_conf_instance_file_path = $tomcat6_instance_config_path + . "/" . $pki_instance_name; + ## Initialize tomcat6 pid file + $tomcat6_instance_pid_file_path = $default_tomcat_pids_path + . "/" . $pki_instance_name + . ".pid"; + + ## Initialize instance directory paths (RA, TPS instances) + if ($subsystem_type eq $RA || $subsystem_type eq $TPS) { + if ($subsystem_type eq $TPS) { + $bin_instance_path = $pki_instance_path + . "/" . $bin_base_instance_dir; + } + + $lib_instance_path = $pki_instance_path + . "/" . $lib_base_instance_dir; + $scripts_instance_path = $pki_instance_path + . "/" . $scripts_base_instance_dir; + + # Apache Specific + if ($subsystem_type eq $TPS) { + $cgibin_instance_path = $pki_instance_path + . "/" . $cgibin_base_instance_dir; + } + + # Apache Specific + $docroot_instance_path = $pki_instance_path + . "/" . $docroot_base_instance_dir; + } else { + ## Initialize instance directory paths (CA, KRA, OCSP, TKS instances) + $emails_instance_path = $pki_instance_path + . "/" . $emails_base_instance_dir; + $profiles_instance_path = $pki_instance_path + . "/" . $profiles_base_instance_dir; + $webapps_instance_path = $pki_instance_path + . "/" . $webapps_base_instance_dir; + $webapps_subsystem_instance_path = $webapps_instance_path . "/" + . $subsystem_type; + + # Tomcat Specific + $shared_instance_path = $pki_instance_path + . "/" . $shared_base_instance_dir; + $tomcat_instance_common_lib_path = $pki_instance_path + . "/" . $tomcat_instance_common_lib_dir; + $temp_instance_path = $pki_instance_path + . "/" . $temp_base_instance_dir; + $work_instance_path = $pki_instance_path + . "/" . $work_base_instance_dir; + } + + return 1; +} + + +# Return 1 if success, 0 if failure +sub initialize_instance_symlink_paths +{ + ## Initialize instance symlinks (instance independent) + $conf_instance_symlink_path = $pki_instance_path + . "/" . $conf_base_instance_symlink; + $logs_instance_symlink_path = $pki_instance_path + . "/" . $logs_base_instance_symlink; + + + ## Initialize instance symlinks (CA instances) + # if ($subsystem_type eq $CA) { + # } + + + ## Initialize instance symlinks (RA, TPS instances) + if ($subsystem_type eq $RA || $subsystem_type eq $TPS) { + # Apache Specific + $run_instance_symlink_path = $pki_instance_path + . "/" . $run_base_instance_symlink; + } + + return 1; +} + + +# Return 1 if success, 0 if failure +sub initialize_subdirectory_paths +{ + ## Initialize subdirectory paths (subsystem independent) + $pki_cfg_subsystem_file_path = $conf_subsystem_path + . "/" . $pki_cfg_base_name; + $setup_config_instance_file_path = $setup_config_area + . "/" . $pki_instance_name + . "-" . $setup_config_name; + $setup_config_subsystem_file_path = $setup_subsystem_path + . "/" . $setup_config_name; + + $pki_registry_initscript = get_registry_initscript_name($subsystem_type); + + ## Initialize subdirectory paths (CA subsystems) + if ($subsystem_type eq $CA) { + $profile_select_template_subsystem_file_path = $ui_subsystem_path + . "/" . $webapps_base_subsystem_dir + . "/" . $subsystem_type + . "/ee/" . $subsystem_type + . "/" . $profile_select_base_name; + $profile_select_template_instance_file_path = $webapps_subsystem_instance_path + . "/ee/". $subsystem_type + . "/" . $profile_select_base_name; + + $proxy_conf_subsystem_file_path = $conf_subsystem_path + . "/" . $proxy_conf_base_name; + } + + ## Initialize subdirectory paths (RA, TPS subsystems) + if ($subsystem_type eq $TPS) { + $cgi_sow_subsystem_file_path = $cgibin_subsystem_path + . "/" + . $cgi_sow_dir_name; + $cgi_sow_instance_cfg_pl_path = $cgibin_instance_path + . "/" + . $cgi_sow_cfg_pl_name; + } + + if ($subsystem_type eq $RA || $subsystem_type eq $TPS) { + + if ($subsystem_type eq $TPS) { + + $cgi_home_instance_file_path = $cgibin_instance_path + . "/" + . $cgi_home_base_name; + $cgi_home_subsystem_file_path = $cgibin_subsystem_path + . "/" + . $cgi_home_base_name; + $cgi_demo_instance_file_path = $cgibin_instance_path + . "/" + . $cgi_demo_base_name; + $cgi_demo_subsystem_file_path = $cgibin_subsystem_path + . "/" + . $cgi_demo_base_name; + $cgi_so_instance_file_path = $cgibin_instance_path + . "/" + . $cgi_so_base_name; + $cgi_so_subsystem_file_path = $cgibin_subsystem_path + . "/" + . $cgi_so_base_name; + $cgi_so_instance_enroll_file_path = $cgibin_instance_path + . "/" + . $cgi_so_enroll_name; + $cgi_so_subsystem_enroll_file_path = $cgibin_subsystem_path + . "/" + . $cgi_so_enroll_name; + $cgi_sow_instance_file_path = $cgibin_instance_path + . "/" + . $cgi_sow_dir_name; + $addAgents_ldif_instance_file_path = $scripts_instance_path + . "/" + . $addAgents_ldif_base_name; + $addAgents_ldif_subsystem_file_path = $scripts_subsystem_path + . "/" + . $addAgents_ldif_base_name; + $addIndexes_ldif_instance_file_path = $scripts_instance_path + . "/" + . $addIndexes_ldif_base_name; + $addIndexes_ldif_subsystem_file_path = $scripts_subsystem_path + . "/" + . $addIndexes_ldif_base_name; + $addTokens_ldif_instance_file_path = $scripts_instance_path + . "/" + . $addTokens_ldif_base_name; + $addTokens_ldif_subsystem_file_path = $scripts_subsystem_path + . "/" + . $addTokens_ldif_base_name; + $addVLVIndexes_ldif_instance_file_path = $scripts_instance_path + . "/" + . $addVLVIndexes_ldif_base_name; + $addVLVIndexes_ldif_subsystem_file_path = $scripts_subsystem_path + . "/" + . $addVLVIndexes_ldif_base_name; + $schemaMods_ldif_instance_file_path = $scripts_instance_path + . "/" + . $schemaMods_ldif_base_name; + $schemaMods_ldif_subsystem_file_path = $scripts_subsystem_path + . "/" + . $schemaMods_ldif_base_name; + } + + $pki_piddir_path = $default_apache_pids_path + . "/" . $subsystem_type; + $pki_lockdir_path = $default_lockdir + . "/" . $subsystem_type; + $pki_apache_initscript_file_path = $pki_subsystem_common_area + . "/" . $scripts_base_subsystem_dir + . "/" . $pki_apache_initscript_base_name; + $nss_pcache_instance_file_path = $scripts_instance_path + . "/" + . $nss_pcache_base_name; + $nss_pcache_subsystem_file_path = $scripts_subsystem_path + . "/" + . $nss_pcache_base_name; + $httpd_conf_subsystem_file_path = $conf_subsystem_path + . "/" . $httpd_conf_base_name; + $magic_subsystem_file_path = $conf_subsystem_path + . "/" . $magic_base_name; + $mime_types_subsystem_file_path = $conf_subsystem_path + . "/" . $mime_types_base_name; + $nss_conf_subsystem_file_path = $conf_subsystem_path + . "/" . $nss_conf_base_name; + $perl_conf_subsystem_file_path = $conf_subsystem_path + . "/" . $perl_conf_base_name; + $perl_instance_symlink_path = $lib_instance_path + . "/" + . $perl_base_instance_symlink; + $perl_subsystem_path = $lib_subsystem_path + . "/" + . $perl_base_subsystem_dir; + } else { + ## Initialize subdirectory paths (CA, KRA, OCSP, TKS subsystems) + + $pki_subsystem_jar_base_name = "pki-${subsystem_type}.jar"; + + if (!defined($pki_certsrv_jar_file_path = find_jar($pki_certsrv_jar_base_name))) { + emit("could not find jar: $pki_certsrv_jar_base_name", "error"); + return 0; + } + + if (!defined($pki_cms_jar_file_path = find_jar($pki_cms_jar_base_name))) { + emit("could not find jar: $pki_cms_jar_base_name", "error"); + return 0; + } + + if (!defined($pki_cmsbundle_jar_file_path = find_jar($pki_cmsbundle_jar_base_name))) { + emit("could not find jar: $pki_cmsbundle_jar_base_name", "error"); + return 0; + } + + if (!defined($pki_cmscore_jar_file_path = find_jar($pki_cmscore_jar_base_name))) { + emit("could not find jar: $pki_cmscore_jar_base_name", "error"); + return 0; + } + + if (!defined($pki_cmsutil_jar_file_path = find_jar($pki_cmsutil_jar_base_name))) { + emit("could not find jar: $pki_cmsutil_jar_base_name", "error"); + return 0; + } + + # jakarta-commons-* has been renamed to apache-commons-* on some + # systems, search which one is available, preferring apache-commons + if (defined($commons_collections_jar_file_path = find_jar($apache_commons_collections_jar_base_name))) { + $commons_collections_jar_base_name = $apache_commons_collections_jar_base_name; + } else { + if (defined($commons_collections_jar_file_path = find_jar($jakarta_commons_collections_jar_base_name))) { + $commons_collections_jar_base_name = $jakarta_commons_collections_jar_base_name; + } else { + emit("could not find jar: $apache_commons_collections_jar_base_name or $jakarta_commons_collections_jar_base_name", "error"); + return 0; + } + } + + if (defined($commons_lang_jar_file_path = find_jar($apache_commons_lang_jar_base_name))) { + $commons_lang_jar_base_name = $apache_commons_lang_jar_base_name; + } else { + if (defined($commons_lang_jar_file_path = find_jar($jakarta_commons_lang_jar_base_name))) { + $commons_lang_jar_base_name = $jakarta_commons_lang_jar_base_name; + } else { + emit("could not find jar: $apache_commons_lang_jar_base_name or $jakarta_commons_lang_jar_base_name", "error"); + return 0; + } + } + + if (defined($commons_logging_jar_file_path = find_jar($apache_commons_logging_jar_base_name))) { + $commons_logging_jar_base_name = $apache_commons_logging_jar_base_name; + } else { + if (defined($commons_logging_jar_file_path = find_jar($jakarta_commons_logging_jar_base_name))) { + $commons_logging_jar_base_name = $jakarta_commons_logging_jar_base_name; + } else { + emit("could not find jar: $apache_commons_logging_jar_base_name or $jakarta_commons_logging_jar_base_name", "error"); + return 0; + } + } + + if (!defined($jss_jar_file_path = find_jar($jss_jar_base_name))) { + emit("could not find jar: $jss_jar_base_name", "error"); + return 0; + } + + if (!defined($ldapjdk_jar_file_path = find_jar($ldapjdk_jar_base_name))) { + emit("could not find jar: $ldapjdk_jar_base_name", "error"); + return 0; + } + + if (!defined($pki_nsutil_jar_file_path = find_jar($pki_nsutil_jar_base_name))) { + emit("could not find jar: $pki_nsutil_jar_base_name", "error"); + return 0; + } + + if (!defined($osutil_jar_file_path = find_jar($osutil_jar_base_name))) { + emit("could not find jar: $osutil_jar_base_name", "error"); + return 0; + } + + if (!defined($pki_subsystem_jar_file_path = find_jar($pki_subsystem_jar_base_name))) { + emit("could not find jar: $pki_subsystem_jar_base_name", "error"); + return 0; + } + + if (!defined($symkey_jar_file_path = find_jar($symkey_jar_base_name))) { + emit("could not find jar: $symkey_jar_base_name", "error"); + return 0; + } + + if (!defined($tomcatjss_jar_file_path = find_jar($tomcatjss_jar_base_name))) { + emit("could not find jar: $tomcatjss_jar_base_name", "error"); + return 0; + } + + if (!defined($velocity_jar_file_path = find_jar($velocity_jar_base_name))) { + emit("could not find jar: $velocity_jar_base_name", "error"); + return 0; + } + + if (!defined($xerces_jar_file_path = find_jar($xerces_jar_base_name))) { + emit("could not find jar: $xerces_jar_base_name", "error"); + return 0; + } + + if (!defined($xml_commons_apis_jar_file_path = find_jar($xml_commons_apis_jar_base_name))) { + emit("could not find jar: $xml_commons_apis_jar_base_name", "error"); + return 0; + } + + if (!defined($xml_commons_resolver_jar_file_path = find_jar($xml_commons_resolver_jar_base_name))) { + emit("could not find jar: $xml_commons_resolver_jar_base_name", "error"); + return 0; + } + + $webinf_instance_path = $webapps_instance_path + . "/" . $subsystem_type + . "/" . $webinf_base_instance_dir; + $webinf_subsystem_path = $webapps_subsystem_path + . "/" . $subsystem_type + . "/" . $webinf_base_instance_dir; + $webinf_lib_instance_path = $webinf_instance_path + . "/" . $lib_base_instance_dir; + $webapps_root_subsystem_path = $webapps_subsystem_path + . "/" + . $webapps_root_base_subsystem_dir; + $webapps_subsystem_instance_path = $webapps_instance_path + . "/" . $subsystem_type; + + $pki_certsrv_jar_symlink_path = $webinf_lib_instance_path + . "/" . $pki_certsrv_jar_base_name; + $pki_cms_jar_symlink_path = $webinf_lib_instance_path + . "/" . $pki_cms_jar_base_name; + $pki_cmsbundle_jar_symlink_path = $webinf_lib_instance_path + . "/" . $pki_cmsbundle_jar_base_name; + $pki_cmscore_jar_symlink_path = $webinf_lib_instance_path + . "/" . $pki_cmscore_jar_base_name; + $pki_cmsutil_jar_symlink_path = $webinf_lib_instance_path + . "/" . $pki_cmsutil_jar_base_name; + $commons_collections_jar_symlink_path = $webinf_lib_instance_path + . "/" . $commons_collections_jar_base_name; + $commons_lang_jar_symlink_path = $webinf_lib_instance_path + . "/" . $commons_lang_jar_base_name; + $commons_logging_jar_symlink_path = $tomcat_instance_common_lib_path + . "/" . $commons_logging_jar_base_name; + $jss_jar_symlink_path = $tomcat_instance_common_lib_path + . "/" . $jss_jar_base_name; + $ldapjdk_jar_symlink_path = $webinf_lib_instance_path + . "/" . $ldapjdk_jar_base_name; + $pki_nsutil_jar_symlink_path = $webinf_lib_instance_path + . "/" . $pki_nsutil_jar_base_name; + $osutil_jar_symlink_path = $webinf_lib_instance_path + . "/" . $osutil_jar_base_name; + $symkey_jar_symlink_path = $webinf_lib_instance_path + . "/" . $symkey_jar_base_name; + $pki_subsystem_jar_symlink_path = $webinf_lib_instance_path + . "/" . $pki_subsystem_jar_base_name; + $tomcatjss_jar_symlink_path = $tomcat_instance_common_lib_path + . "/" . $tomcatjss_jar_base_name; + $velocity_jar_symlink_path = $webinf_lib_instance_path + . "/" . $velocity_jar_base_name; + $xerces_jar_symlink_path = $webinf_lib_instance_path + . "/" . $xerces_jar_base_name; + $xml_commons_apis_jar_symlink_path = $webinf_lib_instance_path + . "/" . $xml_commons_apis_jar_base_name; + $xml_commons_resolver_jar_symlink_path = $webinf_lib_instance_path + . "/" . $xml_commons_resolver_jar_base_name; + + + $webapps_root_instance_path = $webapps_instance_path + . "/" + . $webapps_root_base_instance_dir; + $index_jsp_instance_file_path = $webapps_root_instance_path + . "/" . $index_jsp_base_name; + $index_jsp_subsystem_file_path = $webapps_root_subsystem_path + . "/" . $index_jsp_base_name; + $server_xml_subsystem_file_path = $conf_subsystem_path + . "/" . $server_xml_base_name; + $servercertnick_conf_subsystem_file_path = $conf_subsystem_path + . "/" . $servercertnick_conf_base_name; + $tomcat6_conf_subsystem_file_path = $conf_subsystem_path + . "/" . $tomcat6_conf_base_name; + $velocity_prop_instance_file_path = $webinf_instance_path + . "/" . $velocity_prop_base_name; + $velocity_prop_subsystem_file_path = $webinf_subsystem_path + . "/" . $velocity_prop_base_name; + $web_xml_instance_file_path = $webinf_instance_path + . "/" . $web_xml_base_name; + $web_xml_subsystem_file_path = $webinf_subsystem_path + . "/" . $web_xml_base_name; + $catalina_properties_subsystem_file_path = $conf_subsystem_path + . "/" . $catalina_properties_base_name; + } + return 1; +} + + +# Return 1 if success, 0 if failure +sub initialize_paths +{ + return 0 if !initialize_subsystem_paths(); + return 0 if !initialize_instance_paths(); + return 0 if !initialize_instance_symlink_paths(); + return 0 if !initialize_subdirectory_paths(); + return 1; +} + + +# Return 1 if success, 0 if failure +sub initialize_pki_creation_values +{ + # obtain the fully-qualified domain name of this host + $host = get_FQDN($hostname); + + # we need the certdb password generated now ... + $db_password = generate_random($db_password_low, $db_password_high); + + # generate a random value for a pin ... + $random = generate_random_string(20); + + return 1; +} + + +# Return 1 if success, 0 if failure +sub process_pki_directories +{ + my $remove_dir=""; + + emit("Processing PKI directories for '$pki_instance_path' ...\n"); + + ## Populate instance directory paths (instance independent) + return 0 if !create_directory($alias_instance_path, + $default_dir_permissions, $pki_user, $pki_group); + + # Check for an optionally redirected "conf" directory path ... + if (!$redirected_conf_path) { + $noise_instance_file_path = $conf_instance_path + . "/" . $noise_base_name; + $password_conf_instance_file_path = $conf_instance_path + . "/" . $password_conf_base_name; + $pfile_instance_file_path = $conf_instance_path + . "/" . $pfile_base_name; + $pki_cfg_instance_file_path = $conf_instance_path + . "/" . $pki_cfg_base_name; + $proxy_conf_instance_file_path = $conf_instance_path + . "/" . $proxy_conf_base_name; + $catalina_properties_instance_file_path = $conf_instance_path + . "/" . $catalina_properties_base_name; + + if ($subsystem_type eq $RA || $subsystem_type eq $TPS) { + $httpd_conf_instance_file_path = $conf_instance_path + . "/" . $httpd_conf_base_name; + $magic_instance_file_path = $conf_instance_path + . "/" . $magic_base_name; + $mime_types_instance_file_path = $conf_instance_path + . "/" . $mime_types_base_name; + $nss_conf_instance_file_path = $conf_instance_path + . "/" . $nss_conf_base_name; + $perl_conf_instance_file_path = $conf_instance_path + . "/" . $perl_conf_base_name; + $pwcache_conf_instance_file_path = $conf_instance_path + . "/" . $pwcache_conf_base_name; + + # create instance directory + return 0 if !create_directory($conf_instance_path, + $default_dir_permissions, $pki_user, $pki_group); + + # only copy selected files + return 0 if !copy_file($magic_subsystem_file_path, $magic_instance_file_path, + $default_file_permissions, $pki_user, $pki_group); + + return 0 if !copy_file($mime_types_subsystem_file_path, $mime_types_instance_file_path, + $default_file_permissions, $pki_user, $pki_group); + + } else { + $server_xml_instance_file_path = $conf_instance_path + . "/" . $server_xml_base_name; + $servercertnick_conf_instance_file_path = $conf_instance_path + . "/" . $servercertnick_conf_base_name; + + return 0 if !copy_directory($conf_subsystem_path, $conf_instance_path, + $default_dir_permissions, $default_file_permissions, + $pki_user, $pki_group); + } + } else { + $noise_instance_file_path = $redirected_conf_path + . "/" . $noise_base_name; + $password_conf_instance_file_path = $redirected_conf_path + . "/" . $password_conf_base_name; + $pfile_instance_file_path = $redirected_conf_path + . "/" . $pfile_base_name; + $pki_cfg_instance_file_path = $redirected_conf_path + . "/" . $pki_cfg_base_name; + $proxy_conf_instance_file_path = $redirected_conf_path + . "/" . $proxy_conf_base_name; + $catalina_properties_instance_file_path = $redirected_conf_path + . "/" . $catalina_properties_base_name; + + # Populate optionally redirected instance directory path + # and setup a symlink in the standard area + if ($subsystem_type eq $RA || $subsystem_type eq $TPS) { + $httpd_conf_instance_file_path = $redirected_conf_path + . "/" . $httpd_conf_base_name; + $magic_instance_file_path = $redirected_conf_path + . "/" . $magic_base_name; + $mime_types_instance_file_path = $redirected_conf_path + . "/" . $mime_types_base_name; + $nss_conf_instance_file_path = $redirected_conf_path + . "/" . $nss_conf_base_name; + $perl_conf_instance_file_path = $redirected_conf_path + . "/" . $perl_conf_base_name; + $pwcache_conf_instance_file_path = $redirected_conf_path + . "/" . $pwcache_conf_base_name; + + # create redirected instance directory + return 0 if !create_directory($redirected_conf_path, + $default_dir_permissions, $pki_user, $pki_group); + + # only copy selected files + return 0 if !copy_file($magic_subsystem_file_path, $magic_instance_file_path, + $default_file_permissions, $pki_user, $pki_group); + + return 0 if !copy_file($mime_types_subsystem_file_path, $mime_types_instance_file_path, + $default_file_permissions, $pki_user, $pki_group); + + } else { + $server_xml_instance_file_path = $redirected_conf_path + . "/" . $server_xml_base_name; + $servercertnick_conf_instance_file_path = $redirected_conf_path + . "/" . $servercertnick_conf_base_name; + + return 0 if !copy_directory($conf_subsystem_path, $redirected_conf_path, + $default_dir_permissions, $default_file_permissions, + $pki_user, $pki_group); + } + + return 0 if !create_symlink($conf_instance_symlink_path, $redirected_conf_path, + $pki_user, $pki_group); + + } + + + # Check for an optionally redirected "logs" directory path ... + if (!$redirected_logs_path) { + # create instance directory + return 0 if !create_directory(${logs_instance_path}, + $default_dir_permissions, $pki_user, $pki_group); + + ## (CA, KRA, OCSP, TKS, TPS instances) + if ($subsystem_type ne $RA) { + ## Create a "signedAudit" directory + return 0 if !create_directory("${logs_instance_path}/${signed_audit_base_instance_dir}", + $default_dir_permissions, $pki_user, $pki_group); + } + } else { + # create redirected instance directory + # and setup a symlink in the standard area + return 0 if !create_directory($redirected_logs_path, + $default_dir_permissions, $pki_user, $pki_group); + + ## (CA, KRA, OCSP, TKS, TPS instances) + if ($subsystem_type ne $RA) { + ## Create a "signedAudit" directory + return 0 if !create_directory("${redirected_logs_path}/${signed_audit_base_instance_dir}", + $default_dir_permissions, $pki_user, $pki_group); + } + + return 0 if !create_symlink($logs_instance_symlink_path, $redirected_logs_path, + $pki_user, $pki_group); + + return 0 if !set_owner_group_on_directory_contents($redirected_logs_path, $pki_user, $pki_group); + } + + + ## Populate pki instance registry + # create pki registry for this subsystem + return 0 if !create_directory($pki_registry_subsystem_path, + $default_dir_permissions, $pki_user, $pki_group, 'preserve'); + + + ## Populate instance directory paths (CA instances) + if ($subsystem_type eq $CA) { + return 0 if !copy_directory($emails_subsystem_path, $emails_instance_path, + $default_dir_permissions, $default_file_permissions, + $pki_user, $pki_group); + + return 0 if !copy_directory($profiles_subsystem_path, $profiles_instance_path, + $default_dir_permissions, $default_file_permissions, + $pki_user, $pki_group); + } + + + ## Populate instance directory paths (RA, TPS instances) + if ($subsystem_type eq $RA || $subsystem_type eq $TPS) { + + if ($subsystem_type eq $TPS) { + return 0 if !create_directory($bin_instance_path, + $default_dir_permissions, $pki_user, $pki_group); + } + + return 0 if !create_directory($lib_instance_path, + $default_dir_permissions, $pki_user, $pki_group); + + return 0 if !create_directory($scripts_instance_path, + $default_dir_permissions, $pki_user, $pki_group); + + # Apache Specific + if ($subsystem_type eq $TPS) { + return 0 if !copy_directory($cgibin_subsystem_path, $cgibin_instance_path, + $default_dir_permissions, $default_file_permissions, + $pki_user, $pki_group); + } + + # Apache Specific + return 0 if !copy_directory($docroot_subsystem_path, $docroot_instance_path, + $default_dir_permissions, $default_file_permissions, + $pki_user, $pki_group); + + + return 0 if !copy_directory($ui_subsystem_path, $pki_instance_path, + $default_dir_permissions, $default_file_permissions, + $pki_user, $pki_group); + + # fix permissions + if (!is_Windows()) { + # Apache Specific + if ($subsystem_type eq $TPS) { + set_permissions("${cgibin_instance_path}/demo", $default_dir_permissions); + set_permissions("${cgibin_instance_path}/demo/*.cgi", $default_exe_permissions); + set_permissions("${cgibin_instance_path}/demo/*.html", $default_file_permissions); + set_permissions("${cgibin_instance_path}/home", $default_dir_permissions); + set_permissions("${cgibin_instance_path}/home/*.cgi", $default_exe_permissions); + set_permissions("${cgibin_instance_path}/home/*.html", $default_file_permissions); + set_permissions("${cgibin_instance_path}/so", $default_dir_permissions); + set_permissions("${cgibin_instance_path}/so/*.cgi", $default_exe_permissions); + set_permissions("${cgibin_instance_path}/so/*.html", $default_file_permissions); + set_permissions("${cgibin_instance_path}/sow", $default_dir_permissions); + set_permissions("${cgibin_instance_path}/sow/*.cgi", $default_exe_permissions); + set_permissions("${cgibin_instance_path}/sow/*.html", $default_file_permissions); + set_permissions("${cgibin_instance_path}/sow/*.pl", $default_exe_permissions); + set_permissions("${docroot_instance_path}/", $default_dir_permissions); + set_permissions("${docroot_instance_path}/*.cgi", $default_exe_permissions); + } + } + } else { + ## Populate instance directory paths (CA, KRA, OCSP, TKS instances) + return 0 if !copy_directory($webapps_subsystem_path, $webapps_instance_path, + $default_dir_permissions, $default_file_permissions, + $pki_user, $pki_group); + + return 0 if !copy_directory($common_ui_subsystem_path, $webapps_subsystem_instance_path, + $default_dir_permissions, $default_file_permissions, + $pki_user, $pki_group); + + return 0 if !copy_directory($ui_subsystem_path, $pki_instance_path, + $default_dir_permissions, $default_file_permissions, + $pki_user, $pki_group); + + ## Tomcat Specific + return 0 if !create_directory($shared_instance_path, + $default_dir_permissions, $pki_user, $pki_group); + + return 0 if !create_directory("$shared_instance_path/classes", + $default_dir_permissions, $pki_user, $pki_group); + + return 0 if !create_directory("$shared_instance_path/lib", + $default_dir_permissions, $pki_user, $pki_group); + + return 0 if !create_directory($tomcat_instance_common_lib_path, + $default_dir_permissions, $pki_user, $pki_group); + + return 0 if !create_directory($temp_instance_path, + $default_dir_permissions, $pki_user, $pki_group); + + return 0 if !create_directory($work_instance_path, + $default_dir_permissions, $pki_user, $pki_group); + } + + ## Set appropriate permissions + return 0 if !set_owner_group_on_directory_contents($pki_instance_path, $pki_user, $pki_group); + + return 1; +} + + +# process_file_template +# +# template_name +# Used to identify the template. +# src_path +# The file pathname of the template. +# dst_path +# The file pathname the processed template will be written to. +# substitutions +# Pointer to a hash. Each key is a substitution name, the key's +# value is the string to substitute. +# +# Given a template file, read it's contents in. Then perform text +# replacements on any string of the form "[name]". name will be used +# as a key in the substitutions hash, if the key exists in the hash then +# it's value will replace the string "[name]". +# +# Example, if the src template contained this line: +# +# Open port [PORT] on your firewall. +# +# And the substitutions hash was this {'PORT' => '1234'} +# +# Then the dst file contents will look like this: +# +# Open port 1234 on your firewall. +# +# Return 1 if success, 0 if failure + +sub process_file_template +{ + my ($template_name, $src_path, $dst_path, $substitutions) = @_; + + my $buf = ""; + my $num_subs = 0; + my $total_subs = 0; + my @keys; + my $key; + my $value; + emit(" Template ($template_name) \"${src_path}\" ==> \"${dst_path}\" ...\n"); + + # Check for a valid source file + if (!is_path_valid($src_path)) { + emit("process_file_template(): invalid source path ${src_path}!\n", "error"); + return 0; + } + + # Check for a valid destination file + if (!is_path_valid($dst_path)) { + emit("process_file_template(): invalid destination path ${dst_path}!\n", "error"); + return 0; + } + + # Read in contents of source file + $buf = read_file($src_path); + + # Process each line substituting each [KEY] + # with its corresponding slot hash value + @keys = sort(keys %$substitutions); + foreach $key (@keys) { + $value = $substitutions->{$key}; + # Perform global substitution on buffer and + # get count of how many substitutions were actually performed. + $num_subs = $buf =~ s/\[$key\]/$value/g; + $total_subs += $num_subs; + + # If any substitutions were performed then log what was done. + if ($num_subs > 0) { + # Hide sensitive information by emitting the word "(sensitive)" + # rather rather than the substituted value. + if ($key eq $PKI_CERT_DB_PASSWORD_SLOT) { + emit(sprintf(" %3d substitutions: %s ==> (sensitive)\n", $num_subs, $key)); + } else { + emit(sprintf(" %3d substitutions: %s ==> \"%s\"\n", $num_subs, $key, $value)); + } + } + } + + emit(" $total_subs substitutions were made in '$dst_path'\n"); + + # Sanity check, are there any strings left in the buffer which look + # like a substitution. + foreach my $match ($buf =~ /\[[A-Z_]+\]/g) { + emit("WARNING: Possible missed substitution \"$match\" in $src_path"); + } + + # Record that we've installed this file. + add_install_info($dst_path, 'file'); + + if ($verbose >= 2) { + # For debugging, emit the contents after substitution. + emit(sprintf(">> $dst_path\n%s<< $dst_path\n", $buf)); + } + + if (!$dry_run) { + # Write out these modified contents to the destination file. + write_file($dst_path, \$buf); + } + + return 1; +} + + +# Return 1 if success, 0 if failure +sub process_pki_templates +{ + my $use_port_separation = 0; + if ($agent_secure_port >= 0 && + ($subsystem_type ne $RA) && + ($subsystem_type ne $TPS)) { + $use_port_separation = 1; + } + + my %slot_hash = (); + + emit("Processing PKI templates for '$pki_instance_path' ...\n"); + + $slot_hash{$PKI_SUBSYSTEM_TYPE_SLOT} = $subsystem_type; + $slot_hash{$PKI_INSTANCE_ID_SLOT} = $pki_instance_name; + $slot_hash{$PKI_INSTANCE_ROOT_SLOT} = $pki_instance_root; + $slot_hash{$PKI_INSTANCE_INITSCRIPT} = $pki_instance_initscript_path; + $slot_hash{$PKI_REGISTRY_FILE_SLOT} = $pki_registry_instance_file_path; + $slot_hash{$PKI_USER_SLOT} = $pki_user; + $slot_hash{$PKI_GROUP_SLOT} = $pki_group; + + if ($subsystem_type eq $TPS) { + $slot_hash{$REQUIRE_CFG_PL} = "require \"${cgi_sow_instance_cfg_pl_path}\";"; + } + + if ($subsystem_type eq $RA || $subsystem_type eq $TPS) { + # Setup templates (RA, TPS) + $slot_hash{$HTTPD_CONF} = $httpd_conf_instance_file_path; + $slot_hash{$LIB_PREFIX} = $lib_prefix; + $slot_hash{$NSS_CONF} = $nss_conf_instance_file_path; + $slot_hash{$OBJ_EXT} = $obj_ext; + $slot_hash{$PORT} = $unsecure_port; + $slot_hash{$PROCESS_ID} = $$; + $slot_hash{$SECURE_PORT} = $secure_port; + $slot_hash{$NON_CLIENTAUTH_SECURE_PORT} = $non_clientauth_secure_port; + $slot_hash{$SECURITY_LIBRARIES} = $default_security_libraries; + $slot_hash{$SERVER_NAME} = $host; + $slot_hash{$SERVER_ROOT} = $pki_instance_path; + $slot_hash{$SYSTEM_LIBRARIES} = $default_system_libraries; + $slot_hash{$SYSTEM_USER_LIBRARIES} = $default_system_user_libraries; + $slot_hash{$TMP_DIR} = $tmp_dir; + $slot_hash{$TPS_DIR} = $pki_subsystem_path; + $slot_hash{$PKI_FLAVOR_SLOT} = $pki_flavor; + $slot_hash{$PKI_RANDOM_NUMBER_SLOT} = $random; + $slot_hash{$PKI_PIDDIR} = $pki_piddir_path; + $slot_hash{$PKI_LOCKDIR} = $pki_lockdir_path; + if (is_Fedora() || (is_RHEL() && (! is_RHEL4()))) { + $slot_hash{$FORTITUDE_APACHE} = "Apache2"; + $slot_hash{$FORTITUDE_DIR} = "/usr"; + $slot_hash{$FORTITUDE_LIB_DIR} = "/etc/httpd"; + $slot_hash{$FORTITUDE_MODULE} = "/etc/httpd/modules"; + $slot_hash{$FORTITUDE_AUTH_MODULES} = +" +LoadModule auth_basic_module /etc/httpd/modules/mod_auth_basic.so +LoadModule authn_file_module /etc/httpd/modules/mod_authn_file.so +LoadModule authz_user_module /etc/httpd/modules/mod_authz_user.so +LoadModule authz_groupfile_module /etc/httpd/modules/mod_authz_groupfile.so +LoadModule authz_host_module /etc/httpd/modules/mod_authz_host.so +"; + $slot_hash{$FORTITUDE_NSS_MODULES} = +" +LoadModule nss_module /etc/httpd/modules/libmodnss.so +"; + } + else { + $slot_hash{$FORTITUDE_APACHE} = "Apache"; + $slot_hash{$FORTITUDE_DIR} = "/opt/fortitude"; + $slot_hash{$FORTITUDE_LIB_DIR} = "/opt/fortitude"; + $slot_hash{$FORTITUDE_MODULE} = "/opt/fortitude/modules.local"; + $slot_hash{$FORTITUDE_AUTH_MODULES} = +" +LoadModule auth_module /opt/fortitude/modules/mod_auth.so +LoadModule access_module /opt/fortitude/modules/mod_access.so +"; + $slot_hash{$FORTITUDE_NSS_MODULES} = +" +LoadModule nss_module /opt/fortitude/modules.local/libmodnss.so +"; + } + } else { + # Setup templates (CA, KRA, OCSP, TKS) + $slot_hash{$INSTALL_TIME} = localtime; + $slot_hash{$PKI_CERT_DB_PASSWORD_SLOT} = $db_password; + $slot_hash{$PKI_CFG_PATH_NAME_SLOT} = $pki_cfg_instance_file_path; + $slot_hash{$PKI_INSTANCE_PATH_SLOT} = $pki_instance_path; + $slot_hash{$PKI_MACHINE_NAME_SLOT} = $host; + $slot_hash{$PKI_RANDOM_NUMBER_SLOT} = $random; + $slot_hash{$PKI_SERVER_XML_CONF} = $server_xml_instance_file_path; + $slot_hash{$PKI_UNSECURE_PORT_SLOT} = $unsecure_port; + + # Define "Port Separation" (default) versus "Shared Ports" (legacy) + if ($use_port_separation) { + # Establish "Port Separation" Connector Names + $slot_hash{$PKI_UNSECURE_PORT_CONNECTOR_NAME_SLOT} = $PKI_UNSECURE_PORT_NAME; + $slot_hash{$PKI_SECURE_PORT_CONNECTOR_NAME_SLOT} = $PKI_AGENT_SECURE_PORT_NAME; + $slot_hash{$PKI_ADMIN_SECURE_PORT_CONNECTOR_NAME_SLOT} = $PKI_ADMIN_SECURE_PORT_NAME; + $slot_hash{$PKI_EE_SECURE_PORT_CONNECTOR_NAME_SLOT} = $PKI_EE_SECURE_PORT_NAME; + $slot_hash{$PKI_EE_SECURE_CLIENT_AUTH_PORT_CONNECTOR_NAME_SLOT} = $PKI_EE_SECURE_CLIENT_AUTH_PORT_NAME; + + # Establish "Port Separation" Connector Ports + $slot_hash{$PKI_SECURE_PORT_SLOT} = $agent_secure_port; + $slot_hash{$PKI_AGENT_SECURE_PORT_SLOT} = $agent_secure_port; + $slot_hash{$PKI_EE_SECURE_PORT_SLOT} = $ee_secure_port; + $slot_hash{$PKI_EE_SECURE_CLIENT_AUTH_PORT_SLOT} = $ee_secure_client_auth_port; + $slot_hash{$PKI_EE_SECURE_CLIENT_AUTH_PORT_UI_SLOT} = $ee_secure_client_auth_port; + $slot_hash{$PKI_ADMIN_SECURE_PORT_SLOT} = $admin_secure_port; + + # Comment "Port Separation" appropriately + $slot_hash{$PKI_UNSECURE_PORT_COMMENT_SERVER_SLOT} = $PKI_UNSECURE_SEPARATE_PORTS_COMMENT; + $slot_hash{$PKI_SECURE_PORT_COMMENT_SERVER_SLOT} = $PKI_AGENT_SECURE_SEPARATE_PORTS_COMMENT; + $slot_hash{$PKI_ADMIN_SECURE_PORT_COMMENT_SERVER_SLOT} = $PKI_ADMIN_SECURE_SEPARATE_PORTS_COMMENT; + $slot_hash{$PKI_EE_SECURE_PORT_COMMENT_SERVER_SLOT} = $PKI_EE_SECURE_SEPARATE_PORTS_COMMENT; + $slot_hash{$PKI_EE_SECURE_CLIENT_AUTH_PORT_COMMENT_SERVER_SLOT} = $PKI_EE_SECURE_CLIENT_AUTH_SEPARATE_PORTS_COMMENT; + + # Set appropriate "clientAuth" parameter for "Port Separation" + $slot_hash{$PKI_AGENT_CLIENTAUTH_SLOT} = "true"; + + # Do NOT comment out the "Admin/EE" Ports + $slot_hash{$PKI_OPEN_SEPARATE_PORTS_COMMENT_SERVER_SLOT} = ""; + $slot_hash{$PKI_CLOSE_SEPARATE_PORTS_COMMENT_SERVER_SLOT} = ""; + + # Do NOT comment out the "Admin/Agent/EE" Filters + # used by Port Separation + $slot_hash{$PKI_OPEN_SEPARATE_PORTS_COMMENT_WEB_SLOT} = ""; + $slot_hash{$PKI_CLOSE_SEPARATE_PORTS_COMMENT_WEB_SLOT} = ""; + } else { + # Establish "Shared Ports" Connector Names + $slot_hash{$PKI_UNSECURE_PORT_CONNECTOR_NAME_SLOT} = $PKI_UNSECURE_PORT_NAME; + $slot_hash{$PKI_SECURE_PORT_CONNECTOR_NAME_SLOT} = $PKI_SECURE_PORT_NAME; + $slot_hash{$PKI_ADMIN_SECURE_PORT_CONNECTOR_NAME_SLOT} = $PKI_UNUSED_SECURE_PORT_NAME; + $slot_hash{$PKI_EE_SECURE_PORT_CONNECTOR_NAME_SLOT} = $PKI_UNUSED_SECURE_PORT_NAME; + $slot_hash{$PKI_EE_SECURE_CLIENT_AUTH_PORT_CONNECTOR_NAME_SLOT} = $PKI_UNUSED_SECURE_PORT_NAME; + + # Establish "Shared Ports" Connector Ports + $slot_hash{$PKI_SECURE_PORT_SLOT} = $secure_port; + $slot_hash{$PKI_AGENT_SECURE_PORT_SLOT} = $secure_port; + $slot_hash{$PKI_EE_SECURE_PORT_SLOT} = $secure_port; + $slot_hash{$PKI_EE_SECURE_CLIENT_AUTH_PORT_SLOT} = $secure_port; + $slot_hash{$PKI_EE_SECURE_CLIENT_AUTH_PORT_UI_SLOT} = $secure_port; + $slot_hash{$PKI_ADMIN_SECURE_PORT_SLOT} = $secure_port; + + # Comment "Shared Ports" appropriately + $slot_hash{$PKI_UNSECURE_PORT_COMMENT_SERVER_SLOT} = $PKI_UNSECURE_SHARED_PORTS_COMMENT; + $slot_hash{$PKI_SECURE_PORT_COMMENT_SERVER_SLOT} = $PKI_SECURE_SHARED_PORTS_COMMENT; + $slot_hash{$PKI_ADMIN_SECURE_PORT_COMMENT_SERVER_SLOT} = ""; + $slot_hash{$PKI_EE_SECURE_PORT_COMMENT_SERVER_SLOT} = ""; + $slot_hash{$PKI_EE_SECURE_CLIENT_AUTH_PORT_COMMENT_SERVER_SLOT} = ""; + + # Set appropriate "clientAuth" parameter for "Shared Ports" + $slot_hash{$PKI_AGENT_CLIENTAUTH_SLOT} = "agent"; + + # Comment out the "Admin/EE" Ports + $slot_hash{$PKI_OPEN_SEPARATE_PORTS_COMMENT_SERVER_SLOT} = $PKI_OPEN_COMMENT; + $slot_hash{$PKI_CLOSE_SEPARATE_PORTS_COMMENT_SERVER_SLOT} = $PKI_CLOSE_COMMENT;; + + # Comment out the "Admin/Agent/EE" Filters + $slot_hash{$PKI_OPEN_SEPARATE_PORTS_COMMENT_WEB_SLOT} = $PKI_OPEN_COMMENT; + $slot_hash{$PKI_CLOSE_SEPARATE_PORTS_COMMENT_WEB_SLOT} = $PKI_CLOSE_COMMENT; + } + + if ($enable_proxy) { + if ($use_port_separation) { + $slot_hash{$PKI_AJP_REDIRECT_PORT_SLOT} = $ee_secure_port; + } else { + $slot_hash{$PKI_AJP_REDIRECT_PORT_SLOT} = $secure_port; + } + $slot_hash{$PKI_EE_SECURE_CLIENT_AUTH_PORT_UI_SLOT} = $proxy_secure_port; + $slot_hash{$PKI_AJP_PORT_SLOT} = $ajp_port; + $slot_hash{$PKI_OPEN_AJP_PORT_COMMENT_SLOT} = ""; + $slot_hash{$PKI_CLOSE_AJP_PORT_COMMENT_SLOT} = ""; + $slot_hash{$PKI_OPEN_ENABLE_PROXY_COMMENT_SLOT} = ""; + $slot_hash{$PKI_CLOSE_ENABLE_PROXY_COMMENT_SLOT} = ""; + } else { + $slot_hash{$PKI_OPEN_AJP_PORT_COMMENT_SLOT} = $PKI_OPEN_COMMENT; + $slot_hash{$PKI_CLOSE_AJP_PORT_COMMENT_SLOT} = $PKI_CLOSE_COMMENT; + $slot_hash{$PKI_OPEN_ENABLE_PROXY_COMMENT_SLOT} = $PKI_OPEN_COMMENT; + $slot_hash{$PKI_CLOSE_ENABLE_PROXY_COMMENT_SLOT} = $PKI_CLOSE_COMMENT; + } + + $slot_hash{$PROXY_SECURE_PORT_SLOT} = ($proxy_secure_port >=0) ? + $proxy_secure_port : ""; + $slot_hash{$PROXY_UNSECURE_PORT_SLOT} = ($proxy_unsecure_port>=0) ? + $proxy_unsecure_port : ""; + + $slot_hash{$PKI_WEBAPPS_NAME} = $webapps_base_subsystem_dir; + $slot_hash{$PKI_FLAVOR_SLOT} = $pki_flavor; + $slot_hash{$TOMCAT_SERVER_PORT_SLOT} = $tomcat_server_port; + $slot_hash{$TOMCAT_PIDFILE} = $tomcat6_instance_pid_file_path; + $slot_hash{$TOMCAT_CFG} = $tomcat6_conf_instance_file_path; + $slot_hash{$TOMCAT_SSL_OPTIONS} = "ssl2=true,ssl3=true,tls=true"; + $slot_hash{$TOMCAT_SSL2_CIPHERS} = "-SSL2_RC4_128_WITH_MD5,-SSL2_RC4_128_EXPORT40_WITH_MD5," + . "-SSL2_RC2_128_CBC_WITH_MD5,-SSL2_RC2_128_CBC_EXPORT40_WITH_MD5," + . "-SSL2_DES_64_CBC_WITH_MD5,-SSL2_DES_192_EDE3_CBC_WITH_MD5"; + $slot_hash{$TOMCAT_SSL3_CIPHERS} = "-SSL3_FORTEZZA_DMS_WITH_NULL_SHA,-SSL3_FORTEZZA_DMS_WITH_RC4_128_SHA," + . "+SSL3_RSA_WITH_RC4_128_SHA,-SSL3_RSA_EXPORT_WITH_RC4_40_MD5," + . "+SSL3_RSA_WITH_3DES_EDE_CBC_SHA,+SSL3_RSA_WITH_DES_CBC_SHA," + . "-SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5,-SSL3_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA," + . "-SSL_RSA_FIPS_WITH_DES_CBC_SHA,+SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA," + . "-SSL3_RSA_WITH_NULL_MD5,-TLS_RSA_EXPORT1024_WITH_RC4_56_SHA," + . "-TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,+TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; + $slot_hash{$TOMCAT_TLS3_CIPHERS} = "-SSL3_FORTEZZA_DMS_WITH_NULL_SHA,-SSL3_FORTEZZA_DMS_WITH_RC4_128_SHA," + . "+SSL3_RSA_WITH_RC4_128_SHA,-SSL3_RSA_EXPORT_WITH_RC4_40_MD5," + . "+SSL3_RSA_WITH_3DES_EDE_CBC_SHA,+SSL3_RSA_WITH_DES_CBC_SHA," + . "-SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5,-SSL3_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA," + . "-SSL_RSA_FIPS_WITH_DES_CBC_SHA,+SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA," + . "-SSL3_RSA_WITH_NULL_MD5,-TLS_RSA_EXPORT1024_WITH_RC4_56_SHA," + . "-TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,+TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; + $slot_hash{$TOMCAT_INSTANCE_COMMON_LIB} = "$tomcat_instance_common_lib_path/*.jar"; + if (!$redirected_logs_path) { + $slot_hash{$TOMCAT_LOG_DIR} = $logs_instance_path; + } + else { + $slot_hash{$TOMCAT_LOG_DIR} = $redirected_logs_path; + } + + } + + ## Process templates (instance independent) + # + # NOTE: The values substituted may differ across subsystems. + # + + # process "CS.cfg" template + return 0 if !process_file_template("pki_cfg", + $pki_cfg_subsystem_file_path, + $pki_cfg_instance_file_path, + \%slot_hash); + return 0 if !set_file_props($pki_cfg_instance_file_path, + $default_file_permissions, $pki_user, $pki_group); + + if ($^O eq "linux") { + # process "config.desktop" template + return 0 if !process_file_template("setup_config", + $setup_config_subsystem_file_path, + $setup_config_instance_file_path, + \%slot_hash); + } + + + ## Process registry instance template + return 0 if !process_file_template("pki_registry_template", + $pki_registry_subsystem_file_path, + $pki_registry_instance_file_path, + \%slot_hash); + return 0 if !set_file_props($pki_registry_instance_file_path, + $default_file_permissions, $root_user, $root_group); + + ## Process templates (CA instances) + if ($subsystem_type eq $CA) { + # process ProfileSelect.template + return 0 if !process_file_template("profile_select_template", + $profile_select_template_subsystem_file_path, + $profile_select_template_instance_file_path, + \%slot_hash); + # process proxy.conf file + return 0 if !process_file_template("proxy_conf", + $proxy_conf_subsystem_file_path, + $proxy_conf_instance_file_path, + \%slot_hash); + } + + + ## Process templates (RA, TPS instances) + if ($subsystem_type eq $RA || $subsystem_type eq $TPS) { + + if ($subsystem_type eq $TPS) { + + # process "cgi" template + return 0 if !process_file_template("cgi_home", + $cgi_home_subsystem_file_path, + $cgi_home_instance_file_path, + \%slot_hash); + + return 0 if !process_file_template("cgi_demo", + $cgi_demo_subsystem_file_path, + $cgi_demo_instance_file_path, + \%slot_hash); + + return 0 if !process_file_template("cgi_so", + $cgi_so_subsystem_file_path, + $cgi_so_instance_file_path, + \%slot_hash); + + return 0 if !process_file_template("cgi_so_enroll", + $cgi_so_subsystem_enroll_file_path, + $cgi_so_instance_enroll_file_path, + \%slot_hash); + + # process each "*.cgi" file in subsystem "sow" directory + opendir(SUBSYSTEM_DIR, $cgi_sow_subsystem_file_path); + while (defined(my $entity = readdir(SUBSYSTEM_DIR))) { + if ($entity =~ m/.cgi$/) { + # build complete "sow" subystem ".cgi" file name + $cgi_sow_subsystem_cgi_file_path = "${cgi_sow_subsystem_file_path}/${entity}"; + # build complete "sow" instance ".cgi" file name + $cgi_sow_instance_cgi_file_path = "${cgi_sow_instance_file_path}/${entity}"; + # process complete "sow" instance ".cgi" file name + return 0 if !process_file_template("cgi_sow", + $cgi_sow_subsystem_cgi_file_path, + $cgi_sow_instance_cgi_file_path, + \%slot_hash); + } + } + closedir(SUBSYSTEM_DIR); + + # process "addAgents.ldif" template + return 0 if !process_file_template("addAgents_ldif", + $addAgents_ldif_subsystem_file_path, + $addAgents_ldif_instance_file_path, + \%slot_hash); + + # process "addIndexes.ldif" template + return 0 if !process_file_template("addIndexes_ldif", + $addIndexes_ldif_subsystem_file_path, + $addIndexes_ldif_instance_file_path, + \%slot_hash); + + # process "addTokens.ldif" template + return 0 if !process_file_template("addTokens_ldif", + $addTokens_ldif_subsystem_file_path, + $addTokens_ldif_instance_file_path, + \%slot_hash); + + # process "addVLVIndexes.ldif" template + return 0 if !process_file_template("addVLVIndexes_ldif", + $addVLVIndexes_ldif_subsystem_file_path, + $addVLVIndexes_ldif_instance_file_path, + \%slot_hash); + + # process "schemaMods.ldif" template + return 0 if !process_file_template("schemaMods_ldif", + $schemaMods_ldif_subsystem_file_path, + $schemaMods_ldif_instance_file_path, + \%slot_hash); + } + + + # process "httpd.conf" template + return 0 if !process_file_template("httpd_conf", + $httpd_conf_subsystem_file_path, + $httpd_conf_instance_file_path, + \%slot_hash); + return 0 if !set_file_props($httpd_conf_instance_file_path, + $default_file_permissions, $pki_user, $pki_group); + + + # process "nss.conf" template + return 0 if !process_file_template("nss_conf", + $nss_conf_subsystem_file_path, + $nss_conf_instance_file_path, + \%slot_hash); + return 0 if !set_file_props($nss_conf_instance_file_path, + $default_file_permissions, $pki_user, $pki_group); + + # process "perl.conf" template + return 0 if !process_file_template("perl_conf", + $perl_conf_subsystem_file_path, + $perl_conf_instance_file_path, + \%slot_hash); + + return 0 if !set_file_props($perl_conf_instance_file_path, + $default_file_permissions, $pki_user, $pki_group); + + + # process "nss_pcache" template + return 0 if !process_file_template("nss_pcache", + $nss_pcache_subsystem_file_path, + $nss_pcache_instance_file_path, + \%slot_hash); + + return 0 if !set_permissions($nss_pcache_instance_file_path, + $default_exe_permissions); + + # process "pki_apache_initscript" template + return 0 if !process_file_template("pki_apache_initscript", + $pki_apache_initscript_file_path, + $pki_instance_initscript_path, + \%slot_hash); + + return 0 if !set_permissions($pki_instance_initscript_path, + $default_exe_permissions); + + + } else { + ## Process templates (CA, KRA, OCSP, TKS instances) + # process "index.jsp" template + return 0 if !process_file_template("index_jsp", + $index_jsp_subsystem_file_path, + $index_jsp_instance_file_path, + \%slot_hash); + + # process "server.xml" template + return 0 if !process_file_template("server_xml", + $server_xml_subsystem_file_path, + $server_xml_instance_file_path, + \%slot_hash); + + # process "serverCertNick.conf" template + return 0 if !process_file_template("servercertnick_conf", + $servercertnick_conf_subsystem_file_path, + $servercertnick_conf_instance_file_path, + \%slot_hash); + + # process "tomcat6.conf" template + return 0 if !process_file_template("tomcat6_conf", + $tomcat6_conf_subsystem_file_path, + $tomcat6_conf_instance_file_path, + \%slot_hash); + + # process "velocity.properties" template + return 0 if !process_file_template("velocity_prop", + $velocity_prop_subsystem_file_path, + $velocity_prop_instance_file_path, + \%slot_hash); + + # process "web.xml" template + return 0 if !process_file_template("web_xml", + $web_xml_subsystem_file_path, + $web_xml_instance_file_path, + \%slot_hash); + + # process "catalina.properties" template + return 0 if !process_file_template("catalina_properties", + $catalina_properties_subsystem_file_path, + $catalina_properties_instance_file_path, + \%slot_hash); + } + + return 1; +} + + +# Return 1 if success, 0 if failure +sub process_pki_files_and_symlinks +{ + emit("Processing PKI files and symbolic links for '$pki_instance_path' ...\n"); + + ## Populate instances (instance independent) + + # create a filled in temporary "noise" + # file for this instance + my $noise = generate_random_string(1024); + + return 0 if !create_file($noise_instance_file_path, + $noise, + $default_file_permissions, $pki_user, $pki_group); + + # create a filled in empty "password.conf" + # password file for this instance + if ($subsystem_type eq $RA || $subsystem_type eq $TPS) { + return 0 if !create_file($password_conf_instance_file_path, + "${default_security_token}:${db_password}\n", + $default_file_permissions, $pki_user, $pki_group); + } else { + return 0 if !create_file($password_conf_instance_file_path, + "${default_security_token}=${db_password}\n", + $default_file_permissions, $pki_user, $pki_group); + } + + # create a filled in empty temporary "pfile" + # password file for this instance + return 0 if !create_file($pfile_instance_file_path, + "${db_password}\n", + $default_file_permissions, $pki_user, $pki_group); + + ## Populate instances (RA, TPS instances) + if ($subsystem_type eq $RA || $subsystem_type eq $TPS) { + # create an empty file called "pwcache.conf" for this + return 0 if !create_empty_file($pwcache_conf_instance_file_path, + $default_file_permissions, $pki_user, $pki_group); + + # create instance symlink to subsystem "perl" subdirectory + return 0 if !create_symlink($perl_instance_symlink_path, $perl_subsystem_path, + $pki_user, $pki_group); + + return 0 if !create_symlink($run_instance_symlink_path, + "${default_apache_pids_path}/${subsystem_type}", + $pki_user, $pki_group); + + } else { + ## Populate instances (CA, KRA, OCSP, TKS instances) + # create instance "webapps/$subsystem_type/WEB-INF/lib" subdirectory + + # Create symlink of pki_instance_name pointing to tomcat6 init script. + # This is our per instance init script, tomcat6 will use the basename + # to find our tomcat6 configuration file in /etc/sysconfig + return 0 if !create_symlink($pki_instance_initscript_path, $tomcat6_initscript_path, + $root_user, $root_group); + + return 0 if !create_directory($webinf_lib_instance_path, + $default_dir_permissions, $pki_user, $pki_group); + + # create instance symlink to "pki-certsrv.jar" + return 0 if !create_symlink($pki_certsrv_jar_symlink_path, $pki_certsrv_jar_file_path, + $pki_user, $pki_group); + + # create instance symlink to "pki-cms.jar" + return 0 if !create_symlink($pki_cms_jar_symlink_path, $pki_cms_jar_file_path, + $pki_user, $pki_group); + + # create instance symlink to "pki-cmsbundle.jar" + return 0 if !create_symlink($pki_cmsbundle_jar_symlink_path, $pki_cmsbundle_jar_file_path, + $pki_user, $pki_group); + + # create instance symlink to "pki-cmscore.jar" + return 0 if !create_symlink($pki_cmscore_jar_symlink_path, $pki_cmscore_jar_file_path, + $pki_user, $pki_group); + + # create instance symlink to "pki-cmsutil.jar" + return 0 if !create_symlink($pki_cmsutil_jar_symlink_path, $pki_cmsutil_jar_file_path, + $pki_user, $pki_group); + + # create symlink to either "apache-commons-collections.jar" or "jakarta-commons-collections.jar" + # needed by velocity + return 0 if !create_symlink($commons_collections_jar_symlink_path, + $commons_collections_jar_file_path, + $pki_user, $pki_group); + + # create symlink to either "apache-commons-lang.jar" or "jakarta-commons-lang.jar" + # needed by velocity + return 0 if !create_symlink($commons_lang_jar_symlink_path, + $commons_lang_jar_file_path, + $pki_user, $pki_group); + + # create symlink to "apache-commons-logging.jar or jakarta-commons-logging.jar" + # this is needed by tomcatjss + return 0 if !create_symlink($commons_logging_jar_symlink_path, + $commons_logging_jar_file_path, + $pki_user, $pki_group); + + # create symlink to "jss.jar" + return 0 if !create_symlink($jss_jar_symlink_path, $jss_jar_file_path, + $pki_user, $pki_group); + + # create symlink to "ldapjdk.jar" + return 0 if !create_symlink($ldapjdk_jar_symlink_path, $ldapjdk_jar_file_path, + $pki_user, $pki_group); + + # create instance symlink to "pki-nsutil.jar" + return 0 if !create_symlink($pki_nsutil_jar_symlink_path, $pki_nsutil_jar_file_path, + $pki_user, $pki_group); + + # create instance symlink to "osutil.jar" + return 0 if !create_symlink($osutil_jar_symlink_path, $osutil_jar_file_path, + $pki_user, $pki_group); + + # create instance symlink to "${subsystem_type}.jar" + return 0 if !create_symlink($pki_subsystem_jar_symlink_path, $pki_subsystem_jar_file_path, + $pki_user, $pki_group); + + # create instance symlink to "symkey.jar" + return 0 if !create_symlink($symkey_jar_symlink_path, $symkey_jar_file_path, + $pki_user, $pki_group); + + # create symlink to "tomcatjss.jar" + return 0 if !create_symlink($tomcatjss_jar_symlink_path, $tomcatjss_jar_file_path, + $pki_user, $pki_group); + + # create instance symlink to "velocity.jar" + return 0 if !create_symlink($velocity_jar_symlink_path, $velocity_jar_file_path, + $pki_user, $pki_group); + + # create instance symlink to "xerces.jar" + return 0 if !create_symlink($xerces_jar_symlink_path, $xerces_jar_file_path, + $pki_user, $pki_group); + + # create instance symlink to "xml_commons_apis.jar" + return 0 if !create_symlink($xml_commons_apis_jar_symlink_path, $xml_commons_apis_jar_file_path, + $pki_user, $pki_group); + + # create instance symlink to "xml_commons_resolver.jar" + return 0 if !create_symlink($xml_commons_resolver_jar_symlink_path, $xml_commons_resolver_jar_file_path, + $pki_user, $pki_group); + + } + + return 1; +} + + +# Return 1 if success, 0 if failure +sub process_pki_security_databases +{ + my $result = 0; + my $serial_number = 0; + my $validity_period = 12; + my $time_stamp = get_time_stamp(); + my $subject = "CN=$host,O=$time_stamp"; + my $issuer_name = "CN=$host,O=$time_stamp"; + my $nickname = "Server-Cert cert-$pki_instance_name"; + my $trustargs = "CTu,CTu,CTu"; + + emit("Processing PKI security databases for '$pki_instance_path' ...\n"); + + # now create and configure pki security databases, + # cert3.db, key3.db, secmod.db ... + if (!file_exists($default_certutil_command) && !$dry_run) { + emit("process_pki_security_databases(): $default_certutil_command does not exist!\n", "error"); + return $result; + + } + + if (!file_exists($noise_instance_file_path) && !$dry_run) { + emit("process_pki_security_databases(): Can't find temp noise file!\n", "error"); + return $result; + } + + if (!file_exists($pfile_instance_file_path) && !$dry_run) { + emit("process_pki_security_databases(): Can't find temp file with password!\n", "error"); + return $result; + } + + certutil_create_databases($alias_instance_path, + $pfile_instance_file_path); + + certutil_generate_self_signed_cert($alias_instance_path, + $default_security_token, + $serial_number, + $validity_period, + $subject, + $issuer_name, + $nickname, + $trustargs, + $noise_instance_file_path, + $pfile_instance_file_path); + + remove_file($noise_instance_file_path); + + remove_file($pfile_instance_file_path); + + set_owner_group_on_directory_contents($alias_instance_path, + $pki_user, $pki_group); + + return 1; +} + + +# Return 1 if success, 0 if failure +sub process_pki_security_modules +{ + my $result = 0; + + emit("Processing PKI security modules for '$pki_instance_path' ...\n"); + + if (!file_exists($default_modutil_command) && !$dry_run) { + emit("process_pki_security_modules(): $default_modutil_command must be installed on system!\n", "error"); + return $result; + } + + emit(" Attempting to add hardware security modules to system if applicable ...\n"); + + while (my ($key, $value) = each(%supported_sec_modules_hash)) { + if (!file_exists($value)) { + emit(" module name: $key lib: $value DOES NOT EXIST!\n"); + next; + } else { + modutil_add_token($alias_instance_path, $key, $value); + emit(" Added module name: $key lib: $value\n"); + } + } + + return 1; +} + +sub process_pki_selinux_setup +{ + my $setype = "pki_" . $subsystem_type; + my $setype_p = $setype . "_port_t"; + my $default_instance_name = "pki-" . $subsystem_type; + my $default_instance_root = "/var/lib"; + my $default_log_path = "/var/log/" . $default_instance_name; + my $default_conf_path = "/etc/" . $default_instance_name; + my $status = 0; + + my $conf_path; + my $log_path; + my $ftype; + my $java_component = 0; + my $semanage_cmds = ""; + my @restorecon_cmds; + + emit("configuring SELinux ...\n"); + + if (!$redirected_logs_path) { + $log_path = $logs_instance_path; + } + else { + $log_path =$redirected_logs_path; + } + + if (!$redirected_conf_path) { + $conf_path = $conf_instance_path; + } + else { + $conf_path =$redirected_conf_path; + } + + if ($subsystem_type eq $CA || + $subsystem_type eq $KRA || + $subsystem_type eq $OCSP || + $subsystem_type eq $TKS) { + $java_component =1; + } + + # set file contexts + if ($java_component) { + push (@restorecon_cmds, "$restorecon -F -R /usr/share/java/pki"); + } + push (@restorecon_cmds, "$restorecon -F -R /usr/share/pki"); + + # set file context for $pki_instance_root/$pki_instance_name + if (($pki_instance_name ne $default_instance_name) || ($pki_instance_root ne $default_instance_root)) { + add_selinux_file_context($setype . "_var_lib_t", + "\"${pki_instance_root}/${pki_instance_name}(/.*)?\"", + "a", \$semanage_cmds); + } + push(@restorecon_cmds, "$restorecon -F -R $pki_instance_root/$pki_instance_name"); + + + if ($java_component) { + # set file context for instance pid file + my $pidfile = $tomcat6_instance_pid_file_path; + if ($pki_instance_name ne $default_instance_name) { + add_selinux_file_context($setype . "_var_run_t", + $pidfile, "f", \$semanage_cmds); + } + if (-e $pidfile) { + push(@restorecon_cmds, "$restorecon -F $pidfile"); + } + + my $pidpath = $default_apache_pids_path; + if (-e $pidpath) { + push(@restorecon_cmds, "$restorecon -F -R $pidpath"); + } + } + + # set file context for $log_path + $log_path =~ s/\/+$//; + if (!$log_path) { + emit("Error: Cannot set selinux context $setype" . "_log_t for directory /"); + } else { + if ($log_path ne $default_log_path) { + add_selinux_file_context($setype . "_log_t", + "\"$log_path(/.*)?\"", "a", \$semanage_cmds); + } + push(@restorecon_cmds, "$restorecon -F -R $log_path"); + } + + # set file context for $conf_path + $conf_path =~ s/\/+$//; + if (!$conf_path) { + emit("Error: Cannot set selinux context $setype" . "_etc_rw_t for directory /"); + } else { + if ($conf_path ne $default_conf_path) { + add_selinux_file_context($setype . "_etc_rw_t", + "\"$conf_path(/.*)?\"", "a", \$semanage_cmds); + } + push(@restorecon_cmds, "$restorecon -F -R $conf_path"); + } + + if (! $java_component) { + push(@restorecon_cmds, "$restorecon -F -R /usr/sbin/httpd.worker"); + } + + # add ports + parse_selinux_ports(); + if ($secure_port != -1) { + add_selinux_port($setype_p, $secure_port, \$semanage_cmds); + } + if ($non_clientauth_secure_port != -1) { + add_selinux_port($setype_p, $non_clientauth_secure_port, \$semanage_cmds); + } + if ($unsecure_port != -1) { + add_selinux_port($setype_p, $unsecure_port, \$semanage_cmds); + } + if ($tomcat_server_port != -1) { + add_selinux_port($setype_p, $tomcat_server_port, \$semanage_cmds); + } + if ($agent_secure_port != -1) { + add_selinux_port($setype_p, $agent_secure_port, \$semanage_cmds); + } + if ($ee_secure_port != -1) { + add_selinux_port($setype_p, $ee_secure_port, \$semanage_cmds); + } + if ($ee_secure_client_auth_port != -1) { + add_selinux_port($setype_p, $ee_secure_client_auth_port, \$semanage_cmds); + } + if ($admin_secure_port != -1) { + add_selinux_port($setype_p, $admin_secure_port, \$semanage_cmds); + } + if ($ajp_port != -1) { + add_selinux_port($setype_p, $ajp_port, \$semanage_cmds); + } + + # now run the selinux commands in batch mode + if ($semanage_cmds ne "") { + emit("Running the semanage commands in batch mode\n", "debug"); + if (! $dry_run) { + if(! run_command("$semanage -S targeted -i - " . ' << _EOF' . "\n$semanage_cmds\n" . '_EOF' . "\n")) { + emit("Failed executing semanage batch command \n", "error"); + } + } + } else { + emit("Selinux contexts already set. No need to run semanage.\n", "debug"); + } + + #now run the restorecons + emit("Running restorecon commands\n", "debug"); + foreach my $cmd (@restorecon_cmds) { + emit("$cmd\n", "debug"); + if (! $dry_run) { + if (!run_command($cmd)) { + emit("Failed executing restorecon command; $cmd\n", "error"); + } + } + } + + return 1; +} + +# no args +# return 1 - success, or +# return 0 - failure +sub install_pki_instance +{ + emit("Installing PKI instance ...\n"); + + return 0 if !create_directory($pki_instance_path, + $default_dir_permissions, $pki_user, $pki_group); + + return 0 if !process_pki_directories(); + return 0 if !process_pki_templates(); + return 0 if !process_pki_files_and_symlinks(); + return 0 if !process_pki_security_databases(); + return 0 if !process_pki_security_modules(); + + if (($^O eq "linux") && (is_Fedora() || (is_RHEL() && (! is_RHEL4())))){ + return 0 if !process_pki_selinux_setup(); + } + + return 1; +} + + +############################################################## +# PKI Instance Removal Subroutines +############################################################## + + +# Return 1 if success, 0 if failure +sub cleanup +{ + my $result = 0; + + emit(sprintf("cleanup(%s)\n", join(", ", @_)), "debug"); + + emit("PKI instance creation Cleanup Utility cleaning up on error ...", "info"); + + $result = uninstall(\%installation_info); + + return $result; +} + +# Return 1 if success, 0 if failure +sub write_install_info +{ + if ($dry_run) { + return 1; + } else { + if (!defined($pki_instance_path)) { + return 0; + } + my $install_info_file_path = write_install_info_to_dir($pki_instance_path, + \%installation_info); + if (defined($install_info_file_path)) { + emit(sprintf("Installation manifest: %s", $install_info_file_path)); + return 1; + } else { + return 0; + } + } +} + +############################################################## +# Signal Handlers +############################################################## + +sub die_handler +{ + my ($msg) = @_; + + # If we abort write the installation manifest + # so cleanup can still be performed later. + write_install_info(); +} + +$SIG{'__DIE__'} = \&die_handler; + +############################################################## +# Main Program +############################################################## + +# no args +# no return value +sub main +{ + my $result = 0; + my $parse_result = 0; + my $command = ""; + + chdir("/tmp"); + + print(STDOUT "PKI instance creation Utility ...\n\n"); + + # On Linux/UNIX, insure that this script is being run as "root". + $result = check_for_root_UID(); + if (!$result) { + usage(); + exit 255; + } + + # Setup platform-dependent parameters + setup_platform_dependent_parameters(); + + $parse_result = parse_arguments(); + if (!$parse_result || $parse_result == -1) { + close_logfile(); + exit 255; + } + + exit 255 if !initialize_paths(); + + exit 255 if !initialize_pki_creation_values(); + + $result = install_pki_instance(); + if (!$result) { + print(STDOUT "\n"); + + my $install_description = get_install_description(); + emit(sprintf("The following was performed\n%s\n\n", $install_description)); + +ASK_AGAIN: + my $confirm = prompt("Error detected would you like to clean up ${pki_instance_path} (Y/N)? "); + + if ($confirm eq "Y" || $confirm eq "y") { + cleanup(); + } elsif ($confirm ne "N" && $confirm ne "n") { + goto ASK_AGAIN; + } + + close_logfile(); + + exit 255; + } + + print(STDOUT "\n"); + print(STDOUT "PKI instance creation completed ...\n\n"); + + # Write the installation manifest. + write_install_info(); + + my $install_description = get_install_description(); + emit(sprintf("The following was performed:\n%s\n", $install_description)); + + printf(STDOUT "Installation information recorded in %s.\n", get_logfile_path()); + + $pki_registry_initscript_command = "/sbin/service $pki_registry_initscript restart $pki_instance_name"; + + $command = "${pki_registry_initscript_command}"; + run_command($command); + + if ($dry_run) { + print STDOUT "dry run mode ENABLED, system was not modified\n"; + } else { + + # Notify user to check firewall settings . . . + print(STDOUT + "Before proceeding with the configuration, make sure \n" + . "the firewall settings of this machine permit proper \n" + . "access to this subsystem. \n\n"); + + # EXCEPTION: To enable a user to easily configure their PKI subsystem, + # this is the ONLY instance in which we print out the actual + # value of the the one-time random PIN, as well as store this + # message at the end of the initialization log. + if ($subsystem_type eq $CA || + $subsystem_type eq $KRA || + $subsystem_type eq $OCSP || + $subsystem_type eq $TKS) { + if ($admin_secure_port > 0) { + # Port Separation: CA, KRA, OCSP, TKS + print(STDOUT + "Please start the configuration by accessing:\n\n" + . "https://$host:$admin_secure_port/$subsystem_type/admin/" + . "console/config/login?pin=$random\n\n"); + emit("Configuration Wizard listening on\n" + . "https://$host:$admin_secure_port/$subsystem_type/admin/" + . "console/config/login?pin=$random\n", + "log"); + } else { + # Shared Ports: CA, KRA, OCSP, TKS + print(STDOUT + "Please start the configuration by accessing:\n\n" + . "https://$host:$secure_port/$subsystem_type/admin/" + . "console/config/login?pin=$random\n\n"); + emit("Configuration Wizard listening on\n" + . "https://$host:$secure_port/$subsystem_type/admin/" + . "console/config/login?pin=$random\n", + "log"); + } + } else { + # Port Separation: RA, TPS + print(STDOUT + "Please start the configuration by accessing:\n\n" + . "https://$host:$non_clientauth_secure_port/$subsystem_type/" + . "admin/console/config/login?pin=$random\n\n"); + emit("Configuration Wizard listening on\n" + . "https://$host:$non_clientauth_secure_port/$subsystem_type/" + . "admin/console/config/login?pin=$random\n", + "log"); + } + + print(STDOUT + "After configuration, the server can be operated by the command:\n\n" + . " $pki_registry_initscript_command\n\n"); + emit("After configuration, the server can be operated by the command:\n" + . "${pki_registry_initscript_command}\n", + "log"); + } + + close_logfile(); + + return; +} + + +############################################################## +# PKI Instance Creation +############################################################## + +main(); + +exit 0; + diff --git a/pki/base/setup/pkiremove b/pki/base/setup/pkiremove new file mode 100755 index 000000000..70bb031a9 --- /dev/null +++ b/pki/base/setup/pkiremove @@ -0,0 +1,649 @@ +#!/usr/bin/perl +# +# --- BEGIN COPYRIGHT BLOCK --- +# 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; version 2 of the License. +# +# 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., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2007-2010 Red Hat, Inc. +# All rights reserved. +# --- END COPYRIGHT BLOCK --- +# + +use strict; +use warnings; + +use Getopt::Long qw(GetOptions); + +############################################################## +# This script is used to remove an existing PKI instance. +# +# To execute: +# +# ./pkiremove -pki_instance_root= # Instance root +# # directory destination +# +# -pki_instance_name= # Unique PKI subsystem +# # instance name +# # (e. g. - pki-pki1) +# +# [-force] # Don't ask any +# # questions +# +############################################################## + + +############################################################## +# Execution Check +############################################################## + +# Check to insure that this script's original +# invocation directory has not been deleted! +my $cwd = `/bin/pwd`; +chomp $cwd; +if (!$cwd) { + emit("Cannot invoke '$0' from non-existent directory!\n", "error"); + exit 255; +} + +############################################################## +# Environment Variables +############################################################## + +# untaint called subroutines +if (($^O ne 'Windows_NT') && ($^O ne 'MSWin32')) { + $> = $<; # set effective user ID to real UID + $) = $(; # set effective group ID to real GID + $ENV{'PATH'} = '/bin:/usr/bin'; + $ENV{'ENV'} = '' if !defined($ENV{'ENV'}); +} + + +############################################################## +# Command-Line Variables +############################################################## + +my $ARGS = ($#ARGV + 1); + + +############################################################## +# Shared Common Perl Data and Subroutines +############################################################## + +use lib "/usr/share/pki/scripts"; +use pkicommon; + +# make -w happy by suppressing warnings of Global variables used only once +my $suppress = ""; +$suppress = $default_file_permissions; + +############################################################## +# Local Constants +############################################################## + +my $semanage = "/usr/sbin/semanage"; + +############################################################## +# Local Data Structures +############################################################## + + +############################################################## +# Local Variables +############################################################## + +my $pki_instance_root = undef; +my $pki_instance_name = undef; +my $force = 0; + +my $conf_file = undef; +my $pki_instance_path = undef; +my $subsystem_type = undef; + +# PKI init script variables +my $pki_registry_initscript = undef; +my $pki_registry_initscript_command = undef; + +# PKI registry variables +my $pki_registry_subsystem_path = undef; + +############################################################## +# Platform-Dependent Data Initialization +############################################################## + +if ($^O eq "linux") { +} else { + emit("Unsupported platform '$^O'!\n", "error"); + exit 255; +} + +############################################################## +# Local Data Initialization +############################################################## + +############################################################## +# PKI Instance Removal Subroutines +############################################################## + +# no args +# no return value +sub usage +{ + print STDOUT <<'EOF'; +Usage: pkiremove -pki_instance_root= # Instance root + # directory + # destination + -pki_instance_name= # Unique PKI + # subsystem + # instance name + # (e. g. - pki-pki1) + +[-force] # Don't ask any questions + +[-verbose] # Display detailed information. May be specified multiple times, + # each time increasing the verbosity level. + +[-dry_run] # Do not perform any actions. + # Just report what would have been done. + +Example: pkiremove -pki_instance_root=/var/lib -pki_instance_name=pki-ca + +IMPORTANT: Must be run as root! +EOF + return; +} + +sub update_domain +{ + my $sport; + my $ncsport; + my $sechost; + my $httpport; + my $seceeport; + my $secagentport; + my $secadminport; + my $adminsport; + my $agentsport; + my $secselect; + my $subsystemnick; + my $machinename; + my $subsytemnick; + my $url; + + get_cs_cfg($conf_file, {"service.machineName" => \$machinename, + "service.securityDomainPort" => \$sport, + "service.non_clientauth_securePort" => \$ncsport, + "securitydomain.host" => \$sechost, + "securitydomain.httpport" => \$httpport, + "securitydomain.httpseeport" => \$seceeport, + "securitydomain.httpsagentport" => \$secagentport, + "securitydomain.httpsadminport" => \$secadminport, + "securitydomain.select" => \$secselect, + "pkiremove.cert.subsystem.nickname" => \$subsystemnick, + "pkicreate.admin_secure_port" => \$adminsport, + "pkicreate.agent_secure_port" => \$agentsport}); + + + # NOTE: Don't check for the existence of $httpport, as this will + # be undefined for a Security Domain that has been migrated! + if ((!defined($sechost)) || + (!defined($seceeport)) || + (!defined($secagentport)) || + (!defined($secadminport))) { + print(STDOUT "No security domain defined.\nIf this is an unconfigured instance, then that is OK.\n" . + "Otherwise, manually delete the entry from the security domain master.\n"); + return; + } + + if ($secselect ne "new") { + # This is not a domain master, so we need to update the master + print(STDOUT "Contacting the security domain master to update the security domain\n"); + my $listval = $subsystem_type . "List"; + my $urlheader = "https://" . $sechost . ":" . $seceeport; + my $urlagentheader = "https://" . $sechost . ":" . $secagentport; + my $urladminheader = "https://" . $sechost . ":" . $secadminport; + my $updateURL = "/ca/agent/ca/updateDomainXML"; + my $loginURL = "/ca/admin/ca/securityDomainLogin"; + my $cookieURL = "/ca/admin/ca/getCookie"; + + # Login to security domain + use LWP; + my $browser= LWP::UserAgent->new; + + #create pk12 files for client cert authentication + my $intpw; + my $pwfile = $pki_instance_path . "/conf/password.conf"; + open(DAT, $pwfile) or die "Could not open password.conf file to generate pk12 files."; + my @pw_data=; + foreach my $line (@pw_data) { + chomp($line); + + if (($subsystem_type eq $CA) || + ($subsystem_type eq $KRA) || + ($subsystem_type eq $OCSP) || + ($subsystem_type eq $TKS)) { + (my $varname, my $valname) = split(/=/, $line); + if ($varname eq "internal") { $intpw = $valname; } + } else { # TPS, RA + (my $varname, my $valname) = split(/:/, $line); + if ($varname eq "internal") { $intpw = $valname; } + } + } + close($pwfile); + + my $tempfile = "/tmp/" . $$ . ".p12"; + my $dbpath = $pki_instance_path . "/alias"; + srand(time() ^($$ + ($$ <<15))) ; + my $p12pw = rand(); + + my $errs = `pk12util -d $dbpath -o $tempfile -n "$subsystemnick" -K $intpw -W $p12pw 2>&1`; + if ($? != 0) { + emit($errs, "error"); + die "Could not generate pk12 file for client authentication."; + } + + #update domainXML + + $url = $urlagentheader . $updateURL; + #$ENV{'HTTPS_DEBUG'} = 1; + $ENV{'HTTPS_PKCS12_FILE'} = $tempfile; + $ENV{'HTTPS_PKCS12_PASSWORD'} = $p12pw; + + my $response = $browser->post($url, + [ + 'name' => $pki_instance_name, + 'type' => $subsystem_type, + 'list' => $listval, + 'host' => $machinename, + 'sport' => $sport, + 'ncsport' => $ncsport, + 'adminsport' => $adminsport, + 'agentsport' => $agentsport, + 'operation' => 'remove' + ], +); + + ($response->is_success) or die ("$url error: " . $response->status_line); + unlink $tempfile; + } +} + +sub remove_fcontext +{ + my ($fcontext, $fname, $ftype, $cmd_ref) = @_; + emit(sprintf("remove_fcontext(%s)\n", join(", ", @_)), "debug"); + + my $tmp = `$semanage fcontext -l -C |grep $fcontext |grep $fname |wc -l`; + chomp $tmp; + if ($tmp eq "0" ) { + emit("File context $fcontext for $fname defined in policy, not deleted", "debug"); + return 0; + } + + if ($ftype eq "f") { + $$cmd_ref .= "fcontext -d -t $fcontext -f -- $fname\n"; + } else { + $$cmd_ref .= "fcontext -d -t $fcontext $fname\n"; + } +} + +sub get_selinux_fcontexts +{ + my ($cmd_ref) = @_; + my $setype = "pki_" . $subsystem_type; + my $default_instance_name = "pki-" . $subsystem_type; + my $default_instance_root = "/var/lib"; + my $default_log_path = "/var/log/" . $default_instance_name; + my $default_conf_path = "/etc/" . $default_instance_name; + + my $log_path = "$pki_instance_path/logs"; + my $conf_path = "$pki_instance_path/conf"; + my $ftype; + my $java_component = 0; + + if (($subsystem_type eq $CA) || + ($subsystem_type eq $KRA) || + ($subsystem_type eq $OCSP) || + ($subsystem_type eq $TKS)) { + $java_component=1; + } + + if (-l $log_path) { + $log_path = readlink $log_path; + }; + + if (-l $conf_path) { + $conf_path = readlink $conf_path; + }; + + # For backwards compatibility, support removal of instances + # which use the legacy start/stop implementation + if (entity_exists("$default_initscripts_path/$pki_instance_name")) { + # remove context for "$default_initscripts_path/$pki_instance_name" + if ($pki_instance_name ne $default_instance_name) { + remove_fcontext($setype . "_script_exec_t", + "/etc/rc\\.d/init\\.d/$pki_instance_name", "f", $cmd_ref); + } + } + + # remove context for $pki_instance_root/$pki_instance_name + if (($pki_instance_name ne $default_instance_name) || ($pki_instance_root ne $default_instance_root)) { + remove_fcontext($setype . "_var_lib_t", + "\"$pki_instance_root/$pki_instance_name(/.*)?\"", "a", $cmd_ref); + } + + # remove context for /var/run/$pki_instance_name.pid + if (($java_component) && ($pki_instance_name ne $default_instance_name)) { + remove_fcontext($setype . "_var_run_t", + "/var/run/$pki_instance_name" . '.pid', "f", $cmd_ref); + } + + # remove context for $log_path + if ($log_path ne $default_log_path) { + remove_fcontext($setype . "_log_t", + "\"$log_path(/.*)?\"", "a", $cmd_ref); + } + + # remove context for $conf_path + if ($conf_path ne $default_conf_path) { + remove_fcontext($setype . "_etc_rw_t", + "\"$conf_path(/.*)?\"", "a", $cmd_ref); + } + +} + + +sub get_selinux_ports +{ + my ($cmd_ref) = @_; + my $status; + my $semanage = "/usr/sbin/semanage"; + my $secure_port; + my $non_clientauth_secure_port; + my $unsecure_port; + my @ports = (); + + get_cs_cfg($conf_file, {"service.securePort" => \$secure_port, + "service.non_clientauth_securePort" => \$non_clientauth_secure_port, + "service.unsecurePort" => \$unsecure_port}); + + if (($subsystem_type eq $CA) || + ($subsystem_type eq $KRA) || + ($subsystem_type eq $OCSP) || + ($subsystem_type eq $TKS)) { + use XML::LibXML; + my $parser = XML::LibXML->new(); + my $config = $parser->parse_file($pki_instance_path . "/conf/server.xml") + or die "Could not read XML from server.xml to determine ports."; + + my $root = $config->getDocumentElement; + + my $i = 0; + foreach my $port ($root->findnodes('//@port')) { + $ports[$i] = $port->getValue(); + $i++; + } + } else { # TPS, RA + my $i =0; + if (defined $secure_port) { + $ports[$i] = $secure_port; + $i++; + } + if (defined $non_clientauth_secure_port) { + $ports[$i] = $non_clientauth_secure_port; + $i++; + } + if (defined $unsecure_port) { + $ports[$i] = $unsecure_port; + $i++; + } + } + + print(STDOUT "\n"); + foreach my $port (@ports) { + my $setype = "pki_" . $subsystem_type . "_port_t"; + my $tmp = `$semanage port -l -C |grep $setype |grep $port | wc -l`; + chomp $tmp; + if ($tmp eq "0") { + emit("Port context $setype for $port defined in policy, not deleting", "debug"); + } else { + $$cmd_ref .= "port -d -t $setype -ptcp $port\n"; + } + } +} + + +# Return 1 if success, 0 if failure +sub remove_instance +{ + my ($result, $confirm, $install_info); + $confirm = "Y"; + $result = 1; + + print(STDOUT "PKI instance Deletion Utility cleaning up instance ...\n\n"); + +ASK_AGAIN: + if (!$force) { + $confirm = prompt("You have elected to remove the instance " + . "installed in $pki_instance_path.\n" + . "Are you sure (Y/N)? "); + } + + if ($confirm eq "N" || $confirm eq "n") { + return 1; + } elsif ($confirm ne "Y" && $confirm ne "y") { + goto ASK_AGAIN; + } + + $install_info = read_install_info_from_dir($pki_instance_path); + if (!defined($install_info)) { + emit("Can't remove instance, installation manifest does not exist!", "error"); + return $result; + } + + eval { update_domain(); } if !$dry_run; # FIXME so update_domain shows what it would do + warn "Error updating security domain: " . $@ if $@; + + if (($^O eq "linux") && (is_Fedora() || (is_RHEL() && (! is_RHEL4())))) { + my $semanage_cmds = ""; + + eval { get_selinux_ports(\$semanage_cmds); }; + warn "Error getting selinux ports: " . $@ if $@; + + eval { get_selinux_fcontexts(\$semanage_cmds); }; + warn "Error getting selinux file contexts: " . $@ if $@; + + print STDOUT "Removing selinux contexts\n"; + if ($semanage_cmds ne "") { + emit("Executing selinux commands in batch mode.\n", "debug"); + if (! $dry_run) { + if (! run_command("$semanage -S targeted -i - " . '<< _EOF' . "\n$semanage_cmds\n" . '_EOF' . "\n")) { + emit("Error executing selinux batch commands\n", "error"); + } + } + } else { + emit("No selinux contexts need to be removed. No need to run semanage. \n"); + } + } + + # De-register this instance with "chkconfig" + if ($^O eq "linux") { + if (entity_exists("$default_initscripts_path/$pki_instance_name")) { + # De-register this instance with '/sbin/chkconfig' + print(STDOUT "Removing '$pki_instance_name' from chkconfig.\n"); + deregister_pki_instance_with_chkconfig($pki_instance_name); + } + } + + $pki_registry_initscript = get_registry_initscript_name($subsystem_type); + + # Shutdown this instance + if ($^O eq "linux") { + if (entity_exists("$default_initscripts_path/$pki_instance_name")) { + $pki_registry_initscript_command = "/sbin/service $pki_instance_name stop"; + } else { + $pki_registry_initscript_command = "/sbin/service $pki_registry_initscript stop $pki_instance_name"; + } + } else { + emit("Unsupported platform '$^O'!\n", "error"); + exit 255; + } + run_command($pki_registry_initscript_command); + + print(STDOUT "\n"); + + # Remove all installed files and directories. + $result = 0 if !uninstall($install_info); + + print(STDOUT "\n"); + + return $result; +} + + +############################################################## +# Main Program +############################################################## + +# no args +# return 1 - success, or +# return 0 - failure +sub main +{ + chdir("/tmp"); + + my $result = 0; + + print(STDOUT "PKI instance Deletion Utility ...\n\n"); + + # On Linux/UNIX, insure that this script is being run as "root". + $result = check_for_root_UID(); + if (!$result) { + usage(); + exit 255; + } + + # Check for a valid number of command-line arguments. + if ($ARGS < 2) { + emit("$0: Insufficient arguments!", "error"); + usage(); + exit 255; + } + + # Parse command-line arguments. + $result = GetOptions("pki_instance_root=s" => \$pki_instance_root, + "pki_instance_name=s" => \$pki_instance_name, + "verbose+" => \$verbose, + "dry_run" => \$dry_run, + "force" => \$force); + + # Always disallow root to be the pki_instance_root. + if ($pki_instance_root eq "/") { + emit("$0: Don't even think about making root " + . "the pki_instance_root!", "error"); + usage(); + exit 255; + } + + $pki_instance_root = normalize_path($pki_instance_root); + + # Check for valid content of command-line arguments. + if (!$pki_instance_root) { + emit("$0: Must have value for -pki_instance_root!", "error"); + usage(); + exit 255; + } + + if (!$pki_instance_name) { + emit("$0: The instance ID of the PKI instance " + . "to be removed is required!", "error"); + usage(); + exit 255; + } + + $pki_instance_path = "${pki_instance_root}/${pki_instance_name}"; + + if (!directory_exists($pki_instance_path)) { + emit("$0: Target directory $pki_instance_path " + . "is not a legal directory.", "error"); + usage(); + exit 255; + } + + # Capture uninstall information in a log file, always overwrite this file. + # When removing an instance it's never a fatal error if the logfile + # cannot be created. + my $logfile = "/var/log/${pki_instance_name}-uninstall.log"; + open_logfile($logfile, $default_file_permissions); + + emit("Capturing installation information in $logfile.\n"); + + if ($verbose) { + emit(" verbose mode ENABLED (level=$verbose)\n"); + } + + if ($dry_run) { + emit(" dry run mode ENABLED, system will not be modified, log to $logfile\n"); + print STDOUT "dry run mode ENABLED, system will not be modified\n"; + } + + emit(" pki_instance_root $pki_instance_root\n"); + emit(" pki_instance_name $pki_instance_name\n"); + emit(" pki_instance_path $pki_instance_path\n"); + + $conf_file = $pki_instance_path . "/conf/CS.cfg"; + $subsystem_type = get_cs_cfg($conf_file, "cs.type"); + if (!defined($subsystem_type)) { + emit("Could not determine the subsystem type from the file \"$conf_file\"\n", "error"); + exit 1; + } + $subsystem_type = lc($subsystem_type); + + # Remove the specified instance + $result = remove_instance(); + if ($result != 1) { + exit 255; + } + + # Establish PKI subsystem-level registry + $pki_registry_subsystem_path = "$pki_registry_path/$subsystem_type"; + + # If empty, remove the PKI subsystem-level registry + if (directory_exists($pki_registry_subsystem_path)) { + if (is_directory_empty($pki_registry_subsystem_path)) { + remove_directory($pki_registry_subsystem_path); + } + } + + # If empty, remove the PKI-level registry + if (directory_exists($pki_registry_path)) { + if (is_directory_empty($pki_registry_path)) { + remove_directory($pki_registry_path); + } + } + + if ($dry_run) { + print STDOUT "dry run mode ENABLED, system was not modified\n"; + } + + return $result; +} + + +############################################################## +# PKI Instance Removal +############################################################## + +main(); + +exit 0; + -- cgit