-
Notifications
You must be signed in to change notification settings - Fork 256
Expand file tree
/
Copy pathlogins.udl
More file actions
327 lines (258 loc) · 10.8 KB
/
logins.udl
File metadata and controls
327 lines (258 loc) · 10.8 KB
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
namespace logins {
/// We expose the crypto primitives on the namespace
/// Create a new, random, encryption key.
[Throws=LoginsApiError]
string create_key();
/// Create a "canary" string, which can be used to test if the encryption
//key is still valid for the logins data
[Throws=LoginsApiError]
string create_canary([ByRef]string text, [ByRef]string encryption_key);
/// Check that key is still valid using the output of `create_canary`.
//`text` much match the text you initially passed to `create_canary()`
[Throws=LoginsApiError]
boolean check_canary([ByRef]string canary, [ByRef]string text, [ByRef]string encryption_key);
/// Utility function to create a StaticKeyManager to be used for the time
/// being until support lands for [trait implementation of an UniFFI
/// interface](https://mozilla.github.io/uniffi-rs/next/proc_macro/index.html#structs-implementing-traits)
/// in UniFFI.
KeyManager create_static_key_manager(string key);
/// Similar to create_static_key_manager above, create a
/// ManagedEncryptorDecryptor by passing in a KeyManager
EncryptorDecryptor create_managed_encdec(KeyManager key_manager);
/// Create a LoginStore with StaticKeyManager by passing in a db path and a
/// static key
LoginStore create_login_store_with_static_key_manager(string path, string key);
};
/// A login entry from the user, not linked to any database record.
/// The add/update APIs input these.
dictionary LoginEntry {
// login fields
string origin;
string? http_realm;
string? form_action_origin;
string username_field;
string password_field;
// secure login fields
string password;
string username;
};
/// Metadata fields managed internally by the library.
/// These are automatically set on `add()` and updated on operations like `touch()` and `update()`.
/// Not included in LoginEntry; use `add_with_meta()` when importing records with existing metadata.
dictionary LoginMeta {
string id;
i64 times_used;
i64 time_created;
i64 time_last_used;
i64 time_password_changed;
i64? time_of_last_breach;
i64? time_last_breach_alert_dismissed;
};
/// A login together with record fields, handed over to the store API; ie a login persisted
/// elsewhere, useful for migrations
dictionary LoginEntryWithMeta {
LoginEntry entry;
LoginMeta meta;
};
/// A bulk insert result entry, returned by `add_many` and `add_many_with_meta`
[Enum]
interface BulkResultEntry {
Success(Login login);
Error(string message);
};
/// A login stored in the database
dictionary Login {
// meta fields
string id;
i64 times_used;
i64 time_created;
i64 time_last_used;
i64 time_password_changed;
// breach fields
i64? time_of_last_breach;
i64? time_last_breach_alert_dismissed;
// login fields
string origin;
string? http_realm;
string? form_action_origin;
string username_field;
string password_field;
// secure login fields
string password;
string username;
};
/// Metrics tracking deletion of logins that cannot be decrypted, see `delete_undecryptable_records_for_remote_replacement`
/// for more details
dictionary LoginsDeletionMetrics {
u64 local_deleted;
u64 mirror_deleted;
};
/// These are the errors returned by our public API.
[Error]
interface LoginsApiError {
/// NSS not initialized.
NSSUninitialized();
/// NSS error during authentication
NSSAuthenticationError(string reason);
/// error during authentication (in PrimaryPasswordAuthenticator)
AuthenticationError(string reason);
/// authentication has been cancelled.
AuthenticationCanceled();
/// The login data supplied is invalid. The reason will indicate what's wrong with it.
InvalidRecord(string reason);
/// Asking to do something with a guid which doesn't exist.
NoSuchRecord(string reason);
/// Encryption key is missing.
MissingKey();
/// Encryption key is not valid.
InvalidKey();
/// encryption failed
EncryptionFailed(string reason);
/// decryption failed
DecryptionFailed(string reason);
/// An operation was interrupted at the request of the consuming app.
Interrupted(string reason);
/// something internal went wrong which doesn't have a public error value
/// because the consuming app can not reasonably take any action to resolve it.
/// The underlying error will have been logged and reported.
/// (ideally would just be `Unexpected`, but that would be a breaking change)
UnexpectedLoginsApiError(string reason);
};
[Trait, WithForeign]
interface EncryptorDecryptor {
[Throws=LoginsApiError]
bytes encrypt(bytes cleartext);
[Throws=LoginsApiError]
bytes decrypt(bytes ciphertext);
};
[Trait, WithForeign]
interface KeyManager {
[Throws=LoginsApiError]
bytes get_key();
};
interface StaticKeyManager {
constructor(string key);
};
interface ManagedEncryptorDecryptor {
constructor(KeyManager key_manager);
};
interface LoginStore {
[Throws=LoginsApiError]
constructor(string path, EncryptorDecryptor encdec);
[Throws=LoginsApiError]
Login add(LoginEntry login);
[Throws=LoginsApiError]
sequence<BulkResultEntry> add_many(sequence<LoginEntry> logins);
[Throws=LoginsApiError]
Login add_with_meta(LoginEntryWithMeta entry_with_meta);
[Throws=LoginsApiError]
sequence<BulkResultEntry> add_many_with_meta(sequence<LoginEntryWithMeta> entries_with_meta);
[Throws=LoginsApiError]
Login update([ByRef] string id, LoginEntry login);
[Throws=LoginsApiError]
Login add_or_update(LoginEntry login);
[Throws=LoginsApiError]
boolean delete([ByRef] string id);
[Throws=LoginsApiError, Self=ByArc]
sequence<boolean> delete_many(sequence<string> ids);
/// Clear out locally stored logins data
///
/// If sync is enabled, then we will try to recover the data on the next sync.
///
/// The main reason to call this is when regenerating a new encryption key.
/// In that case, there's no reason to keep around the local data since it can't be decrypted.
/// Calling `wipe_local` is better than keeping around these un-decryptable logins, since we
/// might be able to recover the data via sync.
///
/// This is a no-op for freshly created databases, so it's safe to call this whenever a key is
/// generated.
[Throws=LoginsApiError]
void wipe_local();
[Throws=LoginsApiError, Self=ByArc]
void reset();
/// The `delete_undecryptable_records_for_remote_replacement` function locally deletes stored logins
/// that cannot be decrypted and sets the last sync time to 0 so any existing server records can be downloaded
/// and overwrite the locally deleted records.
///
/// NB: This function was created to unblock iOS logins users who are unable to sync logins and should not be used
/// outside of this use case.
[Throws=LoginsApiError, Self=ByArc]
LoginsDeletionMetrics delete_undecryptable_records_for_remote_replacement();
[Throws=LoginsApiError]
void touch([ByRef] string id);
/// Determines whether a login’s password is potentially breached, based on the breach date and the time of the last password change.
[Throws=LoginsApiError]
boolean is_potentially_breached([ByRef] string id);
/// Checks multiple logins for password reuse in a single batch operation.
///
/// Returns the GUIDs of logins whose passwords match any password in the breach database.
/// This is more efficient than calling `is_potentially_vulnerable_password()` repeatedly,
/// as it decrypts the breach database only once.
[Throws=LoginsApiError]
sequence<string> are_potentially_vulnerable_passwords(sequence<string> ids);
/// Checks if a login's password matches any password in the local breach database.
///
/// Returns true if this login's password appears in the breachesL table, indicating
/// that the same password has been breached on a different domain (password reuse).
/// This is independent of whether this specific login has been marked as breached.
[Throws=LoginsApiError]
boolean is_potentially_vulnerable_password([ByRef] string id);
/// Records a list of potentially vulnerable passwords in the breach database.
///
/// This is used to bulk-populate the breachesL table with known breached passwords,
/// typically during import operations or when syncing breach data.
/// Passwords are encrypted before storage and duplicates are automatically filtered out.
[Throws=LoginsApiError]
void record_potentially_vulnerable_passwords(sequence<string> passwords);
/// Stores a known breach date for a login.
/// In Firefox Desktop this is updated once per session from Remote Settings.
[Throws=LoginsApiError]
void record_breach([ByRef] string id, i64 timestamp);
/// Removes all recorded breaches for all logins (i.e. sets time_of_last_breach to null).
[Throws=LoginsApiError]
void reset_all_breaches();
/// Determines whether a breach alert has been dismissed, based on the breach date and the alert dismissal timestamp.
[Throws=LoginsApiError]
boolean is_breach_alert_dismissed([ByRef] string id);
/// Stores that the user dismissed the breach alert for a login.
[Throws=LoginsApiError]
void record_breach_alert_dismissal([ByRef] string id);
/// Stores the time at which the user dismissed the breach alert for a login.
[Throws=LoginsApiError]
void record_breach_alert_dismissal_time([ByRef] string id, i64 timestamp);
[Throws=LoginsApiError]
boolean is_empty();
[Throws=LoginsApiError]
i64 count();
[Throws=LoginsApiError]
i64 count_by_origin([ByRef] string origin);
[Throws=LoginsApiError]
i64 count_by_form_action_origin([ByRef] string form_action_origin);
[Throws=LoginsApiError]
sequence<Login> list();
[Throws=LoginsApiError]
sequence<Login> get_by_base_domain([ByRef] string base_domain);
[Throws=LoginsApiError]
boolean has_logins_by_base_domain([ByRef] string base_domain);
[Throws=LoginsApiError]
Login? find_login_to_update(LoginEntry look);
[Throws=LoginsApiError]
Login? get([ByRef] string id);
[Throws=LoginsApiError]
void set_checkpoint([ByRef] string checkpoint);
[Throws=LoginsApiError]
string? get_checkpoint();
/// Run maintenance on the DB
///
/// This is intended to be run during idle time and will take steps / to clean up / shrink the
/// database.
[Throws=LoginsApiError]
void run_maintenance();
[Self=ByArc]
void register_with_sync_manager();
[Self=ByArc]
void shutdown();
};