/* Copyright (C) 2013-2014 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 {Cc, Ci} = require("chrome"); var notifications = require("sdk/notifications"); var pkdbf2 = require("pkdbf2").pkdbf2; var aes = require("jsaes").aes; var parseURI = require("parseuri").parseURI; var prefSet = require("sdk/simple-prefs"); var DEBUG = false; var pkdbf2_level = prefSet.prefs.pkdbf2_level; 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++) { 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) { v = "@@" + domain + ";" + login; debug("will encrypt " + v); debug("with " + a2hex(mkey)); enc = aes.encryptLongString(v, aes.init(mkey)); aes.finish(); debug("res " + enc); return enc; } function ask_server(form, field, logins, domain, wdomain, mkey, salt, submit) { mkey = pkdbf2.pkdbf2(mkey, salt, pkdbf2_level, 256/8); keys = ""; for(a=0, b=logins.length; a protocol_version) { notifications.notify({ title: "gPasss", text: "Protocol version not supported, please upgrade your addon", data: "Protocol version not supported, please upgrade your addon", }); ret = SERVER.FAILED; } else { switch (server_protocol_version) { case 2: server_pkdbf2_level = 1000; break; case 3: // Version 3 : nothing special to do break; } } break; case "pass": ciphered_password = params[1]; break; case "pkdbf2_level": server_pkdbf2_level = parseInt(params[1].match(/\d+/)[0], 10); if (server_pkdbf2_level != NaN && server_pkdbf2_level != pkdbf2_level && server_pkdbf2_level >= 1000) // Minimum level for PKDBF2 ! { debug("New pkdbf2 level " + server_pkdbf2_level); pkdbf2_level = server_pkdbf2_level; prefSet.prefs.pkdbf2_level = server_pkdbf2_level; ret = SERVER.RESTART_REQUEST; } break; case "": break; default: debug("Unknown command " + params[0]); notifications.notify({ title: "gPasss", text: "Error : It seems that it's not a gPass server", data: this.responseText, }); ret = SERVER.FAILED; break; } } if (ret != SERVER.OK) return; if (ciphered_password != "") { debug("Ciphered password : " + ciphered_password); clear_password = aes.decryptLongString(hex2a(ciphered_password), aes.init(mkey)); aes.finish(); // 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 { debug("No password found"); ret = SERVER.FAILED; notifications.notify({ title: "gPasss", text: "No password found in database", data: "No password found in database", }); } }, false); gPassRequest.addEventListener("error", function(evt) { debug("error"); ret = false; notifications.notify({ title: "gPasss", text: "Error", data: "Error", }); }, false); debug("connect to " + prefSet.prefs.account_url); gPassRequest.open("POST", prefSet.prefs.account_url, true); gPassRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); gPassRequest.send(keys); return ret; } function wildcard_domain(domain) { 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 on_sumbit(e) { var form = this; var fields = form.getElementsByTagName("input"); domain = parseURI.parseUri(form.ownerDocument.baseURI); domain = domain["host"]; wdomain = wildcard_domain(domain); salt = parseURI.parseUri(prefSet.prefs.account_url); salt = salt["host"] + salt["path"]; debug("salt " + salt); user = null; all_logins = new Array; // Get all && for (i=0; i for (i=0; i