commit 36f6ed351af7712b07f2e1d37155d91bc883c893
Author: bcyrill <cyrill@bannwart.info>
Date:   Mon Jul 2 22:20:06 2012 +0200

    Use Certificate Manager in Captive Portal settings

diff --git a/etc/inc/captiveportal.inc b/etc/inc/captiveportal.inc
index 653139ab9e..ba9d7e4fc4 100644
--- a/etc/inc/captiveportal.inc
+++ b/etc/inc/captiveportal.inc
@@ -454,16 +454,19 @@ function captiveportal_init_webgui_zone($cpcfg) {
 	$use_fastcgi = true;
 
 	if (isset($cpcfg['httpslogin'])) {
-		$cert = base64_decode($cpcfg['certificate']);
-		if (isset($cpcfg['cacertificate']))
-			$cacert = base64_decode($cpcfg['cacertificate']);
-		else
-			$cacert = "";
-		$key = base64_decode($cpcfg['private-key']);
+		$cert = lookup_cert($cpcfg['certref']);
+		$cert_crt = base64_decode($cert['crt']);
+		$cert_prv = base64_decode($cert['prv']);
+		if (isset($cpcfg['caref'])) {
+			$ca = lookup_ca($cpcfg['caref']);
+			$ca_crt = base64_decode($ca['crt']);
+		}
+		else 
+			$ca_crt = "";
 		/* generate lighttpd configuration */
 		$listenporthttps = $cpcfg['listenporthttps'] ? $cpcfg['listenporthttps'] : ($cpcfg['zoneid'] + 1);
 		system_generate_lighty_config("{$g['varetc_path']}/lighty-{$cpzone}-CaptivePortal-SSL.conf",
-			$cert, $key, $cacert, "lighty-{$cpzone}-CaptivePortal-SSL.pid", $listenporthttps, "/usr/local/captiveportal",
+			$cert_crt, $cert_prv, $ca_crt, "lighty-{$cpzone}-CaptivePortal-SSL.pid", $listenporthttps, "/usr/local/captiveportal",
 			"cert-portal.pem", "ca-portal.pem", "1", $use_fastcgi, $cpzone);
 	}
 
diff --git a/etc/inc/certs.inc b/etc/inc/certs.inc
index ec3227dede..862e91bf26 100644
--- a/etc/inc/certs.inc
+++ b/etc/inc/certs.inc
@@ -528,12 +528,24 @@ function is_webgui_cert($certref) {
 		return true;
 }
 
+function is_captiveportal_cert($certref) {
+	global $config;
+	if (!is_array($config['captiveportal']))
+		return;
+	foreach ($config['captiveportal'] as $portal) {
+		if ($portal['enable'] && $portal['httpslogin_enable'] && ($portal['certref'] == $certref))
+			return true;
+	}
+	return false;
+}
+
 function cert_in_use($certref) {
 	return (is_webgui_cert($certref) ||
 		is_user_cert($certref) ||
 		is_openvpn_server_cert($certref) ||
 		is_openvpn_client_cert($certref) ||
-		is_ipsec_cert($certref));
+		is_ipsec_cert($certref) ||
+		is_captiveportal_cert($certref));
 }
 
 /*
diff --git a/etc/inc/globals.inc b/etc/inc/globals.inc
index 519f28cb17..23c3a922b4 100644
--- a/etc/inc/globals.inc
+++ b/etc/inc/globals.inc
@@ -77,7 +77,7 @@ $g = array(
 	"disablecrashreporter" => false,
 	"crashreporterurl" => "http://crashreporter.pfsense.org/crash_reporter.php",
 	"debug" => false,
-	"latest_config" => "8.8",
+	"latest_config" => "8.9",
 	"nopkg_platforms" => array("cdrom"),
 	"minimum_ram_warning" => "101",
 	"minimum_ram_warning_text" => "128 MB",
diff --git a/etc/inc/upgrade_config.inc b/etc/inc/upgrade_config.inc
index bd128304b6..88faba4713 100644
--- a/etc/inc/upgrade_config.inc
+++ b/etc/inc/upgrade_config.inc
@@ -2883,4 +2883,43 @@ function upgrade_087_to_088() {
 		$config['system']['crypto_hardware'] = "glxsb";
 	}
 }
+
+function upgrade_088_to_089() {
+  global $config;
+  if (!is_array($config['ca']))
+    $config['ca'] = array();
+  if (!is_array($config['cert']))
+    $config['cert'] = array();
+    
+  /* migrate captive portal ssl to certifcate mngr */
+  if (is_array($config['captiveportal'])) {
+    foreach ($config['captiveportal'] as $id => &$setting) {
+      if (isset($setting['httpslogin'])) {
+        /* create cert entry */
+        $cert = array();
+        $cert['refid'] = uniqid();
+        $cert['descr'] = "Captive Portal SSL Cert - {$setting['zone']}";
+        $cert['crt'] = $setting['certificate'];
+        $cert['prv'] = $setting['private-key'];
+        $config['cert'][] = $cert;
+        
+        /* create cert reference */
+        unset($setting['certificate']);
+        unset($setting['private-key']);
+        $setting['certref'] = $cert['refid'];
+        
+        /* create ca entry */
+        $ca = array();
+        $ca['refid'] = uniqid();
+        $ca['descr'] = "Captive Portal SSL CA - {$setting['zone']}";
+        $ca['crt'] = $setting['cacertificate'];
+        $config['ca'][] = $ca;
+
+        /* create ca reference */
+        unset($setting['cacertificate']);
+        $setting['caref'] = $ca['refid'];
+      }
+    }
+  }
+}
 ?>
diff --git a/usr/local/www/services_captiveportal.php b/usr/local/www/services_captiveportal.php
index 6dd23aaded..dd59e7ad25 100755
--- a/usr/local/www/services_captiveportal.php
+++ b/usr/local/www/services_captiveportal.php
@@ -76,6 +76,16 @@ if ($_GET['act'] == "viewhtml") {
 	exit;
 }
 
+if (!is_array($config['ca']))
+	$config['ca'] = array();
+
+$a_ca =& $config['ca'];
+
+if (!is_array($config['cert']))
+	$config['cert'] = array();
+
+$a_cert =& $config['cert'];
+
 if ($a_cp[$cpzone]) {
 	$pconfig['zoneid'] = $a_cp[$cpzone]['zoneid'];
 	$pconfig['cinterface'] = $a_cp[$cpzone]['interface'];
@@ -97,9 +107,8 @@ if ($a_cp[$cpzone]) {
 	$pconfig['httpslogin_enable'] = isset($a_cp[$cpzone]['httpslogin']);
 	$pconfig['httpsname'] = $a_cp[$cpzone]['httpsname'];
 	$pconfig['preauthurl'] = strtolower($a_cp[$cpzone]['preauthurl']);
-	$pconfig['cert'] = base64_decode($a_cp[$cpzone]['certificate']);
-	$pconfig['cacert'] = base64_decode($a_cp[$cpzone]['cacertificate']);
-	$pconfig['key'] = base64_decode($a_cp[$cpzone]['private-key']);
+	$pconfig['certref'] = $a_cp[$cpzone]['certref'];
+	$pconfig['caref'] = $a_cp[$cpzone]['caref'];
 	$pconfig['logoutwin_enable'] = isset($a_cp[$cpzone]['logoutwin_enable']);
 	$pconfig['peruserbw'] = isset($a_cp[$cpzone]['peruserbw']);
 	$pconfig['bwdefaultdn'] = $a_cp[$cpzone]['bwdefaultdn'];
@@ -163,17 +172,9 @@ if ($_POST) {
 		}
 
 		if ($_POST['httpslogin_enable']) {
-		 	if (!$_POST['cert'] || !$_POST['key']) {
-				$input_errors[] = gettext("Certificate and key must be specified for HTTPS login.");
-			} else {
-				if (!strstr($_POST['cert'], "BEGIN CERTIFICATE") || !strstr($_POST['cert'], "END CERTIFICATE"))
-					$input_errors[] = gettext("This certificate does not appear to be valid.");
-				if (!strstr($_POST['cacert'], "BEGIN CERTIFICATE") || !strstr($_POST['cacert'], "END CERTIFICATE"))
-					$input_errors[] = gettext("This intermmediate certificate does not appear to be valid.");
-				if (!strstr($_POST['key'], "BEGIN RSA PRIVATE KEY") || !strstr($_POST['key'], "END RSA PRIVATE KEY"))
-					$input_errors[] = gettext("This key does not appear to be valid.");
+		 	if (!$_POST['certref']) {
+				$input_errors[] = gettext("Certificate must be specified for HTTPS login.");
 			}
-
 			if (!$_POST['httpsname'] || !is_domain($_POST['httpsname'])) {
 				$input_errors[] = gettext("The HTTPS server name must be specified for HTTPS login.");
 			}
@@ -263,9 +264,8 @@ if ($_POST) {
 		$newcp['peruserbw'] = $_POST['peruserbw'] ? true : false;
 		$newcp['bwdefaultdn'] = $_POST['bwdefaultdn'];
 		$newcp['bwdefaultup'] = $_POST['bwdefaultup'];
-		$newcp['certificate'] = base64_encode($_POST['cert']);
-		$newcp['cacertificate'] = base64_encode($_POST['cacert']);
-		$newcp['private-key'] = base64_encode($_POST['key']);
+		$newcp['certref'] = $_POST['certref'];
+		$newcp['caref'] = $_POST['caref'];
 		$newcp['logoutwin_enable'] = $_POST['logoutwin_enable'] ? true : false;
 		$newcp['nomacfilter'] = $_POST['nomacfilter'] ? true : false;
 		$newcp['noconcurrentlogins'] = $_POST['noconcurrentlogins'] ? true : false;
@@ -350,6 +350,7 @@ function enable_change(enable_change) {
 	var endis, radius_endis;
 	endis = !(document.iform.enable.checked || enable_change);
 	radius_endis = !((!endis && document.iform.auth_method[2].checked) || enable_change);
+	https_endis = !((!endis && document.iform.httpslogin_enable.checked) || enable_change);
 
 	document.iform.cinterface.disabled = endis;
 	//document.iform.maxproc.disabled = endis;
@@ -388,10 +389,9 @@ function enable_change(enable_change) {
 	document.iform.radmac_enable.disabled = radius_endis;
 	document.iform.httpslogin_enable.disabled = endis;
 	document.iform.radmac_format.disabled = radius_endis;
-	document.iform.httpsname.disabled = endis;
-	document.iform.cert.disabled = endis;
-	document.iform.cacert.disabled = endis;
-	document.iform.key.disabled = endis;
+	document.iform.httpsname.disabled = https_endis;
+	document.iform.certref.disabled = https_endis;
+	document.iform.caref.disabled = https_endis;
 	document.iform.logoutwin_enable.disabled = endis;
 	document.iform.nomacfilter.disabled = endis;
 	document.iform.noconcurrentlogins.disabled = endis;
@@ -860,37 +860,66 @@ function enable_change(enable_change) {
 	<tr>
       <td valign="top" class="vncell"><?=gettext("HTTPS login"); ?></td>
       <td class="vtable">
-        <input name="httpslogin_enable" type="checkbox" class="formfld" id="httpslogin_enable" value="yes" <?php if($pconfig['httpslogin_enable']) echo "checked"; ?>>
+        <input name="httpslogin_enable" type="checkbox" class="formfld" id="httpslogin_enable" value="yes" onClick="enable_change(false)" <?php if($pconfig['httpslogin_enable']) echo "checked"; ?>>
         <strong><?=gettext("Enable HTTPS login"); ?></strong><br>
-    <?=gettext("If enabled, the username and password will be transmitted over an HTTPS connection to protect against eavesdroppers. A server name, certificate and matching private key must also be specified below."); ?></td>
-	  </tr>
+    <?=gettext("If enabled, the username and password will be transmitted over an HTTPS connection to protect against eavesdroppers. A server name and certificate must also be specified below."); ?></td>
+	</tr>
 	<tr>
       <td valign="top" class="vncell"><?=gettext("HTTPS server name"); ?> </td>
       <td class="vtable">
         <input name="httpsname" type="text" class="formfld unknown" id="httpsname" size="30" value="<?=htmlspecialchars($pconfig['httpsname']);?>"><br>
 	<?php printf(gettext("This name will be used in the form action for the HTTPS POST and should match the Common Name (CN) in your certificate (otherwise, the client browser will most likely display a security warning). Make sure captive portal clients can resolve this name in DNS and verify on the client that the IP resolves to the correct interface IP on %s."), $g['product_name']);?> </td>
-	  </tr>
-	<tr>
-      <td valign="top" class="vncell"><?=gettext("HTTPS certificate"); ?></td>
-      <td class="vtable">
-        <textarea name="cert" cols="65" rows="7" id="cert" class="formpre"><?=htmlspecialchars($pconfig['cert']);?></textarea>
-        <br>
-    <?=gettext("Paste a signed certificate in X.509 PEM format here."); ?></td>
-	  </tr>
-	<tr>
-      <td valign="top" class="vncell"><?=gettext("HTTPS private key"); ?></td>
-      <td class="vtable">
-        <textarea name="key" cols="65" rows="7" id="key" class="formpre"><?=htmlspecialchars($pconfig['key']);?></textarea>
-        <br>
-    <?=gettext("Paste an RSA private key in PEM format here."); ?></td>
-	  </tr>
-        <tr>
-      <td valign="top" class="vncell"><?=gettext("HTTPS intermediate certificate"); ?></td>
-      <td class="vtable">
-        <textarea name="cacert" cols="65" rows="7" id="cacert" class="formpre"><?=htmlspecialchars($pconfig['cacert']);?></textarea>
-        <br>
-    <?=gettext("Paste a certificate in X.509 PEM format here."); ?></td>
-          </tr>
+	</tr>
+  <tr id="tls_ca">
+    <td width="22%" valign="top" class="vncell"><?=gettext("Certificate Authority"); ?></td>
+      <td width="78%" class="vtable">
+      <?php if (count($a_ca)): ?>
+      <select name='caref' class="formselect">
+        <option value=""><?=gettext("None"); ?></option>
+      <?php
+        foreach ($a_ca as $ca):
+          $selected = "";
+          if ($pconfig['caref'] == $ca['refid'])
+            $selected = "selected";
+      ?>
+        <option value="<?=$ca['refid'];?>" <?=$selected;?>><?=$ca['descr'];?></option>
+      <?php endforeach; ?>
+      </select>
+      <?php else: ?>
+        <b><?=gettext("No Certificate Authorities defined."); ?></b> <br/>Create one under <a href="system_camanager.php">System &gt; Cert Manager</a>.
+      <?php endif; ?>
+      </td>
+  </tr>
+  <tr id="tls_cert">
+    <td width="22%" valign="top" class="vncell"><?=gettext("Server Certificate"); ?></td>
+      <td width="78%" class="vtable">
+      <?php if (count($a_cert)): ?>
+      <select name='certref' class="formselect">
+        <option value=""><?=gettext("None"); ?></option>
+      <?php
+      foreach ($a_cert as $cert):
+        $selected = "";
+        $caname = "";
+        $inuse = "";
+        $revoked = "";
+        $ca = lookup_ca($cert['caref']);
+        if ($ca)
+          $caname = " (CA: {$ca['descr']})";
+        if ($pconfig['certref'] == $cert['refid'])
+          $selected = "selected";
+        if (cert_in_use($cert['refid']))
+          $inuse = " *In Use";
+        if (is_cert_revoked($cert))
+        $revoked = " *Revoked";
+      ?>
+        <option value="<?=$cert['refid'];?>" <?=$selected;?>><?=$cert['descr'] . $caname . $inuse . $revoked;?></option>
+      <?php endforeach; ?>
+      </select>
+      <?php else: ?>
+        <b><?=gettext("No Certificates defined."); ?></b> <br/>Create one under <a href="system_certmanager.php">System &gt; Cert Manager</a>.
+      <?php endif; ?>
+    </td>
+  </tr>
 	<tr>
 	  <td width="22%" valign="top" class="vncell"><?=gettext("Portal page contents"); ?></td>
 	  <td width="78%" class="vtable">
@@ -898,7 +927,7 @@ function enable_change(enable_change) {
 		<?php
 			list($host) = explode(":", $_SERVER['HTTP_HOST']);
 			$zoneid = $pconfig['zoneid'] ? $pconfig['zoneid'] : 8000;
-			if (isset($pconfig['httpslogin'])) {
+			if ($pconfig['httpslogin_enable']) {
 				$port = $pconfig['listenporthttps'] ? $pconfig['listenporthttps'] : ($zoneid + 1);
 				$href = "https://{$host}:{$port}";
 			} else {
diff --git a/usr/local/www/system_certmanager.php b/usr/local/www/system_certmanager.php
index 6622b40844..c9e9826e2b 100644
--- a/usr/local/www/system_certmanager.php
+++ b/usr/local/www/system_certmanager.php
@@ -1097,6 +1097,9 @@ function internalca_change() {
 							<?php if (is_ipsec_cert($cert['refid'])): ?>
 							IPsec Tunnel<br/>
 							<?php endif; ?>
+							<?php if (is_captiveportal_cert($cert['refid'])): ?>
+							Captive Portal<br/>
+							<?php endif; ?>
 						</td>
 						<td valign="middle" nowrap class="list">
 							<a href="system_certmanager.php?act=exp&id=<?=$i;?>">
