Unbreakable login script?

Coding Critique is the place to post source code for peer review by other members of DevNetwork. Any kind of code can be posted. Code posted does not have to be limited to PHP. All members are invited to contribute constructive criticism with the goal of improving the code. Posted code should include some background information about it and what areas you specifically would like help with.

Popular code excerpts may be moved to "Code Snippets" by the moderators.

Moderator: General Moderators

Post Reply
ben.artiss
Forum Contributor
Posts: 116
Joined: Fri Jan 23, 2009 3:04 pm

Unbreakable login script?

Post by ben.artiss »

Hi,

I have been expanding on the same basic principle for a login system for a while now, and I'm wondering whether it's actually reached a 'bulletproof' stage. The globals.inc.php file is included in every main script/page of the website, and db.inc.php is included within the global file. I'm interested to see what other programmers think of this approach to managing sessions, where users of different privileges (i.e. admin, staff, members) can login from the same place using the same scripts.

/lib/db.inc.php

Code: Select all

<?php
$hostname = "localhost";
$database = "database";
$dbuser   = "user";
$dbpass   = "pass";
$db = mysql_pconnect($hostname, $dbuser, $dbpass) or trigger_error(mysql_error(),E_USER_ERROR);
mysql_select_db($database, $db);
?>
/lib/globals.inc.php

Code: Select all

<?php
# start the session
if (!isset($_SESSION)) {session_start();}
 
# current file information
$currentUrl   = strtolower($_SERVER['PHP_SELF']);
$currentFile  = explode('/', $currentUrl);
$currentFile  = $currentFile[count($currentFile) - 1];
$currentQuery = strtolower($_SERVER['QUERY_STRING']);
empty($currentQuery) ? $current = $currentFile : $current = $currentFile."?".$currentQuery;
 
if ($currentFile=='globals.inc.php') {
    header('Location: ../index.php'); exit;
}
 
# locate and connect to database
$findDb = array('db.inc.php','lib/db.inc.php','../lib/db.inc.php');
 
foreach ($findDb as $loc) {
    if (file_exists($loc)) {
        require_once($loc); break;
    }
}
 
if (!$db) {die('The database could not be loaded! Please check back soon.');}
 
# global functions
function getHost($returnName=false) {
    if (isset($_SERVER['HTTP_CLIENT_IP'])) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } else {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
 
    if ($returnName) {
        return gethostbyaddr($ip);
    } else {
        return $ip;
    }
}
 
function makeSafe($input) {
    if (get_magic_quotes_gpc()) {
        $input = stripslashes($input);
    }
 
    return htmlspecialchars(trim($input));
}
 
function escape($input) {
    if (!get_magic_quotes_gpc()) {
        $input = addslashes($input);
    }
 
    if (phpversion()>='4.3.0') {
        $input = mysql_real_escape_string($input);
    } else {
        $input = mysql_escape_string($input);
    }
 
    return $input;
}
 
 
function generateEncPass($date, $pass) {
    $encpass = md5($date.$pass); # Note: real function much more complex!
    return $encpass;
}
 
# declare some global variables
$error = false;
$onload = false;
$login = false;
$userlevel = false;
 
# check login status based on url
if (stristr($currentUrl, 'admin') || stristr($currentUrl, 'staff') || stristr($currentUrl, 'members')) {
    if (!isset($_SESSION['login']) || $_SESSION['login']!=session_id() || !isset($_SESSION['session_user']) || !isset($_SESSION['session_userid'])) {
        header("Location: ../login.php?e=7"); exit;
    }
 
    $session_user = $_SESSION['session_user'];
    $session_userid = $_SESSION['session_userid'];
 
    if (stristr($currentUrl, 'admin')) {$userlevel=1;}
    if (stristr($currentUrl, 'staff')) {$userlevel=2;}
    if (stristr($currentUrl, 'members')) {$userlevel=3;}
 
    $sql = mysql_query(sprintf("SELECT `users`.`admin`,`users`.`staff` FROM `users` WHERE `users`.`user_id`='%s' LIMIT 1", escape($session_userid)), $db) or die(mysql_error());
 
    if (!mysql_num_rows($sql)) {
        $error = true;
    } else {
        $row = mysql_fetch_assoc($sql);
        $admin = $row['admin'];
        $staff = $row['staff'];
    }
 
    mysql_free_result($sql);
 
    if ($error) {header("Location: ../login.php?e=8"); exit;}
}
 
# check login location and user level
switch ($userlevel) {
    case 1: if ($admin!=1) {header("Location: ../login.php?e=8"); exit;} else {$login = true;} break;
    case 2: if ($admin!=1 && $staff!=1) {header("Location: ../login.php?e=8"); exit;} else {$login = true;} break;
    case 3: $login = true; break;
}
?>
/lib/login.php

Code: Select all

<?php
if (!isset($_POST['username']) || !isset($_POST['password']) || !isset($_POST['login'])) {
    header("Location: ../index.php"); exit;
}
 
require_once('globals.inc.php');
 
$username = makeSafe($_POST['username']);
$password = makeSafe($_POST['password']);
 
if (!$username) {
    header("Location: ../login.php?e=1"); exit;
}
 
$_SESSION['session_user'] = $username;
 
$sql = mysql_query(sprintf("SELECT `users`.`user_id`,`users`.`admin`,`users`.`staff`,`users`.`active`,`users`.`date_activated`,`users`.`date_created`,`users`.`password` FROM `users` WHERE `users`.`email`='%s' LIMIT 1", escape($username)), $db) or die(mysql_error());
 
if (!mysql_num_rows($sql)) {
    mysql_free_result($sql);
    header("Location: ../login.php?e=2");
}
 
$row = mysql_fetch_assoc($sql);
$id = $row['user_id'];
$admin = $row['admin'];
$staff = $row['staff'];
$active = $row['active'];
$activated = $row['date_activated'];
$created = $row['date_created'];
$dbpass = $row['password'];
 
mysql_free_result($sql);
 
if ($active!=1 && !$activated) {
    header("Location: ../login.php?e=5"); exit;
} elseif ($active!=1 && $activated) {
    header("Location: ../login.php?e=6"); exit;
}
 
if (!$password) {
    header("Location: ../login.php?e=3"); exit;
}
 
$password = generateEncPass($created,$password);
 
if ($password!==$dbpass) {
    header("Location: ../login.php?e=4"); exit;
}
 
$sql = mysql_query(sprintf("SELECT * FROM `user_history` WHERE `user_history`.`user_id`='%s' AND `user_history`.`action`='login' ORDER BY `user_history`.`date_created` DESC LIMIT 1", escape($id)), $db) or die(mysql_error());
 
if (!mysql_num_rows($sql)) {
    $_SESSION['firstlogin'] = true;
}
 
mysql_free_result($sql);
 
$action = 'login';
$ip = getHost();
$sid = session_id();
 
$sql = mysql_query(sprintf("INSERT INTO `user_history` (`user_history`.`user_id`,`user_history`.`date_created`,`user_history`.`action`,`user_history`.`ip_address`,`user_history`.`session_id`) VALUES ('%s',NOW(),'%s','%s','%s')",
    escape($id),
    escape($action),
    escape($ip),
    escape($sid)
), $db) or die(mysql_error());
 
$_SESSION['login'] = $sid;
$_SESSION['session_userid'] = $id;
 
$redirArray = array(
    'account.php',
    'reservations.php'
);
 
if ($admin==1) {
    header("Location: ../admin"); exit;
} elseif ($staff==1) {
    header("Location: ../staff"); exit;
} else {
    if (isset($_SESSION['redirect']) && in_array($_SESSION['redirect'],$redirArray)) {
        header("Location: ../members/".$_SESSION['redirect']); exit;
    } else {
        header("Location: ../members"); exit;   
    }
}
?>
ben.artiss
Forum Contributor
Posts: 116
Joined: Fri Jan 23, 2009 3:04 pm

Re: Unbreakable login script?

Post by ben.artiss »

Not quite a snippet I know :oops: apologies if I'm being a bit presumptuous.
adelbarham
Forum Newbie
Posts: 1
Joined: Mon Apr 06, 2009 2:44 pm

Re: Unbreakable login script?

Post by adelbarham »

very nice

what about the rest of it??
login page?? register page?? remember me features and so on??
i would love to have your script...can you manage to complete it?
Post Reply