#!/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, ") { 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.