qubes.policy – Qubes RPC policy

Every Qubes domain can trigger various RPC services, but if such call would be allowed depends on Qubes RPC policy (qrexec policy in short).

Qrexec policy format

Policy consists of a file, which is parsed line-by-line. First matching line is used as an action.

Each line consist of three values separated by white characters (space(s), tab(s)):

  1. Source specification, which is one of:
  • domain name
  • $anyvm - any domain
  • $tag:some-tag - VM having tag some-tag
  • $type:vm-type - VM of vm-type type, available types: AppVM, TemplateVM, StandaloneVM, DispVM
  1. Target specification, one of:
  • domain name
  • $anyvm - any domain, excluding dom0
  • $tag:some-tag - domain having tag some-tag
  • $type:vm-type - domain of vm-type type, available types: AppVM, TemplateVM, StandaloneVM, DispVM
  • $default - used when caller did not specified any VM
  • $dispvm:vm-name - _new_ Disposable VM created from AppVM vm-name
  • $dispvm:$tag:some-tag - _new_ Disposable VM created from AppVM tagged with some-tag
  • $dispvm - _new_ Disposable VM created from AppVM pointed by caller property default_dispvm, which defaults to global property default_dispvm
  • $adminvm - Admin VM aka dom0

Dom0 can only be matched explicitly - either as dom0 or $adminvm keyword. None of $anyvm, $tag:some-tag, $type:AdminVM will match.

  1. Action and optional action parameters, one of:
  • allow - allow the call, without further questions; optional parameters:
    • target= - override caller provided call target - possible values are: domain name, $dispvm or $dispvm:vm-name
    • user= - call the service using this user, instead of the user pointed by target VM’s default_user property
  • deny - deny the call, without further questions; no optional parameters are supported
  • ask - ask the user for confirmation; optional parameters:
    • target= - override user provided call target
    • user= - call the service using this user, instead of the user pointed by target VM’s default_user property
    • default_target= - suggest this target when prompting the user for confirmation

Alternatively, a line may consist of a single keyword $include: followed by a path. This will load a given file as its content would be in place of $include line. Relative paths are resolved relative to /etc/qubes-rpc/policy directory.

Evaluating ask action

When qrexec policy specify ask action, the user is asked whether the call should be allowed or denied. In addition to that, user also need to choose target domain. User have to choose from a set of targets specified by the policy. Such set is calculated using the algorithm below:

1. If ask action have target= option specified, only that target is considered. A prompt window will allow to choose only this value and it will also be pre-filled value.

2. If no target= option is specified, all rules are evaluated to see what target domains (for a given source domain) would result in ask or allow action. If any of them have target= option set, that value is used instead of the one specified in “target” column (for this particular line). Then the user is presented with a confirmation dialog and an option to choose from those domains.

3. If default_target= option is set, it is used as suggested value, otherwise no suggestion is made (regardless of calling domain specified any target or not).

Module contents

Qrexec policy parser and evaluator

exception qubespolicy.AccessDenied[source]

Bases: Exception

Raised when qrexec policy denied access

exception qubespolicy.PolicyNotFound(service_name)[source]

Bases: qubespolicy.AccessDenied

Policy was not found for this service

exception qubespolicy.PolicySyntaxError(filename, lineno, msg)[source]

Bases: qubespolicy.AccessDenied

Syntax error in qrexec policy, abort parsing

exception qubespolicy.QubesMgmtException(exc_type)[source]

Bases: Exception

Exception returned by qubesd

class qubespolicy.Action[source]

Bases: enum.Enum

Action as defined by policy

class qubespolicy.Policy(service, policy_dir='/etc/qubes-rpc/policy')[source]

Bases: object

Full policy for a given service

Usage: >>> system_info = get_system_info() >>> policy = Policy(‘some-service’) >>> action = policy.evaluate(system_info, ‘source-name’, ‘target-name’) >>> if action.action == Action.ask: >>> # … ask the user, see action.targets_for_ask … >>> action.handle_user_response(response, target_chosen_by_user) >>> action.execute(‘process-ident’)

collect_targets_for_ask(system_info, source)[source]

Collect targets the user can choose from in ‘ask’ action

Word ‘targets’ is used intentionally instead of ‘domains’, because it can also contains @dispvm like keywords.

evaluate(system_info, source, target)[source]

Evaluate policy

Raises:AccessDenied – when action should be denied unconditionally

:return tuple(rule, considered_targets) - where considered targets is a list of possible targets for ‘ask’ action (rule.action == Action.ask)

find_matching_rule(system_info, source, target)[source]

Find the first rule matching given arguments

load_policy_file(path)[source]

Load policy file and append rules to policy_rules

Parameters:path – file to load
policy_dir = None

policy storage directory

policy_rules = None

list of PolicyLine objects

service = None

service name

class qubespolicy.PolicyAction(service, source, target, rule, original_target, targets_for_ask=None)[source]

Bases: object

Object representing positive policy evaluation result - either ask or allow action

static cleanup_dispvm(dispvm)[source]

Kill and remove Disposable VM

Parameters:dispvm – name of Disposable VM
Returns:None
ensure_target_running()[source]

Start domain if not running already

Returns:None
execute(caller_ident)[source]

Execute allowed service call

Parameters:caller_ident – Service caller ident (process_ident,source_name, source_id)
handle_user_response(response, target=None)[source]

Handle user response for the ‘ask’ action

Parameters:
  • response – whether the call was allowed or denied (bool)
  • target – target chosen by the user (if reponse==True)
Returns:

None

spawn_dispvm()[source]

Create and start Disposable VM based on AppVM specified in target :return: name of new Disposable VM

original_target = None

original target specified by the caller

rule = None

policy rule from which this action is derived

service = None

service name

source = None

calling domain

targets_for_ask = None

targets for the user to choose from

class qubespolicy.PolicyRule(line, filename=None, lineno=None)[source]

Bases: object

A single line of policy file

expand_override_target(system_info, source)[source]

Replace @dispvm’ with specific @dispvm:…’ value, based on qrexec call source.

Parameters:
  • system_info – System information
  • source – Source domain name
Returns:

override_target with @dispvm’ substituted

expand_target(system_info)[source]

Return domains matching target of this policy line

Parameters:system_info – information about the system
Returns:matching domains
is_match(system_info, source, target)[source]

Check if given (source, target) matches this policy line.

Parameters:
  • system_info – information about the system - available VMs, their types, labels, tags etc. as returned by app_to_system_info()
  • source – name of the source VM
  • target – name of the target VM, or None if not specified
Returns:

True or False

static is_match_single(system_info, policy_value, value)[source]

Evaluate if a single value (VM name or @default’) matches policy specification

Parameters:
  • system_info – information about the system
  • policy_value – value from qrexec policy (either self.source or self.target)
  • value – value to be compared (source or target)
Returns:

True or False

default_target = None

default target when asking the user for confirmation

override_target = None

alternative target, used instead of the one specified by the caller

override_user = None

alternative user, used instead of vm.default_user

qubespolicy.get_system_info()[source]

Get system information

This retrieve information necessary to process qrexec policy. Returned data is nested dict structure with this structure:

  • domains:
    • <domain name>:
      • tags: list of tags
      • type: domain type
      • template_for_dispvms: should DispVM based on this VM be allowed
      • default_dispvm: name of default AppVM for DispVMs started from here
qubespolicy.is_special_value(value)[source]

Check if given source/target specification is special (keyword) value

qubespolicy.verify_special_value(value, for_target=True, specific_target=False)[source]

Verify if given special VM-specifier (‘@…’) is valid

Parameters:
  • value – value to verify
  • for_target – should classify target-only values as valid ( @default’, @dispvm’)
  • specific_target – allow only values naming specific target (for use with target=, default= etc)
Returns:

True or False

qubespolicy.verify_target_value(system_info, value)[source]

Check if given value names valid target

This function check if given value is not only syntactically correct, but also if names valid service call target (existing domain, or valid @dispvm like keyword)

Parameters:
  • system_info – information about the system
  • value – value to be checked