#!/usr/bin/perl

eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
    if 0; # not running under some shell
#
# Copyright (c) 2014 Red Hat, Inc.
#
# This software is licensed to you under the GNU General Public License,
# version 2 (GPLv2). There is NO WARRANTY for this software, express or
# implied, including the implied warranties of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
# along with this software; if not, see
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
#
# Red Hat trademarks are not licensed under GPLv2. No permission is
# granted to use or replicate Red Hat trademarks that are incorporated
# in this software or its documentation.
#

use strict 'refs';
use warnings;

use Getopt::Long;
use Spacewalk::Setup;

sub os_fips_mode_on {
	my $sysctl = (-x '/usr/sbin/sysctl') ? '/usr/sbin/sysctl' : '/sbin/sysctl';
	my $ret = `$sysctl -n crypto.fips_enabled`;
	chomp($ret);

	return $ret;
}

sub mod_ssl_fipsmode_option {
	my $mod_ssl_version = `rpm -q --qf='%{VERSION}' mod_ssl`;
	my $mod_ssl_release = `rpm -q --qf='%{RELEASE}' mod_ssl`;

	# RHEL-5 / CentOS-5 mod_ssl build 2.2.3-66 and above support SSLFIPS directive
	if ($mod_ssl_version eq '2.2.3' and $mod_ssl_release ge '66') {
		return 1;
	}

	# RHEL-6 / CentOS-6 mod_ssl builds do support FIPS, but do not have
	# the SSLFIPS configuration option implemented
	if ($mod_ssl_version eq '2.2.15' and $mod_ssl_release ge '5') {
		return 0;
	}

	# mod_ssl > 2.4 supports SSLFIPS directive (Fedora 19, 20, ...)
	if ($mod_ssl_version gt '2.4.0') {
		return 1;
	}

	return 0;
}

sub modify_conf_content {
	my $conf_content = ${(shift)};
	my $conf_files = shift;
	local *FILE;

	for my $file (glob Spacewalk::Setup::SHARED_DIR . "/$conf_files.*") {
		open FILE, $file or die "Error reading [$file]: $!\n";
		my $regexp = <FILE>;
		chomp $regexp;

		my $content;
		{
			local $/ = undef;
			$content = <FILE>;
		}
		close FILE;

		$conf_content =~ s!$regexp!$content!gm or $conf_content .= $content;
	}
	return $conf_content;
}

sub setup_mod_ssl {
	my $fips_mode_on = shift;

	my ($sslconf_content, $original_sslconf_content, $pre, $vhost, $post);
	my $sslconf_dir = '/etc/httpd/conf.d';
	my $sslconf     = 'ssl.conf';
	my $sslconf_path = "$sslconf_dir/$sslconf";
	local *FILE;

	die "$sslconf_path does not exist.\n" unless (-f $sslconf_path);

	{
		open FILE, $sslconf_path or die "Error opening [$sslconf_path]: $!\n";
		local $/ = undef;
		$sslconf_content = <FILE>;
		$original_sslconf_content = $sslconf_content;
		close FILE;
	}

	if ($sslconf_content =~ /(.*<VirtualHost _default_:443>)(.*)(<\/VirtualHost>.*)/s) {
		$pre = $1;
		$vhost = $2;
		$post = $3;
	} else {
		print Spacewalk::Setup::loc("Setup was unable to locate VirtualHost section " .
			"in existing mod_ssl configuration.\n");
		exit;
	}

	$vhost = modify_conf_content(\$vhost, 'mod_ssl.conf.vhost');

	# (If requested explicitly or the OS is already switched into FIPS mode) and
	# the particular mod_ssl being used supports SSLFIPS option
	if (($fips_mode_on or os_fips_mode_on()) and mod_ssl_fipsmode_option()) {
		$post = modify_conf_content(\$post, 'mod_ssl.conf.sslfips');
	}

	$sslconf_content = $pre . $vhost . $post;

	if ($sslconf_content ne $original_sslconf_content) {
		Spacewalk::Setup::backup_file($sslconf_dir, $sslconf);

		open FILE, ">$sslconf_path" or die "Error opening [$sslconf_path]: $!\n";
		chmod 0644, $sslconf_path;
		print FILE $pre . $vhost . $post;
		close FILE;
	}

	return;
}

# main

my $help;
my $fips_mode_on;

my $usage = <<EOHELP;
Usage: $0 --help | --fips-mode-on
Options:
	--help			Print this help message
	--fips-mode-on	Turn SSL FIPS mode on (when applicable)
EOHELP

GetOptions(
	"help" => \$help,
	"fips-mode-on" => \$fips_mode_on
	) or die $usage;

if ($help) {
	print $usage;
	exit 0;
}

setup_mod_ssl($fips_mode_on);

=head1 NAME

spacewalk-setup-httpd - utility for configuring httpd service to work with
Spacewalk / Red Hat Satellite

=head1 SYNOPSIS

B<spacewalk-setup-httpd>
[B<--help>]
[B<--fips-mode-on>]

=head1 OPTIONS

=over 5

=item B<--fips-mode-on>

Configure httpd to work correctly in FIPS mode. For mod_ssl, this means turning
the SSLFIPS directive on in ssl.conf where applicable.

=item B<--help>

Print help message.

=back

=head1 DESCRIPTION

B<spacewalk-setup-httpd> is a utility for configuring httpd service to work
with Spacewalk / Red Hat Satellite. The script uses configuration templates
to modify existing httpd configuration files.

Ordinarily, spacewalk-setup-httpd is called by spacewalk-setup(1) during
initial Spacewalk / Red Hat Satellite configuration or upgrade.

=head1 FILES

mod_ssl configuration

F</etc/httpd/conf.d/ssl.conf>

Configuration templates

F</usr/share/spacewalk/setup/mod_ssl*>

=head1 SEE ALSO

B<spacewalk-setup>(1) - Spacewalk setup program

=head1 AUTHORS

Milan Zazrivec <mzazrivec@redhat.com>

=cut
