#!/usr/bin/perl
# The LearningOnline Network
# CrGrant.pl - Grant a loncapa SSL certificate.
#
# $Id: CrGrant.pl,v 1.2 2004/07/05 11:37:39 foxr Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA 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.
#
# LON-CAPA 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 LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
# This script operates on a certificate request that has been
# extracted from the attachment sent to the loncapa certificate
# administrator and:
#
# 1. Creates an ssl certificate corresponding to the request.
# 2. Constructs an installation script that will install
# the certificate along with the certificate authority's
# certificate in a loncapa system.
# 3. Constructs an email which contains a cover letter
# describing what to do with the attachment, and an
# attachment that consists of the installation script
# created in step 2.
# 4. Emails the message to the email address in the certificate
# request.
#
# There are some assumptions we need to make in order to
# get this all to work:
# - The certificate authority is installed on a
# loncapa system with configuration files that specify
# the same certificate directory and certificate filenames
# as the target system (otherwise we can't generate the
# installation script).
# - The loncapa certificate authority configuration file is
# $SSLDir/loncapaca.cnf and that it specifies that:
# o The certificate authority files are in $SSLDir/loncapaca
# o The certificate authority certificate is in:
# $SSLDir/loncapaca/cacert.pem
# o Only one instance of this script will be run at a time in
# this directory.
# o The person that runs this script knows the passphrase
# for the loncapa certificate authority's private key
# which remains encrypted for security reasons.
#
#
# Import section:
use strict;
use lib '/home/httpd/lib/perl';
use MIME::Entity;
use LONCAPA::Configuration;
# Global variable declarations
my $ssl_command = "/usr/bin/openssl "; # Command to run openssl.
my $ssl_dir = "/usr/share/ssl"; # Where ssl config files etc. live
my $ca_cert_file = $ssl_dir."/loncapa/cacert.pem"; # CA's certificate file.
my $ca_config_file= $ssl_dir."/loncapaca.cnf"; # CA's config file.
# Debug/log support
my $DEBUG=1;
sub Debug {
my $msg = shift;
if($DEBUG) {
print STDERR "$msg\n";
}
}
# Support subs:
#
# 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
}
# 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 {
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;
}
sub CreateInstallScript {}
sub CreateEmail {
return "Dummy message"; # Stub.
}
sub SendEmail {
my ($EmailAddress, $Message) = @_;
}
sub Cleanup {}
# Program entry point
# The usage is:
# CrGrant.pl {request_file}
#
my $argc = @ARGV; # Count number of command parameters.
if($argc != 1) {
Usage;
exit -1;
}
my $CertificateRequest = $ARGV[0];
my $email_address = CreateCertificate($CertificateRequest);
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.
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>