MeeGo 1.2 Harmattan Developer Documentation Develop for the Nokia N9

Aegis manifest syntax

MeeGo 1.2 Harmattan applications must list the protected services they need or provide in the Aegis manifest XML file. Applications that do not access or provide any protected services do not need the Aegis manifest file. For more information on Harmattan security, see the Security guide.

The manifest is an XML document that has the aegis element as the top level. All elements under the top level are optional and, except for the provide element, they can be in any order and occur multiple times.

<aegis name="...">
  <provide> ... </provide>
  <constraint> ... </constraint>
  <account> ... </account>
  <request> ... </request>
  <domain> ... </domain>
  <docstring> ... </docstring>
</aegis>

The parser only recognizes the above, and ignores everything else silently. To be on the safe side, the Aegis manifest files should be verified against the schema or DTD before being included into a Debian package. See the Aegis manifest syntax attachment page.

The docstring contains optional documentation in XHTML. It can appear anywhere within the manifest file, either on top level or within any element at any level.

The name attribute is only used in specifying Special policy configurations, as described later.

Defining resources and protected services

The following example is an Aegis manifest file for a package which contains a data manager application for accessing user's location:

<aegis>
   <request>
      <credential name="Location" />
      <for path="/usr/bin/userdatamanager" />
   </request>
</aegis>

The above example states that whenever /usr/bin/userdatamanager is executed, the task context includes the credential Location.

The value of the name attribute <credential> element defines the requested credential. The general syntax of credential value is:

[namespace "::"] name

If the namespace is omitted, the name refers either to the package's local token or global token. The currently usable namespaces are:

  • CAP::capability, request Linux capability (the capability is the lower case string of the capability defined in usr/include/linux/capability.h with the CAP_ prefix removed, for example, CAP_CHOWN is represented as CAP::chown
  • UID::user, request to set UID to user, as defined in /etc/passwd
  • GID::group, request to set GID to group, as defined in /etc/group
  • GRP::group, request to have the group included in supplementary groups
  • pkgname::token, request for a token defined in package pkgname

The following namespaces are also possible, but they are not purposeful in a request:

  • SRC::origin, defines a symbol for software origin
  • AID::id, namespace for generated application IDs

If a package implements a private service with controlled access, you can define a private credential token for the service. This token can be requested by other applications. For example:

<aegis>
   <provide>
     <credential name="userdata" />
   </provide>
</aegis>

An Aegis manifest file with a provide section can also be used to document the credentials:

<aegis>
  <provide>
  ...
     <credential name="phone-control">
        <docstring>
         A resource which gives access to the lower level phone functionality. For example,
         see the DBus services
         <ul>
           <li>com.nokia.phone.SMS (Phone.SMS)</li>
           <li>com.nokia.phone.SIM (Phone.Sim, Phone.Sim.Security, Phone.Sim.Phonebook)</li>
           <li>com.nokia.phone.net (Phone.Net)</li> 
         </ul>
         </docstring>
     </credential>
     ...
  </provide>
</aegis>

The predefined credentials token can then be referenced in other provide definitions. See the following example for a libsms. Because libsms implements a D-Bus service, the example uses the dbus element:

<aegis>
  <provide>
     <dbus name="com.nokia.phone.SMS" own="csd::csd">
       <node name="/">
         <interface name="Phone.SMS">
               <annotation name="com.maemo.Aegis" value="phone-control"/>
         </interface>
       </node>
    </dbus>
  </provide>
</aegis>

The content of the dbus element is an extract from the introspect notation, where the access control is indicated by special annotations using the identifier com.maemo.Aegis. In above example the same access control is required for all methods and signals, therefore the annotation is on the interface level and the rest of the introspect definition does not need to be included. For more information, see D-Bus Specification.

<provide> element

<provide>
  <credential> ... </credential>
  <for> ... </for>
  <dbus> ... </dbus>
</provide>

The <provide> element defines the new package-specific credential tokens. The element, when present, contains one or more <credential> elements.

The dbus element, which generates a DBus policy configuration, is described in the section Controlling automatic DBus policy configuration.

<credential> within <provide>

Each credential defines a new package specific token. The name given in the credential element is implicitly prefixed with the name of the package. It cannot have a namespace definition and it is not possible to provide a token that belongs to another package. The valid attributes in provide context are:

  • name: The name of the provided credential.
  • checkorigin: Include credential into origin check process if the value is yes. If omitted, the value defaults to no and the credential is not included into origin checked credentials.

Example:

  <credential name="foo" />
  <credential name="bar" checkorigin="yes" />

<for> within <provide>

The for element within provide defines which origins can grant the provided tokens. The element must specify the attribute origin and the value must be one of the following:

  • "trusted": The provided credentials can be granted from current and higher ranked origins. This is the default, when the for element is omitted.
  • "current": The provided credentials can be granted only from the origin of the package
  • "all": The provided credentials can be granted by any origin
  • "none": The provided credentials are only usable within this package (do not enable checkorigin)

Example:

 <for origin="current" />

Note: Using any other mode except the default trusted when combined with checkorigin="yes" requires good understanding of the implications of the origin checking. An executable code, such as main program, library or a script started as a command, executes only if it comes from an origin that can grant all origin checked credentials in the current context.

<request> element

<request policy="..." context="...">
  <credential> ... </credential>
  <for> ... </for>
</request>

The <request> element defines the credentials that are requested for a component of the package. The element includes zero or more <credential> elements, and one or more <for> elements. The ordering of the elements is not significant: all listed credentials apply to all components listed. By default, a component is an executable installed from the package and it is identified by the absolute install path of the executable.

If different sets of credentials are needed, the Aegis manifest file can include multiple <request> elements (with the restriction that the same target file can only occur in one <request> section).

The policy attribute

The mode in which the requested credentials are used can be controlled with the optional policy attribute. The value of the policy attribute is in the form of a space-separated keyword list.

  • not-inheritable modifier: When set, the requested credentials apply only to the specified executable(s). If that executable calls another executable (performs execve) without defined policy, all capabilities and tokens are removed and only supplementary groups, UID and GID remain. The default mode is represented by the keyword inheritable.
  • setxid modifier: When set, and if the request contains UID::user or GID::group, then the real GID or UID remains unchanged. This modifier emulates the file setuid/setgid bits. In default mode (realxid) policy sets both real and effective GID or UID.
  • trust-zone modifier: When set, the new credentials resulting from processing the policy are included into the set of credentials which are checked against the origins of any subsequent executables started by this task. For example, if the set includes the token tcb, then all possible helper utilities used by the application must also come from origin that can grant it.
  • inherit policy type: In this mode, the final credentials are the intersection of the requested and the current credentials set.
  • add policy type: In this mode, the final credentials are the union of the requested and current credentials.
  • set policy type (the default if policy attribute or type keyword is omitted): In this mode, the final credentials are the requested set.

Each keyword can only appear only once in the list, and only one of the type keywords (inherit, add or set) is allowed.

Example:

  <request policy="trust-zone not-inheritable add">
     <credential name="foo::bar" />
  </request>

The context attribute

This attribute gives additional instructions for request processing. Currently, only supported value of this attribute is INSTALL.

By default the Debian maintainer scripts are run as the root user without any capabilities. If the maintainer scripts need something more, the context="INSTALL" in one request element can be used to specify that it also applies to the maintainer scripts (in addition to whatever is specified with <for> elements).

For example, a request for capability to kill processes running under another UID than your maintainer script, can be expressed with the following:

<request context="INSTALL">
   <credential name="CAP::kill" />
</request>

<for> within <request>

<for path="..." id="..." />

The <for> element within <request> defines a receiver of the credentials in the request list for the component identified by the path attribute.

A plain absolute path starting with / refers to an executable installed from the current package.

<request>
   <credential name=" ... " />
  <for path="/usr/bin/foo" />
</request>

The Aegis manifest file can also request credentials for an executable in another package. For example, this is the case with an application invoker/launcher, when the application launcher daemon needs to have all the credentials for launching an application. In such cases, the path must be prefixed with the target package name. This package must be already installed and the referenced executable must come from that package. Also, you must set the dependency to the application launcher in your binary package so that application launcher is always available before your package is being installed.

<request>
   <credential name=" ... " />
   <for path="foopackage::/usr/bin/foo" />
</request>

This method of adding credentials to an executable of an another package is only allowed if that other package has a manifest, and the target executable is mentioned there. At minimum, the receiving package must declare an empty request, for example in package foopackage

<request>
  <for path="/usr/bin/foo" />
</request>

In addition to the path attribute, the <for> element can include a request for an application identifier by adding an id attribute. The value of this attribute is combined with the source domain and package name, and the resulting string is the actual application identifier, example

 <for path="/usr/bin/foo" id="foo" />
 <for path="barpackage::/usr/bin/bar" id="foo" />


would add a generated credential

AID::com.nokia.maemo/ovi.foopkg.foo

to the target executables, assuming the package name was foopkg and that it came from origin com.nokia.maemo/ovi.

<credential> within <request>

<credential name="..." match="..." />

Specifies the requested credential(s) with either with name or match attribute:

  • name: The value is the exact credential name.
  • match: The value is a simple wildcard expression that matches against available credential names. The only supported match rules are: * matches zero or more characters, ? matches exactly one character. The expression must match the complete credential name - there is no implied * in the beginning or in the end. All matched credentials allowed by the package origin are included into the request.

If a credential is defined by name, it must be known at the package installation time. If a credential is not defined, installer gives a warning message and ignores it.

There will be no warnings if match results an empty set.

<account> element

The <account> is an optional element. It creates users and groups while installing the package.

<user> within <account>

<user name="..." group="..." />
  • name: The attribute is the user name.
  • group: The attribute is the group name.

For example:

<aegis>
  <account>
    <user name="donald" group="duck"/>
    <user name="mickey" group="mouse"/>
  </account>
</aegis>

If you specify a non-existing group, the group is created. You are allowed to specify an existing user and/or an existing group.

Note: The users or groups created while installing the package are not removed when the package is removed.

<domain> element

<domain name="..." rank="..." untrusted="...">
  <allow> ... </allow>
  <origin> ... </origin>
</domain>
   

Each domain represents a possible program source and defines the access rights that can be potentially granted for programs originating from this domain.

The device maintains a list of identifiable program sources (origins/domains). The default initial file is part of the installed factory image.

The program sources can be updated by Debian packages, which include an Aegis manifest file with a domain section. This element is placed directly under the aegis element.

The information for the domain can come from multiple packages. For example, the configuration for each distinct physical repository bound to the same domain can come from different packages. The domain defining packages are ordinary Debian packages, which can also be uninstalled.

Example:

 <aegis>
  <domain name="Nokia" rank="20">
    <allow>
     ... credentials to be allowed from this domain ...
      <credential name="telephony"/>
      <credential name="netservice"/>
      <credential match="CAP::cap_net*"/>
      <deny>
         <credential name="CAP::cap_net_admin" />
      </deny>
    </allow>
    <origin>
      <keyinfo>
         ...base64 coded binary value...
      </keyinfo>
      <access data="deb http://repository.example.com test main" />
   </origin>
  </domain>
 </aegis>

The normal credential checking rules apply for the policy request. All allowed credentials in the list must be available for the source domain.

Any domain can create a new domain. The domain name is treated like a path name. The device can have a preconfigured list of domains, for example Aegis, Nokia, Maemo, etc. Any of those can create new domains, but the real name of the new domain will be a concatenation of the creating domain and new name, for example, if Maemo creates a new domain special, the real name of the domain will be Maemo/special. Therefore if the above example policy packet came from Nokia, it would create a new domain called Nokia/Nokia, if it came from Maemo, the new domain would be Maemo/Nokia.

The name attribute

The name attribute identifies the domain. The name ties in locally to the necessary information, which is used to authenticate the source. If omitted, the current origin domain is assumed.

The rank attribute

The rank defines the ordering of the child domains. This attribute is effective only if the name attribute specifies a child domain. The rank value must be in range -10000..+10000. If omitted, the rank value defaults to 0.

A package installed from a higher ranking domain will not be automatically installed from the lower ranking domain, even if it advertises higher version number.

The tree structure of the domains defines the ordering. Each domain parent in the tree structure can define the ordering of child domains, and the position of self within them as follows:

  • The rank in parent-children context is defined by signed integer.
  • The ordering is defined by ascending order of the assigned rank values.
  • The parent in this context has fixed rank of zero.
  • If a child has a negative rank, it precedes the parent in ordering.
  • If a child has a positive rank, it follows the parent in ordering.
  • Ordering of domains with the same rank value is undeterministic.

The untrusted attribute

The untrusted signals to the package manager that the child domain is untrusted. This attribute is effective only if the name attribute specifies a child domain. Once a domain is marked as untrusted, all its children are also be untrusted.

The value of this attribute is not checked, as the presence of the attribute itself is sufficient. However, because XML syntax always requires a value, then untrusted="true" should be used.

Note: The Aegis framework does not use this value for anything internally.

<allow>

<allow>
  <credential> ... </credential>
  <deny> ... </deny>
</allow>

The list of credential elements specify the allowed credential(s) for the domain using the name or match attributes. The deny section subtracts from this set.

<deny>

<deny>
  <credential> ... </credential>
</deny>

Each credential identifies the credential(s), which are removed from the initial set of credentials created by the containing allow.

<origin>

The origin element collects the repository information: the public key(s) and how to access the content of the repository. A domain can be bound to multiple physical repositories of different or same type. The origin has single attribute type, which is the type of repository. The following values are currently recognized:

  • DEBIAN: (The default if type is omitted) A Debian repository with PGP keys.
  • X509: Origin identified by X.509 signature in the Debian package.
  • LOCAL: Origin identified by local signature in the Debian pacakge.

The type determines the handling of the key info and access elements. For DEBIAN, the keys are added to the apt key ring and all access lines will be written into file /etc/apt/sources.list.d/aegis.pkg-name.list.

<keyinfo>

This section defines or updates the key information associated with the indicated origin. The content of this element is base64 encoded binary blob. The interpretation of the key information depends on the type of the origin being defined.

For DEBIAN the key information is a raw PGP packet as defined in chapter 5 of RFC-2440.

For example, the pgp key information is the output of

 gpg --export <key-selection> | base64

<access>

The <access> element defines how the repository content can be accessed. The element has one attribute: data for accessing information.

The content of the data attribute depends on the type of the origin being defined.

For example, defining a access to Debian repository would use

 <access data="deb URL1 foo" />
 <access date="deb URL2 bar" />

and assuming the package name is myrepo, the install would create the file

 /etc/apt/sources.d/aegis.myrepo.list

with content (the values of data attributes are copied verbatim)

 deb URL1 foo
 deb URL2 bar

<constraint> element

The constraint element can be used to limit the package installation to a specific device, or devices which fill the specific constrain requirement. The attributes of the element are:

  • name The name of the constraint to be tested
  • value The required value

Currently, the only supported names are imei and mode.

The following allows installation of the package only to a device that has the IMEI 123456789:

 <aegis>
    ...
    <constraint name="imei" value="123456789" />
    ...
  </aegis>

Special policy configurations

All policy settings on the device can be modified and updated by Debian packages and a suitably written Aegis manifest file. However, some of the settings require special handling by the installer.

The aegis element can have a name attribute, which selects and triggers the special handling. Valid attribute value must start and end with an underscore (_). Only one package at a time can own an action. Installing a new package with an action will completely replace any previously installed package using the same action.

The source ranking applies also to the special keywords: a package cannot activate the special feature, if the system already has another package from higher precedence source activating this same action.

A package, which declares to be a policy configuration through the use of a name attribute in the aegis element, cannot be removed. Such packages can only be updated. To remove the package, you must first update the package so that it does not have binding to policy configuration.

The installer recognizes the following special actions:

  • _system_
  • _default_

_system_

A package that declares _system_ indicates that it provides global tokens. The provide section of the package declares the tokens. For example:

 <aegis name="_system_">
   <provide>
     <credential name="tcb" checkorigin="yes" />
     <credential name="Cellular" checkorigin="yes" />
     <credential name="Synchronization" checkorigin="yes" />
     <credential name="TrackerReadAccess" checkorigin="yes" />
     <credential name="TrackerWriteAccess" checkorigin="yes" />
     <credential name="Location" checkorigin="yes" />
     <credential name="WrtDmServiceAccess" checkorigin="yes" />
     <credential name="LocalSourceOrigin" checkorigin="yes" />
   </provide>
 </aegis>

_default_

A package that declares _default_ defines the credentials which are available for applications from unknown sources. The credentials are defined in the standard way in the request section, and the source of this package must have rights to them. For example:

 <aegis name="_default_">
   <request>
     <credential match="*" />
     <deny>
       <credential match="CAP::*" />
       <credential name="tcb" />
     </deny>
   </request>
 </aegis>

Controlling automatic DBus policy configuration

<dbus> within <provide>

The dbus element can be used when the service is implemented as a D-Bus service. When used, the dbus element informs the installer that access control for this service is delegated to the D-Bus daemon, and that the policy is generated automatically at installation.

DBus instrospect format defines the XML syntax usable within the dbus element.

For example, the following Aegis manifest file is used in aegis-dbus-example:

<aegis>
  <provide>
    <credential name="access" />
    <dbus name="com.maemo.Aegis.example" own="aegis-dbus-server" bus="session">
      <node name="/">
        <interface name="Aegis.Example">
           <annotation name="com.maemo.Aegis" value="access"/>
         </interface>
      </node>
    </dbus>
  </provide>
  <request>
    <for path="/usr/bin/aegis-dbus-server" />
  </request>
</aegis>

The dbus element is allowed inside the provide, and uses the introspect definitions with supplemented access annotations.

  • name: The attribute gives the well-known bus name for the service.
  • own: The attribute, when listed, defines the required credential for owning this bus name. If omitted, installer does not generate any configuration to control the owning of the service name.
  • bus: The attribute defines the bus for which the policy is intended. The value can be either "session" or "system"

The generated policy goes into file

 /etc/dbus-1/system.d/aegis.pkgname.conf

or

 /etc/dbus-1/session.d/aegis.pkgname.conf

depending on the value of the bus attribute.

<annotation> element

The <annotation> element is defined by the D-Bus introspect format. This document defines only the new annotation name value: com.maemo.Aegis. When present, the annotation value specifies the required credential for the action. The access annotation can be placed at any level (dbus, node, interface, method or signal) to get the desired granularity of the access control.

  • name="com.maemo.Aegis"
  • value: Defines the credentials requirement.

If the value attribute is an empty string, it requests a default allow policy at the indicated level.

Integration with Debian packaging

Integration with Debian packaging is basically done by adding the Aegis manifest file into the .deb file as _aegis.

The following file naming convention is the proposed way of storing Aegis manifest file for a package in a debian source tree.

debian/<package>.aegis

The normal build process for the package should pick this up and add it into the .deb file itself (ar archive) as a member _aegis.

Further information