toolkit/components/passwordmgr/crypto-SDR.js

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5
michael@0 6 const Cc = Components.classes;
michael@0 7 const Ci = Components.interfaces;
michael@0 8 const Cr = Components.results;
michael@0 9
michael@0 10 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 11 Components.utils.import("resource://gre/modules/Services.jsm");
michael@0 12
michael@0 13 function LoginManagerCrypto_SDR() {
michael@0 14 this.init();
michael@0 15 };
michael@0 16
michael@0 17 LoginManagerCrypto_SDR.prototype = {
michael@0 18
michael@0 19 classID : Components.ID("{dc6c2976-0f73-4f1f-b9ff-3d72b4e28309}"),
michael@0 20 QueryInterface : XPCOMUtils.generateQI([Ci.nsILoginManagerCrypto]),
michael@0 21
michael@0 22 __sdrSlot : null, // PKCS#11 slot being used by the SDR.
michael@0 23 get _sdrSlot() {
michael@0 24 if (!this.__sdrSlot) {
michael@0 25 let modules = Cc["@mozilla.org/security/pkcs11moduledb;1"].
michael@0 26 getService(Ci.nsIPKCS11ModuleDB);
michael@0 27 this.__sdrSlot = modules.findSlotByName("");
michael@0 28 }
michael@0 29 return this.__sdrSlot;
michael@0 30 },
michael@0 31
michael@0 32 __decoderRing : null, // nsSecretDecoderRing service
michael@0 33 get _decoderRing() {
michael@0 34 if (!this.__decoderRing)
michael@0 35 this.__decoderRing = Cc["@mozilla.org/security/sdr;1"].
michael@0 36 getService(Ci.nsISecretDecoderRing);
michael@0 37 return this.__decoderRing;
michael@0 38 },
michael@0 39
michael@0 40 __utfConverter : null, // UCS2 <--> UTF8 string conversion
michael@0 41 get _utfConverter() {
michael@0 42 if (!this.__utfConverter) {
michael@0 43 this.__utfConverter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
michael@0 44 createInstance(Ci.nsIScriptableUnicodeConverter);
michael@0 45 this.__utfConverter.charset = "UTF-8";
michael@0 46 }
michael@0 47 return this.__utfConverter;
michael@0 48 },
michael@0 49
michael@0 50 _utfConverterReset : function() {
michael@0 51 this.__utfConverter = null;
michael@0 52 },
michael@0 53
michael@0 54 _debug : false, // mirrors signon.debug
michael@0 55 _uiBusy : false,
michael@0 56
michael@0 57
michael@0 58 /*
michael@0 59 * log
michael@0 60 *
michael@0 61 * Internal function for logging debug messages to the Error Console.
michael@0 62 */
michael@0 63 log : function (message) {
michael@0 64 if (!this._debug)
michael@0 65 return;
michael@0 66 dump("PwMgr cryptoSDR: " + message + "\n");
michael@0 67 Services.console.logStringMessage("PwMgr cryptoSDR: " + message);
michael@0 68 },
michael@0 69
michael@0 70
michael@0 71 init : function () {
michael@0 72 // Connect to the correct preferences branch.
michael@0 73 this._prefBranch = Services.prefs.getBranch("signon.");
michael@0 74
michael@0 75 this._debug = this._prefBranch.getBoolPref("debug");
michael@0 76
michael@0 77 // Check to see if the internal PKCS#11 token has been initialized.
michael@0 78 // If not, set a blank password.
michael@0 79 let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"].
michael@0 80 getService(Ci.nsIPK11TokenDB);
michael@0 81
michael@0 82 let token = tokenDB.getInternalKeyToken();
michael@0 83 if (token.needsUserInit) {
michael@0 84 this.log("Initializing key3.db with default blank password.");
michael@0 85 token.initPassword("");
michael@0 86 }
michael@0 87 },
michael@0 88
michael@0 89
michael@0 90 /*
michael@0 91 * encrypt
michael@0 92 *
michael@0 93 * Encrypts the specified string, using the SecretDecoderRing.
michael@0 94 *
michael@0 95 * Returns the encrypted string, or throws an exception if there was a
michael@0 96 * problem.
michael@0 97 */
michael@0 98 encrypt : function (plainText) {
michael@0 99 let cipherText = null;
michael@0 100
michael@0 101 let wasLoggedIn = this.isLoggedIn;
michael@0 102 let canceledMP = false;
michael@0 103
michael@0 104 this._uiBusy = true;
michael@0 105 try {
michael@0 106 let plainOctet = this._utfConverter.ConvertFromUnicode(plainText);
michael@0 107 plainOctet += this._utfConverter.Finish();
michael@0 108 cipherText = this._decoderRing.encryptString(plainOctet);
michael@0 109 } catch (e) {
michael@0 110 this.log("Failed to encrypt string. (" + e.name + ")");
michael@0 111 // If the user clicks Cancel, we get NS_ERROR_FAILURE.
michael@0 112 // (unlike decrypting, which gets NS_ERROR_NOT_AVAILABLE).
michael@0 113 if (e.result == Cr.NS_ERROR_FAILURE) {
michael@0 114 canceledMP = true;
michael@0 115 throw Components.Exception("User canceled master password entry", Cr.NS_ERROR_ABORT);
michael@0 116 } else {
michael@0 117 throw Components.Exception("Couldn't encrypt string", Cr.NS_ERROR_FAILURE);
michael@0 118 }
michael@0 119 } finally {
michael@0 120 this._uiBusy = false;
michael@0 121 // If we triggered a master password prompt, notify observers.
michael@0 122 if (!wasLoggedIn && this.isLoggedIn)
michael@0 123 this._notifyObservers("passwordmgr-crypto-login");
michael@0 124 else if (canceledMP)
michael@0 125 this._notifyObservers("passwordmgr-crypto-loginCanceled");
michael@0 126 }
michael@0 127 return cipherText;
michael@0 128 },
michael@0 129
michael@0 130
michael@0 131 /*
michael@0 132 * decrypt
michael@0 133 *
michael@0 134 * Decrypts the specified string, using the SecretDecoderRing.
michael@0 135 *
michael@0 136 * Returns the decrypted string, or throws an exception if there was a
michael@0 137 * problem.
michael@0 138 */
michael@0 139 decrypt : function (cipherText) {
michael@0 140 let plainText = null;
michael@0 141
michael@0 142 let wasLoggedIn = this.isLoggedIn;
michael@0 143 let canceledMP = false;
michael@0 144
michael@0 145 this._uiBusy = true;
michael@0 146 try {
michael@0 147 let plainOctet;
michael@0 148 plainOctet = this._decoderRing.decryptString(cipherText);
michael@0 149 plainText = this._utfConverter.ConvertToUnicode(plainOctet);
michael@0 150 } catch (e) {
michael@0 151 this.log("Failed to decrypt string: " + cipherText +
michael@0 152 " (" + e.name + ")");
michael@0 153
michael@0 154 // In the unlikely event the converter threw, reset it.
michael@0 155 this._utfConverterReset();
michael@0 156
michael@0 157 // If the user clicks Cancel, we get NS_ERROR_NOT_AVAILABLE.
michael@0 158 // If the cipherText is bad / wrong key, we get NS_ERROR_FAILURE
michael@0 159 // Wrong passwords are handled by the decoderRing reprompting;
michael@0 160 // we get no notification.
michael@0 161 if (e.result == Cr.NS_ERROR_NOT_AVAILABLE) {
michael@0 162 canceledMP = true;
michael@0 163 throw Components.Exception("User canceled master password entry", Cr.NS_ERROR_ABORT);
michael@0 164 } else {
michael@0 165 throw Components.Exception("Couldn't decrypt string", Cr.NS_ERROR_FAILURE);
michael@0 166 }
michael@0 167 } finally {
michael@0 168 this._uiBusy = false;
michael@0 169 // If we triggered a master password prompt, notify observers.
michael@0 170 if (!wasLoggedIn && this.isLoggedIn)
michael@0 171 this._notifyObservers("passwordmgr-crypto-login");
michael@0 172 else if (canceledMP)
michael@0 173 this._notifyObservers("passwordmgr-crypto-loginCanceled");
michael@0 174 }
michael@0 175
michael@0 176 return plainText;
michael@0 177 },
michael@0 178
michael@0 179
michael@0 180 /*
michael@0 181 * uiBusy
michael@0 182 */
michael@0 183 get uiBusy() {
michael@0 184 return this._uiBusy;
michael@0 185 },
michael@0 186
michael@0 187
michael@0 188 /*
michael@0 189 * isLoggedIn
michael@0 190 */
michael@0 191 get isLoggedIn() {
michael@0 192 let status = this._sdrSlot.status;
michael@0 193 this.log("SDR slot status is " + status);
michael@0 194 if (status == Ci.nsIPKCS11Slot.SLOT_READY ||
michael@0 195 status == Ci.nsIPKCS11Slot.SLOT_LOGGED_IN)
michael@0 196 return true;
michael@0 197 if (status == Ci.nsIPKCS11Slot.SLOT_NOT_LOGGED_IN)
michael@0 198 return false;
michael@0 199 throw Components.Exception("unexpected slot status: " + status, Cr.NS_ERROR_FAILURE);
michael@0 200 },
michael@0 201
michael@0 202
michael@0 203 /*
michael@0 204 * defaultEncType
michael@0 205 */
michael@0 206 get defaultEncType() {
michael@0 207 return Ci.nsILoginManagerCrypto.ENCTYPE_SDR;
michael@0 208 },
michael@0 209
michael@0 210
michael@0 211 /*
michael@0 212 * _notifyObservers
michael@0 213 */
michael@0 214 _notifyObservers : function(topic) {
michael@0 215 this.log("Prompted for a master password, notifying for " + topic);
michael@0 216 Services.obs.notifyObservers(null, topic, null);
michael@0 217 },
michael@0 218 }; // end of nsLoginManagerCrypto_SDR implementation
michael@0 219
michael@0 220 let component = [LoginManagerCrypto_SDR];
michael@0 221 this.NSGetFactory = XPCOMUtils.generateNSGetFactory(component);

mercurial