/* Copyright (C) 2013-2016 Grégory Soutadé This file is part of gPass. gPass is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. gPass is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with gPass. If not, see . */ var DEBUG = true; var protocol_version = 3; SERVER = {OK : 0, FAILED : 1, RESTART_REQUEST : 2}; // http://stackoverflow.com/questions/3745666/how-to-convert-from-hex-to-ascii-in-javascript function hex2a(hex) { var str = ''; for (var i = 0; i < hex.length; i += 2) str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); return str; } function a2hex(_str_) { var hex = ''; for (var i = 0; i < _str_.length; i++) { var c = _str_.charCodeAt(i).toString(16); if (c.length == 1) c = "0" + c; hex += c; } return hex; } function debug(s) { if (DEBUG) console.log(s); } function generate_request(domain, login, mkey) { var v = "@@" + domain + ";" + login; debug("will encrypt " + v); //debug("with " + a2hex(mkey)); enc = encrypt(mkey, v); //debug("res " + a2hex(enc)); return enc; } async function ask_server(form, field, logins, domain, wdomain, mkey, submit) { account_url = await getPref("account_url"); var salt = parseURI.parseUri(account_url); salt = salt["host"] + salt["path"]; debug("salt " + salt); pbkdf2_level = await getPref("pbkdf2_level"); mkey = pbkdf2(mkey, salt, pbkdf2_level); keys = ""; for(a=0, b=logins.length; a protocol_version) { notify("Protocol version not supported, please upgrade your addon", "Protocol version not supported, please upgrade your addon"); ret = SERVER.FAILED; } else { switch (server_protocol_version) { case 2: server_pbkdf2_level = 1000; break; case 3: // Version 3 : nothing special to do break; } } break; case "pass": ciphered_password = params[1]; break; case "pbkdf2_level": server_pbkdf2_level = parseInt(params[1].match(/\d+/)[0], 10); if (server_pbkdf2_level != NaN && server_pbkdf2_level != pbkdf2_level && server_pbkdf2_level >= 1000) // Minimum level for PBKDF2 ! { debug("New pbkdf2 level " + server_pbkdf2_level); pbkdf2_level = server_pbkdf2_level; setPref("pbkdf2_level", pbkdf2_level); ret = SERVER.RESTART_REQUEST; } break; case "": break; default: debug("Unknown command " + params[0]); notify("Error : It seems that it's not a gPass server", this.responseText); ret = SERVER.FAILED; break; } } if (ret != SERVER.OK) return; if (ciphered_password != "") { debug("Ciphered password : " + ciphered_password); clear_password = await decrypt(mkey, hex2a(ciphered_password)); // Remove trailing \0 and salt clear_password = clear_password.replace(/\0*$/, ""); clear_password = clear_password.substr(0, clear_password.length-3); debug("Clear password " + clear_password); field.value = clear_password; // Remove gPass event listener and submit again with clear password if (submit) { form.removeEventListener("submit", on_sumbit, true); form.submit(); } else { notify("Password successfully replaced", "Password successfully replaced"); } } else { debug("No password found"); ret = SERVER.FAILED; notify("No password found in database", "No password found in database"); } }, false); gPassRequest.addEventListener("error", function(evt) { debug("error"); ret = false; notify("Error", "Error"); }, false); debug("connect to " + await getPref("account_url")); gPassRequest.open("POST", await getPref("account_url"), true); gPassRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); gPassRequest.send(keys); return ret; } function wildcard_domain(domain) { var parts = domain.split("."); if (parts.length >= 3) { // Seems to be a two level root domain (ie zzz.xxx.co.uk ...) if (parts[parts.length-2].lenght <= 3) { if (parts.length > 3) return "*" + "." + parts[parts.length-3] + "." + parts[parts.length-2] + "." + parts[parts.length-1]; } // Standard root domain (zzz.xxx.com) else return "*" + "." + parts[parts.length-2] + "." + parts[parts.length-1]; } // Simple xxx.com else if (parts.length == 2) return "*" + "." + parts[0] + "." + parts[1]; return ""; } function _add_name(logins, name) { for(var i=0; i && type_filters.push("text"); type_filters.push("email"); logins = try_get_name(fields, type_filters, true); // Get all other fields except text, email and password if (!logins.length) { type_filters.push("password"); logins = try_get_name(fields, type_filters, false); } // Look for for (var i=0; i