-
-
Notifications
You must be signed in to change notification settings - Fork 199
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
Screencast restore #638
Screencast restore #638
Conversation
@smcv here's the screencast restore thing I've mentioned. I'd love to hear your thoughts on this. I'm not confident that this is a good approach, much less a secure one. |
Host system apps can also arbitrarily impersonate each other, e.g. if a host system app suspects that you might give Steam permission to record your screen (for Remote Play), it can tell xdg-desktop-portal "hello, I'm Steam". Or it can impersonate a web browser, or a standalone video-streaming client, or anything else, in a way that is indistinguishable from a Flatpak app. Anything Flatpak can do (not a Flatpak app, but Flatpak itself!), a host system app can do too. In general, a host system app can also ptrace xdg-desktop-portal, or append The solution is to avoid running host system apps that you don't completely trust: they are in the trusted computing base (TCB), on the trusted side of the airtight hatchway. Of course, this is far from ideal - if we were designing a modern app framework from scratch, without backward-compatibility concerns, we'd want literally every app to be identifiable as part of the app framework, as they are in Android or iOS, with a minimum of code in the TCB. However, users of Unix OSs are used to being able to add arbitrary programs to the TCB, with the tradition being that host system apps are the majority and sandboxed apps are a minority; and the price we pay for that freedom is that the programs added to the TCB are ... in the TCB. |
A host system app could also do the equivalent of If we assume an attacker that somehow only has the ability to monitor D-Bus passively (Monitoring and/or legacy eavesdropping, the same mechanisms used in new and old dbus-monitor respectively), then we could craft a way to avoid the token being visible on the bus. The easiest way would be for the portal's client (browser, VNC server, Steam, etc.) to fd-pass the write end of a pipe to the portal, and the portal could write the token into the pipe, then close the pipe; the client could read into a buffer until EOF, and that's their token. An eavesdropper can't read from the write end of a pipe, so it would be useless to them. However, that's 100% security theatre, because a host-system app that is only a passive attacker is not a realistic security model. If an attacker has the unfiltered access to the session bus that is necessary to carry out Monitoring or legacy eavesdropping, then they can also carry out active attacks. Perhaps the simplest active attack would be to ask the bus nicely for the |
From browser point of view, I think it only makes sense to use the |
@grulja this proposal contemplates this specific case in the form of the "transient" persist mode. It wouldn't touch the permissions store in this mode. I'm curious as to why it's not possible to simply pass the PipeWire stream between dialogs though. |
b5b420f
to
84fec1e
Compare
84fec1e
to
70851b0
Compare
This is ready for review now. The missing bits (removing transient permissions when a client disconnects, and apply review comments) are implemented. |
ebf7007
to
67ed97d
Compare
67ed97d
to
1935bb4
Compare
See https://gitlab.gnome.org/GNOME/xdg-desktop-portal-gnome/-/merge_requests/14 for a working, complete implementation of this feature. |
While working on the corresponding API in libportal, a question arised: should "restoring a stream" also restore extra information like the cursor mode, output types, etc? To expand a bit, libportal has this API: void xdp_portal_create_screencast_session (XdpPortal *portal,
XdpOutputType outputs,
XdpScreencastFlags flags,
XdpCursorMode cursor_mode,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data); Inspired by that, I thought about adding a sibling function that would look like this: void xdp_portal_restore_screencast_session (XdpPortal *portal,
XdpScreencastPersistMode persist_mode,
const char *restore_token,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data); Which seems quite natural, almost obvious of an API. Which is great. I'm still pondering the pros and cons of making stream restore also account for cursor mode, output types, etc. Pros:
Cons:
I'm currently leaning towards the current pull request, which does not store any additional information. I'd love to hear your thoughts on this |
I've been talking to various design-oriented folks about this feature, and what would an ideal interaction would look like, and apparently this proposal is flexible enough to allow portal implementations to do pretty sophisticated things (like, waiting for a window or monitor to be plugged when restoring a previous stream, etc). It doesn't seem necessary to add more properties to SelectSources() to be able to do that. So I guess this API design is playing out nicely in practice! |
Another reason to not attempt to restore cursor mode etc is that the session might not be available to be restored, meaning the application still needs to provide those parameters in case a new session will be created. |
Great point... scratch that idea then :) |
1935bb4
to
f64fe30
Compare
First implementation of a mechanism to restore previously configured screencast sessions. There are 2 important workflows happening in parallel: acquiring a token, and using it. # Acquiring a restore token 1. Applications that want to be able to restore screencast streams pass the `persist_mode` option to the `SelectSources()` method. Persist modes are explained below. 2. `xdg-desktop-portal` pass the `persist_mode` option to the portal implementation. 3. The portal implementation queries the user (usually via a dialog) which monitor or window to share, and whether they allow it to be restored. 4. If the screencast session should be restored, the portal implementation hands `xdg-desktop-portal` the implementation-specific data to be restored. This is passed via the `restore_data` option, at the response of the `Start()` call. 5. `xdg-desktop-portal` stores this data somewhere with an unique identifier that I called `restore_token`. 6. `xdg-desktop-portal` pass `restore_token` to the application. The application then should save this restore token however it thinks it's appropriate. # Using the restore token Now that the application has a restore token, it can restore a previous stream. This is how it happens: 1. Applications that want to restore a screencast stream pass the `restore_token` option to the `SelectSources()` method. 2. `xdg-desktop-portal` receives the token, and performs a lookup for the implementation-specific data associated with this token. 3. `xdg-desktop-portal` consumes this token and removes the permission. 4. `xdg-desktop-portal` sends this restore data to the portal implementation as the `restore_data` option to the `SelectSources()` method. 5. The portal implementation uses this restore data to match windows and monitors without presenting a dialog. If it fails to match (due to, for example, any monitors or windows not being available), it fallbacks to presenting the dialog. Tokens can only be used once to restore streams. The permissions they hold are revoked after use. That's what xdg-desktop-portal does at step 2.3. Applications must not assume anything about tokens. Portal implementations never have access to the restore tokens. # Persistence modes There are two modes of persistence: 1. Transient: the restore token is valid as long as the application is alive. It's stored in memory and revoked when the application closes its D-Bus connection. 2. Persistent: the restore token is stored in disk, using the permissions store, and is valid until the user manually revokes it. Extra care is taken to ensure that restore tokens aren't predictable. For the multi-stream case, add a new 'id' property to the list of stream properties. This allows applications to uniquely identify each stream.
e92b34b
to
9aad2ff
Compare
With the version 4 of the screencast portal, it is now possible to request and use restore tokens [1] so that apps can restore a previously configured screencast session without user interaction. Add the corresponding code to linux-capture's PipeWire source. Store the restore token in the source data, since each restore token corresponds to an OBS source, and use it as soon as we try to create a new session. Implement the obs_source_info.save vfunc, and save the restore token when it's received by the Start() response using obs_source_save(). [1] flatpak/xdg-desktop-portal#638
With the version 4 of the screencast portal, it is now possible to request and use restore tokens [1] so that apps can restore a previously configured screencast session without user interaction. Add the corresponding code to linux-capture's PipeWire source. Store the restore token in the source data, since each restore token corresponds to an OBS source, and use it as soon as we try to create a new session. Implement the obs_source_info.save vfunc, and save the restore token when it's received by the Start() response using obs_source_save(). [1] flatpak/xdg-desktop-portal#638
With the version 4 of the screencast portal, it is now possible to request and use restore tokens [1] so that apps can restore a previously configured screencast session without user interaction. Add the corresponding code to linux-capture's PipeWire source. Store the restore token in the source data, since each restore token corresponds to an OBS source, and use it as soon as we try to create a new session. Implement the obs_source_info.save vfunc, and save the restore token when it's received by the Start() response using obs_source_save(). [1] flatpak/xdg-desktop-portal#638
With the version 4 of the screencast portal, it is now possible to request and use restore tokens [1] so that apps can restore a previously configured screencast session without user interaction. Add the corresponding code to linux-capture's PipeWire source. Store the restore token in the source data, since each restore token corresponds to an OBS source, and use it as soon as we try to create a new session. Implement the obs_source_info.save vfunc, and save the restore token when it's received by the Start() response using obs_source_save(). [1] flatpak/xdg-desktop-portal#638
In which portal version will this be implemented? I'm looking forward this "remember the choice" feature to not have always these prompts. |
I'm pretty sure GNOME already has it, for Plasma it should be available for 5.25 https://invent.kde.org/plasma/xdg-desktop-portal-kde/-/merge_requests/79/ |
which version of GNOME? I have 41.5 and don't have it |
42 according to https://gitlab.gnome.org/GNOME/xdg-desktop-portal-gnome/-/blob/main/NEWS |
I have updated my archlinux to GNOME 42, but portal window still has not the option to remember the choice |
Does the application make use of the new feature? Are you running it in a flatpak? |
no.
I thought that this new update would automatically add the option "remember the choice". So the application devs have to manually implement it? I can make a feature request in flameshot git repo |
If not via flatpak (or snap) then they need to be run in a cgroup compatible with #719
No, the application needs to keep track of a token that it can use to restore a previous session. |
Ok thanks. But is this only for screencast, or can it be implemented on Flameshot (that uses Screenshot portal)? |
That's #649 |
Is there a way to readapt the "Screencast portal" restore code by @GeorgesStavracas to "Screenshot portal" in a fast and easy way so that a new volunteer who has to take time to do it is not needed? I mean, can the Screencast code be reused easily to apply it to Screenshot portal? If yes, I can try to do it, if it's not difficult, just suggest me how. |
Is there any reason this couldn't also be added to remote desktop sessions? P.S. the documentation in the PR description is great, but, would be very helpful to include some of those details in the documentation (i.e. details about the Token lifecycle, now all the "funny business" I saw in WebRTC's screencast usage makes sense). |
See #850. |
This is my first working version of a working way to restore screencast streams. First, I'd like to remind what goals I had in mind when working on it:
That being said, let's jump right into the implementation.
Implementation
There are 2 important workflows happening in parallel: acquiring a token, and using it.
1. Acquiring a restore token
persist_mode
option to theSelectSources()
method. I'll explain persist modes below.xdg-desktop-portal
pass thepersist_mode
option to the portal implementation.xdg-desktop-portal
the implementation-specific data to be restored. This is passed via therestore_data
option, at the response of theStart()
call.xdg-desktop-portal
stores this data somewhere with an unique identifier that I calledrestore_token
.xdg-desktop-portal
passrestore_token
to the application.The application then should save this restore token wherever it thinks it's appropriate.
2. Using the restore token
Now that the application has a restore token, it can restore a previous stream. This is how it happens:
restore_token
option to theSelectSources()
method.xdg-desktop-portal
receives the token, and performs a lookup for the implementation-specific data associated with this token.xdg-desktop-portal
consumes this token and removes the permission.xdg-desktop-portal
sends this restore data to the portal implementation as therestore_data
option to theSelectSources()
method.Token lifecycle
Tokens can only be used once to restore streams. The permissions they hold are revoked after use. That's what xdg-desktop-portal does at step 2.3. Applications must not assume anything about tokens. Portal implementations never have access to the restore tokens.
Persist modes
In this first implementation, I've added two modes of persistence:
See https://gitlab.gnome.org/GNOME/xdg-desktop-portal-gnome/-/merge_requests/14 for a reference implementation.