summaryrefslogtreecommitdiff
path: root/data/patches/0003-Bug-1013064-part-3-only-migrate-data-into-the-loginm.patch
blob: 063a031226b217da9faf42fdde6c6134521760fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
From 86c67f9b9081ce905442c86b38575b3422c8dce3 Mon Sep 17 00:00:00 2001
From: Mark Hammond <mhammond@skippinet.com.au>
Date: Wed, 18 Jun 2014 15:07:41 +1000
Subject: Bug 1013064 (part 3) - only migrate data into the loginmgr when it is
 unlocked. r=ckarlof

---
 services/fxaccounts/FxAccounts.jsm                 |  25 ++++-
 .../tests/xpcshell/test_loginmgr_storage.js        | 113 +++++++++++++++++++++
 2 files changed, 137 insertions(+), 1 deletion(-)

diff --git a/services/fxaccounts/FxAccounts.jsm b/services/fxaccounts/FxAccounts.jsm
index e9328dd..14d71fc 100644
--- a/services/fxaccounts/FxAccounts.jsm
+++ b/services/fxaccounts/FxAccounts.jsm
@@ -1025,17 +1025,40 @@ LoginManagerStorage.prototype = {
       // it previously and then we are done.
       yield this._clearLoginMgrData();
       return null;
     }
 
     // if we have encryption keys it must have been saved before we
     // used the login manager, so re-save it.
     if (data.accountData.kA || data.accountData.kB || data.keyFetchToken) {
-      log.info("account data needs migration to the login manager.");
+      // We need to migrate, but the MP might be locked (eg, on the first run
+      // with this enabled, we will get here very soon after startup, so will
+      // certainly be locked.)  This means we can't actually store the data in
+      // the login manager (and thus might lose it if we migrated now)
+      // So if the MP is locked, we *don't* migrate, but still just return
+      // the subset of data we now store in the JSON.
+      // This will cause sync to notice the lack of keys, force an unlock then
+      // re-fetch the account data to see if the keys are there.  At *that*
+      // point we will end up back here, but because the MP is now unlocked
+      // we can actually perform the migration.
+      if (!this._isLoggedIn) {
+        // return the "safe" subset but leave the storage alone.
+        log.info("account data needs migration to the login manager but the MP is locked.");
+        let result = {
+          version: data.version,
+          accountData: {},
+        };
+        for (let fieldName of FXA_PWDMGR_PLAINTEXT_FIELDS) {
+          result.accountData[fieldName] = data.accountData[fieldName];
+        }
+        return result;
+      }
+      // actually migrate - just calling .set() will split everything up.
+      log.info("account data is being migrated to the login manager.");
       yield this.set(data);
     }
 
     try { // Services.logins might be third-party and broken...
       // read the data from the login manager and merge it for return.
       yield Services.logins.initializationPromise;
 
       if (!this._isLoggedIn) {
diff --git a/services/fxaccounts/tests/xpcshell/test_loginmgr_storage.js b/services/fxaccounts/tests/xpcshell/test_loginmgr_storage.js
index 297b256..a9cf5f4 100644
--- a/services/fxaccounts/tests/xpcshell/test_loginmgr_storage.js
+++ b/services/fxaccounts/tests/xpcshell/test_loginmgr_storage.js
@@ -98,16 +98,129 @@ add_task(function test_MPLocked() {
 
   Assert.ok(!("kA" in data.accountData), "kA not stored in clear text");
   Assert.ok(!("kB" in data.accountData), "kB not stored in clear text");
 
   Assert.strictEqual(getLoginMgrData(), null, "login mgr data doesn't exist");
   yield fxa.signOut(/* localOnly = */ true)
 });
 
+add_task(function test_migrationMPUnlocked() {
+  // first manually save a signedInUser.json to simulate a first-run with
+  // pre-migrated data.
+  let fxa = new FxAccounts({});
+
+  let creds = {
+    email: "test@example.com",
+    sessionToken: "sessionToken",
+    kA: "the kA value",
+    kB: "the kB value",
+    verified: true
+  };
+  let toWrite = {
+    version: fxa.version,
+    accountData: creds,
+  }
+
+  let path = OS.Path.join(OS.Constants.Path.profileDir, "signedInUser.json");
+  yield CommonUtils.writeJSON(toWrite, path);
+
+  // now load it - it should migrate.
+  let data = yield fxa.getSignedInUser();
+  Assert.deepEqual(data, creds, "we got all the data back");
+
+  // and verify it was actually migrated - re-read signedInUser back.
+  let data = yield CommonUtils.readJSON(path);
+
+  Assert.strictEqual(data.accountData.email, creds.email, "correct email in the clear text");
+  Assert.strictEqual(data.accountData.sessionToken, creds.sessionToken, "correct sessionToken in the clear text");
+  Assert.strictEqual(data.accountData.verified, creds.verified, "correct verified flag");
+
+  Assert.ok(!("kA" in data.accountData), "kA not stored in clear text");
+  Assert.ok(!("kB" in data.accountData), "kB not stored in clear text");
+
+  let login = getLoginMgrData();
+  Assert.strictEqual(login.username, creds.email, "email matches");
+  let loginData = JSON.parse(login.password);
+  Assert.strictEqual(loginData.version, data.version, "same version flag in both places");
+  Assert.strictEqual(loginData.accountData.kA, creds.kA, "correct kA in the login mgr");
+  Assert.strictEqual(loginData.accountData.kB, creds.kB, "correct kB in the login mgr");
+
+  Assert.ok(!("email" in loginData), "email not stored in the login mgr json");
+  Assert.ok(!("sessionToken" in loginData), "sessionToken not stored in the login mgr json");
+  Assert.ok(!("verified" in loginData), "verified not stored in the login mgr json");
+
+  yield fxa.signOut(/* localOnly = */ true);
+  Assert.strictEqual(getLoginMgrData(), null, "login mgr data deleted on logout");
+});
+
+add_task(function test_migrationMPLocked() {
+  // first manually save a signedInUser.json to simulate a first-run with
+  // pre-migrated data.
+  let fxa = new FxAccounts({});
+
+  let creds = {
+    email: "test@example.com",
+    sessionToken: "sessionToken",
+    kA: "the kA value",
+    kB: "the kB value",
+    verified: true
+  };
+  let toWrite = {
+    version: fxa.version,
+    accountData: creds,
+  }
+
+  let path = OS.Path.join(OS.Constants.Path.profileDir, "signedInUser.json");
+  yield CommonUtils.writeJSON(toWrite, path);
+
+  // pretend the MP is locked.
+  fxa.internal.signedInUserStorage.__defineGetter__("_isLoggedIn", function() false);
+
+  // now load it - it should *not* migrate, but should only give the JSON-safe
+  // data back.
+  let data = yield fxa.getSignedInUser();
+  Assert.ok(!data.kA);
+  Assert.ok(!data.kB);
+
+  // and verify the data on disk wan't migrated.
+  data = yield CommonUtils.readJSON(path);
+  Assert.deepEqual(data, toWrite);
+
+  // Now "unlock" and re-ask for the signedInUser - it should migrate.
+  fxa.internal.signedInUserStorage.__defineGetter__("_isLoggedIn", function() true);
+  data = yield fxa.getSignedInUser();
+  // this time we should have got all the data, not just the JSON-safe fields.
+  Assert.strictEqual(data.kA, creds.kA);
+  Assert.strictEqual(data.kB, creds.kB);
+
+  // And verify the data in the JSON was migrated
+  data = yield CommonUtils.readJSON(path);
+  Assert.strictEqual(data.accountData.email, creds.email, "correct email in the clear text");
+  Assert.strictEqual(data.accountData.sessionToken, creds.sessionToken, "correct sessionToken in the clear text");
+  Assert.strictEqual(data.accountData.verified, creds.verified, "correct verified flag");
+
+  Assert.ok(!("kA" in data.accountData), "kA not stored in clear text");
+  Assert.ok(!("kB" in data.accountData), "kB not stored in clear text");
+
+  let login = getLoginMgrData();
+  Assert.strictEqual(login.username, creds.email, "email matches");
+  let loginData = JSON.parse(login.password);
+  Assert.strictEqual(loginData.version, data.version, "same version flag in both places");
+  Assert.strictEqual(loginData.accountData.kA, creds.kA, "correct kA in the login mgr");
+  Assert.strictEqual(loginData.accountData.kB, creds.kB, "correct kB in the login mgr");
+
+  Assert.ok(!("email" in loginData), "email not stored in the login mgr json");
+  Assert.ok(!("sessionToken" in loginData), "sessionToken not stored in the login mgr json");
+  Assert.ok(!("verified" in loginData), "verified not stored in the login mgr json");
+
+  yield fxa.signOut(/* localOnly = */ true);
+  Assert.strictEqual(getLoginMgrData(), null, "login mgr data deleted on logout");
+});
+
 add_task(function test_consistentWithMPEdgeCases() {
   let fxa = new FxAccounts({});
 
   let creds1 = {
     email: "test@example.com",
     sessionToken: "sessionToken",
     kA: "the kA value",
     kB: "the kB value",
-- 
1.8.3.msysgit.0