From 948cac6b583bb8dbd43667a2837f3e641d172844 Mon Sep 17 00:00:00 2001
From: BlackLight <blacklight@autistici.org>
Date: Sat, 25 Dec 2010 21:52:37 +0100
Subject: [PATCH] Multiuser support improved, su command

---
 blash.js                        |  40 +++++++++++++++
 blash.json                      |   7 +--
 commands/su.json                |  87 ++++++++++++++++++++++++++++++++
 commands/whoami.json            |  37 +++++++++++++-
 modules/users/.userlist.php.swp | Bin 12288 -> 0 bytes
 modules/users/.users.php.swp    | Bin 12288 -> 12288 bytes
 modules/users/userlist.php      |   2 +-
 modules/users/users.php         |  79 ++++++++++++++++++++++++++++-
 8 files changed, 246 insertions(+), 6 deletions(-)
 create mode 100644 commands/su.json
 delete mode 100644 modules/users/.userlist.php.swp

diff --git a/blash.js b/blash.js
index bc46107..30f6a74 100644
--- a/blash.js
+++ b/blash.js
@@ -13,6 +13,9 @@ var shell = null;
 function blash ()
 {
 	/************ ATTRIBUTES **************/
+	/** Current user */
+	this.user = '';
+
 	/** Object containing the parsed JSON configuration object */
 	this.json = {};
 
@@ -75,6 +78,38 @@ function blash ()
 		http.send ( null );
 	}
 
+	if ( document.cookie )
+	{
+		if ( document.cookie.match ( 'auth=' ) && document.cookie.match ( 'username=([^;]+);?' ))
+		{
+			this.user = RegExp.$1;
+			var params = 'action=getuser';
+			var users_php = window.location.href;
+			users_php = users_php.replace ( /\/([a-zA-Z\.]+)$/, '/modules/users/users.php' );
+
+			var xml = new XMLHttpRequest();
+			xml.open ( "POST", users_php, true );
+			xml.setRequestHeader ( "Content-type", "application/x-www-form-urlencoded" );
+			xml.setRequestHeader ( "Content-length", params.length );
+			xml.setRequestHeader ( "Connection", "close" );
+
+			xml.onreadystatechange = function ()
+			{
+				if ( xml.readyState == 4 && xml.status == 200 )
+				{
+					if ( xml.responseText.length > 0 )
+					{
+						shell.user = xml.responseText;
+					} else {
+						shell.user = shell.json.user;
+					}
+				}
+			}
+
+			xml.send ( params );
+		}
+	}
+
 	this.prompt.focus();
 
 	var json_config = window.location.href;
@@ -89,6 +124,11 @@ function blash ()
 		{
 			shell.json = eval ( '(' + http.responseText + ')' );
 
+			if ( shell.user == '' )
+			{
+				shell.user = shell.json.user;
+			}
+
 			shell.promptText.innerHTML = ( shell.json.promptText ) ? shell.json.promptText : "[%n@%m %W] $ ";
 			shell.promptText.innerHTML = shell.unescapePrompt ( promptText.innerHTML, shell.json.promptSequences );
 
diff --git a/blash.json b/blash.json
index 974ff6c..d8fca3c 100644
--- a/blash.json
+++ b/blash.json
@@ -24,9 +24,9 @@
 	"promptSequences" : [
 		{
 			"sequence" : "%n",
-			"default_text" : "blacklight",
+			"default_text" : "guest",
 			"text" : function ()  {
-				return shell.json.user;
+				return shell.user;
 			},
 		},
 		{
@@ -38,7 +38,7 @@
 		},
 		{
 			"sequence" : "%W",
-			"default_text" : "~",
+			"default_text" : "/",
 			"text" : function ()  {
 				return shell.path;
 			},
@@ -195,6 +195,7 @@
 		"ls",
 		"man",
 		"pwd",
+		"su",
 		"useradd",
 		"whoami",
 	],
diff --git a/commands/su.json b/commands/su.json
new file mode 100644
index 0000000..ea03868
--- /dev/null
+++ b/commands/su.json
@@ -0,0 +1,87 @@
+{
+	"name" : "su",
+
+	"info" : {
+		"syntax" : "su [username]",
+		"brief" : "Change user ID or become superuser",
+	},
+
+	"action" : function ( arg )
+	{
+		var out = '';
+
+		if ( !arg || arg.length == 0 )
+		{
+			arg = 'root';
+		}
+
+		if ( shell.__first_cmd )
+		{
+			shell.cmdOut.innerHTML = '<br/>';
+			shell.__first_cmd = false;
+		}
+
+		shell.getPassword = this.getPassword;
+		shell.newuser = arg;
+
+		shell.cmdOut.innerHTML += 'Password: <input type="password" ' +
+			'name="password" class="password" ' +
+			'onkeyup="shell.getPassword ( event )">' +
+			'<br/>';
+
+		shell.auto_prompt_focus = false;
+		shell.auto_prompt_refresh = false;
+
+		this.password = document.getElementsByName ( "password" )[0];
+		this.password.focus();
+
+		return out;
+	},
+
+	"getPassword" : function ( e )
+	{
+		var evt = ( window.event ) ? window.event : e;
+		var key = ( evt.charCode ) ? evt.charCode : evt.keyCode;
+		var password = document.getElementsByName ( "password" )[0];
+
+		if ( key == 13 && password.value.length > 0 )
+		{
+			var users_php = window.location.href;
+			users_php = users_php.replace ( /\/([a-zA-Z\.]+)$/, '/modules/users/users.php' );
+			params = 'action=login&user=' + escape ( shell.newuser ) + '&pass=' + md5 ( password.value );
+
+			var http = new XMLHttpRequest();
+			http.open ( "POST", users_php, true );
+			http.setRequestHeader ( "Content-type", "application/x-www-form-urlencoded" );
+			http.setRequestHeader ( "Content-length", params.length );
+			http.setRequestHeader ( "Connection", "close" );
+
+			http.onreadystatechange = function ()
+			{
+				if ( http.readyState == 4 && http.status == 200 )
+				{
+					if ( http.responseText.match ( /^Successfully logged in as '(.+?)'\s+(.*)\s*$/i ))
+					{
+						var user = RegExp.$1;
+						var auth = RegExp.$2;
+
+						shell.user = user;
+						shell.cmdOut.innerHTML = "Successfully logged in as '" + user + "'";
+					} else  {
+						shell.cmdOut.innerHTML = '';
+					}
+
+					shell.refreshPrompt ( false, false );
+				}
+			}
+
+			http.send ( params );
+
+			shell.cmdOut.innerHTML = '';
+			shell.auto_prompt_focus = true;
+			shell.auto_prompt_refresh = true;
+			shell.refreshPrompt ( false, false );
+		}
+	},
+}
+
diff --git a/commands/whoami.json b/commands/whoami.json
index 2e1dbf0..049a868 100644
--- a/commands/whoami.json
+++ b/commands/whoami.json
@@ -15,7 +15,42 @@
 			return "whoami: extra operand `" + arg + "'<br/>\n";
 		}
 
-		return shell.json.user + "<br/>\n";
+		if ( shell.user == shell.json.user )
+		{
+			return shell.json.user + "<br/>\n";
+		} else {
+			shell.auto_prompt_refresh = false;
+
+			var users_php = window.location.href;
+			users_php = users_php.replace ( /\/([a-zA-Z\.]+)$/, '/modules/users/users.php' );
+			params = 'action=getuser';
+
+			var http = new XMLHttpRequest();
+			http.open ( "POST", users_php, true );
+			http.setRequestHeader( "Content-type", "application/x-www-form-urlencoded" );
+			http.setRequestHeader( "Content-length", params.length );
+			http.setRequestHeader( "Connection", "close" );
+
+			http.onreadystatechange = function ()
+			{
+				if ( http.readyState == 4 && http.status == 200 )
+				{
+					if ( http.responseText.length > 0 )
+					{
+						shell.cmdOut.innerHTML = http.responseText + "\n";
+					} else {
+						shell.cmdOut.innerHTML = shell.json.user + "<br/>\n";
+					}
+
+					shell.auto_prompt_refresh = true;
+					shell.refreshPrompt ( false, false );
+				}
+			}
+
+			http.send ( params );
+			shell.cmdOut.innerHTML = '';
+			return out;
+		}
 	},
 }
 
diff --git a/modules/users/.userlist.php.swp b/modules/users/.userlist.php.swp
deleted file mode 100644
index 225fe82e97e1262078188cb7964271ddf855b2d2..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 12288
zcmYc?2=nw+FxN9?U|?VnU|@LsNYuCg0~5oYECz<8oW$hpoXqr$5|AWrT%MU%l3J8o
zT9S%e4M?UAVW56SNl8J9env@3esZyXQchxVhJJ2-N@-4Nv3_ZBY7vCY$t*6>E66AS
zX&%L+Aut*O<cC0MNt&(&FN3j>p@FiJqJpqcDEVfM>KqM$(GVC7fzc2c4S~@R7!85Z
z5Eu=C(GVDtAy87l$nc+mfq{vEfq{#Gfq@Z<hooml9X%QXqaiRF0;3@?8UmvsFd71*
zAut*OqaiRF0;3@?8UmvsfHedXQy3UR`571{@<ZnTL1O^F_!$^}@-r|z;b&l2!_UC5
zgr9+7Ha`QyEPe)tsr(EKQ=sa9@nJP`RB$u|MnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU
z1V%$(Gz11y2-w>(FhuzJSTiu#fR>yq<R#{&+A1X$rzj~DBo-IjDw$gtnwnXfr6wn(
z875nrrJ7k-nk1Q<Tbh`fr5GC<q$(+7<b$;6gD8EFMtwVEqjK_dNH+?}RgjhNb`a+k
z+cDVKSLEg>l%*CGXXfYGDjDh-C@G}oCFiGP=B3*zg@(B4S|}+Lmn7z;B<AGjrP?Z0
mrWPyN+cBtA<mM#j=ar=9l_=OM*x1-a`1&v~*w}+s)&l@NeS$Oq

diff --git a/modules/users/.users.php.swp b/modules/users/.users.php.swp
index 21565a08a031df67544dafea0e404665a73514e1..74c3fa5ec14fafde2ab681da86a53a03d7ae73bc 100644
GIT binary patch
delta 1638
zcmZojXh;xGG6?hZRWR2xW?*1o5MW@~7a``mV>-h|@vr=h6F2h;eCOxYU}RuuV1`If
zoGhqNUcZl*fng&r1H)Qg28K1f3=Ac_3=9Rl3=9su3=GD+3=I0b3=Dd_3=DsG7#M!=
zFfi=pVPM$7!@$ta!@y9<!@y9&!@y9$!@!Ww!@%Iq!@wZU!@%&In}J~sHv_|JZU%;G
zZU%;OZUzQRZUzP&ZUzPoZUzQ*ZU%;PTnr3*xESggc5^W>L~=1O1aL7h_;WEZIB+pA
z$a66;{NrR`_{+(_aFUaO;V35q!wyachAo^744XL_80tA07^*oL7}Pi!7$i9v7(_W4
z7(_T3818T|Fx=o^U|7Myz%ZMGfnhoa1H&{928Kuu28K`$1_mh(1_n_M28LVg3=CJ;
z85pLs*E2A5urn}JvokQ5vNJGzV`E@A!^XgHnvH>>pN)Z`fsKKoij9Gxl#PL*kd1+%
zfQ^B{nT>(Lij9H6l8u2ugN=dVF)IVZeO3mBWvmPg3t1T$3RoE!l2{oSVp$m&Vptg%
z<X9OPBv~04F0n8$oMB;LXk%euXk}qw2x4Ji@J?i5U{GgaU=U|vVBln7VEDq!!0?2b
zf#EJQ1H*M@28K(_3=9{U85s66GcasoW?)#y%)qdgnSo&rGXui}W(J0KW(I~<W(I~9
zW(I~vW=P~lGBYqlF*7juGBYr|VVbzHUEAJ{fuWXxlQXF(H8I<ofs?Z+wWPEtPr(qx
zE-1>(D^XBNFHJ2jQL>(_s4H6!Wiv2va&m(7!AJ&}L7)@{W8*gzt_8m`u-zd0K-Nvx
z)D^|)2B?Ej{lLk|$%*O@kkdIiYZX#+ic=M;Av~D34M5&TXi=%i&C#_hElw?pR>_Qw
zR?kb!O;zWKg(?E+oxD*;JR`BRBtu6*CEnTJ-`mqQS{=k!k5$mr1UZ|NlT!sGpkS+z
zn_{Y<p@7xUSOq-{iGsx9VvsQq>#7+zCvVizmxbE`au(P@V4FBOIYBBu=xB;4sHrI^
zs-)$Y=A~FGsAOtuD`+xIPS=s2Y^STi0#=owYf%qY&zYH~prMdiT%1}0av4^$LB?UK
z0C@@II86r5<iz4s1@-jQ5|E43tw5fJM=3PuLyJ?3KyFpY%P&y?yR6<yL0tu;0VJ#*
zlc!`2(g%uTXf%SE@VJCU4Ai{f(&XgS;^MT@oSaI9oc#3k)D(rxJcYz!WJ49e;SMvJ
zlasSJwIn$|KRYv3K|`S)5=%M|MLG%wItohqN(!2gz(!H34tJ&wMjU}%AB&+KY%|^%
zuU97=<)~>CIcFjgb$C&JUb+G(sg&mzr6?2><(Flqq^2mO<rgV{+>IO{;Gh7d?rH{3
z4o*%;<WJtEBP#;ZuO6$TpaNom4bs${yjmxZ8x;A_v@}^#clqWVJz++Uoc#36JasFE
P&CXi=%$x7&Dlq{7Xa95U

delta 277
zcmZojXh;xGG6?hZRWR2xW?*1o5MW@~^hnfqDi6~}@vr=hE}MA;zVq`+axyU3azUhB
zCJQQ**KguwU|7n_z_5^)fnfnJ149Nc149Zg1A_@K1A{s*1A{Uz1A`JT1H%U%28K60
z3=A827#P;@Ffdf}FfiouFfe5BFfgR>Ffb(ZFfds2FfefQFfiQaW?)#r&A>39n}H#p
zn}H#ln}I=>n}I=rn}I=wn}I=^n}OjF7X!lvE(Upq^;`@LzFZ6pE?f)@PFxHOj$8~3
zc3co=YIAL7WckaXU~k93P|Ltz&j4X?awZj}CT4@Y2@%=suhq}Yt*%m#SX^A5UzDQ0
J`L3=q6989&F023m

diff --git a/modules/users/userlist.php b/modules/users/userlist.php
index 29108df..5111870 100644
--- a/modules/users/userlist.php
+++ b/modules/users/userlist.php
@@ -3,7 +3,7 @@
 $xmlcontent = <<<XML
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <users>
-</users>
+<user name="blacklight" pass="26cc112004f6e530291f74d193a0c0b4" home="/home/blacklight"/></users>
 
 XML;
 
diff --git a/modules/users/users.php b/modules/users/users.php
index e381134..971346a 100644
--- a/modules/users/users.php
+++ b/modules/users/users.php
@@ -27,7 +27,7 @@ switch ( $action )
 
 		if ( preg_match ( '/[^a-zA-Z0-9]/', $password ) || strlen ( $password ) != 32 )
 		{
-			print "The provided password '$password' is not a valid hash\n";
+			print "The provided password is not a valid hash\n";
 			return 1;
 		}
 
@@ -62,6 +62,83 @@ switch ( $action )
 
 		print 'User "'.$username.' successfully added, home directory set to "/home/'.$username."\"\n";
 		break;
+
+	case 'login':
+		$username = $_REQUEST['user'];
+		$password = $_REQUEST['pass'];
+
+		if ( !( $username != null && $password != null ))
+		{
+			die ("");
+		}
+
+		if ( preg_match ( '/[^a-zA-Z0-9_]/', $username ))
+		{
+			print "The username can only contain characters in the charset '[a-zA-Z0-9_]'\n";
+			return 1;
+		}
+
+		if ( !( $xml = new SimpleXMLElement ( $xmlcontent )))
+		{
+			print "Unable to open the users XML file\n";
+			return 1;
+		}
+
+		for ( $i = 0; $i < count ( $xml->user ) && !$found; $i++ )
+		{
+			if ( !strcasecmp ( $xml->user[$i]['name'], $username ))
+			{
+				if ( strcasecmp ( $xml->user[$i]['pass'], $password ))
+				{
+					print "Wrong password provided for user '$username'\n";
+					return 1;
+				} else {
+					$auth = md5 ( $xml->user[$i]['name'] . $xml->user[$i]['pass'] );
+					setcookie ( 'username', $xml->user[$i]['name'], 0, "/" );
+					setcookie ( 'auth', $auth, 0, "/" );
+
+					print "Successfully logged in as '$username' $auth\n";
+					return 0;
+				}
+			}
+		}
+
+		print "Username not found: '$username'\n";
+		break;
+
+	case 'getuser':
+		if ( isset ( $_COOKIE['username'] ) && isset ( $_COOKIE['auth'] ))
+		{
+			if ( !( $xml = new SimpleXMLElement ( $xmlcontent )))
+			{
+				print "Unable to open the users XML file\n";
+				return 1;
+			}
+
+			for ( $i = 0; $i < count ( $xml->user ) && !$found; $i++ )
+			{
+				if ( !strcasecmp ( $xml->user[$i]['name'], $_COOKIE['username'] ))
+				{
+					$auth = md5 ( $xml->user[$i]['name'] . $xml->user[$i]['pass'] );
+
+					if ( !strcasecmp ( $auth, $_COOKIE['auth'] ))
+					{
+						print $xml->user[$i]['name'];
+						return 0;
+					} else {
+						print "guest";
+						return 1;
+					}
+				}
+			}
+
+			print "guest";
+			return 1;
+		}
+
+		print "guest";
+		return 1;
+		break;
 }
 
 ?>