version 1.1, 2004/07/02 10:51:18
|
version 1.3, 2004/07/06 11:05:45
|
Line 55
|
Line 55
|
# o The certificate authority files are in $SSLDir/loncapaca |
# o The certificate authority files are in $SSLDir/loncapaca |
# o The certificate authority certificate is in: |
# o The certificate authority certificate is in: |
# $SSLDir/loncapaca/cacert.pem |
# $SSLDir/loncapaca/cacert.pem |
# o The certificate authority maintains a certificate index file |
# o Only one instance of this script will be run at a time in |
# $SSLDIR/loncapaca/index.txt |
# this directory. |
# o Only one instance of this script will be run at a time!!!!! |
|
# (otherwise the last line of the index file may not be the |
|
# index to our certificate. We'll do some rudimentary |
|
# error checking, but have no idea how to recover in case |
|
# of problems). |
|
# o The generated certificates are stored in $SSLDIR/loncapaca/certs |
|
# o The person that runs this script knows the passphrase |
# o The person that runs this script knows the passphrase |
# for the loncapa certificate authority's private key |
# for the loncapa certificate authority's private key |
# which remains encrypted for security reasons. |
# which remains encrypted for security reasons. |
Line 72
|
Line 66
|
# Import section: |
# Import section: |
|
|
use strict; |
use strict; |
use lib '/home/httpd/lib/perl'; |
use lib '/home/httpd/lib/perl'; # An assumption!!! |
use MIME::Entity; |
use MIME::Entity; |
use LONCAPA::Configuration; |
use LONCAPA::Configuration; |
|
|
Line 81 use LONCAPA::Configuration;
|
Line 75 use LONCAPA::Configuration;
|
# Global variable declarations |
# Global variable declarations |
|
|
|
|
|
my $ssl_dir = "/usr/share/ssl"; # Where ssl config files etc. live |
|
my $ca_cert_file = $ssl_dir."/loncapaca/cacert.pem"; # CA's certificate file. |
|
my $ca_config_file= $ssl_dir."/loncapaca.cnf"; # CA's config file. |
|
|
|
|
|
# LONCAPA Configuration global variables: |
|
|
|
# Items read from our configuration file. |
|
|
|
my $ssl_command = "/usr/bin/openssl "; # Command to run openssl. |
|
my $loncapa_cert_dir; # Name of target cert dir (from config) |
|
my $loncapa_hostcert_name; # Name of host's signed cert file (config) |
|
my $loncapa_cacert_name; # Name of the CA's certificate file (config) |
|
|
|
# Items I just need to know: |
|
|
|
my $loncapa_config = "loncapa.conf"; # User's override config file. |
|
my $loncapa_apache_user = 'www'; # Name of apache daemon's user |
|
my $loncapa_apache_group = 'www'; # Name of apache daemon's group |
|
|
|
|
|
|
# Debug/log support |
# Debug/log support |
|
|
Line 94 sub Debug {
|
Line 109 sub Debug {
|
} |
} |
# Support subs: |
# Support subs: |
|
|
sub Usage {} |
# |
|
# Print out program usage. |
|
# |
|
# Side effects: |
|
# Output goes to stderr. |
|
# |
|
sub Usage { |
|
print STDERR << "USAGE"; |
|
|
|
Usage: |
|
CrGrant.pl requestfile.pem |
|
|
|
Where: |
|
requestfile.pem is a PEM formatted certificate extracted from an email |
|
to the LonCAPA certificate manager. |
|
USAGE |
|
|
|
} |
|
# |
|
# Read the loncapa configuration file and pull out the items |
|
# we need: |
|
# |
|
# Implicit inputs: |
|
# $loncapa_config - The name of the auxilliary config file. |
|
# Side effects: |
|
# - On failure exits with an error message. |
|
# - On success set the following variables: |
|
# o loncapa_cert_dir - Path to certificates. |
|
# o loncapa_hostcert_name - Name of host's cert file in that dir |
|
# o loncapa_cacert_name - Name of CA's cert file in that dir. |
|
# o ssl_command - Name of ssl utility command. |
|
sub ReadConfig { |
|
Debug("Reading the config files"); |
|
my $perlvarref = LONCAPA::Configuration::read_conf($loncapa_config); |
|
|
|
# Pull out the individual variables or die: |
|
|
|
# SSL Command: |
|
|
|
if($perlvarref->{SSLProgram}) { |
|
$ssl_command = $perlvarref->{SSLProgram}; |
|
Debug("SSL utility program is $ssl_command"); |
|
} |
|
else { |
|
die "LonCAPA configuration errror: Can't read SSLProgram variable"; |
|
} |
|
# Certificate directory: |
|
|
|
if($perlvarref->{lonCertificateDirectory}) { |
|
$loncapa_cert_dir = $perlvarref->{lonCertificateDirectory}; |
|
Debug("Certificates will be installed in $loncapa_cert_dir"); |
|
} |
|
else { |
|
die "LonCAPA configuration error can't read lonCertificateDirectory variable"; |
|
|
|
} |
|
# Get the name of the host's certificate: |
|
|
|
if($perlvarref->{lonnetCertificate}) { |
|
$loncapa_hostcert_name = $perlvarref->{lonnetCertificate}; |
|
Debug("Host's certificate will be $loncapa_hostcert_name"); |
|
} |
|
else { |
|
die "LonCAPA configuration error: Can't read lonnetCertificate variable"; |
|
} |
|
# Get the name of the certificate authority's certificate. |
|
|
|
if($perlvarref->{lonnetCertificateAuthority}) { |
|
$loncapa_cacert_name = $perlvarref->{lonnetCertificateAuthority}; |
|
Debug("CA's certificate will be $loncapa_cacert_name"); |
|
} |
|
else { |
|
die "LonCAPA configuration error: Can't read lonnetCertificateAuthority variable"; |
|
} |
|
|
|
|
|
} |
|
|
|
# Create a certificate from the request file. The certificate |
|
# is used, in conjunction with the openssl command with the |
|
# certificate authority configuration to produce a certificate |
|
# file. |
|
# |
|
# The certificate is parsed to determine the email address |
|
# of the requestor, which is returned to the caller. |
|
# |
|
#Parameters: |
|
# request_file - Name of the file containing the certificate request. |
|
#Returns: |
|
# If the request file exists and is able to produce a certificate |
|
# the email address of the requester is returned to the caller. |
|
# If not, undef is returned. |
|
# |
sub CreateCertificate { |
sub CreateCertificate { |
my $RequestFile = shift; |
my ($request_file) = @_; |
|
|
|
Debug("CreateCertificate"); |
|
|
|
if(!(-e $request_file)) { |
|
Debug("Certificate file $request_file does not exist"); |
|
return undef; |
|
} |
|
Debug("Certificate file $request_file exists"); |
|
|
|
# Create the certificate: The status of the openssl command |
|
# is used to determine if the certificate succeeded: |
|
|
|
my $create_command = $ssl_command." ca -config ".$ca_config_file |
|
." -in ".$request_file |
|
." -out hostCertificate.pem"; |
|
my $status = system($create_command); |
|
if($status) { |
|
Debug("openssl ca failed"); |
|
print STDERR "Certificate generation failed... probably bad"; |
|
print STDERR " request file!\n"; |
|
return undef; |
|
} |
|
Debug("openssl ca succeeded"); |
|
|
|
# Now we have a shining new signed certificate in ./hostCertificate.pem |
|
# we parse it to get the email address to which the certificate should |
|
# be emailed. |
|
# The certificate's return email address will be in the Subject line: |
|
# |
|
|
|
Debug("Parsing certificate file for Subject:"); |
|
open CERTIFICATE, "<hostCertificate.pem"; |
|
my $line; |
|
my $subject_found = 0; |
|
while ($line = <CERTIFICATE>) { |
|
Debug("Line = $line"); |
|
if($line =~ /Subject:/) { |
|
Debug("Found Subject: in $line"); |
|
$subject_found =1; |
|
last; |
|
} |
|
} |
|
close CERTIFICATE; |
|
|
|
if(!$subject_found) { |
|
Debug("Did not find Subject line in cert"); |
|
print STDERR "Output certificate parse failed: no Subject:\n"; |
|
return undef; |
|
} |
|
# The subject line contains an Email= string amidst the other stuff. |
|
# First break in to comma separated stuff, then locate the piece that |
|
# contains /Email= |
|
|
|
my @subject_fields = split(/,/, $line); |
|
my $email_found = 0; |
|
my $element; |
|
my $email_element; |
|
Debug("Parsing subject line for Email="); |
|
foreach $element (@subject_fields) { |
|
$email_element = $element; |
|
Debug("Parsing $element"); |
|
if($element =~ /\/Email=/) { |
|
Debug("Found /Email="); |
|
$email_found = 1; |
|
last; |
|
} |
|
} |
|
if(!$email_found) { |
|
Debug("Failed to fine Email="); |
|
print STDERR "Unable to find line with /Email= in cert. Subject\n"; |
|
return undef; |
|
} |
|
|
|
# The piece we found must first be split at the / |
|
# to isolate the Email= part and then that part at the = to isolate |
|
# the address: |
|
|
|
Debug("Splitting $email_element at /"); |
|
my ($junk, $email) = split(/\//, $email_element); |
|
Debug("Email part is $email"); |
|
my ($junk, $address) = split(/=/, $email); |
|
Debug("CreateCertificate Returning $address to caller"); |
|
|
|
return $address; |
|
|
return 'fox@nscl.msu.edu'; # Stub.. |
|
} |
} |
sub CreateInstallScript {} |
# |
|
# Create the installation script. This will be bash script |
|
# that will install the certifiate and the CA's certificate with ownership |
|
# WebUser:WebGroup and permissions 0400. I thought about using a perl |
|
# script in order to be able to get the certificate file/directory from |
|
# the configuration files. Unfortunately this is not as easy as it looks. |
|
# Root has a chicken and egg problem. In order to read the config file |
|
# you need to have added the ..../lib/perl to the perl lib path. To do |
|
# that correctly, you need to have read the config file to know where |
|
# it is...What we will do is read our local configuration file and |
|
# assume that our configuration is the same as the target's system in |
|
# all respects we care about. |
|
# Implicit Inputs: |
|
# - Bash is in /bin/bash |
|
# - $loncapa_cert_dir - install target directory. |
|
# - $loncapa_hostcert_name - Name of installed host cert file. |
|
# - $loncapa_cacert_name - Name of installed ca cert file. |
|
# - $loncapa_apache_user - username under which httpd runs. |
|
# - $loncapa_apache_group - group under which httpd runs. |
|
# - 0400 - install permissions. |
|
# - The host's certificate is now in ./hostCertificate.pem |
|
# - The CA's certificate is now in $ca_cert_file |
|
# |
|
# Implicit Outputs: |
|
# A file named CertInstall.sh |
|
# |
|
sub CreateInstallScript { |
|
open INSTALLER,">CertInstall.sh"; |
|
print INSTALLER <<BASH_HEADER; |
|
#!/bin/bash |
|
# |
|
# Installer for your lonCAPA certificates. Please check the |
|
# configuration variables to be sure they match your installation. |
|
# Then run this script under a root shell to complete the |
|
# installation of the certificates. |
|
# |
|
# Configuration Variables: |
|
CERTDIR="$loncapa_cert_dir" # Directory with your host key. |
|
HOSTCERT="$loncapa_hostcert_name" # Name of host's certificate file. |
|
CACERT="$loncapa_cacert_name" # Name of certifiate authority file. |
|
HTTPDUID="$loncapa_apache_user" # UID of httpd. |
|
HTTPDGID="$loncapa_apache_group" # GID of httpd. |
|
|
|
# End of configuration variables. |
|
|
|
MODE=0444 # certificates get this mode. |
|
HOSTCERTPATH="\$CERTDIR/\$HOSTCERT" |
|
CACERTPATH="\$CERTDIR/\$CACERT" |
|
|
|
# Create the host certificate file to install: |
|
|
|
echo unpacking host certificate |
|
|
|
cat <<-HOSTCERTTEXT >\$HOSTCERT |
|
BASH_HEADER |
|
|
|
# Now copy the host certificate into the script: |
|
|
|
open HOSTCERT, "<hostCertificate.pem"; |
|
while(my $line = <HOSTCERT>) { |
|
print INSTALLER $line; # Line presumably has a \n. |
|
} |
|
close HOSTCERT; |
|
|
|
# Close the here doc, and start up the cat of the ca cert: |
|
|
|
print INSTALLER "HOSTCERTTEXT\n"; |
|
print INSTALLER "echo unpacking CA certificate\n"; |
|
print INSTALLER "cat <<-CACERTTEXT >\$CACERT\n"; |
|
open CACERT, "<$ca_cert_file"; |
|
while(my $line = <CACERT>) { |
|
print INSTALLER $line; |
|
} |
|
close CACERT; |
|
print INSTALLER "CACERTTEXT\n"; |
|
|
|
# Ok, the script can create the two files, now it must install |
|
# install them >and< clean up after itself. |
|
|
|
print INSTALLER <<BASH_TRAILER; |
|
|
|
echo Installing certificates |
|
|
|
install -m \$MODE -o \$HTTPDUID -g \$HTTPDGID \$CACERT \$CACERTPATH |
|
install -m \$MODE -o \$HTTPDUID -g \$HTTPDGID \$HOSTCERT \$HOSTCERTPATH |
|
|
|
echo done |
|
|
|
# rm -f \$CACERT |
|
# rm -f \$HOSTCERT |
|
|
|
# Do they want to restart loncapa: |
|
# |
|
|
|
echo In order to start running in secure mode you will need to start |
|
echo lonCAPA. If you want I can do that now for you. Otherwise, |
|
echo you will have to do it yourself later either by rebooting your |
|
echo system or by typing: |
|
echo |
|
echo /etc/init.d/loncontrol restart |
|
echo |
|
read -p "Restart loncapa now [yN]?" yesno |
|
|
|
if [ "{\$yesno:0:1}" = "Y" ] |
|
then |
|
/etc/init.d/loncontrol restart |
|
fi |
|
BASH_TRAILER |
|
|
|
close INSTALLER; |
|
} |
|
|
sub CreateEmail { |
sub CreateEmail { |
return "Dummy message"; # Stub. |
return "Dummy message"; # Stub. |
Line 125 if($argc != 1) {
|
Line 424 if($argc != 1) {
|
} |
} |
my $CertificateRequest = $ARGV[0]; |
my $CertificateRequest = $ARGV[0]; |
|
|
my $EmailAddress = CreateCertificate($CertificateRequest); |
&ReadConfig; |
CreateInstallScript; |
|
my $Message = CreateEmail; |
my $email_address = &CreateCertificate($CertificateRequest); |
SendEmail($EmailAddress, $Message); |
Debug("CreateCertificate returned: $email_address"); |
Cleanup; |
|
|
if(!defined $email_address) { |
|
print STDERR "Bad or missing certificate file!!"; |
|
Usage; |
|
exit -1; |
|
} |
|
|
|
&CreateInstallScript; |
|
my $Message = &CreateEmail; |
|
&SendEmail($email_address, $Message); |
|
&Cleanup; |
|
|
# POD documentation. |
# POD documentation. |