changepassword.js (5894B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 "use strict"; 5 6 const { XPCOMUtils } = ChromeUtils.importESModule( 7 "resource://gre/modules/XPCOMUtils.sys.mjs" 8 ); 9 10 ChromeUtils.defineLazyGetter( 11 this, 12 "l10n", 13 () => new Localization(["security/pippki/pippki.ftl"], true) 14 ); 15 16 var params; 17 var token; 18 var pw1; 19 20 function doPrompt(messageL10nId) { 21 let msg = l10n.formatValueSync(messageL10nId); 22 Services.prompt.alert(window, null, msg); 23 } 24 25 function onLoad() { 26 document.getElementById("set_password").getButton("accept").disabled = true; 27 document.addEventListener("dialogaccept", setPassword); 28 29 pw1 = document.getElementById("pw1"); 30 pw1.addEventListener("input", () => { 31 setPasswordStrength(); 32 checkPasswords(); 33 }); 34 35 let pw2 = document.getElementById("pw2"); 36 pw2.addEventListener("input", () => { 37 checkPasswords(); 38 }); 39 40 params = window.arguments[0].QueryInterface(Ci.nsIDialogParamBlock); 41 token = params.objects.GetElementAt(0).QueryInterface(Ci.nsIPK11Token); 42 43 document.l10n.setAttributes( 44 document.getElementById("tokenName"), 45 "change-password-token", 46 { tokenName: token.tokenName } 47 ); 48 process(); 49 } 50 51 function process() { 52 let bundle = document.getElementById("pippki_bundle"); 53 let oldpwbox = document.getElementById("oldpw"); 54 let msgBox = document.getElementById("message"); 55 // If the token is unitialized, don't use the old password box. 56 // Otherwise, do. 57 if ((token.needsLogin() && token.needsUserInit) || !token.needsLogin()) { 58 oldpwbox.hidden = true; 59 msgBox.setAttribute("value", bundle.getString("password_not_set")); 60 msgBox.hidden = false; 61 62 if (!token.needsLogin()) { 63 oldpwbox.setAttribute("inited", "empty"); 64 } else { 65 oldpwbox.setAttribute("inited", "true"); 66 } 67 68 // Select first password field 69 document.getElementById("pw1").focus(); 70 } else { 71 // Select old password field 72 oldpwbox.hidden = false; 73 msgBox.hidden = true; 74 oldpwbox.setAttribute("inited", "false"); 75 oldpwbox.focus(); 76 } 77 78 // Return value 0 means "canceled" 79 params.SetInt(1, 0); 80 81 checkPasswords(); 82 } 83 84 function setPassword(event) { 85 var oldpwbox = document.getElementById("oldpw"); 86 var initpw = oldpwbox.getAttribute("inited"); 87 88 var success = false; 89 90 if (initpw == "false" || initpw == "empty") { 91 try { 92 var oldpw = ""; 93 var passok = 0; 94 95 if (initpw == "empty") { 96 passok = 1; 97 } else { 98 oldpw = oldpwbox.value; 99 passok = token.checkPassword(oldpw); 100 } 101 102 if (passok) { 103 if (initpw == "empty" && pw1.value == "") { 104 // checkPasswords() should have prevented this path from being reached. 105 } else { 106 if (pw1.value == "") { 107 var secmoddb = Cc[ 108 "@mozilla.org/security/pkcs11moduledb;1" 109 ].getService(Ci.nsIPKCS11ModuleDB); 110 if (secmoddb.isFIPSEnabled) { 111 // empty passwords are not allowed in FIPS mode 112 doPrompt("pippki-pw-change2empty-in-fips-mode"); 113 passok = 0; 114 } 115 } 116 if (passok) { 117 token.changePassword(oldpw, pw1.value); 118 if (pw1.value == "") { 119 doPrompt("pippki-pw-erased-ok"); 120 } else { 121 doPrompt("pippki-pw-change-ok"); 122 } 123 success = true; 124 } 125 } 126 } else { 127 oldpwbox.focus(); 128 oldpwbox.setAttribute("value", ""); 129 doPrompt("pippki-incorrect-pw"); 130 } 131 } catch (e) { 132 doPrompt("pippki-failed-pw-change"); 133 } 134 } else { 135 token.initPassword(pw1.value); 136 if (pw1.value == "") { 137 doPrompt("pippki-pw-not-wanted"); 138 } 139 success = true; 140 } 141 142 if (success && params) { 143 // Return value 1 means "successfully executed ok" 144 params.SetInt(1, 1); 145 } 146 147 // Terminate dialog 148 if (!success) { 149 event.preventDefault(); 150 } 151 } 152 153 function setPasswordStrength() { 154 // We weigh the quality of the password by checking the number of: 155 // - Characters 156 // - Numbers 157 // - Non-alphanumeric chars 158 // - Upper and lower case characters 159 160 let pw = document.getElementById("pw1").value; 161 162 let pwlength = pw.length; 163 if (pwlength > 5) { 164 pwlength = 5; 165 } 166 167 let numnumeric = pw.replace(/[0-9]/g, ""); 168 let numeric = pw.length - numnumeric.length; 169 if (numeric > 3) { 170 numeric = 3; 171 } 172 173 let symbols = pw.replace(/\W/g, ""); 174 let numsymbols = pw.length - symbols.length; 175 if (numsymbols > 3) { 176 numsymbols = 3; 177 } 178 179 let numupper = pw.replace(/[A-Z]/g, ""); 180 let upper = pw.length - numupper.length; 181 if (upper > 3) { 182 upper = 3; 183 } 184 185 let pwstrength = 186 pwlength * 10 - 20 + numeric * 10 + numsymbols * 15 + upper * 10; 187 188 // Clamp strength to [0, 100]. 189 if (pwstrength < 0) { 190 pwstrength = 0; 191 } 192 if (pwstrength > 100) { 193 pwstrength = 100; 194 } 195 196 let meter = document.getElementById("pwmeter"); 197 meter.setAttribute("value", pwstrength); 198 } 199 200 function checkPasswords() { 201 let pw1 = document.getElementById("pw1").value; 202 let pw2 = document.getElementById("pw2").value; 203 204 var oldpwbox = document.getElementById("oldpw"); 205 if (oldpwbox) { 206 var initpw = oldpwbox.getAttribute("inited"); 207 208 if (initpw == "empty" && pw1 == "") { 209 // The token has already been initialized, therefore this dialog 210 // was called with the intention to change the password. 211 // The token currently uses an empty password. 212 // We will not allow changing the password from empty to empty. 213 document.getElementById("set_password").getButton("accept").disabled = 214 true; 215 return; 216 } 217 } 218 219 document.getElementById("set_password").getButton("accept").disabled = 220 pw1 != pw2; 221 } 222 223 window.addEventListener("load", onLoad);