-
-
Notifications
You must be signed in to change notification settings - Fork 89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make working with encrypted storage RAII #3063
Conversation
This refactors the APIs to work with encrypted storage to folow the Resource Acquisition Is Initialisation principle. Having our structures behave like this is beneficial because it reoves a lot of edge-cases that would need to be handled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some API review, haven't looked at implementation yet.
@@ -103,74 +103,62 @@ pub fn get_info() -> BTreeMap<&'static str, String> { | |||
res | |||
} | |||
|
|||
#[derive(Debug, thiserror::Error)] | |||
pub enum ContextError { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can having a public error type and matching on errors be avoided?
E.g. return anyhow::Result<Option<Self>>
from Context::new
, with None
meaning the key is probably wrong. Then in load_accounts
you can use Context::new(...).with_context(|| "failed to create context from file {}", ..)?
.
If you don't like Option
you can make your own enum
type, but errors are something that is either passed upwards with ?
or written to logs if there is a fallback to be tried.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum, going to have to sleep over this. I think with #[error(transparent)]
this is a fairly nice option here that allows matching on just what we care about while still letting you propagate errors. I'm not sure if nested types are that much nicer.
Originally I was calling thing "password" a lot, but the consistent naming is "passphrase" and "encrypted account".
Otherwise you do not know which account needs unlocking if the selected account is locked.
just a quick feedback: i am a bit skeptical to this approach. as discussed in dev-chat already, that will cause troubles in all UIs as the context is a very basic object, more regarded as "the app" (logging, stockstrings, database) and not only a database. most things currently cannot exist without a context, Activities and ViewController expect them and pass them around etc. sure, changable, but that is effort and noise on all UIs. we should take that into account. i also do not really like the removed "list all accounts" functionality - now the ui has to glue different lists together, also, doable, but additional effort - all other lists are "well prepared" for ui use. however, this point is probably easy changable. in general, i'd like to think about the ffi more about what the ui "needs". i am wondering if we cannot leave the ffi as is and do the RAII-thinie rust-internally only. afaik, ffi-context is only a wrapper around rust-context - we we could probably change rust-context on opening, if needed. that would break RAII at some point, but that is a much more well defined point then - and, we can then see in the future to change the ffi. otherwise, i fear, we will get in timing and stress issues right in march/april, when it comes to M2 ... there are already so many things to do in the UI. |
Logging is an internal thing, all the UI sees is an event emitter.
Then UI will have to do what it does already: if there are no contexts available (because there are none or because they are all locked), create a new context just to display Welcome screen. It's even implemented already.
Currently locked accounts are useless, you can't even get the display name as it will error out due to database being closed. We need a different UI for locked accounts anyway because they are indistinguishable from each other except for their account ID. Maybe display a counter saying how many locked accounts are there, so when user enters a passphrase we try to open all the locked accounts with it. Locked accounts are really different from the UI point of view. If we decide we want an unified list (which will require storing display name copy in TOML), then it will be not a list of contexts, but a list of new type dc_account_t which has limited number of methods just enough to display a list item and unlock it. |
sure, everything is doable, i was just saying that that will be some effort. maybe okay, but after all experience i tend to be more pessimistic in that area :) i think for the locked account ui: this is just not decided yet. i assume we will dive deeper into that the next weeks. but that is also not directly related to the refactored ui. we could also have a dc_accounts_get_displayname() etc. that would not need much refactoring. but yes, that depdends on what we want at the end. EDIT: in general, if we agree on that we want these new api changes, maybe before merging this pr, better first have the corresponding desktop/ios/android prs ready, so that we can be sure, things are doable with reasonable effort. maybe, this is no issue, but, tbh, i cannot oversee that at the moment. |
So I think in general the feedback (apart from r10s' 😉) has been leaning towards the positive side (also in chat), though of course it does incur extra work.
So, I tentatively suggest we attempt to adopt this? Could we convince a UI to try this out before merging? |
cc @Hocuri @Jikstra @Simon-Laux for someone who can try to adopt this API for Android or Desktop. |
TBH, from an overall perspective, tackling this PR's approach right now sounds pretty dangerous.
Let me recap that for the march release that we have three things pending for enc storage:
- automatic migration from unencrypted to encrypted databases. Probably
all in core but there are at least out-of-space errors to deal with gracefully.
- set a passphrase on export and input a passphrase on import (FFIs plus UI changes)
- Desktop implementing system-keyring and encrypted db's (or a master passphrase mechanism)
this is quite a bit of things to get ready for end march including tested releases and pushes to app store (also some folks are still travelling).
So unless i am missing something about the state of the three tasks above i am rather -1 to introduce breaking changes right now that require work on all UIs before we tackle the above three points. Besides, encrypted storage is not the only thing happening in the next weeks and desktop 1.28 wasn't even released yet at all.
…On Sun, Feb 20, 2022 at 09:06 -0800, link2xt wrote:
> So, I tentatively suggest we attempt to adopt this? Could we convince a UI to try this out before merging?
cc @Hocuri @Jikstra @Simon-Laux for someone who can try to adopt this API for Android or Desktop.
--
Reply to this email directly or view it on GitHub:
#3063 (comment)
You are receiving this because you are subscribed to this thread.
Message ID: ***@***.***>
|
FTR, I'll copy my older comment from the dev chat here:
All in all, from a technical perspective, I'm +/-0 on which API would be better, and -0.5 on this PR as it's already implemented the other way. From an overall perspective, @hpk42's concerns sound sensible (I don't know much about what's left to do for the march release though; I think Android would be no problem even if we switched to RAII first, but of course there may always be unforeseen problems, and there are two other platform to worry about; in any case we should not merge this PR before all platforms have PRs ready to switch to the new API because otherwise we might get problems when we want to do the release and one platform hasn't switched yet). |
I think we can close this, as it seems unrealistic that it will be merged? |
As discussed during irc session we move this to resurrection because there is currently no further work planned on encrypted storage, and desktop uses jsonrpc anyway which is the missing (and most important probably) platform for encrypted storage. |
This refactors the APIs to work with encrypted storage to follow the Resource Acquisition Is Initialisation principle. Having our structures behave like this is beneficial because it removes a lot of edge-cases that would need to be handled, in the end resulting in a more stable core.
This will break current UIs. In particular it does not attempt to transition as doing so makes things even worse. I think this tradeoff is desirable, and my apologies for not having the time to engage better at the time this was originally introduced.
Using the new FFI
dc_context_new_closed()
,dc_context_is_open
anddc_context_open
are gone, if a context exists it is always open and usable.dc_context_new_encrypted()
can be used to create a new standalone context with encrypted storage.dc_accounts_add_encrypted_account()
creates a new account with encrypted storage when using the account manager.dc_accounts_get_all()
will now only return "loaded" contexts, when creatingdc_accounts_t
all unencrypted databases are automatically loaded.dc_accounts_get_encrypted()
will return all accounts which need to be decrypted before they can be used,dc_accounts_load_encrypted()
does this. Once loaded the encrypted account will show up indc_accounts_get_all()
and no longer appear indc_accounts_get_encrypted()
.dc_accounts_get_selected()
has been renamed todc_accounts_get_selected_id()
and now only returns the ID of the account. This lets you usedc_accounts_get_encrypted()
anddc_accounts_load_encrypted()
if it is an encrypted-not-yet-loaded account. Use the existingdc_accounts_get_account()
to get the pointer to the context.Design notes
Just like with the current implementation this can not distinguish between broken databases and encrypted ones. So if a corrupted database appears it will show up in
dc_accounts_get_encrypted()
forever.I have not tried to make the sql module RAII internally and tried to keep the changes there minimal to support the RAII interface. This PR is more than large enough already and this can be done as a followup.