. */ /* 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); } ?>