gensslcert.php3 12.6 KB
Newer Older
1 2
<?php
#
3
# Copyright (c) 2000-2013 University of Utah and the Flux Group.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
# 
# {{{EMULAB-LICENSE
# 
# This file is part of the Emulab network testbed software.
# 
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
# 
# This file 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 Affero General Public
# License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this file.  If not, see <http://www.gnu.org/licenses/>.
# 
# }}}
23 24 25 26 27 28
#
include("defs.php3");

#
# Only known and logged in users can do this.
#
29 30 31
$this_user = CheckLoginOrDie();
$uid       = $this_user->uid();
$isadmin   = ISADMIN();
32 33

#
34 35 36 37
# Verify page arguments
#
$optargs = OptionalPageArguments("target_user", PAGEARG_USER,
				 "submit",      PAGEARG_STRING,
38
				 "which",       PAGEARG_STRING,
39 40
				 "finished",    PAGEARG_BOOLEAN,
				 "formfields",  PAGEARG_ARRAY);
41

42 43 44 45
# Default to current user if not provided.
if (!isset($target_user)) {
     $target_user = $this_user;
}
46 47 48
if (!isset($which)) {
    $which = null;
}
49

50 51 52 53 54 55 56
# Need these below
$target_uid = $target_user->uid();

#
# The conclusion.
# 
if (isset($finished)) {
57 58
    PAGEHEADER("Download SSL Certificate for user: $target_uid");

59 60
    $sslurl = CreateURL("getsslcert", $target_user);
    $sshurl = CreateURL("getsslcert", $target_user, "ssh", 1);
61
    
62
    echo "<blockquote>
63
          <a href='$sslurl'>Download</a> your 
64
          certificate and private key in PEM format, and then save
65 66 67
          it to a file in your .ssl directory.
          <br>
          <br>
68
          You can also download it in <a href='$sslurl&p12=1'><em>pkc12</em></a>
69 70 71
          format for loading
          into your web browser (if you do not know what this means, or why
          you need to do this, then ignore this).
72 73 74 75 76 77 78 79 80 81 82 83 84
	  <br>
	  <br>
	  We have also created a SSH key pair for you, derived from your new 
          ssl certificate, using the same pass phrase.
          You can <a href='$sshurl'>Download</a> the private
          key and load it into your ssh agent. The private key is typically
	  placed in your .ssh directory on your desktop machine. If you are
          running an agent such as
	  <a href='http://www.chiark.greenend.org.uk/~sgtatham/putty/'>Putty</a>
          or
	  <a href='http://sshkeychain.sourceforge.net/'>SSHKeychain</a>,
	  please consult the
	  documentation for those programs.
85
          </blockquote>\n";
86 87 88 89 90
	    
    PAGEFOOTER();
    return;
}

91 92 93 94 95
#
# Standard Testbed Header, now that we know what we want to say.
#
PAGEHEADER("Generate SSL Certificate for user: $target_uid");

96 97 98
#
# Only admin people can create SSL certs for another user.
#
99 100 101
if (!$isadmin && !$target_user->SameUser($this_user)) {
    USERERROR("You do not have permission to create SSL certs ".
	      "for $target_uid!", 1);
102 103
}

104
function SPITFORM($target_user, $formfields, $errors)
105
{
106
    global $isadmin, $BOSSNODE;
107 108 109

    $target_uid    = $target_user->uid();
    $target_webid  = $target_user->webid();
Leigh Stoller's avatar
Leigh Stoller committed
110
    $url           = CreateURL("gensslcert", $target_user);
111 112

    echo "<blockquote>
113
          By creating an encrypted SSL certificate, you are able to use
114 115 116
          Emulab's XMLRPC server from your desktop or home machine. This
          certificate must be pass phrase protected, and allows you to issue
          any of the RPC requests documented in the <a href=xmlrpcapi.php3>
117
          Emulab XMLRPC Reference</a>.</blockquote>\n";
118 119 120 121 122 123 124 125 126 127 128 129 130
    
    if ($errors) {
	echo "<table class=nogrid
                     align=center border=0 cellpadding=6 cellspacing=0>
              <tr>
                 <th align=center colspan=2>
                   <font size=+1 color=red>
                      &nbsp;Oops, please fix the following errors!&nbsp;
                   </font>
                 </td>
              </tr>\n";

	while (list ($name, $message) = each ($errors)) {
131 132
            # XSS prevention.
	    $message = CleanString($message);
133 134 135 136 137 138 139 140 141
	    echo "<tr>
                     <td align=right>
                       <font color=red>$name:&nbsp;</font></td>
                     <td align=left>
                       <font color=red>$message</font></td>
                  </tr>\n";
	}
	echo "</table><br>\n";
    }
142 143 144 145
    # XSS prevention.
    while (list ($key, $val) = each ($formfields)) {
	$formfields[$key] = CleanString($val);
    }
146

147 148 149 150 151 152 153 154
    echo "<table align=center class=stealth>\n";
    echo "<tr>\n";
    echo "<td class=stealth>\n";
    
    echo "<center>
          Create an SSL Certificate[<b>1</b>]
          </center>\n";

155 156
    echo "<table align=center border=1> 
          <form enctype=multipart/form-data
157
                action='$url' method=post>\n";
158
    echo "<input type=hidden name=which value=create>\n";
159 160

    echo "<tr>
161
              <td>PassPhrase[<b>2</b>]:</td>
162 163 164
              <td class=left>
                  <input type=password
                         name=\"formfields[passphrase1]\"
165
                         value=\"" . $formfields["passphrase1"] . "\"
166 167 168 169 170 171 172 173
                         size=24></td>
          </tr>\n";

    echo "<tr>
              <td>Confirm PassPhrase:</td>
              <td class=left>
                  <input type=password
                         name=\"formfields[passphrase2]\"
174
                         value=\"" . $formfields["passphrase1"] . "\"
175 176 177
                         size=24></td>
          </tr>\n";

178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
    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";
    }
    
195 196 197 198 199
    #
    # Verify with password.
    #
    if (!$isadmin) {
	echo "<tr>
200
                  <td>Emulab Password[<b>4</b>]:</td>
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
                  <td class=left>
                      <input type=password
                             name=\"formfields[password]\"
                             size=12></td>
              </tr>\n";
    }

    echo "<tr>
              <td colspan=2 align=center>
                 <b><input type=submit name=submit value='Create SSL Cert'></b>
              </td>
          </tr>\n";

    echo "</form>
          </table>\n";

217 218 219 220 221 222 223 224 225 226 227 228
    echo "</td>\n";
    echo "<td class=stealth>\n";
    echo " OR ";
    echo "</td>\n";
    echo "<td valign=top class=stealth>\n";

    echo "<center>
          Change Passphrase
          </center>\n";
    
    echo "<table align=center border=1> 
          <form enctype=multipart/form-data
229
                action='$url' method=post>\n";
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
    echo "<input type=hidden name=which value=change>\n";

    echo "<tr>
              <td>New PassPhrase[<b>2</b>]:</td>
              <td class=left>
                  <input type=password
                         name=\"formfields[passphrase1]\"
                         value=\"" . $formfields["passphrase1"] . "\"
                         size=24></td>
          </tr>\n";
    echo "<tr>
              <td>Confirm PassPhrase:</td>
              <td class=left>
                  <input type=password
                         name=\"formfields[passphrase2]\"
                         value=\"" . $formfields["passphrase2"] . "\"
                         size=24></td>
          </tr>\n";
248 249 250 251
    
    if (!isset($formfields["oldpassphrase"])) {
	$formfields["oldpassphrase"] = "";
    }
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
    echo "<tr>
              <td>Old PassPhrase:</td>
              <td class=left>
                  <input type=password
                         name=\"formfields[oldpassphrase]\"
                         value=\"" . $formfields["oldpassphrase"] . "\"
                         size=24></td>
          </tr>\n";
    echo "<tr>
              <td colspan=2 align=center>
                 <b><input type=submit name=submit value='Change Passphrase'>
                 </b>
              </td>
          </tr>\n";

    echo "</form>
          </table>\n";

    echo "</td>\n";
    echo "</tr>\n";
    echo "</table>\n";

274 275
    echo "<blockquote><blockquote><blockquote>
          <ol>
276
            <li> This is an <b>encrypted key</b> and should <b>not</b> replace
277
                 <tt>emulab.pem</tt> in your <tt>.ssl</tt> directory.
278 279 280
            <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
281 282 283
                 a good one!
            <li> Reuse your existing private key unless you think it has been
                 compromised. Must provide correct passphrase for your key.";
284 285 286 287 288
    if (!$isadmin) {
	echo "<li> As a security precaution, you must supply your Emulab user
                 password when creating new ssl certificates. ";
    }
    echo "</ol>
289 290 291 292 293 294 295 296
          </blockquote></blockquote></blockquote>\n";
}

#
# On first load, display a form of current values.
#
if (! isset($_POST['submit'])) {
    $defaults = array();
297 298 299 300
    $defaults["reusekey"]        = "Yep";
    $defaults["passphrase1"]     = "";
    $defaults["passphrase2"]     = "";
    $defaults["oldpassphrase"]   = "";
301
    
302
    SPITFORM($target_user, $defaults, 0);
303 304 305 306
    PAGEFOOTER();
    return;
}

307 308
# Must get formfields.
if (!isset($formfields)) {
309
    PAGEARGERROR("Invalid form arguments; no formfields array.");
310 311
}

312 313 314 315 316
#
# Otherwise, must validate and redisplay if errors
#
$errors = array();

317 318 319 320 321 322 323
#
# Need to get the which variable to tell us which form.
#
if (! ($which && ($which == "create" || $which == "change"))) {
    PAGEARGERROR("Invalid form arguments; which form?");
}

324 325 326
#
# Need this for checkpass.
#
327 328
$user_name  = $target_user->name();
$user_email = $target_user->email();
329

330 331 332
#TBERROR("$target_uid, $user_name, $user_email, " .
#	$formfields[passphrase1], 0); 

333 334 335
#
# Must supply a reasonable passphrase.
# 
336 337
if (!isset($formfields["passphrase1"]) ||
    strcmp($formfields["passphrase1"], "") == 0) {
338 339
    $errors["Passphrase"] = "Missing Field";
}
340 341
if (!isset($formfields["passphrase2"]) ||
    strcmp($formfields["passphrase2"], "") == 0) {
342 343
    $errors["Confirm Passphrase"] = "Missing Field";
}
344
elseif (strcmp($formfields["passphrase1"], $formfields["passphrase2"])) {
345 346 347
    $errors["Confirm Passphrase"] = "Does not match Passphrase";
}
elseif (! CHECKPASSWORD($target_uid,
348
			$formfields["passphrase1"],
349 350 351 352 353 354 355 356
			$user_name,
			$user_email, $checkerror)) {
    $errors["Passphrase"] = "$checkerror";
}

#
# Must verify passwd to create an SSL key.
#
357
if ($which == "create" && !$isadmin) {
358 359
    if (!isset($formfields["password"]) ||
	strcmp($formfields["password"], "") == 0) {
360 361
	$errors["Password"] = "Must supply a verification password";
    }
362
    elseif (VERIFYPASSWD($target_uid, $formfields["password"]) != 0) {
363 364 365 366
	$errors["Password"] = "Incorrect password";
    }
}

367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
if ($which == "change") {
    $query_result =&
	$target_user->TableLookUp("user_sslcerts",
				  "cert,privkey,idx",
				  "encrypted=1 and revoked is null");

    if (!mysql_num_rows($query_result)) {
	$errors["Change Passphrase"] =
	    "You have not created an encrypted certificate yet";
    }

    if (!isset($formfields["oldpassphrase"]) ||
	strcmp($formfields["oldpassphrase"], "") == 0) {
	$errors["Old Passphrase"] = "Must supply current passphrase";
    }
    # Ascii only.
    elseif (! TBvalid_userdata($formfields["oldpassphrase"])) {
	$errors["Old Passphrase"] = "Invalid characters in old passphrase";
	return 0;
    }
}

389 390
# Spit the errors
if (count($errors)) {
391
    SPITFORM($target_user, $formfields, $errors);
392 393 394 395
    PAGEFOOTER();
    return;
}

396 397 398 399 400 401 402 403 404
$opt = "";
if ($which == "create") {
    if (isset($formfields["reusekey"]) &&
	strcmp($formfields["reusekey"], "Yep") == 0) {
	$opt = "-r";
    }
}
else {
    $opt = "-c " . escapeshellarg($formfields["oldpassphrase"]);
405 406
}

407 408 409
#
# Insert key, update authkeys files and nodes if appropriate.
#
410 411 412
STARTBUSY(($which == "create" ?
	   "Generating Certificate" : "Changing Passphrase"));

413
$retval = SUEXEC($target_uid, "nobody",
414
		 "webmkusercert $opt -p " .
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
		 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;
}
440 441 442

#
# Redirect back, avoiding a POST in the history.
443 444
#
PAGEREPLACE(CreateURL("gensslcert", $target_user, "finished", 1));
445

446
PAGEFOOTER();
447
?>