summaryrefslogtreecommitdiffstats
path: root/pki/base/setup/pkicommon
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/setup/pkicommon')
-rwxr-xr-xpki/base/setup/pkicommon2150
1 files changed, 2150 insertions, 0 deletions
diff --git a/pki/base/setup/pkicommon b/pki/base/setup/pkicommon
new file mode 100755
index 000000000..e5913c12b
--- /dev/null
+++ b/pki/base/setup/pkicommon
@@ -0,0 +1,2150 @@
+#!/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 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+
+##############################################################
+# 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" eq "" ) {
+ print( STDERR "Cannot invoke '$0' from non-existent directory!\n" );
+ print( STDOUT "\n" );
+ 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 $ENV{ 'ENV' } ne '';
+}
+
+
+##############################################################
+# Perl Modules
+##############################################################
+
+# "File/Copy.pm", "FileHandle.pm", "Getopt/Long.pm",
+# "Socket.pm", and "Sys/Long.pm" are all part of the
+# standard Perl library and should therefore always be
+# available
+use File::Copy;
+use FileHandle;
+use Getopt::Long;
+use Socket;
+use Sys::Hostname;
+
+
+##############################################################
+# Shared Default Values
+##############################################################
+
+$default_hardware_platform = "";
+$default_system_binaries = "";
+$default_system_libraries = "";
+$default_system_user_binaries = "";
+$default_system_user_libraries = "";
+$default_system_jni_java_path = "";
+$default_security_libraries = "";
+$default_certutil_command = "";
+$default_ldapmodify_command = "";
+$default_modutil_command = "";
+
+# Compute "hardware platform" of Operating System
+$default_hardware_platform = `pkiarch`;
+$default_hardware_platform =~ s/\s+$//g;
+chomp( $default_hardware_platform );
+if( $^O eq "linux" ) {
+ 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_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_system_jni_java_path = "/usr/lib/java";
+ } else {
+ print( STDERR
+ "ERROR: Unsupported '$^O' hardware platform "
+ . "'$default_hardware_platform'!\n" );
+ print( "\n" );
+ exit 255;
+ }
+} elsif( $^O eq "solaris" ) {
+ if( $default_hardware_platform eq "sparc" ) {
+ # 32-bit Solaris
+ $default_system_binaries = "/bin";
+ $default_system_libraries = "/lib";
+ $default_system_user_binaries = "/usr/bin";
+ $default_system_user_libraries = "/usr/lib";
+ $default_system_jni_java_path = "/usr/lib/java";
+ } elsif( $default_hardware_platform eq "sparcv9" ) {
+ # 64-bit Solaris
+ $default_system_binaries = "/bin";
+ $default_system_libraries = "/lib/sparcv9";
+ $default_system_user_binaries = "/usr/bin";
+ $default_system_user_libraries = "/usr/lib/sparcv9";
+ $default_system_jni_java_path = "/usr/lib/java";
+ } else {
+ print( STDERR
+ "ERROR: Unsupported '$^O' hardware platform "
+ . "'$default_hardware_platform'!\n" );
+ print( "\n" );
+ exit 255;
+ }
+} else {
+ print( STDERR
+ "ERROR: Unsupported platform '$^O'!\n" );
+ print( "\n" );
+ exit 255;
+}
+
+
+$default_security_libraries = "$default_system_user_libraries/dirsec";
+
+$default_certutil_command = "$default_system_user_binaries/certutil";
+$default_ldapmodify_command = "$default_system_user_libraries/"
+ . "mozldap/ldapmodify";
+$default_modutil_command = "$default_system_user_binaries/modutil";
+
+
+##############################################################
+# Global Constants
+##############################################################
+
+$ROOTUID = 0;
+
+$MAX_WELL_KNOWN_PORT = 511; # well-known ports = 0 through 511
+$MAX_RESERVED_PORT = 1023; # reserved ports = 512 through 1023
+$MAX_REGISTERED_PORT = 49151; # registered ports = 1024 through 49151
+$MAX_DYNAMIC_PORT = 65535; # dynamic/private ports = 49152 through 65535
+
+$FILE_PREFIX = "file://";
+$FTP_PREFIX = "ftp://";
+$HTTP_PREFIX = "http://";
+$HTTPS_PREFIX = "https://";
+$LDAP_PREFIX = "ldap://";
+$LDAPS_PREFIX = "ldaps://";
+
+
+##############################################################
+# Global Variables
+##############################################################
+
+# Platform-dependent parameters
+$lib_prefix = "";
+$obj_ext = "";
+$path_sep = "";
+$tmp_dir = "";
+
+# Retrieve hostname using Sys::Hostname
+$hostname = hostname;
+
+# "logging" parameters
+$logfile = "";
+
+# Whether or not to do verbose mode
+$verbose = 0;
+
+
+##############################################################
+# Local Variables
+##############################################################
+
+# "identity" parameters
+my $fqdn = "";
+
+# "time" parameters
+my $sec = 0;
+my $min = 0;
+my $hour = 0;
+my $mday = 0;
+my $mon = 0;
+my $year = 0;
+my $wday = 0;
+my $yday = 0;
+my $isdst = 0;
+
+# "logging" parameters
+my $logfd = new FileHandle;
+
+
+##############################################################
+# 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($line = <$releasefd>) ) {
+ if($line =~ /4/) {
+ 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;
+}
+
+
+# arg0 Library Path
+# no return value
+sub set_library_path
+{
+ my( $path ) = @_;
+
+ 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 ) ) {
+ print( STDERR
+ "ERROR: This script must be run as root!\n" );
+ print( STDOUT "\n" );
+ $result = 0;
+ } else {
+ # Success -- running script as root
+ $result = 1;
+ }
+ } else {
+ print( STDERR
+ "ERROR: Root UID makes no sense on Windows machines!\n" );
+ print( STDOUT "\n" );
+ $result = 0;
+ }
+
+ return $result;
+}
+
+
+# arg0 username
+# return 1 - exists, or
+# return 0 - DOES NOT exist
+sub user_exists
+{
+ my( $username ) = $_[0];
+
+ my $result = 0;
+
+ my $uid = getpwnam( $username );
+
+ if( $uid ne "" ) {
+ $result = 1;
+ }
+
+ return $result;
+}
+
+
+# arg0 groupname
+# return 1 - exists, or
+# return 0 - DOES NOT exist
+sub group_exists
+{
+ my( $groupname ) = $_[0];
+
+ my $result = 0;
+
+ my $gid = getgrnam( $groupname );
+
+ if( $gid ne "" ) {
+ $result = 1;
+ }
+
+ return $result;
+}
+
+
+# arg0 username
+# arg1 groupname
+# return 1 - is a member, or
+# return 0 - is NOT a member
+sub user_is_a_member_of_group
+{
+ my( $username ) = $_[0];
+ my( $groupname ) = $_[1];
+
+ my $result = 0;
+
+ if( !user_exists( $username ) ) {
+ return $result;
+ }
+
+ if( !group_exists( $groupname ) ) {
+ return $result;
+ }
+
+ my( $name, $passwd, $gid, $members ) = getgrnam( $groupname );
+
+ my $groupuser = $members =~ m/$username/;
+
+ if( $groupuser >= 1 ) {
+ $result = 1;
+ }
+
+ return $result;
+}
+
+
+# arg0 username
+# return UID, or
+# return (-1) - user is not in password file
+sub get_UID_from_username
+{
+ my( $user ) = @_;
+
+ my $my_username;
+ my $my_passwd;
+ my $my_uid;
+
+ ( $my_username, $my_passwd, $my_uid ) = getpwnam( $user );
+
+ if( $my_username ne "" ) {
+ # return UID (0 implies root user)
+ return $my_uid;
+ } else {
+ # username '$user' is NOT in the password file
+ return ( -1 );
+ }
+}
+
+
+# arg0 hostname, or
+# arg0 IP address
+# return fully-qualified domain name (FQDN)
+sub get_FQDN
+{
+ if( $_[0] !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ ) {
+ # Retrieve FQDN via a "mnemonic" hostname
+ ( $fqdn ) = gethostbyname( $_[0] );
+ } else {
+ # Retrieve FQDN via a "4-tuple" IP address
+ $fqdn = gethostbyaddr( pack( 'C4', $1, $2, $3, $4 ), 2 );
+ }
+
+ return( $fqdn );
+}
+
+
+##############################################################
+# Generic "availability" Subroutines
+##############################################################
+
+# arg0 URL prefix
+# 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;
+}
+
+
+# arg0 username
+# arg1 port
+# 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 ) {
+ print( "\n" );
+ print( STDERR
+ "User '$user' is NOT in the password file!\n" );
+ print( "\n" );
+ return 0;
+ }
+
+ # insure that well-known ports cannot be used by a non-root user
+ if( ( $port <= $MAX_WELL_KNOWN_PORT ) && ( $uid != $ROOTUID ) ) {
+ print( "\n" );
+ print( STDERR
+ "ERROR: User '$user' is not allowed to bind to well-known "
+ . "port $port!\n" );
+ print( "\n" );
+ return 0;
+ }
+
+ # insure that reserved ports cannot be used by a non-root user
+ if( ( $port <= $MAX_RESERVED_PORT ) && ( $uid != $ROOTUID ) ) {
+ print( "\n" );
+ print( STDERR
+ "ERROR: User '$user' is not allowed to bind to reserved "
+ . "port $port!\n" );
+ print( "\n" );
+ return 0;
+ }
+
+ # insure that the user has not specified a port greater than
+ # the number of dynamic/private ports
+ if( $port > $MAX_DYNAMIC_PORT ) {
+ print( "\n" );
+ print( STDERR
+ "ERROR: User '$user' is not allowed to bind to a "
+ . "port greater than $MAX_DYNAMIC_PORT!\n" );
+ print( "\n" );
+ 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 ) {
+ print( "\n" );
+ print( STDERR
+ "WARNING: User '$user' is binding to port $port; use of "
+ . "a dynamic/private port is discouraged!\n" );
+ print( "\n" );
+ }
+ }
+
+ # 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" ) {
+ print( "\n" );
+ print( STDERR
+ "ERROR: Unable to bind to local port $port : $status\n" );
+ print( "\n" );
+ $rv = 0;
+ } else {
+ print( "\n" );
+ print( STDERR
+ "ERROR: Unable to bind to local port $port : $status\n" );
+ print( "\n" );
+ $rv = 0;
+ }
+
+ # close local server socket
+ close( SERVER );
+
+ # return result
+ return $rv;
+}
+
+
+# arg0 HTTP or LDAP prefix
+# arg1 host
+# arg2 port
+# 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 ) {
+ print( "\n" );
+ print( STDERR
+ "ERROR: Specified unknown url prefix\n"
+ . " '$prefix'!\n" );
+ print( "\n" );
+ 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" ) {
+ print( "\n" );
+ print( STDERR
+ "ERROR: Unable to contact the Server at\n"
+ . " '$url' :\n"
+ . " $status\n" );
+ print( "\n" );
+ 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 {
+ print( "\n" );
+ print( STDERR
+ "WARNING: Unable to contact the Server at\n"
+ . " '$url' :\n"
+ . " $status\n" );
+ print( "\n" );
+ }
+
+ # close local client socket
+ close( CLIENT );
+
+ # return result
+ return $rv;
+}
+
+
+##############################################################
+# Generic "time" Subroutines
+##############################################################
+
+# no args
+# return time stamp
+sub get_time_stamp()
+{
+ my $stamp = sprintf "%4d-%02d-%02d %02d:%02d:%02d",
+ $year+1900, $mon+1, $mday, $hour, $min, $sec;
+
+ return $stamp;
+}
+
+
+##############################################################
+# Generic "random" Subroutines
+##############################################################
+
+# arg0 low watermark value
+# arg1 high watermark value
+# return random number
+sub generate_random
+{
+ my $low = $_[0];
+ my $high = $_[1];
+
+ my $number = 0;
+
+ if( $low >= $high || $low < 0 || $high < 0 ) {
+ return -1;
+ }
+
+ $number = int( rand( $high -$low +1 ) ) + $low;
+
+ return $number;
+}
+
+
+# arg0 length of string
+# return random string
+sub generate_random_string()
+{
+ my $length_of_randomstring=shift; # the length of the string
+
+ 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
+##############################################################
+
+# arg0 password
+# return 1 - success
+# return 0 - failure; report an error
+sub password_quality_checker
+{
+ my( $password ) = @_;
+
+ # 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
+##############################################################
+
+# arg0 tokendb hostname - LDAP server name or IP address (default: localhost)
+# arg1 tokendb port - LDAP server TCP port number (default: 389)
+# arg2 tokendb password - bind passwd (for simple authentication)
+# arg3 tokendb 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();
+
+ set_library_path( $default_security_libraries . $path_sep
+ . $default_system_user_libraries . $path_sep
+ . $default_system_libraries . $path_sep
+ . $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;
+}
+
+
+# arg0 tokendb hostname - LDAP server name or IP address (default: localhost)
+# arg1 tokendb port - LDAP server TCP port number (default: 389)
+# arg2 tokendb password - bind passwd (for simple authentication)
+# arg3 tokendb 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();
+
+ set_library_path( $default_security_libraries . $path_sep
+ . $default_system_user_libraries . $path_sep
+ . $default_system_libraries . $path_sep
+ . $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
+##############################################################
+
+# arg0 instance path - Security databases directory (default is ~/.netscape)
+# arg1 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();
+
+ set_library_path( $default_security_libraries . $path_sep
+ . $default_system_user_libraries . $path_sep
+ . $default_system_libraries . $path_sep
+ . $original_library_path );
+
+ if( "$pwdfile" eq "" ) {
+ $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;
+}
+
+
+# arg0 instance path - Security databases directory (default is ~/.netscape)
+# arg1 token - Name of token in which to look for cert (default is internal,
+# use "all" to look for cert on all tokens)
+# arg2 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();
+
+ set_library_path( $default_security_libraries . $path_sep
+ . $default_system_user_libraries . $path_sep
+ . $default_system_libraries . $path_sep
+ . $original_library_path );
+
+ $command = "$default_certutil_command "
+ . "-D "
+ . "-d $instance_path "
+ . "-h '$token' "
+ . "-n '$nickname'";
+
+ system( "$command" );
+
+ set_library_path( $original_library_path );
+
+ return;
+}
+
+
+# arg0 instance path - Security databases directory (default is ~/.netscape)
+# arg1 token - Name of token in which to generate key (default is internal)
+# arg2 subject - Specify the subject name (using RFC1485)
+# arg3 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();
+
+ set_library_path( $default_security_libraries . $path_sep
+ . $default_system_user_libraries . $path_sep
+ . $default_system_libraries . $path_sep
+ . $original_library_path );
+
+ if( "$pwdfile" eq "" ) {
+ $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;
+}
+
+
+# arg0 instance path - Security databases directory (default is ~/.netscape)
+# arg1 token - Name of token in which to store the certificate
+# (default is internal)
+# arg2 serial number - Cert serial number
+# arg3 validity period - Months valid (default is 3)
+# arg4 subject - Specify the subject name (using RFC1485)
+# arg5 issuer name - The nickname of the issuer cert
+# arg6 nickname - Specify the nickname of the server certificate
+# arg7 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
+# arg8 noise file - Specify the noise file to be used
+# (to introduce randomness during key generation)
+# arg9 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();
+
+ set_library_path( $default_security_libraries . $path_sep
+ . $default_system_user_libraries . $path_sep
+ . $default_system_libraries . $path_sep
+ . $original_library_path );
+
+ if( "$pwdfile" eq "" ) {
+ $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;
+}
+
+
+# arg0 instance path - Security databases directory (default is ~/.netscape)
+# arg1 token - Name of token in which to store the certificate
+# (default is internal)
+# arg2 nickname - Specify the nickname of the server certificate
+# arg3 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')
+# arg4 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();
+
+ set_library_path( $default_security_libraries . $path_sep
+ . $default_system_user_libraries . $path_sep
+ . $default_system_libraries . $path_sep
+ . $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;
+}
+
+
+# arg0 instance path - Security databases directory (default is ~/.netscape)
+# arg1 token - Name of token in which to look for cert (default is internal,
+# use "all" to look for cert on all tokens)
+# arg2 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();
+
+ set_library_path( $default_security_libraries . $path_sep
+ . $default_system_user_libraries . $path_sep
+ . $default_system_libraries . $path_sep
+ . $original_library_path );
+
+ if( $token ne "" ) {
+ # 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
+# arg0 instance path - Security databases directory (default is ~/.netscape)
+# arg1 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();
+
+ set_library_path( $default_security_libraries . $path_sep
+ . $default_system_user_libraries . $path_sep
+ . $default_system_libraries . $path_sep
+ . $original_library_path );
+
+ $command = "$default_certutil_command "
+ . "-L "
+ . "-d $instance_path "
+ . "-h '$token'";
+
+ system( "$command" );
+
+ set_library_path( $original_library_path );
+
+ return;
+}
+
+
+# arg0 instance path - Security databases directory (default is ~/.netscape)
+# arg1 token - Add the named token to the module database
+# arg2 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();
+
+ set_library_path( $default_security_libraries . $path_sep
+ . $default_system_user_libraries . $path_sep
+ . $default_system_libraries . $path_sep
+ . $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
+##############################################################
+
+# arg0 logfile name
+# no return value
+sub open_logfile
+{
+ my $logfile_name = $_[0];
+
+ $logfd->open( ">$logfile_name" ) or
+ die "Could not open $logfile_name\n";
+
+ return;
+}
+
+
+# arg0 logfile name
+# arg1 message
+# no return value
+sub print_to_logfile
+{
+ my $logfile_name = $_[0];
+ my $message = $_[1];
+
+ if( "$logfile_name" ne "" ) {
+ $logfd->print( "$message" );
+ }
+
+ return;
+}
+
+
+# arg0 logfile name
+# no return value
+sub close_logfile
+{
+ my $logfile_name = $_[0];
+
+ if( "$logfile_name" ne "" ) {
+ $logfd->close();
+ }
+
+ return;
+}
+
+
+##############################################################
+# Generic "response" Subroutines
+##############################################################
+
+# arg0 question
+# return answer
+sub prompt
+{
+ my $promptStr = $_[0];
+
+ my $answer = "";
+
+ print( STDOUT "$promptStr " );
+
+ $| = 1;
+ $answer = <STDIN>;
+
+ chomp $answer;
+
+ print( STDOUT "\n" );
+
+ return $answer;
+}
+
+
+##############################################################
+# Generic "reply" Subroutines
+##############################################################
+
+# arg0 file handle
+# no return value
+sub printFile
+{
+ my $fileHandle = $_[0];
+
+ while( <$fileHandle> ) {
+ my $line = $_;
+ chomp( $line );
+ print( STDOUT "$line\n" );
+ }
+
+ return;
+}
+
+
+# arg0 message
+# arg1 message type
+# no return value
+sub emit
+{
+ my $string = $_[0];
+ my $type = $_[1];
+
+ my $force_emit = 0;
+ my $log_entry = "";
+
+ if( $type eq "error" || $type eq "info" ) {
+ $force_emit = 1;
+ }
+
+ if( $type eq "" ) {
+ $type = "debug";
+ }
+
+ if( $string eq "" ) {
+ return;
+ }
+
+ ( $sec, $min, $hour, $mday,
+ $mon, $year, $wday, $yday, $isdst ) = localtime( time );
+
+ my $stamp = get_time_stamp();
+
+ if( $verbose || $force_emit ) {
+ # print to stdout
+ if( $type ne "log" ) {
+ print( STDOUT "[$stamp] [$type] $string" );
+ }
+ }
+
+ # If a log file exists, write all types
+ # ( "debug", "error", "info", or "log" )
+ # to this specified log file
+ $log_entry = "[$stamp] [$type] $string";
+ print_to_logfile( "$logfile", "$log_entry" );
+
+ return;
+}
+
+
+##############################################################
+# Generic "validity" Subroutines
+##############################################################
+
+# arg0 path
+# return 1 - valid, or
+# return 0 - invalid
+sub is_path_valid
+{
+ my $path = $_[0];
+
+ 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;
+}
+
+
+# arg0 name
+# return 1 - valid, or
+# return 0 - invalid
+sub is_name_valid
+{
+ my $name = $_[0];
+
+ my $result = 0;
+
+ if( !( $name !~ /^[-_.a-zA-Z0-9]+$/ ) ) {
+ $result = 1;
+ }
+
+ return $result;
+}
+
+
+##############################################################
+# Generic "entity" Subroutines
+##############################################################
+
+# arg0 entity
+# return type of entity
+sub entity_type
+{
+ my( $entity ) = $_[0];
+
+ 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";
+}
+
+
+# arg0 entity
+# return 1 - exists, or
+# return 0 - DOES NOT exist
+sub entity_exists
+{
+ my( $entity ) = $_[0];
+
+ my $result = 0;
+
+ if( -e $entity ) {
+ my $type = entity_type( $entity );
+ $result = 1;
+ }
+
+ return $result;
+}
+
+
+##############################################################
+# Generic "file" Subroutines
+##############################################################
+
+# arg0 file candidate
+# return 1 - exists, or
+# return 0 - DOES NOT exist
+sub file_exists
+{
+ my( $file ) = $_[0];
+
+ 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;
+}
+
+
+# arg0 file
+# return 1 - empty, or
+# return 0 - NOT empty
+sub is_file_empty
+{
+ my( $file ) = $_[0];
+
+ my $result = 0;
+
+ if( -z $file ) {
+ $result = 1;
+ }
+
+ return $result;
+}
+
+
+# arg0 file
+# no return value
+sub create_empty_file
+{
+ my( $file ) = @_;
+
+ if( is_Windows() ) {
+ open( FILE, "> $file" );
+ close( FILE );
+ } else {
+ my $rv = 0;
+
+ $rv = `touch $file`;
+ if( !$rv ) {
+ emit( "create_empty_file(): unable to create empty file called "
+ . "$file.\n",
+ "error" );
+ }
+ }
+
+ return;
+}
+
+
+# arg0 file
+# arg1 message
+# no return value
+sub create_file
+{
+ my( $file, $message ) = @_;
+
+ $command = "";
+
+ if( is_Windows() ) {
+ if( "$message" eq "" ) {
+ open( FILE, "> $file" );
+ close( FILE );
+ } else {
+ open( FILE, "> $file" );
+ print( FILE "$message" );
+ close( FILE );
+ }
+ } else {
+ my $rv = 0;
+
+ if( "$message" eq "" ) {
+ $rv = `touch $file`;
+ if( !$rv ) {
+ emit( "create_file(): unable to create empty file called "
+ . "$file.\n",
+ "error" );
+ }
+ } else {
+ $command = "echo '$message' > $file";
+
+ system( "$command" );
+ }
+ }
+
+ return;
+}
+
+
+# arg0 file
+# arg1 destination path
+# return 1 - successfully moved file, or
+# return 0 - failed moving file
+sub move_file
+{
+ my( $file ) = $_[0];
+ my( $dest ) = $_[1];
+
+ my $result = 0;
+
+ if( !is_path_valid( $file ) ) {
+ emit( "move_file(): illegal source path => $file.\n",
+ "error" );
+ return 0;
+ }
+
+ if( !is_path_valid( $dest ) ) {
+ emit( "move_file(): illegal destination path => $dest.\n",
+ "error" );
+ return 0;
+ }
+
+ $result = `mv $file $dest`;
+ if( $result == 0 ) {
+ return 1;
+ }
+
+ emit( "move_file(): failed moving file $file to $dest.\n",
+ "error" );
+
+ return 0;
+}
+
+
+# arg0 source path
+# arg1 destination path
+# return 1 - successfully copied file, or
+# return 0 - failed copying file
+sub copy_file
+{
+ my $source_path = $_[0];
+ my $dest_path = $_[1];
+
+ my $result = 0;
+
+ if( !is_path_valid( $source_path ) ) {
+ emit( "copy_file(): illegal source path => $source_path.\n",
+ "error" );
+ return 0;
+ }
+
+ if( !is_path_valid( $dest_path ) ) {
+ emit( "copy_file(): illegal destination path => $dest_path.\n",
+ "error" );
+ return 0;
+ }
+
+ $result = `cp -f $source_path $dest_path`;
+ if( $result == 0 ) {
+ return 1;
+ }
+
+ emit( "copy_file(): failed copying file from $source_path to "
+ . "$dest_path.\n",
+ "error" );
+
+ return 0;
+}
+
+
+# arg0 file
+# return 1 - successfully removed file, or
+# return 0 - failed removing file
+sub remove_file
+{
+ my( $file ) = $_[0];
+
+ my $result = 0;
+
+ if( $file eq "" ) {
+ # file is NULL
+ return 1;
+ }
+
+ if( !file_exists( $file ) ) {
+ return 1;
+ }
+
+ $result = `rm -f $file`;
+ if( $result == 0 ) {
+ return 1;
+ }
+
+ emit( "remove_file(): failed to remove file $file.\n",
+ "error" );
+
+ return 0;
+}
+
+
+# arg0 file
+# arg1 user
+# arg2 group
+# return 1 - success, or
+# return 0 - failure
+sub give_file_to
+{
+ my $file = $_[0];
+ my $new_user = $_[1];
+ my $new_group = $_[2];
+
+ my $result = 0;
+
+ if( $file eq "" || !file_exists( $file ) ) {
+ emit( "give_file_to(): invalid file specified.\n",
+ "error" );
+ return 0;
+ }
+
+ if( $new_user eq "" || $new_group eq "" ) {
+ emit( "give_file_to(): file $file needs a user and group!\n",
+ "error" );
+ return 0;
+ }
+
+ $result = `chgrp $new_group $file`;
+ if( $result ) {
+ emit( "give_file_to(): can't change file $file ownership to "
+ . "group $new_group!\n",
+ "error" );
+ return 0;
+ }
+
+ $result = `chown $new_user $file`;
+ if( $result ) {
+ emit( "give_file_to(): can't change file $file ownership to "
+ . "user $new_user!\n",
+ "error" );
+ return 0;
+ }
+
+ return 1;
+}
+
+
+##############################################################
+# Generic "directory" Subroutines
+##############################################################
+
+# arg0 directory candidate
+# return 1 - exists, or
+# return 0 - DOES NOT exist
+sub directory_exists
+{
+ my( $dir ) = $_[0];
+
+ 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;
+}
+
+
+# arg0 directory
+# return 1 - empty, or
+# return 0 - NOT empty
+sub is_directory_empty
+{
+ my $dir = $_[0];
+
+ 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;
+}
+
+
+# arg0 directory
+# return 1 - success, or
+# return 0 - failure
+sub create_directory
+{
+ my( $dir ) = $_[0];
+
+ my $result = 0;
+
+ if( $dir eq "" ) {
+ # directory is NULL
+ # Just return success
+ return 1;
+ }
+
+ $result = `mkdir -p $dir`;
+ if( $result == 0 ) {
+ return 1;
+ }
+
+ emit( "create_directory(): failed creating directory $dir.\n",
+ "error" );
+
+ return 0;
+}
+
+
+# arg0 directory
+# arg1 destination path
+# return 1 - successfully moved directory, or
+# return 0 - failed moving directory
+sub move_directory
+{
+ my( $dir ) = $_[0];
+ my( $dest ) = $_[1];
+
+ my $result = 0;
+
+ if( !is_path_valid( $dir ) ) {
+ emit( "move_directory(): illegal source path => $dir.\n",
+ "error" );
+ return 0;
+ }
+
+ if( !is_path_valid( $dest ) ) {
+ emit( "move_directory(): illegal destination path => $dest.\n",
+ "error" );
+ return 0;
+ }
+
+ if( !directory_exists( $dest ) ) {
+ $result = create_directory( $dest );
+ if( !$result ) {
+ emit( "move_directory(): failed moving dir $dir to new $dest.\n",
+ "error" );
+ return 0;
+ }
+ }
+
+ $result = `mv $dir $dest`;
+ if( $result == 0 ) {
+ return 1;
+ }
+
+ emit( "move_directory(): failed moving dir $dir to $dest.\n",
+ "error" );
+
+ return 0;
+}
+
+
+# arg0 source directory
+# arg1 destination path
+# return 1 - successfully copied directory, or
+# return 0 - failed copying directory
+sub copy_directory
+{
+ my $source_dir_path = $_[0];
+ my $dest_dir_path = $_[1];
+
+ my $result = 0;
+
+ if( !is_path_valid( $source_dir_path ) ) {
+ emit( "copy_directory(): illegal source path => $source_dir_path.\n",
+ "error" );
+ return 0;
+ }
+
+ if( !is_path_valid( $dest_dir_path ) ) {
+ emit( "copy_directory(): illegal destination path => "
+ . "$dest_dir_path.\n",
+ "error" );
+ return 0;
+ }
+
+ if( !directory_exists( $source_dir_path ) ) {
+ # Take the case where this directory does not exist
+ # Just return true
+ return 1;
+ }
+
+ if( !directory_exists( $dest_dir_path ) ) {
+ $result = create_directory( $dest_dir_path );
+ if( !$result ) {
+ return 0;
+ }
+ }
+
+ if( !is_directory_empty( $source_dir_path ) ) {
+ $result = `cp -fr $source_dir_path/* $dest_dir_path`;
+ } else {
+ $result = 0;
+ }
+
+ # System call returns 0 on success.
+ if( $result == 0 ) {
+ return 1;
+ }
+
+ emit( "copy_directory(): failed copying directory from $source_dir_path "
+ . "to $dest_dir_path.\n",
+ "error" );
+
+ return 0;
+}
+
+
+# arg0 directory
+# return 1 - successfully removed directory, or
+# return 0 - failed removing directory
+sub remove_directory
+{
+ my( $dir ) = $_[0];
+
+ my $result = 0;
+
+ 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;
+ }
+
+ $result = `rm -rf $dir`;
+ if( $result == 0 ) {
+ return 1;
+ }
+
+ emit( "remove_directory(): failed to remove directory $dir.\n",
+ "error" );
+
+ return 0;
+}
+
+
+# arg0 directory
+# arg1 user
+# arg2 group
+# return 1 - success, or
+# return 0 - failure
+sub give_directory_to
+{
+ my $directory = $_[0];
+ my $new_user = $_[1];
+ my $new_group = $_[2];
+
+ my $result = 0;
+
+ if( $directory eq "" || !directory_exists( $directory ) ) {
+ emit( "give_directory_to(): invalid directory specified.\n",
+ "error" );
+ return 0;
+ }
+
+ if( $new_user eq "" || $new_group eq "" ) {
+ emit( "give_directory_to(): directory $directory needs a user "
+ . "and group!\n",
+ "error" );
+ return 0;
+ }
+
+ $result = `chgrp -R $new_group $directory`;
+ if( $result ) {
+ emit( "give_directory_to(): can't change directory $directory "
+ . "ownership to group $new_group!\n",
+ "error" );
+ return 0;
+ }
+
+ $result = `chown -R $new_user $directory`;
+ if( $result ) {
+ emit( "give_directory_to(): can't change directory $directory "
+ . "ownership to user $new_user!\n",
+ "error" );
+ return 0;
+ }
+
+ return 1;
+}
+
+
+##############################################################
+# Generic "symbolic link" Subroutines
+##############################################################
+
+# arg0 symbolic link candidate
+# return 1 - exists, or
+# return 0 - DOES NOT exist
+sub symbolic_link_exists
+{
+ my( $symlink ) = $_[0];
+
+ 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;
+}
+
+
+# arg0 symbolic link
+# arg1 destination path
+# return 1 - success, or
+# return 0 - failure
+sub create_symbolic_link
+{
+ my $symlink = $_[0];
+ my $dest_path = $_[1];
+
+ my $result = 0;
+
+
+ if( symbolic_link_exists( $symlink ) ) {
+ # delete symbolic link so that we can recreate link for upgrades
+ $result = `rm -rf $symlink`;
+ if( !$result ) {
+ emit( "create_symbolic_link(): unable to delete original "
+ . "$symlink.\n",
+ "error" );
+ return 0;
+ }
+ }
+
+ if( !is_path_valid( $symlink ) ) {
+ emit( "create_symbolic_link(): invalid source path => $symlink.\n",
+ "error" );
+ return 0;
+ }
+
+ if( !is_path_valid( $dest_path ) || !entity_exists( $dest_path ) ) {
+ emit( "create_symbolic_link(): illegal destination path => "
+ . "$dest_path.\n",
+ "error" );
+ return 0;
+ }
+
+ $result = `ln -s $dest_path $symlink`;
+ if( $result == 0 ) {
+ return 1;
+ }
+
+ emit( "create_symbolic_link(): failed creating symbolic link "
+ . "$symlink to destination directory $dest_path.\n",
+ "error" );
+
+ return 0;
+}
+
+
+# arg0 symbolic link
+# return 1 - successfully removed symbolic link, or
+# return 0 - failed removing symbolic link
+sub remove_symbolic_link
+{
+ my( $symlink ) = $_[0];
+
+ my $result = 0;
+
+ if( $symlink eq "" ) {
+ # symlink is NULL
+ return 1;
+ }
+
+ if( !symbolic_link_exists( $symlink ) ) {
+ return 1;
+ }
+
+ $result = `rm -f $symlink`;
+ if( $result == 0 ) {
+ return 1;
+ }
+
+ emit( "remove_symbolic_link(): failed to remove symbolic_link "
+ . "$symlink.\n",
+ "error" );
+
+ return 0;
+}
+
+
+# arg0 file
+# arg1 user
+# arg2 group
+# return 1 - success, or
+# return 0 - failure
+sub give_symbolic_link_to
+{
+ my $symlink = $_[0];
+ my $new_user = $_[1];
+ my $new_group = $_[2];
+
+ my $result = 0;
+
+ if( $symlink eq "" || !symbolic_link_exists( $symlink ) ) {
+ emit( "give_symbolic_link_to(): invalid symbolic link specified.\n",
+ "error" );
+ return 1;
+ }
+
+ if( $new_user eq "" || $new_group eq "" ) {
+ emit( "give_symbolic_link_to(): symbolic link $symlink needs a "
+ . "user and group!\n",
+ "error" );
+ return 0;
+ }
+
+ $result = `chgrp -h $new_group $symlink`;
+ if( $result ) {
+ emit( "give_symbolic_link_to(): can't change symbolic link $symlink "
+ . "ownership to group $new_group!\n",
+ "error" );
+ return 0;
+ }
+
+ $result = `chown -h $new_user $symlink`;
+ if( $result ) {
+ emit( "give_symbolic_link_to(): can't change symbolic link $symlink "
+ . "ownership to user $new_user!\n",
+ "error" );
+ return 0;
+ }
+
+ return 1;
+}
+
+1;
+