.
*/
/*
login is stored as :
@@url;login
Password is salted (3 random characters) and encrypted
All is encrypted with AES256 and key : sha256(master key)
*/
$MAX_ENTRY_LEN = 512;
$USERS_PATH = "./users/";
function get_mkey_hash($mkey)
{
return bin2hex(hash("sha256", $mkey, true));
}
function open_crypto($mkey)
{
if (!isset($_SESSION['td']))
{
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
if ($td == false)
die("Unable to open mcrypt");
$ret = mcrypt_generic_init($td, hex2bin($mkey), '0000000000000000');
if ($ret < 0)
{
echo "
Unable to set key $ret
";
return null;
}
$_SESSION['td'] = $td;
}
else
$td = $_SESSION['td'];
return $td;
}
function decrypt($mkey, $val, $salted)
{
$td = open_crypto($mkey);
if ($td == null) return;
$val = mdecrypt_generic($td, hex2bin($val));
// Remove 0 added by encrypt
$val = str_replace("\0", '', $val);
// Remove salt
if ($salted)
$val = substr($val, 0, strlen($val)-3);
return $val;
}
function encrypt($mkey, $val, $salted)
{
global $MAX_ENTRY_LEN;
$td = open_crypto($mkey);
if ($td == null) return;
if ($salted)
{
$val .= dechex(rand(256,4095)); //between 0x100 and 0xfff
}
$val = mcrypt_generic($td, $val);
if (strlen($val) > $MAX_ENTRY_LEN)
{
echo "Value to encrypt is too long
";
return null;
}
return bin2hex($val);
}
// From http://php.net/manual/en/function.copy.php
function recurse_copy($src,$dst) {
$dir = opendir($src);
if ($dir == FALSE) return FALSE;
if (!@mkdir($dst)) return FALSE;
while(false !== ( $file = readdir($dir)) ) {
if (( $file != '.' ) && ( $file != '..' )) {
if ( is_dir($src . '/' . $file) ) {
return recurse_copy($src . '/' . $file,$dst . '/' . $file);
}
else {
copy($src . '/' . $file,$dst . '/' . $file);
}
}
}
closedir($dir);
return TRUE;
}
function create_user($user)
{
global $USERS_PATH;
if (strpos($user, "..") || strpos($user, "/") || $user[0] == "." || $user[0] == "_")
{
echo "Invalid user
";
}
else
{
$user = $USERS_PATH . $user;
if (file_exists($user))
{
echo "User already exists
";
}
else
{
if (!recurse_copy("./ref", $user))
{
echo "Cannot create user $user
";
}
else
{
return true;
}
}
}
return false;
}
function load_database($user)
{
global $USERS_PATH;
try {
$db = new SQLite3($USERS_PATH . "$user/gpass.bdd", SQLITE3_OPEN_READWRITE);
}
catch(Exception $e)
{
echo "Unable to load database for user $user !
";
return null;
}
// New access need to reset crypto
unset($_SESSION['td']);
return $db;
}
function add_entry($user, $mkey, $url, $login, $password)
{
$db = load_database($user);
if ($db == null) return false;
$password = encrypt($mkey, $password, true);
$login = encrypt($mkey, "@@" . $url . ";" . $login, false);
if ($password == null || $login == null)
return false;
$count = $db->querySingle("SELECT COUNT(*) FROM gpass WHERE login='" . $login . "'");
if ($count != 0)
{
echo "Entry already exists
";
return false;
}
$result = $db->query("INSERT INTO gpass ('login', 'password') VALUES ('" . $login . "', '" . $password . "')");
return true;
}
function delete_entry($user, $login)
{
$db = load_database($user);
if ($db == null) return false;
$db->query("DELETE FROM gpass WHERE login='" . $login . "'");
return true;
}
function update_entry($user, $mkey, $old_login, $url, $login, $password)
{
if (delete_entry($user, $old_login))
return add_entry($user, $mkey, $url, $login, $password);
return false;
}
function list_entries($user, $mkey)
{
$db = load_database($user);
if ($db == null) return;
$result = $db->query("SELECT * FROM gpass");
$res = array();
$valid_accounts = 0;
$total_accounts = 0;
while ($row = $result->fetchArray())
{
$total_accounts++;
if ($mkey != "")
$login = decrypt($mkey, $row['login'], false);
if ($login[0] != '@' && $login[1] != '@')
{
$subres = array('login_ciph' => $row['login'],
'url' => '', 'login' => '',
'password' => $row['password'],
'ciphered' => 1);
array_push($res, $subres);
continue;
}
$login = substr($login, 2);
$sep = strpos($login, ';');
$url = substr($login, 0, $sep);
$login = substr($login, $sep+1);
$password = decrypt($mkey, $row['password'], true);
$subres = array('login_ciph' => $row['login'],
'url' => $url, 'login' => $login,
'password' => $password,
'ciphered' => 0);
array_push($res, $subres);
$valid_accounts++;
}
return array($total_accounts-$valid_accounts, $res);
}
?>