mirror of
https://github.com/QubesOS/qubes-doc.git
synced 2025-01-27 14:57:26 -05:00
begin standardizing markdown lineation of qrexec3 docs
This commit is contained in:
parent
cc0d62e2d4
commit
bdffd0fa59
@ -18,92 +18,68 @@ redirect_from:
|
|||||||
|
|
||||||
# Command execution in VMs #
|
# Command execution in VMs #
|
||||||
|
|
||||||
(*This page is about qrexec v3. For qrexec v2, see
|
(*This page is about qrexec v3. For qrexec v2, see [here](/doc/qrexec2/).*)
|
||||||
[here](/doc/qrexec2/).*)
|
|
||||||
|
|
||||||
The **qrexec** framework is used by core Qubes components to implement
|
The **qrexec** framework is used by core Qubes components to implement communication between domains.
|
||||||
communication between domains. Qubes domains are isolated by design, but
|
Qubes domains are isolated by design, but there is a need for a mechanism to allow the administrative domain (dom0) to force command execution in another domain (VM).
|
||||||
there is a need for a mechanism to allow the administrative domain (dom0) to
|
For instance, when user selects an application from the KDE menu, it should be started in the selected VM.
|
||||||
force command execution in another domain (VM). For instance, when user
|
Also, it is often useful to be able to pass stdin/stdout/stderr from an application running in a VM to dom0 (and the other way around).
|
||||||
selects an application from the KDE menu, it should be started in the selected
|
In specific circumstances, Qubes allows VMs to be initiators of such communications (so, for example, a VM can notify dom0 that there are updates available for it).
|
||||||
VM. Also, it is often useful to be able to pass stdin/stdout/stderr from an
|
|
||||||
application running in a VM to dom0 (and the other way around). In specific
|
|
||||||
circumstances, Qubes allows VMs to be initiators of such communications (so,
|
|
||||||
for example, a VM can notify dom0 that there are updates available for it).
|
|
||||||
|
|
||||||
|
|
||||||
## Qrexec basics ##
|
## Qrexec basics ##
|
||||||
|
|
||||||
Qrexec is built on top of vchan (a library providing data links between
|
Qrexec is built on top of vchan (a library providing data links between VMs).
|
||||||
VMs). During domain creation a process named `qrexec-daemon` is started
|
During domain creation a process named `qrexec-daemon` is started in dom0, and a process named `qrexec-agent` is started in the VM.
|
||||||
in dom0, and a process named `qrexec-agent` is started in the VM. They are
|
They are connected over **vchan** channel.
|
||||||
connected over **vchan** channel. `qrexec-daemon` listens for connections
|
`qrexec-daemon` listens for connections from dom0 utility named `qrexec-client`.
|
||||||
from dom0 utility named `qrexec-client`. Typically, the first thing that a
|
Typically, the first thing that a `qrexec-client` instance does is to send a request to `qrexec-daemon` to start a process (let's name it `VMprocess`) with a given command line in a specified VM (`someVM`).
|
||||||
`qrexec-client` instance does is to send a request to `qrexec-daemon` to
|
`qrexec-daemon` assigns unique vchan connection details and sends them both to `qrexec-client` (in dom0) and `qrexec-agent` (in `someVM`).
|
||||||
start a process (let's name it `VMprocess`) with a given command line in
|
`qrexec-client` starts a vchan server which `qrexec-agent` connects to.
|
||||||
a specified VM (`someVM`). `qrexec-daemon` assigns unique vchan connection
|
Since then, stdin/stdout/stderr from the VMprocess is passed via vchan between `qrexec-agent` and the `qrexec-client` process.
|
||||||
details and sends them both to `qrexec-client` (in dom0) and `qrexec-agent`
|
|
||||||
(in `someVM`). `qrexec-client` starts a vchan server which `qrexec-agent`
|
|
||||||
connects to. Since then, stdin/stdout/stderr from the VMprocess is passed
|
|
||||||
via vchan between `qrexec-agent` and the `qrexec-client` process.
|
|
||||||
|
|
||||||
So, for example, executing in dom0:
|
So, for example, executing in dom0:
|
||||||
|
|
||||||
qrexec-client -d someVM user:bash
|
qrexec-client -d someVM user:bash
|
||||||
|
|
||||||
allows to work with the remote shell. The string before the first
|
allows to work with the remote shell.
|
||||||
semicolon specifies what user to run the command as. Adding `-e` on the
|
The string before the first semicolon specifies what user to run the command as.
|
||||||
`qrexec-client` command line results in mere command execution (no data
|
Adding `-e` on the `qrexec-client` command line results in mere command execution (no data passing), and `qrexec-client` exits immediately after sending the execution request and receiving status code from `qrexec-agent` (whether the process creation succeeded).
|
||||||
passing), and `qrexec-client` exits immediately after sending the execution
|
There is also the `-l local_program` flag -- with it, `qrexec-client` passes stdin/stdout of the remote process to the (spawned for this purpose) `local_program`, not to its own stdin/stdout.
|
||||||
request and receiving status code from `qrexec-agent` (whether the process
|
|
||||||
creation succeeded). There is also the `-l local_program` flag -- with it,
|
|
||||||
`qrexec-client` passes stdin/stdout of the remote process to the (spawned
|
|
||||||
for this purpose) `local_program`, not to its own stdin/stdout.
|
|
||||||
|
|
||||||
The `qvm-run` command is heavily based on `qrexec-client`. It also takes care
|
The `qvm-run` command is heavily based on `qrexec-client`.
|
||||||
of additional activities, e.g. starting the domain if it is not up yet and
|
It also takes care of additional activities, e.g. starting the domain if it is not up yet and starting the GUI daemon.
|
||||||
starting the GUI daemon. Thus, it is usually more convenient to use `qvm-run`.
|
Thus, it is usually more convenient to use `qvm-run`.
|
||||||
|
|
||||||
There can be almost arbitrary number of `qrexec-client` processes for a
|
There can be almost arbitrary number of `qrexec-client` processes for a domain (so, connected to the same `qrexec-daemon`, same domain) -- their data is multiplexed independently.
|
||||||
domain (so, connected to the same `qrexec-daemon`, same domain) -- their
|
Number of available vchan channels is the limiting factor here, it depends on the underlying hypervisor.
|
||||||
data is multiplexed independently. Number of available vchan channels is
|
|
||||||
the limiting factor here, it depends on the underlying hypervisor.
|
|
||||||
|
|
||||||
|
|
||||||
## Qubes RPC services ##
|
## Qubes RPC services ##
|
||||||
|
|
||||||
Some tasks (like inter-vm file copy) share the same rpc-like structure:
|
Some tasks (like inter-vm file copy) share the same rpc-like structure: a process in one VM (say, file sender) needs to invoke and send/receive data to some process in other VM (say, file receiver).
|
||||||
a process in one VM (say, file sender) needs to invoke and send/receive
|
Thus, the Qubes RPC framework was created, facilitating such actions.
|
||||||
data to some process in other VM (say, file receiver). Thus, the Qubes RPC
|
|
||||||
framework was created, facilitating such actions.
|
|
||||||
|
|
||||||
Obviously, inter-VM communication must be tightly controlled to prevent one
|
Obviously, inter-VM communication must be tightly controlled to prevent one VM from taking control over other, possibly more privileged, VM.
|
||||||
VM from taking control over other, possibly more privileged, VM. Therefore
|
Therefore the design decision was made to pass all control communication via dom0, that can enforce proper authorization.
|
||||||
the design decision was made to pass all control communication via dom0,
|
Then, it is natural to reuse the already-existing qrexec framework.
|
||||||
that can enforce proper authorization. Then, it is natural to reuse the
|
|
||||||
already-existing qrexec framework.
|
|
||||||
|
|
||||||
Also, note that bare qrexec provides `VM <-> dom0` connectivity, but the
|
Also, note that bare qrexec provides `VM <-> dom0` connectivity, but the command execution is always initiated by dom0.
|
||||||
command execution is always initiated by dom0. There are cases when VM needs
|
There are cases when VM needs to invoke and send data to a command in dom0 (e.g. to pass information on newly installed `.desktop` files).
|
||||||
to invoke and send data to a command in dom0 (e.g. to pass information on
|
Thus, the framework allows dom0 to be the rpc target as well.
|
||||||
newly installed `.desktop` files). Thus, the framework allows dom0 to be
|
|
||||||
the rpc target as well.
|
|
||||||
|
|
||||||
Thanks to the framework, RPC programs are very simple -- both rpc client
|
Thanks to the framework, RPC programs are very simple -- both rpc client and server just use their stdin/stdout to pass data.
|
||||||
and server just use their stdin/stdout to pass data. The framework does all
|
The framework does all the inner work to connect these processes to each other via `qrexec-daemon` and `qrexec-agent`.
|
||||||
the inner work to connect these processes to each other via `qrexec-daemon`
|
Additionally, disposable VMs are tightly integrated -- rpc to a DisposableVM is identical to rpc to a normal domain, all one needs is to pass `$dispvm` as the remote domain name.
|
||||||
and `qrexec-agent`. Additionally, disposable VMs are tightly integrated --
|
|
||||||
rpc to a DisposableVM is identical to rpc to a normal domain, all one needs
|
|
||||||
is to pass `$dispvm` as the remote domain name.
|
|
||||||
|
|
||||||
|
|
||||||
## Qubes RPC administration ##
|
## Qubes RPC administration ##
|
||||||
|
|
||||||
(*TODO: fix for non-linux dom0*)
|
(*TODO: fix for non-linux dom0*)
|
||||||
|
|
||||||
In dom0, there is a bunch of files in `/etc/qubes-rpc/policy` directory,
|
In dom0, there is a bunch of files in `/etc/qubes-rpc/policy` directory, whose names describe the available rpc actions.
|
||||||
whose names describe the available rpc actions. Their content is the rpc
|
Their content is the rpc access policy database.
|
||||||
access policy database. Currently defined actions are:
|
Currently defined actions are:
|
||||||
|
|
||||||
qubes.ClipboardPaste
|
qubes.ClipboardPaste
|
||||||
qubes.Filecopy
|
qubes.Filecopy
|
||||||
@ -128,47 +104,31 @@ These files contain lines with the following format:
|
|||||||
|
|
||||||
srcvm destvm (allow|deny|ask)[,user=user_to_run_as][,target=VM_to_redirect_to]
|
srcvm destvm (allow|deny|ask)[,user=user_to_run_as][,target=VM_to_redirect_to]
|
||||||
|
|
||||||
You can specify srcvm and destvm by name, or by one of `$anyvm`, `$dispvm`,
|
You can specify srcvm and destvm by name, or by one of `$anyvm`, `$dispvm`, `dom0` reserved keywords (note string `dom0` does not match the `$anyvm` pattern; all other names do).
|
||||||
`dom0` reserved keywords (note string `dom0` does not match the `$anyvm`
|
Only `$anyvm` keyword makes sense in srcvm field (service calls from dom0 are currently always allowed, `$dispvm` means "new VM created for this particular request," so it is never a source of request).
|
||||||
pattern; all other names do). Only `$anyvm` keyword makes sense in srcvm
|
Currently there is no way to specify source VM by type.
|
||||||
field (service calls from dom0 are currently always allowed, `$dispvm`
|
Whenever a rpc request for action X is received, the first line in `/etc/qubes-rpc/policy/X` that match srcvm/destvm is consulted to determine whether to allow rpc, what user account the program should run in target VM under, and what VM to redirect the execution to.
|
||||||
means "new VM created for this particular request," so it is never a
|
Note that if the request is redirected (`target=` parameter), policy action remains the same - even if there is another rule which would otherwise deny such request.
|
||||||
source of request). Currently there is no way to specify source VM by
|
If the policy file does not exist, user is prompted to create one; if still there is no policy file after prompting, the action is denied.
|
||||||
type. Whenever a rpc request for action X is received, the first line in
|
|
||||||
`/etc/qubes-rpc/policy/X` that match srcvm/destvm is consulted to determine
|
|
||||||
whether to allow rpc, what user account the program should run in target VM
|
|
||||||
under, and what VM to redirect the execution to. Note that if the request is
|
|
||||||
redirected (`target=` parameter), policy action remains the same - even if
|
|
||||||
there is another rule which would otherwise deny such request. If the policy
|
|
||||||
file does not exist, user is prompted to create one; if still there is no
|
|
||||||
policy file after prompting, the action is denied.
|
|
||||||
|
|
||||||
In the target VM, the `/etc/qubes-rpc/RPC_ACTION_NAME` must exist, containing
|
In the target VM, the `/etc/qubes-rpc/RPC_ACTION_NAME` must exist, containing the file name of the program that will be invoked, or being that program itself - in which case it must have executable permission set (`chmod +x`).
|
||||||
the file name of the program that will be invoked, or being that program itself
|
|
||||||
- in which case it must have executable permission set (`chmod +x`).
|
|
||||||
|
|
||||||
In the src VM, one should invoke the client via:
|
In the src VM, one should invoke the client via:
|
||||||
|
|
||||||
/usr/lib/qubes/qrexec-client-vm target_vm_name RPC_ACTION_NAME rpc_client_path client arguments
|
/usr/lib/qubes/qrexec-client-vm target_vm_name RPC_ACTION_NAME rpc_client_path client arguments
|
||||||
|
|
||||||
Note that only stdin/stdout is passed between rpc server and client --
|
Note that only stdin/stdout is passed between rpc server and client -- notably, no command line arguments are passed.
|
||||||
notably, no command line arguments are passed. Source VM name is specified by
|
Source VM name is specified by `QREXEC_REMOTE_DOMAIN` environment variable.
|
||||||
`QREXEC_REMOTE_DOMAIN` environment variable. By default, stderr of client
|
By default, stderr of client and server is logged to respective `/var/log/qubes/qrexec.XID` files.
|
||||||
and server is logged to respective `/var/log/qubes/qrexec.XID` files.
|
It is also possible to call service without specific client program - in which case server stdin/out will be connected with the terminal:
|
||||||
It is also possible to call service without specific client program - in which
|
|
||||||
case server stdin/out will be connected with the terminal:
|
|
||||||
|
|
||||||
/usr/lib/qubes/qrexec-client-vm target_vm_name RPC_ACTION_NAME
|
/usr/lib/qubes/qrexec-client-vm target_vm_name RPC_ACTION_NAME
|
||||||
|
|
||||||
Be very careful when coding and adding a new rpc service. Unless the
|
Be very careful when coding and adding a new rpc service.
|
||||||
offered functionality equals full control over the target (it is the case
|
Unless the offered functionality equals full control over the target (it is the case with e.g. `qubes.VMShell` action), any vulnerability in an rpc server can be fatal to Qubes security.
|
||||||
with e.g. `qubes.VMShell` action), any vulnerability in an rpc server can
|
On the other hand, this mechanism allows to delegate processing of untrusted input to less privileged (or disposable) AppVMs, thus wise usage of it increases security.
|
||||||
be fatal to Qubes security. On the other hand, this mechanism allows to
|
|
||||||
delegate processing of untrusted input to less privileged (or disposable)
|
|
||||||
AppVMs, thus wise usage of it increases security.
|
|
||||||
|
|
||||||
For example, this command will run the `firefox` command in a DisposableVM based
|
For example, this command will run the `firefox` command in a DisposableVM based on `work`:
|
||||||
on `work`:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
$ qvm-run --dispvm=work firefox
|
$ qvm-run --dispvm=work firefox
|
||||||
@ -180,133 +140,95 @@ By contrast, consider this command:
|
|||||||
$ qvm-run --dispvm=work --service qubes.StartApp+firefox
|
$ qvm-run --dispvm=work --service qubes.StartApp+firefox
|
||||||
```
|
```
|
||||||
|
|
||||||
This will look for a `firefox.desktop` file in a standard location in a
|
This will look for a `firefox.desktop` file in a standard location in a DisposableVM based on `work`, then launch the application described by that file.
|
||||||
DisposableVM based on `work`, then launch the application described by that
|
The practical difference is that the bare `qvm-run` command uses the `qubes.VMShell` service, which allows you to run an arbitrary command with arbitrary arguments, essentially providing full control over the target VM.
|
||||||
file. The practical difference is that the bare `qvm-run` command uses the
|
By contrast, the `qubes.StartApp` service allows you to run only applications that are advertised in `/usr/share/applications` (or other standard locations) *without* control over the arguments, so giving a VM access to `qubes.StartApp` is much safer.
|
||||||
`qubes.VMShell` service, which allows you to run an arbitrary command with
|
While there isn't much practical difference between the two commands above when starting an application from dom0 in Qubes 4.0, there is a significant security risk when launching applications from a domU (e.g., from a separate GUI domain).
|
||||||
arbitrary arguments, essentially providing full control over the target VM. By
|
This is why `qubes.StartApp` uses our standard `qrexec` argument grammar to strictly filter the permissible grammar of the `Exec=` lines in `.desktop` files that are passed from untrusted domUs to dom0, thereby protecting dom0 from command injection by maliciously-crafted `.desktop` files.
|
||||||
contrast, the `qubes.StartApp` service allows you to run only applications that
|
|
||||||
are advertised in `/usr/share/applications` (or other standard locations)
|
|
||||||
*without* control over the arguments, so giving a VM access to `qubes.StartApp`
|
|
||||||
is much safer. While there isn't much practical difference between the two
|
|
||||||
commands above when starting an application from dom0 in Qubes 4.0, there is a
|
|
||||||
significant security risk when launching applications from a domU (e.g., from
|
|
||||||
a separate GUI domain). This is why `qubes.StartApp` uses our standard `qrexec`
|
|
||||||
argument grammar to strictly filter the permissible grammar of the `Exec=` lines
|
|
||||||
in `.desktop` files that are passed from untrusted domUs to dom0, thereby
|
|
||||||
protecting dom0 from command injection by maliciously-crafted `.desktop` files.
|
|
||||||
|
|
||||||
### Extra keywords available in Qubes 4.0 and later
|
### Extra keywords available in Qubes 4.0 and later
|
||||||
|
|
||||||
**This section is about a not-yet-released version, some details may change**
|
**This section is about a not-yet-released version, some details may change**
|
||||||
|
|
||||||
In Qubes 4.0, target VM can be specified also as `$dispvm:DISP_VM`, which is
|
In Qubes 4.0, target VM can be specified also as `$dispvm:DISP_VM`, which is very similar to `$dispvm` but forces using a particular VM (`DISP_VM`) as a base VM to be started as DisposableVM.
|
||||||
very similar to `$dispvm` but forces using a particular VM (`DISP_VM`) as a base
|
For example:
|
||||||
VM to be started as DisposableVM. For example:
|
|
||||||
|
|
||||||
anon-whonix $dispvm:anon-whonix-dvm allow
|
anon-whonix $dispvm:anon-whonix-dvm allow
|
||||||
|
|
||||||
Adding such policy itself will not force usage of this particular `DISP_VM` -
|
Adding such policy itself will not force usage of this particular `DISP_VM` - it will only allow it when specified by the caller.
|
||||||
it will only allow it when specified by the caller. But `$dispvm:DISP_VM` can
|
But `$dispvm:DISP_VM` can also be used as target in request redirection, so _it is possible_ to force particular `DISP_VM` usage, when caller didn't specify it:
|
||||||
also be used as target in request redirection, so _it is possible_ to force
|
|
||||||
particular `DISP_VM` usage, when caller didn't specify it:
|
|
||||||
|
|
||||||
anon-whonix $dispvm allow,target=$dispvm:anon-whonix-dvm
|
anon-whonix $dispvm allow,target=$dispvm:anon-whonix-dvm
|
||||||
|
|
||||||
Note that without redirection, this rule would allow using default Disposable
|
Note that without redirection, this rule would allow using default Disposable VM (`default_dispvm` VM property, which itself defaults to global `default_dispvm` property).
|
||||||
VM (`default_dispvm` VM property, which itself defaults to global
|
Also note that the request will be allowed (`allow` action) even if there is no second rule allowing calls to `$dispvm:anon-whonix-dvm`, or even if there is a rule explicitly denying it.
|
||||||
`default_dispvm` property).
|
This is because the redirection happens _after_ considering the action.
|
||||||
Also note that the request will be allowed (`allow` action) even if there is no
|
|
||||||
second rule allowing calls to `$dispvm:anon-whonix-dvm`, or even if
|
|
||||||
there is a rule explicitly denying it. This is because the redirection happens
|
|
||||||
_after_ considering the action.
|
|
||||||
|
|
||||||
In Qubes 4.0 there are also additional methods to specify source/target VM:
|
In Qubes 4.0 there are also additional methods to specify source/target VM:
|
||||||
|
|
||||||
* `$tag:some-tag` - meaning a VM with tag `some-tag`
|
* `$tag:some-tag` - meaning a VM with tag `some-tag`
|
||||||
* `$type:type` - meaning a VM of `type` (like `AppVM`, `TemplateVM` etc)
|
* `$type:type` - meaning a VM of `type` (like `AppVM`, `TemplateVM` etc)
|
||||||
|
|
||||||
Target VM can be also specified as `$default`, which matches the case when
|
Target VM can be also specified as `$default`, which matches the case when calling VM didn't specified any particular target (either by using `$default` target, or empty target).
|
||||||
calling VM didn't specified any particular target (either by using `$default`
|
|
||||||
target, or empty target).
|
|
||||||
|
|
||||||
In Qubes 4.0 policy confirmation dialog (`ask` action) allow the user to
|
In Qubes 4.0 policy confirmation dialog (`ask` action) allow the user to specify target VM.
|
||||||
specify target VM. User can choose from VMs that, according to policy, would
|
User can choose from VMs that, according to policy, would lead to `ask` or `allow` actions.
|
||||||
lead to `ask` or `allow` actions. It is not possible to select VM that policy
|
It is not possible to select VM that policy would deny.
|
||||||
would deny. By default no VM is selected, even if the caller provided some, but
|
By default no VM is selected, even if the caller provided some, but policy can specify default value using `default_target=` parameter.
|
||||||
policy can specify default value using `default_target=` parameter. For
|
For example:
|
||||||
example:
|
|
||||||
|
|
||||||
work-mail work-archive allow
|
work-mail work-archive allow
|
||||||
work-mail $tag:work ask,default_target=work-files
|
work-mail $tag:work ask,default_target=work-files
|
||||||
work-mail $default ask,default_target=work-files
|
work-mail $default ask,default_target=work-files
|
||||||
|
|
||||||
The first rule allow call from `work-mail` to `work-archive`, without any
|
The first rule allow call from `work-mail` to `work-archive`, without any confirmation.
|
||||||
confirmation.
|
The second rule will ask the user about calls from `work-mail` VM to any VM with tag `work`.
|
||||||
The second rule will ask the user about calls from `work-mail` VM to any VM with
|
And the confirmation dialog will have `work-files` VM chosen by default, regardless of the VM specified by the caller (`work-mail` VM).
|
||||||
tag `work`. And the confirmation dialog will have `work-files` VM chosen by
|
The third rule allow the caller to not specify target VM at all and let the user choose, still - from VMs with tag `work` (and `work-archive`, regardless of tag), and with `work-files` as default.
|
||||||
default, regardless of the VM specified by the caller (`work-mail` VM). The
|
|
||||||
third rule allow the caller to not specify target VM at all and let the user
|
|
||||||
choose, still - from VMs with tag `work` (and `work-archive`, regardless of
|
|
||||||
tag), and with `work-files` as default.
|
|
||||||
|
|
||||||
### Service argument in policy
|
### Service argument in policy
|
||||||
|
|
||||||
Sometimes just service name isn't enough to make reasonable qrexec policy. One
|
Sometimes just service name isn't enough to make reasonable qrexec policy.
|
||||||
example of such a situation is [qrexec-based USB
|
One example of such a situation is [qrexec-based USB passthrough](https://github.com/qubesos/qubes-issues/issues/531) - using just service name isn't possible to express the policy "allow access to device X and deny to others".
|
||||||
passthrough](https://github.com/qubesos/qubes-issues/issues/531) - using just
|
It also isn't feasible to create a separate service for every device...
|
||||||
service name isn't possible to express the policy "allow access to device X and
|
|
||||||
deny to others". It also isn't feasible to create a separate service for every
|
|
||||||
device...
|
|
||||||
|
|
||||||
For this reason, starting with Qubes 3.2, it is possible to specify a service
|
For this reason, starting with Qubes 3.2, it is possible to specify a service argument, which will be subject to policy.
|
||||||
argument, which will be subject to policy. Besides the above example of USB
|
Besides the above example of USB passthrough, a service argument can make many service policies more fine-grained and easier to write precise policy with "allow" and "deny" actions, instead of "ask" (offloading additional decisions to the user).
|
||||||
passthrough, a service argument can make many service policies more fine-grained
|
And generally the less choices the user must make, the lower the chance to make a mistake.
|
||||||
and easier to write precise policy with "allow" and "deny" actions, instead of
|
|
||||||
"ask" (offloading additional decisions to the user). And generally the less
|
|
||||||
choices the user must make, the lower the chance to make a mistake.
|
|
||||||
|
|
||||||
The syntax is simple: when calling a service, add an argument to the service name
|
The syntax is simple: when calling a service, add an argument to the service name separated with `+` sign, for example:
|
||||||
separated with `+` sign, for example:
|
|
||||||
|
|
||||||
/usr/lib/qubes/qrexec-client-vm target_vm_name RPC_ACTION_NAME+ARGUMENT
|
/usr/lib/qubes/qrexec-client-vm target_vm_name RPC_ACTION_NAME+ARGUMENT
|
||||||
|
|
||||||
Then create a policy as usual, including the argument
|
Then create a policy as usual, including the argument (`/etc/qubes-rpc/policy/RPC_ACTION_NAME+ARGUMENT`).
|
||||||
(`/etc/qubes-rpc/policy/RPC_ACTION_NAME+ARGUMENT`). If the policy for the specific
|
If the policy for the specific argument is not set (file does not exist), then the default policy for this service is loaded (`/etc/qubes-rpc/policy/RPC_ACTION_NAME`).
|
||||||
argument is not set (file does not exist), then the default policy for this service
|
|
||||||
is loaded (`/etc/qubes-rpc/policy/RPC_ACTION_NAME`).
|
|
||||||
|
|
||||||
In target VM (when the call is allowed) the service file will searched as:
|
In target VM (when the call is allowed) the service file will searched as:
|
||||||
|
|
||||||
- `/etc/qubes-rpc/RPC_ACTION_NAME+ARGUMENT`
|
- `/etc/qubes-rpc/RPC_ACTION_NAME+ARGUMENT`
|
||||||
- `/etc/qubes-rpc/RPC_ACTION_NAME`
|
- `/etc/qubes-rpc/RPC_ACTION_NAME`
|
||||||
|
|
||||||
In any case, the script will receive `ARGUMENT` as its argument and additionally as
|
In any case, the script will receive `ARGUMENT` as its argument and additionally as `QREXEC_SERVICE_ARGUMENT` environment variable.
|
||||||
`QREXEC_SERVICE_ARGUMENT` environment variable. This means it is also possible
|
This means it is also possible to install a different script for a particular service argument.
|
||||||
to install a different script for a particular service argument.
|
|
||||||
|
|
||||||
See below for an example service using an argument.
|
See below for an example service using an argument.
|
||||||
|
|
||||||
### Revoking "Yes to All" authorization ###
|
### Revoking "Yes to All" authorization ###
|
||||||
|
|
||||||
Qubes RPC policy supports "ask" action. This will prompt the user whether given
|
Qubes RPC policy supports "ask" action.
|
||||||
RPC call should be allowed. That prompt window also has a "Yes to All" option,
|
This will prompt the user whether given RPC call should be allowed.
|
||||||
which will allow the action and add a new entry to the policy file, which will
|
That prompt window also has a "Yes to All" option, which will allow the action and add a new entry to the policy file, which will unconditionally allow further calls for the given service-srcVM-dstVM tuple.
|
||||||
unconditionally allow further calls for the given service-srcVM-dstVM tuple.
|
|
||||||
|
|
||||||
In order to remove such authorization, issue this command from a dom0 terminal
|
In order to remove such authorization, issue this command from a dom0 terminal (for `qubes.Filecopy` service):
|
||||||
(for `qubes.Filecopy` service):
|
|
||||||
|
|
||||||
sudo nano /etc/qubes-rpc/policy/qubes.Filecopy
|
sudo nano /etc/qubes-rpc/policy/qubes.Filecopy
|
||||||
|
|
||||||
and then remove the first line(s) (before the first `##` comment) which are
|
and then remove the first line(s) (before the first `##` comment) which are the "Yes to All" results.
|
||||||
the "Yes to All" results.
|
|
||||||
|
|
||||||
|
|
||||||
### Qubes RPC example ###
|
### Qubes RPC example ###
|
||||||
|
|
||||||
We will show the necessary files to create an rpc call that adds two integers
|
We will show the necessary files to create an rpc call that adds two integers on the target and returns back the result to the invoker.
|
||||||
on the target and returns back the result to the invoker.
|
|
||||||
|
|
||||||
* rpc client code (`/usr/bin/our_test_add_client`):
|
* rpc client code (`/usr/bin/our_test_add_client`):
|
||||||
|
|
||||||
@ -334,17 +256,14 @@ on the target and returns back the result to the invoker.
|
|||||||
|
|
||||||
and we should get "3" as answer, after dom0 allows it.
|
and we should get "3" as answer, after dom0 allows it.
|
||||||
|
|
||||||
**Note:** For a real world example of writing a qrexec service, see this
|
**Note:** For a real world example of writing a qrexec service, see this [blog post](https://blog.invisiblethings.org/2013/02/21/converting-untrusted-pdfs-into-trusted.html).
|
||||||
[blog post](https://blog.invisiblethings.org/2013/02/21/converting-untrusted-pdfs-into-trusted.html).
|
|
||||||
|
|
||||||
### Qubes RPC example - with argument usage ###
|
### Qubes RPC example - with argument usage ###
|
||||||
|
|
||||||
We will show the necessary files to create an rpc call that reads a specific file
|
We will show the necessary files to create an rpc call that reads a specific file from a predefined directory on the target.
|
||||||
from a predefined directory on the target. Besides really naive storage, it may
|
Besides really naive storage, it may be a very simple password manager.
|
||||||
be a very simple password manager.
|
Additionally, in this example a simplified workflow will be used - server code placed directly in the service definition file (in `/etc/qubes-rpc` directory).
|
||||||
Additionally, in this example a simplified workflow will be used - server code
|
And no separate client script will be used.
|
||||||
placed directly in the service definition file (in `/etc/qubes-rpc` directory). And
|
|
||||||
no separate client script will be used.
|
|
||||||
|
|
||||||
* rpc server code (*/etc/qubes-rpc/test.File*)
|
* rpc server code (*/etc/qubes-rpc/test.File*)
|
||||||
|
|
||||||
@ -385,13 +304,11 @@ no separate client script will be used.
|
|||||||
|
|
||||||
# Qubes RPC internals #
|
# Qubes RPC internals #
|
||||||
|
|
||||||
(*This is about the implementation of qrexec v3. For the implementation of
|
(*This is about the implementation of qrexec v3.
|
||||||
qrexec v2, see [here](/doc/qrexec2/#qubes-rpc-internals).*)
|
For the implementation of qrexec v2, see [here](/doc/qrexec2/#qubes-rpc-internals).*)
|
||||||
|
|
||||||
Qrexec framework consists of a number of processes communicating with each
|
Qrexec framework consists of a number of processes communicating with each other using common IPC protocol (described in detail below).
|
||||||
other using common IPC protocol (described in detail below). Components
|
Components residing in the same domain (`qrexec-client-vm` to `qrexec-agent`, `qrexec-client` to `qrexec-daemon`) use pipes as the underlying transport medium, while components in separate domains (`qrexec-daemon` to `qrexec-agent`, data channel between `qrexec-agent`s) use vchan link.
|
||||||
residing in the same domain (`qrexec-client-vm` to `qrexec-agent`, `qrexec-client` to `qrexec-daemon`) use pipes as the underlying transport medium,
|
|
||||||
while components in separate domains (`qrexec-daemon` to `qrexec-agent`, data channel between `qrexec-agent`s) use vchan link.
|
|
||||||
Because of [vchan limitation](https://github.com/qubesos/qubes-issues/issues/951), it is not possible to establish qrexec connection back to the source domain.
|
Because of [vchan limitation](https://github.com/qubesos/qubes-issues/issues/951), it is not possible to establish qrexec connection back to the source domain.
|
||||||
|
|
||||||
|
|
||||||
@ -457,16 +374,15 @@ by an optional data packet.
|
|||||||
uint32_t len; /* data length */
|
uint32_t len; /* data length */
|
||||||
};
|
};
|
||||||
|
|
||||||
When two peers establish connection, the server sends `MSG_HELLO` followed by
|
When two peers establish connection, the server sends `MSG_HELLO` followed by `peer_info` struct:
|
||||||
`peer_info` struct:
|
|
||||||
|
|
||||||
struct peer_info {
|
struct peer_info {
|
||||||
uint32_t version; /* qrexec protocol version */
|
uint32_t version; /* qrexec protocol version */
|
||||||
};
|
};
|
||||||
|
|
||||||
The client then should reply with its own `MSG_HELLO` and `peer_info`. The
|
The client then should reply with its own `MSG_HELLO` and `peer_info`.
|
||||||
lower of two versions define protocol used for this connection. If either side
|
The lower of two versions define protocol used for this connection.
|
||||||
does not support this version, the connection is closed.
|
If either side does not support this version, the connection is closed.
|
||||||
|
|
||||||
Details of all possible use cases and the messages involved are described below.
|
Details of all possible use cases and the messages involved are described below.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user