commit 6e0b68bfdea29b2943b6f104373f43cc56537bd8
Author: jim-p <jimp@pfsense.org>
Date:   Fri May 25 16:33:29 2012 -0400

    List logged-in IPsec xauth users and provide a mechanism to disconnect them. Implements #1986

diff --git a/etc/inc/ipsec.inc b/etc/inc/ipsec.inc
index 867081f85a..08d66e4107 100644
--- a/etc/inc/ipsec.inc
+++ b/etc/inc/ipsec.inc
@@ -497,6 +497,37 @@ function ipsec_dump_sad()
 	return $sad;
 }
 
+/*
+ * Return dump of mobile user list
+ */
+function ipsec_dump_mobile() {
+	$command = "/usr/local/sbin/racoonctl show-users";
+	$fd = @popen($command, "r");
+	$mobile = array();
+	if ($fd) {
+		while (!feof($fd)) {
+			$user = array();
+			$line = chop(fgets($fd));
+			if (!$line)
+				continue;
+			if ($line == "User|Source|Destination|CreatedOn|SPI")
+				continue;
+
+			// jim|192.168.20.243:4500|192.168.20.5:24146|2012-05-25 09:54:39|989d10e1e2d4eca4:7243830d5fd2afe7
+			$linea = explode("|", trim($line));
+			$user['username'] = $linea[0];
+			$user['local'] = $linea[1];
+			$user['remote'] = $linea[2];
+			$user['logintime'] = $linea[3];
+			$user['spi'] = $linea[4];
+			$mobile[] = $user;
+		}
+		pclose($fd);
+	}
+
+	return $mobile;
+}
+
 function ipsec_mobilekey_sort() {
 	global $config;
 
@@ -524,4 +555,10 @@ function ipsec_get_number_of_phase2($ikeid) {
 	return $nbph2;
 }
 
+function ipsec_disconnect_mobile($username) {
+	if (empty($username))
+		return false;
+	exec("/usr/local/sbin/racoonctl logout-user " . escapeshellarg($username));
+}
+
 ?>
diff --git a/usr/local/www/diag_ipsec.php b/usr/local/www/diag_ipsec.php
index 7eae5ec445..3729fd1f8d 100644
--- a/usr/local/www/diag_ipsec.php
+++ b/usr/local/www/diag_ipsec.php
@@ -57,6 +57,15 @@ if ($_GET['act'] == "connect") {
 	}
 }
 
+
+if ($_GET['act'] == "disconnect") {
+	if (!empty($_GET['user'])) {
+		ipsec_disconnect_mobile($_GET['user']);
+		sleep(1);
+		$savemsg = gettext("Disconnected user") . " " . $_GET['user'];
+	}
+}
+
 if (!is_array($config['ipsec']['phase2']))
     $config['ipsec']['phase2'] = array();
 
@@ -64,10 +73,11 @@ $a_phase2 = &$config['ipsec']['phase2'];
 
 $spd = ipsec_dump_spd();
 $sad = ipsec_dump_sad();
+$mobile = ipsec_dump_mobile();
 
 ?>
 
-<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?php echo $jsevents["body"]["onload"]; ?>">
 <?php include("fbegin.inc"); ?>
 <div id="inputerrors"></div>
 <table width="100%" border="0" cellpadding="0" cellspacing="0">
@@ -84,19 +94,24 @@ $sad = ipsec_dump_sad();
 		</td>
 	</tr>
 	<tr>
-    	<td>
+	<td>
 			<div id="mainarea">
 				<table width="100%" border="0" cellpadding="6" cellspacing="0" class="tabcont sortable">
+					<thead>
 					<tr>
-						<td nowrap class="listhdrr"><?=gettext("Local IP");?></td>
-						<td nowrap class="listhdrr"><?=gettext("Remote IP");?></a></td>
-						<td nowrap class="listhdrr"><?=gettext("Local Network");?></td>
-						<td nowrap class="listhdrr"><?=gettext("Remote Network");?></a></td>
-						<td nowrap class="listhdrr"><?=gettext("Description");?></a></td>
-						<td nowrap class="listhdrr"><?=gettext("Status");?></td>
+						<th nowrap class="listhdrr"><?php echo gettext("Local IP");?></th>
+						<th nowrap class="listhdrr"><?php echo gettext("Remote IP");?></a></th>
+						<th nowrap class="listhdrr"><?php echo gettext("Local Network");?></th>
+						<th nowrap class="listhdrr"><?php echo gettext("Remote Network");?></a></th>
+						<th nowrap class="listhdrr"><?php echo gettext("Description");?></a></th>
+						<th nowrap class="listhdrr"><?php echo gettext("Status");?></th>
 					</tr>
+					</thead>
+					<tbody>
 					<?php
 						foreach ($a_phase2 as $ph2ent) {
+							if ($ph2ent['remoteid']['type'] == "mobile")
+								continue;
 							ipsec_lookup_phase1($ph2ent,$ph1ent);
 							if (!isset($ph2ent['disabled']) && !isset($ph1ent['disabled'])) {
 								if(ipsec_phase2_status($spd,$sad,$ph1ent,$ph2ent)) {
@@ -112,10 +127,10 @@ $sad = ipsec_dump_sad();
 					?>
 					<tr>
 						<td class="listlr">
-							<?=htmlspecialchars(ipsec_get_phase1_src($ph1ent));?>
+							<?php echo htmlspecialchars(ipsec_get_phase1_src($ph1ent));?>
 						</td>
 						<td class="listr">
-							<?=htmlspecialchars($ph1ent['remote-gateway']);?>
+							<?php echo htmlspecialchars($ph1ent['remote-gateway']);?>
 						</td>
 						<td class="listr">
 							<?php echo ipsec_idinfo_to_text($ph2ent['localid']); ?>
@@ -123,10 +138,10 @@ $sad = ipsec_dump_sad();
 						<td class="listr">
 							<?php echo ipsec_idinfo_to_text($ph2ent['remoteid']); ?>
 						</td>
-						<td class="listr"><?=htmlspecialchars($ph2ent['descr']);?></td>
+						<td class="listr"><?php echo htmlspecialchars($ph2ent['descr']);?></td>
 						<td class="listr">
 							<center>
-								<img src ="/themes/<?=$g['theme']?>/images/icons/icon_<?=$icon?>.gif" title="<?=$status?>">
+								<img src ="/themes/<?php echo $g['theme']; ?>/images/icons/icon_<?php echo $icon; ?>.gif" title="<?php echo $status; ?>">
 							</center>
 						</td>
 						<td class="list">
@@ -155,8 +170,8 @@ $sad = ipsec_dump_sad();
 							?>
 							<?php if (($ph2ent['remoteid']['type'] != "mobile") && ($icon != "pass") && ($source != "")): ?>
 							<center>
-								<a href="diag_ipsec.php?act=connect&remoteid=<?= $ph2ent['remoteid']['address'] ?>&source=<?= $source ?>">
-								<img src ="/themes/<?=$g['theme']?>/images/icons/icon_service_start.gif" alt="Connect VPN" title="Connect VPN" border="0">
+								<a href="diag_ipsec.php?act=connect&remoteid=<?php echo $ph2ent['remoteid']['address']; ?>&source=<?php echo $source; ?>">
+								<img src ="/themes/<?php echo $g['theme']; ?>/images/icons/icon_service_start.gif" alt="Connect VPN" title="Connect VPN" border="0">
 								</a>
 							</center>
 							<?php else: ?>
@@ -168,7 +183,32 @@ $sad = ipsec_dump_sad();
 							}
 						}
 					?>
+					</tbody>
+				</table>
+				<?php if (isset($config['ipsec']['client']['enable'])): ?>
+				<table width="100%" border="0" cellpadding="6" cellspacing="0" class="tabcont sortable">
+					<thead>
+					<tr>
+						<th nowrap class="listhdrr"><?php echo gettext("Mobile User");?></th>
+						<th nowrap class="listhdrr"><?php echo gettext("Login Time");?></a></th>
+						<th nowrap class="listhdrr"><?php echo gettext("Local");?></th>
+						<th nowrap class="listhdrr"><?php echo gettext("Remote");?></a></th>
+						<th nowrap class="list">&nbsp;</th>
+					</tr>
+					</thead>
+					<tbody>
+					<?php	foreach ($mobile as $muser): ?>
+					<tr>
+						<td class="listlr"><?php echo $muser['username']; ?></td>
+						<td class="listr" align="center"><?php echo $muser['logintime']; ?></td>
+						<td class="listr" align="center"><?php echo $muser['local']; ?></td>
+						<td class="listr" align="center"><?php echo $muser['remote']; ?></td>
+						<td class="list" align="center"><a href="diag_ipsec.php?act=disconnect&user=<?php echo $muser['username']; ?>"><img src='/themes/<?php echo $g['theme']; ?>/images/icons/icon_x.gif' height='17' width='17' border='0'/></a></td>
+					</tr>
+					<?php	endforeach; ?>
+					</tbody>
 				</table>
+				<?php endif; ?>
 			</div>
 		</td>
 	</tr>
@@ -178,9 +218,9 @@ $sad = ipsec_dump_sad();
 
 <span class="vexpl">
 	<span class="red">
-		<strong><?=gettext("Note:");?><br /></strong>
+		<strong><?php echo gettext("Note:");?><br /></strong>
 	</span>
-	<?=gettext("You can configure your IPsec");?> 
+	<?php echo gettext("You can configure IPsec");?>
 	<a href="vpn_ipsec.php">here</a>.
 </span>
 
diff --git a/usr/local/www/widgets/widgets/ipsec.widget.php b/usr/local/www/widgets/widgets/ipsec.widget.php
index dd0c10e491..e7b29e6ec3 100644
--- a/usr/local/www/widgets/widgets/ipsec.widget.php
+++ b/usr/local/www/widgets/widgets/ipsec.widget.php
@@ -37,123 +37,155 @@ require_once("guiconfig.inc");
 require_once("functions.inc");
 require_once("ipsec.inc");
 
-	if (isset($config['ipsec']['phase1'])){?>
+if (isset($config['ipsec']['phase1'])){?>
 	<div>&nbsp;</div>
-	<?php	
+	<?php
 	$tab_array = array();
 	$tab_array[0] = array("Overview", true, "ipsec-Overview");
-	$tab_array[1] = array("Tunnel Status", false, "ipsec-tunnel");
+	$tab_array[1] = array("Tunnels", false, "ipsec-tunnel");
+	$tab_array[2] = array("Mobile", false, "ipsec-mobile");
 	display_widget_tabs($tab_array);
 
 	$spd = ipsec_dump_spd();
 	$sad = ipsec_dump_sad();
+	$mobile = ipsec_dump_mobile();
 
 	$activecounter = 0;
 	$inactivecounter = 0;
-	
+
 	$ipsec_detail_array = array();
-		foreach ($config['ipsec']['phase2'] as $ph2ent){ 
-			ipsec_lookup_phase1($ph2ent,$ph1ent);
-			$ipsecstatus = false;
-			
-			$tun_disabled = "false";
-			$foundsrc = false;
-			$founddst = false; 
-	
-			if (isset($ph1ent['disabled']) || isset($ph2ent['disabled'])) {
-				$tun_disabled = "true";
-				continue;
-			}
-			
-			if(ipsec_phase2_status($spd,$sad,$ph1ent,$ph2ent)) {
-				/* tunnel is up */
-				$iconfn = "true";
-				$activecounter++;
-			} else {
-				/* tunnel is down */
-				$iconfn = "false";
-				$inactivecounter++;
-			}
-			
-			$ipsec_detail_array[] = array('src' => $ph1ent['interface'],
-						'dest' => $ph1ent['remote-gateway'],
-						'remote-subnet' => ipsec_idinfo_to_text($ph2ent['remoteid']),
-						'descr' => $ph2ent['descr'],
-						'status' => $iconfn,
-						'disabled' => $tun_disabled);
+	foreach ($config['ipsec']['phase2'] as $ph2ent){
+		if ($ph2ent['remoteid']['type'] == "mobile")
+			continue;
+		ipsec_lookup_phase1($ph2ent,$ph1ent);
+		$ipsecstatus = false;
+
+		$tun_disabled = "false";
+		$foundsrc = false;
+		$founddst = false;
+
+		if (isset($ph1ent['disabled']) || isset($ph2ent['disabled'])) {
+			$tun_disabled = "true";
+			continue;
 		}
+
+		if(ipsec_phase2_status($spd,$sad,$ph1ent,$ph2ent)) {
+			/* tunnel is up */
+			$iconfn = "true";
+			$activecounter++;
+		} else {
+			/* tunnel is down */
+			$iconfn = "false";
+			$inactivecounter++;
+		}
+
+		$ipsec_detail_array[] = array('src' => $ph1ent['interface'],
+					'dest' => $ph1ent['remote-gateway'],
+					'remote-subnet' => ipsec_idinfo_to_text($ph2ent['remoteid']),
+					'descr' => $ph2ent['descr'],
+					'status' => $iconfn,
+					'disabled' => $tun_disabled);
 	}
-	
+}
+
 	if (isset($config['ipsec']['phase2'])){ ?>
 
 <div id="ipsec-Overview" style="display:block;background-color:#EEEEEE;">
 	<div>
-	  <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">	
-		  <tr>
-		        <td nowrap class="listhdrr">Active Tunnels</td>
-		        <td nowrap class="listhdrr">Inactive Tunnels</td>
-			</tr>
-			<tr>
-				<td class="listlr"><?=$activecounter;?></td>
-				<td class="listr"><?=$inactivecounter;?></td>
-			</tr>
-		</table>
+	<table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">
+	<tr>
+		<td nowrap class="listhdrr">Active Tunnels</td>
+		<td nowrap class="listhdrr">Inactive Tunnels</td>
+		<td nowrap class="listhdrr">Mobile Users</td>
+	</tr>
+	<tr>
+		<td class="listlr"><?php echo $activecounter; ?></td>
+		<td class="listr"><?php echo $inactivecounter; ?></td>
+		<td class="listr"><?php echo count($mobile); ?></td>
+	</tr>
+	</table>
 	</div>
 </div>
 
 <div id="ipsec-tunnel" style="display:none;background-color:#EEEEEE;">
 	<div style="padding: 10px">
 		<div style="display:table-row;">
-	                <div class="widgetsubheader" style="display:table-cell;width:40px">Source</div>
-	                <div class="widgetsubheader" style="display:table-cell;width:100px">Destination</div>
-	                <div class="widgetsubheader" style="display:table-cell;width:90px">Description</div>
-	                <div class="widgetsubheader" style="display:table-cell;width:30px">Status</div>				
+			<div class="widgetsubheader" style="display:table-cell;width:40px">Source</div>
+			<div class="widgetsubheader" style="display:table-cell;width:100px">Destination</div>
+			<div class="widgetsubheader" style="display:table-cell;width:90px">Description</div>
+			<div class="widgetsubheader" style="display:table-cell;width:30px">Status</div>
 		</div>
 		<div style="max-height:105px;overflow:auto;">
 	<?php
 	foreach ($ipsec_detail_array as $ipsec) :
-		
+
 		if ($ipsec['disabled'] == "true"){
 			$spans = "<span class=\"gray\">";
 			$spane = "</span>";
-		} 
+		}
 		else {
 			$spans = $spane = "";
-		}		
+		}
 
 		?>
-	
+
 		<div style="display:table-row;">
 			<div class="listlr" style="display:table-cell;width:39px">
-				<?=$spans;?>
-					<?=htmlspecialchars($ipsec['src']);?>						
-				<?=$spane;?>
+				<?php echo $spans;?>
+					<?php echo htmlspecialchars($ipsec['src']);?>
+				<?php echo $spane;?>
 			</div>
-			<div class="listr"  style="display:table-cell;width:100px"><?=$spans;?>			
-				<?=$ipsec['remote-subnet'];?>
+			<div class="listr"  style="display:table-cell;width:100px"><?php echo $spans;?>
+				<?php echo $ipsec['remote-subnet'];?>
 				<br/>
-				(<?=htmlspecialchars($ipsec['dest']);?>)<?=$spane;?>
+				(<?php echo htmlspecialchars($ipsec['dest']);?>)<?php echo $spane;?>
 			</div>
-			<div class="listr"  style="display:table-cell;width:90px"><?=$spans;?><?=htmlspecialchars($ipsec['descr']);?><?=$spane;?></div>
-			<div class="listr"  style="display:table-cell;width:37px"><?=$spans;?><center>
-			<?php 
-			
-			if($ipsec['status'] == "true") { 
+			<div class="listr"  style="display:table-cell;width:90px"><?php echo $spans;?><?php echo htmlspecialchars($ipsec['descr']);?><?php echo $spane;?></div>
+			<div class="listr"  style="display:table-cell;width:37px"><?php echo $spans;?><center>
+			<?php
+
+			if($ipsec['status'] == "true") {
 				/* tunnel is up */
 				$iconfn = "interface_up";
 			} else {
 				/* tunnel is down */
 				$iconfn = "interface_down";
 			}
-			
+
 			echo "<img src ='/themes/{$g['theme']}/images/icons/icon_{$iconfn}.gif'>";
-						
-			?></center><?=$spane;?></div>
+
+			?></center><?php echo $spane;?></div>
 		</div>
 	<?php endforeach; ?>
 	</div>
  </div>
-</div><?php //end ipsec tunnel
+</div>
+<div id="ipsec-mobile" style="display:none;background-color:#EEEEEE;">
+	<div style="padding: 10px">
+		<div style="display:table-row;">
+			<div class="widgetsubheader" style="display:table-cell;width:140px">User/Time</div>
+			<div class="widgetsubheader" style="display:table-cell;width:130px">Local/Remote</div>
+			<div class="widgetsubheader" style="display:table-cell;width:30px">&nbsp;</div>
+		</div>
+		<div style="max-height:105px;overflow:auto;">
+<?php	foreach ($mobile as $muser) : ?>
+		<div style="display:table-row;">
+			<div class="listlr" style="display:table-cell;width:139px">
+				<?php echo htmlspecialchars($muser['username']);?><br/>
+				<?php echo htmlspecialchars($muser['logintime']);?>
+			</div>
+			<div class="listr"  style="display:table-cell;width:130px">
+				<?php echo htmlspecialchars($muser['local']);?><br/>
+				<?php echo htmlspecialchars($muser['remote']);?>
+			</div>
+			<div class="listr"  style="display:table-cell;width:30px">
+				<center><a href="diag_ipsec.php?act=disconnect&user=<?php echo $muser['username']; ?>"><img src='/themes/<?php echo $g['theme']; ?>/images/icons/icon_x.gif' height='17' width='17' border='0'/></a></center>
+			</div>
+		</div>
+<?php	endforeach; ?>
+	</div>
+</div>
+<?php //end ipsec tunnel
 }//end if tunnels are configured, else show code below
 else { ?>
 <div style="display:block">
@@ -167,7 +199,7 @@ else { ?>
 	              Note: There are no configured IPsec Tunnels<br />
 	            </strong>
 	          </span>
-	          You can configure your IPsec 
+	          You can configure your IPsec
 	          <a href="vpn_ipsec.php">here</a>.
 	        </span>
 	      </p>
@@ -175,6 +207,4 @@ else { ?>
 	  </tr>
 	</table>
 </div>
-<? } ?>
-
-
+<? } ?>
\ No newline at end of file
