Commit 5ccc258a authored by Leigh B Stoller's avatar Leigh B Stoller

When generating a new ssl certificate, allow reuse of existing private

key so that existing delegations are not invalidated. In general this
is fine if the key has not been compromised. User has a choice, with
the check box.
parent 58aa3b92
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2008 University of Utah and the Flux Group.
# Copyright (c) 2000-2011 University of Utah and the Flux Group.
# All rights reserved.
#
use strict;
......@@ -22,14 +22,15 @@ use User;
#
sub usage()
{
print("Usage: mkusercert [-d] [-o] [-g] [-p password] <user>\n");
print("Usage: mkusercert [-d] [-o] [-r] [-g] [-p password] <user>\n");
exit(-1);
}
my $optlist = "dp:og";
my $optlist = "dp:ogr";
my $debug = 0;
my $output = 0;
my $password = "";
my $geniflag = 0;
my $reusekey = 0;
#
# Configure variables
......@@ -93,6 +94,7 @@ $| = 1;
# Function prototypes
#
sub fatal($);
sub UserFatal($);
#
# Rewrite audit version of ARGV to prevent password in mail logs.
......@@ -116,6 +118,9 @@ if (! getopts($optlist, \%options)) {
if (defined($options{"d"})) {
$debug = 1;
}
if (defined($options{"r"})) {
$reusekey = 1;
}
if (defined($options{"g"})) {
$geniflag = 1;
}
......@@ -144,6 +149,9 @@ if (@ARGV != 1) {
if ($geniflag && !$encrypted) {
fatal("GENI certs must be encrypted (use -p password).");
}
if ($reusekey && !$encrypted) {
fatal("Cannot reuse the key for an unencrypted cert (use -p password).");
}
my $user = $ARGV[0];
#
......@@ -168,16 +176,6 @@ if (! defined($this_user)) {
fatal("You ($UID) do not exist!");
}
#
# This script is always audited. Mail is sent automatically upon exit.
#
if (AuditStart(0)) {
#
# Parent exits normally
#
exit(0);
}
#
# CD to the workdir, and then serialize on the lock file since there is
# some shared goop that the ssl tools muck with (serial number, index, etc.).
......@@ -188,6 +186,54 @@ chdir("$WORKDIR") or
TBScriptLock("mkusercert") == 0 or
fatal("Could not get the lock!");
#
# Create a client side cert. Reuse the original key if are told to,
# and it actually exists, and the password is valid.
#
# Do this before the AuditStart() so that user error goes back to web.
#
my $reqargs = "";
if ($reusekey) {
my $privkey;
my $cert;
if ($target_user->SSLCert(1, \$cert, \$privkey)) {
$reusekey = 0;
goto newkey;
}
open(KEYF, "> usercert_key.pem") or
fatal("Could not create file to store existing private key");
print KEYF "-----BEGIN RSA PRIVATE KEY-----\n";
print KEYF $privkey;
print KEYF "-----END RSA PRIVATE KEY-----\n";
close(KEYF);
#
# Make sure the user provided the proper passphrase.
#
system("$OPENSSL rsa -check -in usercert_key.pem ".
" -passin 'pass:${sh_password}' -noout >/dev/null 2>&1") == 0
or UserFatal("Cannot decrypt private key. Correct pass phrase?");
$reqargs = "-key usercert_key.pem -passin 'pass:${sh_password}' ";
}
else {
newkey:
$reqargs = "-keyout usercert_key.pem";
$reqargs .= ($encrypted ? " -passout 'pass:${sh_password}' " : " -nodes ")
}
#
# This script is always audited. Mail is sent automatically upon exit.
#
if (AuditStart(0)) {
#
# Parent exits normally
#
exit(0);
}
#
# Get the user info (the user being operated on).
#
......@@ -267,8 +313,7 @@ close(TEMP)
# Create a client side private key and certificate request.
#
system("$OPENSSL req -new -config usercert.cnf ".
($encrypted ? " -passout 'pass:${sh_password}' " : " -nodes ") .
" -keyout usercert_key.pem -out usercert_req.pem") == 0
"$reqargs -out usercert_req.pem") == 0
or fatal("Could not create certificate request");
#
......@@ -421,3 +466,11 @@ sub fatal($) {
die("*** $0:\n".
" $mesg\n");
}
sub UserFatal($) {
my($mesg) = $_[0];
TBScriptUnlock();
print STDERR $mesg;
# Tell web interface to tell user.
exit(1);
}
<?php
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2009 University of Utah and the Flux Group.
# Copyright (c) 2000-2011 University of Utah and the Flux Group.
# All rights reserved.
#
include("defs.php3");
......@@ -128,12 +128,29 @@ function SPITFORM($target_user, $formfields, $errors)
size=24></td>
</tr>\n";
if (1) {
echo "<tr>
<td>Reuse Private Key?[<b>3</b>]:</td>
<td class=left>
<input type=checkbox
name=\"formfields[reusekey]\"
value=Yep";
if (isset($formfields["reusekey"]) &&
strcmp($formfields["reusekey"], "Yep") == 0)
echo " checked";
echo " > Yes
</td>
</tr>\n";
}
#
# Verify with password.
#
if (!$isadmin) {
echo "<tr>
<td>Emulab Password[<b>3</b>]:</td>
<td>Emulab Password[<b>4</b>]:</td>
<td class=left>
<input type=password
name=\"formfields[password]\"
......@@ -157,7 +174,9 @@ function SPITFORM($target_user, $formfields, $errors)
<li> You must supply a passphrase to use when encrypting the
private key for your SSL certificate. You will be prompted
for this passphrase whenever you attempt to use it. Pick
a good one!";
a good one!
<li> Reuse your existing private key unless you think it has been
compromised. Must provide correct passphrase for your key.";
if (!$isadmin) {
echo "<li> As a security precaution, you must supply your Emulab user
password when creating new ssl certificates. ";
......@@ -171,6 +190,7 @@ function SPITFORM($target_user, $formfields, $errors)
#
if (! isset($_POST['submit'])) {
$defaults = array();
$defaults["reusekey"] = "Yep";
SPITFORM($target_user, $defaults, 0);
PAGEFOOTER();
......@@ -237,15 +257,43 @@ if (count($errors)) {
return;
}
$reusekey = "";
if (isset($formfields["reusekey"]) &&
strcmp($formfields["reusekey"], "Yep") == 0) {
$reusekey = "-r";
}
#
# Insert key, update authkeys files and nodes if appropriate.
#
STARTBUSY("Generating Certificate");
SUEXEC($target_uid, "nobody",
"webmkusercert -p " .
escapeshellarg($formfields["passphrase1"]) . " $target_uid",
SUEXEC_ACTION_DIE);
STOPBUSY();
$retval = SUEXEC($target_uid, "nobody",
"webmkusercert $reusekey -p " .
escapeshellarg($formfields["passphrase1"]) . " $target_uid",
SUEXEC_ACTION_IGNORE);
HIDEBUSY();
#
# Fatal Error. Report to tbops.
#
if ($retval < 0) {
SUEXECERROR(SUEXEC_ACTION_DIE);
#
# Never returns ...
#
die("");
}
#
# User Error. Report to user.
#
if ($retval > 0) {
$errors["PassPhrase"] = $suexec_output;
SPITFORM($target_user, $formfields, $errors);
PAGEFOOTER();
return;
}
#
# Redirect back, avoiding a POST in the history.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment