#!/usr/bin/perl

# Copyright (C) 2007, 2009 Free Software Foundation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# generate-cacerts.pl generates a gkeytool keystore named 'cacerts'
# from OpenSSL's certificate bundle.

# First extract each of OpenSSL's bundled certificates into its own
# aliased filename.
chomp($file=@ARGV[0]);
$file = "/etc/pki/tls/cert.pem" unless $file ne "";
open(CERTS, $file);
@certs = <CERTS>;
close(CERTS);

$pem_file_number = 0;
$writing_cert = 0;
foreach $cert (@certs)
{
	 if ($cert eq "-----BEGIN CERTIFICATE-----\n")
	 {
		  if ($writing_cert != 0)
		  {
				die "$file is malformed.";
		  }
		  $pem_file_number++;
		  # Numbering each file guarantees that cert aliases will be
		  # unique.
		  $pem_file_name = "$pem_file_number$cert_alias.pem";
		  $writing_cert = 1;
		  open(PEM, ">$pem_file_name");
		  print PEM $cert;
	 }
	 elsif ($cert eq "-----END CERTIFICATE-----\n")
	 {
		  $writing_cert = 0;
		  print PEM $cert;
		  close(PEM);
	 }
	 elsif ($cert =~ /Issuer: /)
	 {
		  # Generate an alias using the OU and CN attributes of the
		  # Issuer field if both are present, otherwise use only the CN
		  # attribute.  The Issuer field must have either the OU or the
		  # CN attribute.
		  $_ = $cert;
		  if ($cert =~ /OU=/)
		  {
				s/Issuer:.*?OU=//;
				# Remove other occurrences of OU=.
				s/OU=.*CN=//;
				# Remove CN= if there were not other occurrences of OU=.
				s/CN=//;
		  }
		  elsif ($cert =~ /CN=/)
		  {
				s/Issuer:.*CN=//;
		  }
		  s/\W//g;
		  tr/A-Z/a-z/;
		  $cert_alias = $_
	 }
	 else
	 {
		  if ($writing_cert == 1)
		  {
				print PEM $cert;
		  }
	 }
}

# Check that the correct number of .pem files were produced.
@pem_files = <*.pem>;
if (@pem_files != $pem_file_number)
{
	 die "Number of .pem files produced does not match".
		  " number of certs read from $file.";
}

# Now store each cert in the 'cacerts' file using gkeytool.
$certs_written_count = 0;
foreach $pem_file (@pem_files)
{
	 system "yes | gkeytool@gcc_suffix@ -import -alias `basename $pem_file .pem`".
		  " -keystore cacerts -storepass '' -file $pem_file".
		  " 2>&1 >/dev/null";
	 unlink($pem_file);
	 $certs_written_count++;
}

# Check that the correct number of certs were added to the keystore.
if ($certs_written_count != $pem_file_number)
{
	 die "Number of certs added to keystore does not match".
		  " number of certs read from $file.";
}
