File:  [LON-CAPA] / loncom / CrGenerate.pl
Revision 1.4: download - view: text, annotated - select for diffs
Wed Jun 30 11:14:35 2004 UTC (19 years, 10 months ago) by foxr
Branches: MAIN
CVS tags: HEAD
Implement:
GenerateRequest - Generate the hostkey and the certificate request for
                  the host.
InstallKey      - Install the host key, if necessary creating the
                  target directory.

Note that keys are locked down tight, even the encoded key.  This is because:
- The encoded key's passphrase is 'well known'.
- The decoded key can be used to forge signatures certificates etc. and that would be
  bad.

    1: #!/usr/bin/perl
    2: # The LearningOnline Network
    3: # CrGenerate - Generate a loncapa certificate request.
    4: #
    5: # $Id: CrGenerate.pl,v 1.4 2004/06/30 11:14:35 foxr Exp $
    6: #
    7: # Copyright Michigan State University Board of Trustees
    8: #
    9: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
   10: #
   11: # LON-CAPA is free software; you can redistribute it and/or modify
   12: # it under the terms of the GNU General Public License as published by
   13: # the Free Software Foundation; either version 2 of the License, or 
   14: # (at your option) any later version.
   15: #
   16: # LON-CAPA is distributed in the hope that it will be useful,
   17: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   18: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19: # GNU General Public License for more details.
   20: #
   21: # You should have received a copy of the GNU General Public License
   22: # along with LON-CAPA; if not, write to the Free Software
   23: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   24: #
   25: # /home/httpd/html/adm/gpl.txt
   26: #
   27: 
   28: 
   29: # http://www.lon-capa.org/
   30: #
   31: #
   32: #  This script:
   33: #  1. Generates a private host key and certificate request/
   34: #  2. Decodes the private host key
   35: #  3. Installs the private host key with appropriate permissions
   36: #     in the  appropriate directory (sorry to be vague about this, but
   37: #     the installation directory is determined by external configuration
   38: #     info).
   39: # 4. Constructs an email to the loncapa cluster administrator
   40: #    consisting of a generic heading and the certificate request as a MIME
   41: #    attachment.
   42: # 5. Sends the email and
   43: # 6. Cleans up after itself by removing any temp files generated.
   44: #
   45: #
   46: 
   47: 
   48: # Import section:
   49: 
   50: use strict;
   51: use MIME::Entity;
   52: use Mail::Mailer;
   53: use LONCAPA::Configuration;
   54: use File::Copy;
   55: 
   56: #  Global variable declarations:4
   57: 
   58: my $SSLCommand;			  # Full path to openssl command.
   59: my $CertificateDirectory;	  # LONCAPA Certificate directory.
   60: my $KeyFilename;	          # Key filename (within CertificateDirectory).
   61: my $RequestEmail;		  # Email address of loncapa cert admin.
   62: my $WebUID;			# UID of web user.
   63: my $WebGID;			# GID of web user.
   64: 
   65: my $Passphrase="loncapawhatever";      # Initial passphrase for keyfile
   66: my $RequestFile="loncapaRequest.pem";  # Name of Certificate request file.
   67: my $EncodedKey="hostkey.pem";	       # Name of encoded key file.
   68: 
   69: my $WebUser="www";		# Username running the web server.
   70: my $WebGroup="www";		# Group name running the web server.
   71: 
   72: #   Debug/log support:
   73: #
   74: my $DEBUG = 1;			# 1 for on, 0 for off.
   75: 
   76: # Send debugging to stderr.
   77: # Parameters:
   78: #     msg   - Message to send to stderr.
   79: # Implicit Inputs:
   80: #    $DEBUG - message is only written if this is true.
   81: #
   82: sub Debug {
   83:     my $msg  = shift;
   84:     if($DEBUG) {
   85: 	print STDERR "$msg\n";
   86:     }
   87: }
   88: 
   89: #
   90: #   Read the LonCAPA web config files to get the values of the 
   91: #   configuration global variables we need:
   92: # Implicit inputs:
   93: #   loncapa.conf   - configuration file to read (user specific).
   94: # Implicit outputs (see global variables section):
   95: #   SSLCommand,
   96: #   CertificateDirectory
   97: #   KeyfileName
   98: #   RequestEmail
   99: # Side-Effects:
  100: #   Exit with error if cannot complete.
  101: #
  102: sub ReadConfig {
  103: 
  104:     Debug("Reading configuration");
  105:     my $perlvarref = LONCAPA::Configuration::read_conf('loncapa.conf');
  106:     
  107:     # Name of the SSL Program
  108: 
  109:     if($perlvarref->{SSLProgram}) {
  110: 	$SSLCommand = $perlvarref->{SSLProgram};
  111: 	Debug("SSL Command: $SSLCommand");
  112:     }
  113:     else {
  114: 	die "Unable to read the SSLCommand configuration option\n";
  115:     }
  116: 
  117:     # Where the certificates, and host key are installed:
  118: 
  119:     if($perlvarref->{lonCertificateDirectory}) {
  120: 	$CertificateDirectory = $perlvarref->{lonCertificateDirectory};
  121: 	Debug("Local certificate Directory: $CertificateDirectory");
  122:     }
  123:     else {
  124: 	die "Unable to read SSLDirectory configuration option\n";
  125:     }
  126:     # The name of the host key file (to be installed in SSLDirectory).
  127:     #
  128:     if($perlvarref->{lonnetPrivateKey}) {
  129: 	$KeyFilename  = $perlvarref->{lonnetPrivateKey};
  130: 	Debug("Private key will be installed as $KeyFilename");
  131:     } 
  132:     else {
  133: 	die "Unable to read lonnetPrivateKey conrig paraemter\n";
  134:     }
  135:     #  The email address to which the certificate request is sent:
  136: 
  137:     if($perlvarref->{SSLEmail}) {
  138: 	$RequestEmail = $perlvarref->{SSLEmail};
  139: 	Debug("Certificate request will be sent to $RequestEmail");
  140:     }
  141:     else {
  142: 	die "Could not read SSLEmail coniguration key";
  143:     }
  144:     #  The UID/GID of the web user: It's possible the web user's
  145:     #  GID is not its primary, so we'll translate that form the
  146:     #  group file separately.
  147: 
  148:     my ($login, $pass, $uid, $gid) = getpwnam($WebUser);
  149:     if($uid) {
  150: 	$WebUID = $uid;
  151: 	Debug("Web user: $WebUser -> UID: $WebUID");
  152:     }
  153:     else {
  154: 	die "Could not translate web user: $WebUser to a uid.";
  155:     }
  156:     my $gid = getgrnam($WebGroup);
  157:     if($gid) {
  158: 	$WebGID = $gid;
  159: 	Debug("Web group: $WebGroup -> GID $WebGID");
  160:     }
  161:     else {
  162: 	die "Unable to translate web group $WebGroup to a gid.";
  163:     }
  164: }
  165: #
  166: #   Generate a certificate request.
  167: #   The openssl command is issued to create a local host key and
  168: #   a certificate request.  The key is initially encoded.
  169: #   We will eventually decode this, however, since the key
  170: #   passphrase is open source we'll protect even the initial 
  171: #   encoded key file too.  We'll need to decode the keyfile since
  172: #   otherwise, openssl will need a passphrase everytime an ssl connection
  173: #   is created (ouch).
  174: # Implicit Inputs:
  175: #    Passphrase   - Initial passphrase for the encoded key.
  176: #    RequestFile  - Filename of the certificate request.
  177: #    EncodedKey   - Filename of the encoded key file.
  178: #
  179: # Side-Effects:
  180: #
  181: sub GenerateRequest {
  182:     Debug("Generating the request and key");
  183: 
  184:     print "We are now going to generate the certificate request\n";
  185:     print "You will be prompted by openssl for several pieces of \n";
  186:     print "information.  Most of this information is for documentation\n";
  187:     print "purposes only, so it's not critical if you make a mistake.\n";
  188:     print "However:  The generated certificate will be sent to the \n";
  189:     print "Email address you provide, and you should leave the optional\n";
  190:     print "Challenge password blank.\n";
  191: 
  192:     my $requestcmd = $SSLCommand." req -newkey rsa:1024 "
  193:                                 ." -keyout hostkey.pem "
  194:                                 ." -keyform PEM "
  195:                                 ." -out request.pem "
  196:                                 ." -outform PEM "
  197:                                 ." -passout pass:$Passphrase";
  198:     my $status = system($requestcmd);
  199:     if($status) {
  200: 	die "Certificate request generation failed: $status";
  201:     }
  202: 
  203:     chmod(0600, "hostkey.pem");	# Protect key since passphrase is opensrc.
  204: 
  205:     Debug("Decoding the key");
  206:     my $decodecmd = $SSLCommand." rsa -in  hostkey.pem"
  207:                                ."     -out hostkey.dec"
  208:                                ."     -passin pass:$Passphrase";
  209:     my $status = system($decodecmd);
  210:     if($status) {
  211: 	die "Host key decode failed";
  212:     }
  213: 
  214:     chmod(0600, "hostkey.dec");	# Protect the decoded hostkey.
  215:     Debug("Done");
  216: }
  217: #
  218: #  Installs the decoded host key (hostkey.dec) in the 
  219: #  certificate directory with the correct permissions.
  220: #
  221: # Implicit Inputs:
  222: #    hostkey.dec           - the name of the host key file.
  223: #    $CertificateDirectory - where the key file gets installed
  224: #    $KeyFilename          - Final name of the key file.
  225: #    $WebUser              - User who should own the key file.
  226: #    $WebGroup             - Group who should own the key file.
  227: #    0400                  - Permissions to give to the installed key
  228: #                            file.
  229: #    0700                  - Permissions given to the certificate
  230: #                            directory if created.
  231: # Side-Effects:
  232: #    If necessary, $CertificateDirectory is created.
  233: #    $CertificateDirectory/$KeyFilename is ovewritten with the
  234: #          contents of hostkey.dec in the cwd.
  235: #
  236: sub InstallKey {
  237:     Debug("InstallKey");
  238: 
  239:     Debug("Need to create certificate directory?");
  240:     if(!(-d $CertificateDirectory)) {
  241: 	
  242: 	Debug("Creating");
  243: 	mkdir($CertificateDirectory, 0700);
  244: 	chown($WebUID, $WebGID, $CertificateDirectory);
  245:     }
  246:     else {
  247: 	Debug("Exists");
  248:     }
  249: 
  250:     Debug("Installing the key file:");
  251:     my $FullKeyPath = $CertificateDirectory."/".$KeyFilename;
  252:     copy("hostkey.dec", $FullKeyPath);
  253: 
  254:     Debug("Setting ownership and permissions");
  255:     chmod(0400, $FullKeyPath);
  256:     chown($WebUID, $WebGID, $FullKeyPath);
  257: 
  258:     Debug("Done");
  259: }
  260: sub MailRequest {}
  261: sub Cleanup {}
  262: 
  263: 
  264: 
  265: #  Entry point:
  266: 
  267: Debug("Starting program");
  268: ReadConfig;			# Read loncapa apache config file.
  269: GenerateRequest;		# Generate certificate request.
  270: InstallKey;			# Install the user's key.
  271: MailRequest;			# Mail certificate request to loncapa 
  272: Cleanup;			# Cleanup temp files created.
  273: 
  274: Debug("Done");

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>