Introduce shadow logins
This commit is contained in:
@@ -99,7 +99,7 @@ body {
|
||||
}
|
||||
|
||||
#scorebar {
|
||||
background-image: url(/ressources/bg_strength_gradient.jpg);
|
||||
background-image: url(/resources/bg_strength_gradient.jpg);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 0;
|
||||
position:absolute;
|
||||
|
||||
@@ -50,20 +50,21 @@ Element.prototype.removeAllChilds = function() {
|
||||
this.removeChild(this.childNodes[0]);
|
||||
};
|
||||
|
||||
|
||||
function generate_password()
|
||||
function generate_random(size, only_ascii)
|
||||
{
|
||||
// symbols 32 - 47 / 58 - 64 / 91 - 96 / 123 - 126
|
||||
// numbers 48 - 57
|
||||
// upper 65 - 90
|
||||
// lower 97 - 122
|
||||
// Give priority to letters (65 - 122 duplicated in front and end of array)
|
||||
var symbols = new Array(65, 90, 97, 122, 40, 47, 48, 57, 65, 90, 97, 122, 123, 126, 65, 90, 97, 122);
|
||||
|
||||
field = document.getElementById("new_password");
|
||||
var symbols;
|
||||
if (only_ascii)
|
||||
symbols = new Array(65, 90, 97, 122, 40, 47, 48, 57, 65, 90, 97, 122, 123, 126, 65, 90, 97, 122);
|
||||
else
|
||||
symbols = new Array(1, 255);
|
||||
|
||||
var res = "";
|
||||
while (res.length < 16)
|
||||
while (res.length < size)
|
||||
{
|
||||
a = Math.round(Math.random() * (symbols.length/2) * 2);
|
||||
diff = symbols[a+1] - symbols[a];
|
||||
@@ -73,7 +74,12 @@ function generate_password()
|
||||
res += String.fromCharCode(r + symbols[a]);
|
||||
}
|
||||
|
||||
field.value = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
function generate_password()
|
||||
{
|
||||
document.getElementById("new_password").value = generate_random(16, true);
|
||||
}
|
||||
|
||||
function url_domain(data) {
|
||||
@@ -111,7 +117,7 @@ var passwords;
|
||||
var current_user = "";
|
||||
var current_mkey = "";
|
||||
|
||||
function PasswordEntry (ciphered_login, ciphered_password) {
|
||||
function PasswordEntry (ciphered_login, ciphered_password, salt="", shadow_login="") {
|
||||
this.ciphered_login = ciphered_login;
|
||||
this.ciphered_password = ciphered_password;
|
||||
this.unciphered = false;
|
||||
@@ -119,6 +125,9 @@ function PasswordEntry (ciphered_login, ciphered_password) {
|
||||
this.clear_login = "";
|
||||
this.clear_password = "";
|
||||
this.masterkey = "";
|
||||
this.salt = salt;
|
||||
this.shadow_login = shadow_login;
|
||||
this.access_token = "";
|
||||
|
||||
this.decrypt = function(masterkey)
|
||||
{
|
||||
@@ -163,25 +172,43 @@ function PasswordEntry (ciphered_login, ciphered_password) {
|
||||
{
|
||||
return !(this.isUnciphered(masterkey));
|
||||
}
|
||||
|
||||
this.shadow_login_to_access_token = function(masterkey)
|
||||
{
|
||||
var aes = new AES();
|
||||
var key = pkdbf2(hex2a(masterkey), hex2a(this.salt), pkdbf2_level, 256/8);
|
||||
var a_key = aes.init(hex2a(key));
|
||||
this.access_token = aes.encryptLongString(hex2a(this.shadow_login), a_key);
|
||||
this.access_token = a2hex(this.access_token);
|
||||
aes.finish();
|
||||
}
|
||||
|
||||
this.generate_access_token = function(masterkey)
|
||||
{
|
||||
this.salt = a2hex(generate_random(16, false));
|
||||
this.shadow_login = a2hex(generate_random(16, false));
|
||||
|
||||
return this.shadow_login_to_access_token(masterkey);
|
||||
}
|
||||
}
|
||||
|
||||
function list_all_entries(user)
|
||||
{
|
||||
passwords = new Array();
|
||||
|
||||
|
||||
req = new XMLHttpRequest();
|
||||
req.addEventListener("load", function(evt) {
|
||||
entries = this.responseText.split("\n");
|
||||
if (entries[0] == "entries")
|
||||
j = JSON.parse(this.responseText);
|
||||
for(i=0; i<j.entries.length; i++)
|
||||
{
|
||||
for(i=1; i<entries.length; i++)
|
||||
{
|
||||
if (entries[i] == "") continue;
|
||||
entry = entries[i].split(";");
|
||||
passwords.push(new PasswordEntry(entry[0], entry[1]));
|
||||
}
|
||||
if (j.entries[i].hasOwnProperty('login'))
|
||||
p = new PasswordEntry(j.entries[i].login, j.entries[i].password, "", "");
|
||||
else
|
||||
p = new PasswordEntry("", "", j.entries[i].salt, j.entries[i].shadow_login);
|
||||
passwords.push(p);
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
, false);
|
||||
req.open("POST", document.documentURI, false);
|
||||
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
|
||||
req.send("get_passwords=1&user=" + user);
|
||||
@@ -219,16 +246,77 @@ function update_stats()
|
||||
div.appendChild(document.createElement("br"));
|
||||
}
|
||||
|
||||
// Remove all password without credentials
|
||||
function put_ciphered_credentials(passwords, masterkey)
|
||||
{
|
||||
for(var i=0; i<passwords.length; i++)
|
||||
{
|
||||
passwords[i].generate_access_token(masterkey);
|
||||
remove_password_server(current_user, passwords[i].ciphered_login, '');
|
||||
add_password_server(current_user, passwords[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function get_ciphered_credentials(masterkey)
|
||||
{
|
||||
access_tokens = '';
|
||||
old_passwords = new Array();
|
||||
|
||||
for(var i=0; i<passwords.length; i++)
|
||||
{
|
||||
// Already got
|
||||
if (passwords[i].ciphered_login.length)
|
||||
{
|
||||
if (!passwords[i].access_token.length)
|
||||
old_passwords.push(passwords[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
passwords[i].shadow_login_to_access_token(masterkey);
|
||||
if (access_tokens.length) access_tokens += ",";
|
||||
access_tokens += passwords[i].access_token;
|
||||
}
|
||||
|
||||
if (old_passwords.length)
|
||||
put_ciphered_credentials(old_passwords, masterkey);
|
||||
|
||||
if (!access_tokens.length)
|
||||
return;
|
||||
|
||||
req = new XMLHttpRequest();
|
||||
req.addEventListener("load", function(evt) {
|
||||
j = JSON.parse(this.responseText);
|
||||
for(i=0; i<j.entries.length; i++)
|
||||
{
|
||||
for (k=0; k<passwords.length; k++)
|
||||
{
|
||||
if (passwords[k].access_token == j.entries[i].access_token)
|
||||
{
|
||||
passwords[k].ciphered_login = j.entries[i].login;
|
||||
passwords[k].ciphered_password = j.entries[i].password;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
req.open("POST", document.documentURI, false);
|
||||
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
|
||||
req.send("get_secure_passwords=1&user=" + user + "&access_tokens=" + access_tokens);
|
||||
}
|
||||
|
||||
function change_master_key(warning_unciphered)
|
||||
{
|
||||
var nb_unciphered = 0;
|
||||
|
||||
if (current_mkey.length && use_shadow_logins)
|
||||
get_ciphered_credentials(current_mkey);
|
||||
|
||||
for(i=0; i<passwords.length; i++)
|
||||
{
|
||||
if (passwords[i].decrypt(current_mkey))
|
||||
nb_unciphered++;
|
||||
}
|
||||
|
||||
|
||||
if (!nb_unciphered && warning_unciphered)
|
||||
alert("No password unciphered with this master key !");
|
||||
|
||||
@@ -305,7 +393,6 @@ function change_master_key(warning_unciphered)
|
||||
ciph_login = document.createElement("input");
|
||||
ciph_login.setAttribute("name", "ciphered_login");
|
||||
ciph_login.setAttribute("type", "hidden");
|
||||
ciph_login.setAttribute("login", passwords[i].ciphered_login);
|
||||
div.appendChild(ciph_login);
|
||||
|
||||
div.appendChild(document.createTextNode("URL"));
|
||||
@@ -313,7 +400,6 @@ function change_master_key(warning_unciphered)
|
||||
url.setAttribute("class", "hash");
|
||||
url.setAttribute("type", "text");
|
||||
url.setAttribute("name", "URL");
|
||||
url.setAttribute("value", passwords[i].ciphered_login);
|
||||
div.appendChild(url);
|
||||
|
||||
div.appendChild(document.createTextNode("password"));
|
||||
@@ -321,7 +407,6 @@ function change_master_key(warning_unciphered)
|
||||
password.setAttribute("class", "hash");
|
||||
password.setAttribute("type", "text");
|
||||
password.setAttribute("name", "password");
|
||||
password.setAttribute("value", passwords[i].ciphered_password);
|
||||
div.appendChild(password);
|
||||
|
||||
delete_button = document.createElement("input");
|
||||
@@ -331,6 +416,19 @@ function change_master_key(warning_unciphered)
|
||||
div.appendChild(delete_button);
|
||||
|
||||
password_div.appendChild(div);
|
||||
|
||||
if (passwords[i].ciphered_login.length)
|
||||
{
|
||||
ciph_login.setAttribute("login", passwords[i].ciphered_login);
|
||||
url.setAttribute("value", passwords[i].ciphered_login);
|
||||
password.setAttribute("value", passwords[i].ciphered_password);
|
||||
}
|
||||
else
|
||||
{
|
||||
ciph_login.setAttribute("login", passwords[i].shadow_login);
|
||||
url.setAttribute("value", passwords[i].shadow_login);
|
||||
// password empty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,7 +491,7 @@ function add_password_server(user, pentry)
|
||||
}, 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);
|
||||
req.send("add_entry=1&user=" + user + "&login=" + pentry.ciphered_login + "&password=" + pentry.ciphered_password + "&shadow_login=" + pentry.shadow_login + "&salt=" + pentry.salt + "&access_token=" + pentry.access_token);
|
||||
|
||||
return ok;
|
||||
}
|
||||
@@ -445,12 +543,7 @@ function construct_pentry(user, url, password, login, mkey, derive_masterkey)
|
||||
ciphered_login = "@@" + url + ";" + login;
|
||||
|
||||
// Add salt
|
||||
for(i=0; i<3; i++)
|
||||
{
|
||||
password += String.fromCharCode((Math.random() * 128)+1);
|
||||
}
|
||||
|
||||
ciphered_password = password;
|
||||
ciphered_password = password + generate_random(3, false);
|
||||
|
||||
aes = new AES();
|
||||
a_masterkey = aes.init(hex2a(mkey));
|
||||
@@ -461,13 +554,15 @@ function construct_pentry(user, url, password, login, mkey, derive_masterkey)
|
||||
pentry.unciphered = true;
|
||||
pentry.clear_url = url;
|
||||
pentry.clear_login = login;
|
||||
pentry.clear_password = password.substr(0, password.length-3);
|
||||
pentry.clear_password = password;
|
||||
pentry.masterkey = mkey;
|
||||
if (use_shadow_logins)
|
||||
pentry.generate_access_token(mkey);
|
||||
|
||||
return pentry;
|
||||
}
|
||||
|
||||
function remove_password_server(user, login)
|
||||
function remove_password_server(user, login, access_token)
|
||||
{
|
||||
var ok = false;
|
||||
|
||||
@@ -481,7 +576,7 @@ function remove_password_server(user, login)
|
||||
}, 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);
|
||||
req.send("delete_entry=1&user=" + user + "&login=" + login + "&access_token=" + access_token);
|
||||
|
||||
return ok;
|
||||
}
|
||||
@@ -579,7 +674,7 @@ function delete_entry(entry_number)
|
||||
if(!confirm("Are you sure want to delete this entry ?"))
|
||||
return;
|
||||
|
||||
ok = remove_password_server(current_user, ciphered_login.getAttribute("login"));
|
||||
ok = remove_password_server(current_user, ciphered_login.getAttribute("login"), passwords[i].access_token);
|
||||
|
||||
if (!ok) return;
|
||||
|
||||
@@ -644,7 +739,7 @@ function update_entry(entry_number)
|
||||
|
||||
if (pentry == null) return;
|
||||
|
||||
ok = remove_password_server(current_user, passwords[found].ciphered_login);
|
||||
ok = remove_password_server(current_user, passwords[found].ciphered_login, passwords[found].access_token);
|
||||
if (!ok) return;
|
||||
|
||||
ok = add_password_server(current_user, pentry);
|
||||
|
||||
Reference in New Issue
Block a user