Add update + fix a lot of bugs

This commit is contained in:
Gregory Soutade 2013-10-23 19:39:47 +02:00
parent c44e84124b
commit 0f76ccb06e
2 changed files with 263 additions and 122 deletions

View File

@ -24,7 +24,15 @@ session_start();
$VIEW_CIPHERED_PASSWORDS=true; $VIEW_CIPHERED_PASSWORDS=true;
$ADMIN_MODE=true; $ADMIN_MODE=true;
$user = "";
if ($ADMIN_MODE && isset($_POST['create_user']))
{
if (create_user($_POST['user']))
$user = $_POST['user'];
}
else
{
if (isset($_POST['get_passwords']) && isset($_POST['user'])) if (isset($_POST['get_passwords']) && isset($_POST['user']))
return list_entries($_POST['user']); return list_entries($_POST['user']);
@ -35,6 +43,7 @@ if (isset($_POST['add_entry']) && isset($_POST['user']) &&
if (isset($_POST['delete_entry']) && isset($_POST['user']) && if (isset($_POST['delete_entry']) && isset($_POST['user']) &&
isset($_POST['login'])) isset($_POST['login']))
return delete_entry($_POST['user'], $_POST['login']); return delete_entry($_POST['user'], $_POST['login']);
}
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
@ -61,6 +70,7 @@ if (isset($_POST['delete_entry']) && isset($_POST['user']) &&
</div> </div>
<div id="user"> <div id="user">
<?php <?php
global $user;
$users = scandir("./users/"); $users = scandir("./users/");
$count = 0; $count = 0;
foreach($users as $u) foreach($users as $u)
@ -89,7 +99,7 @@ else
echo ' <b>Master key </b> <input id="master_key" type="password" onkeypress="if (event.keyCode == 13) update_master_key();"/>'; echo ' <b>Master key </b> <input id="master_key" type="password" onkeypress="if (event.keyCode == 13) update_master_key();"/>';
echo "<input type=\"button\" value=\"See\" onclick=\"update_master_key();\" />" . "\n"; echo "<input type=\"button\" value=\"See\" onclick=\"update_master_key();\" />" . "\n";
if ($_SERVER['HTTPS'] == "") if (!isset($_SERVER['HTTPS']))
echo "<div id=\"addon_address\">Current addon address is : http://" . $_SERVER['SERVER_NAME'] . "/" . $user . "</div>\n"; echo "<div id=\"addon_address\">Current addon address is : http://" . $_SERVER['SERVER_NAME'] . "/" . $user . "</div>\n";
else else
echo "<div id=\"addon_address\">Current addon address is : https://" . $_SERVER['SERVER_NAME'] . "/" . $user . "</div>\n"; echo "<div id=\"addon_address\">Current addon address is : https://" . $_SERVER['SERVER_NAME'] . "/" . $user . "</div>\n";
@ -108,7 +118,7 @@ if ($user != "")
echo 'URL <input type="text" name="url"/>'; echo 'URL <input type="text" name="url"/>';
echo 'login <input type="text" name="login" />'; echo 'login <input type="text" name="login" />';
echo 'password <input id="new_password" type="text" name="password"/>'; echo 'password <input id="new_password" type="text" name="password"/>';
echo 'master key <input type="password" name="mkey"/>'; echo 'master key <input type="password" name="mkey" onkeypress="if (event.keyCode == 13) add_password();"/>';
echo '<input type="button" value="Generate password" onClick="generate_password();"/>'; echo '<input type="button" value="Generate password" onClick="generate_password();"/>';
echo "<input type=\"button\" name=\"add\" value=\"Add\" onclick=\"add_password();\"/>"; echo "<input type=\"button\" name=\"add\" value=\"Add\" onclick=\"add_password();\"/>";
} }

View File

@ -45,6 +45,12 @@ Array.prototype.remove = function(from, to) {
return this.push.apply(this, rest); return this.push.apply(this, rest);
}; };
Element.prototype.removeAllChilds = function() {
while (this.hasChildNodes())
this.removeChild(this.childNodes[0]);
};
function generate_password() function generate_password()
{ {
// symbols 32 - 47 / 58 - 64 / 91 - 96 / 123 - 126 // symbols 32 - 47 / 58 - 64 / 91 - 96 / 123 - 126
@ -118,6 +124,7 @@ function PasswordEntry (ciphered_login="", ciphered_password="") {
aes = new AES(); aes = new AES();
a_masterkey = aes.init(hex2a(masterkey)); a_masterkey = aes.init(hex2a(masterkey));
login = aes.decryptLongString(hex2a(this.ciphered_login), a_masterkey); login = aes.decryptLongString(hex2a(this.ciphered_login), a_masterkey);
login = login.replace(/\0*$/, "");
if (login.indexOf("@@") != 0) if (login.indexOf("@@") != 0)
{ {
aes.finish(); aes.finish();
@ -144,6 +151,11 @@ function PasswordEntry (ciphered_login="", ciphered_password="") {
{ {
return (this.unciphered == true && masterkey == this.masterkey && masterkey != "") return (this.unciphered == true && masterkey == this.masterkey && masterkey != "")
} }
this.isCiphered = function(masterkey)
{
return !(this.isUnciphered(masterkey));
}
} }
function list_all_entries(user) function list_all_entries(user)
@ -168,36 +180,56 @@ function list_all_entries(user)
req.send("get_passwords=1&user=" + user); req.send("get_passwords=1&user=" + user);
} }
function change_master_key() function update_stats()
{ {
nb_ciphered_passwords = 0; nb_ciphered_passwords = 0;
nb_unciphered_passwords = 0; nb_unciphered_passwords = 0;
for(i=0; i<passwords.length; i++) for(i=0; i<passwords.length; i++)
{ {
ret = passwords[i].decrypt(current_mkey); if (passwords[i].isUnciphered(current_mkey))
if (ret)
nb_unciphered_passwords++; nb_unciphered_passwords++;
else else
nb_ciphered_passwords++; nb_ciphered_passwords++;
} }
password_div = document.getElementById("passwords"); div = document.getElementById("nb_unciphered_passwords");
while (password_div.hasChildNodes()) div.removeAllChilds();
password_div.removeChild(password_div.childNodes[0]);
text = document.createElement("b"); text = document.createElement("b");
text.appendChild(document.createTextNode(nb_unciphered_passwords + " unciphered password(s)")); text.appendChild(document.createTextNode(nb_unciphered_passwords + " unciphered password(s)"));
password_div.appendChild(text); div.appendChild(text);
password_div.appendChild(document.createElement("br")); div.appendChild(document.createElement("br"));
password_div.appendChild(document.createElement("br")); div.appendChild(document.createElement("br"));
div = document.getElementById("nb_ciphered_passwords");
div.removeAllChilds();
text = document.createElement("b");
text.appendChild(document.createTextNode(nb_ciphered_passwords + " ciphered password(s)"));
div.appendChild(text);
div.appendChild(document.createElement("br"));
div.appendChild(document.createElement("br"));
}
function change_master_key()
{
for(i=0; i<passwords.length; i++)
passwords[i].decrypt(current_mkey);
password_div = document.getElementById("passwords");
password_div.removeAllChilds();
div = document.createElement("div");
div.setAttribute("id", "nb_unciphered_passwords");
password_div.appendChild(div);
for(i=0; i<passwords.length; i++) for(i=0; i<passwords.length; i++)
{ {
if (passwords[i].isUnciphered(current_mkey)) if (passwords[i].isUnciphered(current_mkey))
{ {
div = document.createElement("div"); div = document.createElement("div");
div.setAttribute("id", "entry_" + i); div.setAttribute("id", "unciph_entry_" + i);
div.setAttribute("class", "password"); div.setAttribute("class", "password");
ciph_login = document.createElement("input"); ciph_login = document.createElement("input");
@ -209,7 +241,7 @@ function change_master_key()
div.appendChild(document.createTextNode("URL")); div.appendChild(document.createTextNode("URL"));
url = document.createElement("input"); url = document.createElement("input");
url.setAttribute("type", "text"); url.setAttribute("type", "text");
url.setAttribute("name", "URL"); url.setAttribute("name", "url");
url.setAttribute("value", passwords[i].clear_url); url.setAttribute("value", passwords[i].clear_url);
div.appendChild(url); div.appendChild(url);
@ -230,32 +262,29 @@ function change_master_key()
delete_button = document.createElement("input"); delete_button = document.createElement("input");
delete_button.setAttribute("type", "button"); delete_button.setAttribute("type", "button");
delete_button.setAttribute("value", "Delete"); delete_button.setAttribute("value", "Delete");
delete_button.setAttribute("onclick", "delete_entry(\"entry_" + i + "\");"); delete_button.setAttribute("onclick", "delete_entry(\"unciph_entry_" + i + "\");");
div.appendChild(delete_button); div.appendChild(delete_button);
update_button = document.createElement("input"); update_button = document.createElement("input");
update_button.setAttribute("type", "button"); update_button.setAttribute("type", "button");
update_button.setAttribute("value", "Update"); update_button.setAttribute("value", "Update");
update_button.setAttribute("onclick", "update_entry(\"unciph_entry_" + i + "\");");
div.appendChild(update_button); div.appendChild(update_button);
password_div.appendChild(div); password_div.appendChild(div);
} }
} }
text = document.createElement("b"); div = document.createElement("div");
text.appendChild(document.createTextNode(nb_ciphered_passwords + " ciphered password(s)")); div.setAttribute("id", "nb_ciphered_passwords");
password_div.appendChild(document.createElement("br")); password_div.appendChild(div);
password_div.appendChild(document.createElement("br"));
password_div.appendChild(text);
password_div.appendChild(document.createElement("br"));
password_div.appendChild(document.createElement("br"));
for(i=0; i<passwords.length; i++) for(i=0; i<passwords.length; i++)
{ {
if (!passwords[i].isUnciphered(current_mkey)) if (passwords[i].isCiphered(current_mkey))
{ {
div = document.createElement("div"); div = document.createElement("div");
div.setAttribute("id", "entry_" + i); div.setAttribute("id", "ciph_entry_" + i);
div.setAttribute("class", "password"); div.setAttribute("class", "password");
ciph_login = document.createElement("input"); ciph_login = document.createElement("input");
@ -283,12 +312,14 @@ function change_master_key()
delete_button = document.createElement("input"); delete_button = document.createElement("input");
delete_button.setAttribute("type", "button"); delete_button.setAttribute("type", "button");
delete_button.setAttribute("value", "Delete"); delete_button.setAttribute("value", "Delete");
delete_button.setAttribute("onclick", "delete_entry(\"entry_" + i + "\");"); delete_button.setAttribute("onclick", "delete_entry(\"ciph_entry_" + i + "\");");
div.appendChild(delete_button); div.appendChild(delete_button);
password_div.appendChild(div); password_div.appendChild(div);
} }
} }
update_stats();
} }
function update_master_key() function update_master_key()
@ -304,7 +335,8 @@ function update_master_key()
list_all_entries(current_user); list_all_entries(current_user);
addon_address = document.getElementById("addon_address"); addon_address = document.getElementById("addon_address");
addon_address.removeChild(addon_address.childNodes[0]); addon_address.removeAllChilds();
addon_address.appendChild(document.createTextNode("Current addon address is : " + document.documentURI + current_user)); addon_address.appendChild(document.createTextNode("Current addon address is : " + document.documentURI + current_user));
} }
@ -325,6 +357,112 @@ function start()
return update_master_key(); return update_master_key();
} }
function add_password_server(user, pentry)
{
var ok = false;
req = new XMLHttpRequest();
req.addEventListener("load", function(evt) {
resp = this.responseText;
if (resp == "OK")
ok = true;
else
alert(resp);
}, false);
req.open("POST", document.documentURI, false);
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
req.send("add_entry=1&user=" + user + "&login=" + pentry.ciphered_login + "&password=" + pentry.ciphered_password);
return ok;
}
function construct_pentry(user, url, password, login, mkey, derive_masterkey)
{
var ret = null;
if (url == "")
{
alert("URL is empty");
return ret;
}
if (login == "")
{
alert("Login is empty");
return ret;
}
if (password == "")
{
alert("Password is empty");
return ret;
}
if (mkey == "")
{
alert("Master key is empty");
return ret;
}
if (derive_masterkey)
mkey = derive_mkey(current_user, mkey);
for(i=0; i<passwords.length; i++)
{
p = passwords[i];
if (p.clear_url == url &&
p.clear_password == password &&
p.clear_login == login &&
p.masterkey == mkey)
{
alert("Entry already exists");
return ret;
}
}
ciphered_login = "@@" + url + ";" + login;
// Add salt
for(i=0; i<3; i++)
{
password += String.fromCharCode((Math.random() * 128)+1);
}
ciphered_password = password;
aes = new AES();
a_masterkey = aes.init(hex2a(mkey));
ciphered_login = a2hex(aes.encryptLongString(ciphered_login, a_masterkey));
ciphered_password = a2hex(aes.encryptLongString(ciphered_password, a_masterkey));
pentry = new PasswordEntry(ciphered_login, ciphered_password);
pentry.unciphered = true;
pentry.clear_url = url;
pentry.clear_login = login;
pentry.clear_password = password.substr(0, password.length-3);
pentry.masterkey = mkey;
return pentry;
}
function remove_password_server(user, login)
{
var ok = false;
req = new XMLHttpRequest();
req.addEventListener("load", function(evt) {
resp = this.responseText;
if (resp == "OK")
ok = true;
else
alert(resp);
}, false);
req.open("POST", document.documentURI, false);
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
req.send("delete_entry=1&user=" + user + "&login=" + login);
return ok;
}
function add_password() function add_password()
{ {
var url = ""; var url = "";
@ -348,88 +486,26 @@ function add_password()
mkey = inputs[i].value; mkey = inputs[i].value;
} }
if (url == "") pentry = construct_pentry(current_user, url, password, login, mkey, true)
{
alert("URL is empty");
return false;
}
if (login == "") if (pentry == null) return;
{
alert("Login is empty");
return false;
}
if (password == "") res = add_password_server(current_user, pentry);
{
alert("Password is empty");
return false;
}
if (mkey == "") if (!res) return false;
{
alert("Master key is empty");
return false;
}
mkey = derive_mkey(current_user, mkey); current_mkey = pentry.masterkey;
for(i=0; i<passwords.length; i++)
{
p = passwords[i];
if (p.clear_url == url &&
p.clear_password == password &&
p.clear_login == login &&
p.masterkey == mkey)
{
alert("Entry already exists");
return false;
}
}
ciphered_login = "@@" + url + ";" + login;
ciphered_password = password;
for(i=0; i<3; i++)
{
password += String.fromCharCode((Math.random() * 128)+1);
}
aes = new AES();
a_masterkey = aes.init(hex2a(mkey));
ciphered_login = a2hex(aes.encryptLongString(ciphered_login, a_masterkey));
ciphered_password = a2hex(aes.encryptLongString(ciphered_password, a_masterkey));
var ok = false;
req = new XMLHttpRequest();
req.addEventListener("load", function(evt) {
resp = this.responseText;
if (resp == "OK")
ok = true;
else
alert(resp);
}, false);
req.open("POST", document.documentURI, false);
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
req.send("add_entry=1&user=" + user + "&login=" + ciphered_login + "&password=" + ciphered_password);
if (!ok) return false;
current_mkey = mkey;
pentry = new PasswordEntry(ciphered_login, ciphered_password);
pentry.unciphered = true;
pentry.clear_url = url;
pentry.clear_login = login;
pentry.clear_password = password.substr(0, password.length-3);
pentry.masterkey = mkey;
passwords.push(pentry); passwords.push(pentry);
change_master_key(); change_master_key();
for(i=0; i<inputs.length; i++) for(i=0; i<inputs.length; i++)
{
if (inputs[i].getAttribute("type") == "text" ||
inputs[i].getAttribute("type") == "password")
inputs[i].value = ""; inputs[i].value = "";
}
return true; return true;
} }
@ -462,10 +538,9 @@ function delete_entry(entry_number)
} }
var found = -1; var found = -1;
ciphered_login = ciphered_login.getAttribute("login");
for(i=0; i<passwords.length; i++) for(i=0; i<passwords.length; i++)
{ {
if (passwords[i].ciphered_login == ciphered_login) if (passwords[i].ciphered_login == ciphered_login.getAttribute("login"))
{ {
found = i; found = i;
break; break;
@ -481,23 +556,79 @@ function delete_entry(entry_number)
if(!confirm("Are you sure want to delete this entry ?")) if(!confirm("Are you sure want to delete this entry ?"))
return; return;
var ok = false; ok = remove_password_server(current_user, ciphered_login.getAttribute("login"));
req = new XMLHttpRequest();
req.addEventListener("load", function(evt) {
resp = this.responseText;
if (resp == "OK")
ok = true;
else
alert(resp);
}, false);
req.open("POST", document.documentURI, false);
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
req.send("delete_entry=1&user=" + user + "&login=" + ciphered_login);
if (!ok) return false; if (!ok) return;
entry.parentNode.removeChild(entry); parent = ciphered_login.parentNode;
parent.removeAllChilds();
passwords.remove(found); passwords.remove(found);
update_stats();
} }
function update_entry(entry_number)
{
var url = "";
var login = "";
var password = "";
var mkey = "";
var ciphered_login;
entry = document.getElementById(entry_number);
if (entry == null) {
alert(entry_number + " not found");
return;
}
inputs = entry.getElementsByTagName("input");
var ciphered_login = null;
for(i=0; i<inputs.length; i++)
{
if (inputs[i].getAttribute("name") == "url")
url = url_domain(inputs[i].value);
else if (inputs[i].getAttribute("name") == "login")
login = inputs[i].value.trim();
else if (inputs[i].getAttribute("name") == "password")
password = inputs[i].value.trim();
else if (inputs[i].getAttribute("name") == "ciphered_login")
ciphered_login = inputs[i];
}
var found = -1;
for(i=0; i<passwords.length; i++)
{
if (passwords[i].ciphered_login == ciphered_login.getAttribute("login"))
{
found = i;
break;
}
}
if (found == -1)
{
alert("Password not found int database");
return;
}
if(!confirm("Are you sure want to update this entry ?"))
return;
pentry = construct_pentry(current_user, url, password, login, current_mkey, false);
if (pentry == null) return;
ok = remove_password_server(current_user, passwords[found].ciphered_login);
if (!ok) return;
ok = add_password_server(current_user, pentry);
if (!ok) return;
passwords[found] = pentry;
ciphered_login.setAttribute("login", pentry.ciphered_login);
alert("Entry updated");
}