I.T. Security and Linux Administration

Sep 1 2011   9:09PM GMT

[Revisited] SquirrelMail PHP Hack

Eric Hansen Eric Hansen Profile: Eric Hansen

Even though I just posted an article on listing domains in SquirrelMail earlier today, I decided to revamp it a little more.  Now, it works the same, but looks a little bit more like the old-school Hotmail log in, where you had the area to put in your username, and then next to it is the domain(s) to choose from.  However, I’ve added another little tweak to it as well, which I’ll showcase, just “continue”…!

The first file to edit will be functions/constants.php.  There’s only 1 line of code to actually add, which I placed at the end.  Before the do_hook() line, put this:

/* Define constants for listing domains. */

define(‘SM_LISTDOMAINS’, 1);

This will be used later on to determine whether the domains should be listed or not (i.e.: see the updated image for this post).  If you don’t want domains listed, change the 1 to a 0.

Next, we’ll edit functions/forms.php.  There’s two things we need to do here.   The first, which is the easiest, is edit the first function, addInputField().  What you’ll want to do is take out the “\n” part at the end of the return code, as seen in bold here:

function addInputField($type, $name = null, $value = null, $attributes = ”) {

return ‘<input type=”‘.$type.'”‘.

($name  !== null ? ‘ name=”‘.htmlspecialchars($name).'”‘   : ”).

($value !== null ? ‘ value=”‘.htmlspecialchars($value).'”‘ : ”).

$attributes . ” />”;


If you’re wondering why this two-character change is being done, its because without it, it’ll not look pretty (it seems that the html_tag() function has a built-in nl2br() into it).  This is done to make it not look broken.  The next part of this file, while very slightly more advanced than the code in the previous article of fetching domains, isn’t very strange at all, but is commented for the fun of it.  Place the following at the end of the page:

/** listDomains(): lists all (or only current) domain(s).  $form_name is the name of the form item. **/

function listDomains($form_name){

// Shouldn’t surprise you what this does…

$currd = str_replace(“www.”, “”, $_SERVER[‘HTTP_HOST’]);

// This is where that define comes in handy


// Change required information…YMMV, works for my set up though.

mysql_connect(“localhost”, “un”, “pw”) or die(“Cannot connect to database.”);


// LIMIT 1,30 because my system puts in a ALL domain…and, well, 30 because I can.

$q = mysql_query(“SELECT domain FROM domain LIMIT 1,30″);

// Store domains into an array

$domains = array();

$i = 0;

while($res = mysql_fetch_array($q)){

$domains[$i] = $res[‘domain’];



// Same code as before, just condensed

return addSelect($form_name, $domains, $currd);


// We don’t want to list domains, print only current domain, and make it a hidden item as well

return $currd .”\n”. addHidden($form_name, $currd);


This function is pretty self-explanatory, so I’m not going to go into it.  However, as before, you have to make the necessary changes.  I like this, though, as it doesn’t necessarily give a “no entry” to non-virtual systems.  The change to reflect non-virtual systems, however, is essentially a scandir() away (hehe).

Okay, so now that we’re done with this, we’ll go ahead and edit the src/login.php file again, reflecting these new changes.  First thing I did was delete all the code placed in the previous article, except for the $domain_form_name =… line.  After that, I went down to the html_tag() that had the addInput($username_form_name,…) code, and modified it like so:

html_tag( ‘td’,

addInput($username_form_name, $loginname_value, 0, 0, ‘ onfocus=”alreadyFocused=true;” size=”10″‘) .”@”.

listDomains($domain_form_name) ,

‘left’, ”, ‘width=”70%”‘ )

) . “\n” .

The changes made are in bold.  First, I added the “size” attribute to the input field because its just too wide for this feature.  Now, before you get all happy, yes, this will work…but it’ll still look ugly if you visit your log in page right now, which I’ll get into in a second.  Second, after the addInput() line, I put “. “@” . listDomains($domain_form_name)” so it will look something like this to the end-user:


You don’t have to, but this was the whole purpose of this article, but you can also make it look how you want.  A little side-note below will show how to not even make the domain visible.

Now, finally, to make it all stretch out nice and evenly, you’ll probably have to edit (unless you’re lucky) the width of the table row.  To do this, near the bottom of the page, not far above from do_hook(‘login_form’), there’ll be a line that looks like this:

”, $color[4], ‘border=”0″ width=”350″‘ ) . ‘</center>’,

What you’ll wanna do here is edit the “width” value until your page looks like the screenshot I provided for this post.  Since its dependent on your page’s layout and such, I can’t give any exact numbers to do, but mine had  to end up being 448 before it looked correct.

Side Note As I said, there is a way to make it so the domain doesn’t even have to be visible to the end user (unless they view the source of the page).  Granted, you can take it one step further by editing the src/redirect.php file, I’ll leave that for homework.  What you want to do here, however, is remove the “. “@” . listDomains(…)” part of src/login.php.  Then, pretty much anywehre between the ‘<form>’ and ‘</form>’ tags, you will add the following:

addHidden(‘domain’, str_replace(“www.”, “”, $_SERVER[‘HTTP_HOST’]));

This will make the domain hidden from the form, so the user can’t see it, but still passed through when submitted, so authentication will work.

 Comment on this Post

There was an error processing your information. Please try again later.
Thanks. We'll let you know when a new response is added.
Send me notifications when other members comment.

Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to:

Share this item with your network: