ARPA2 Common Libraries  2.2.14
Access Control for Communication

We explain how to restrict access under the InternetWide Architecture. Given the ARPA2 Common libraries, it is easy enough to integrate with the ambituous goals or freeing our online presence as users!

This document is about libarpa2access.so, the Access Control library, and more specifically about its angle on Communication ACLs. Access Control for Communication is an application of the general framework for Policy Rules, to which it adds semantics that are implemented in higher-level functions.

Below you will find:

Quick description of Concepts

Access Domain is the domain name offering services and user accounts. It is the Access Domain who generally erects a barrier of Access Control at its perimeter.

Remote Identity is an authenticated identity for a client trying to access a service or user under the Access Domain. This client may be part of another domain than the Access Domain, but even when that is not the case this is still how we speak of the access-seeking party as the Remote Identity, to emphasise the general idea that it is impartial to Access Control what assurance of the client identity we got.

Access Type is a general concept for an application that requires Access Control. The application is usually not specific to software or even a protocol, but tries to describe a usage pattern. Access Types define a number of aspects of Access Control that the application can use. An example of an Access Type is Communication; this may cover all of email, chat and telephony, in spite of software or the protocol du jour.

Access Name describes an instance of an Access Type under a specific Access Domain. The format is always a UTF-8 string, but the precise format is specified by the Access Type. Since this is scoped underneath the Access Domain there cannot be a clash when two Access Domains use the same Access Name, such as when a local username is used as Access Name; this is both a convenience and a security measure.

Remote Selector is the most concrete iteration output from the Remote Identity that defines one or more Rules for a requested Access Domain, Access Type and Access Name.

Rules define policy choices that are to be applied; see the Rules documentation for details.

Rights are a set of FLAGS in Rules, each describing a permission to use the service for which it is defined. They are sent to the service application by way of a callback. Communication Access defines rights for white, grey and black lists, as well as to stave off an attacker towards a honeypot.

Attributes are named by a single lowercase letter, like x in =xval, and may be assigned values in Rules. The policies for Communication Access define a few of these. See below for their definitions.

Triggers are short strings that provoke a callback to the service application. No semantics are defined for this in the Communication framework.

API for ARPA2 Access Control

This API builds on the one for Identity which you are assumed to understand.

A service application knows which Access Domain, Access Type and Access Name to use for each request by a Remote Identity. Some applications may have the Access Type hard-coded, others may make it a configuration parameter.

Though the Access Type defines many things, the form is general enough to support generic handling:

Think of the Communcation ACL process as a call

(accessLevel,localID',[group]) := access_comm (localID,remoteID,aclData...)

where the localID may be modified in-place to redirect the traffic to an alias, a group or whatever else makes sense. See the attribute definitions below for controls that support this kind of redirection.

In practice, there are two variants for two different service scales:

The two service kinds differ in where the Rules come from; a basic configuration means that a set of Rules is provided in all API calls for Access Control. Scalable configuration does not supply that information, because it is already present in the database.

Manual Deployments

When Rules are stored in the service application to request access, then the choice of the ruleset is up to the application. For this reason, the only required inputs are those that help to evaluate that ruleset. Having zoomed in on a ruleset already, the only need is the Remote Identity.

#include <stdint.h>
#include <stdbool.h>
#include <arpa2/identity.h>
#include <arpa2/access_comm.h>
bool access_comm (const a2id_t *remote, a2id_t *local,
const uint8_t *opt_svckey, unsigned svckeylen,
const char *opt_acl, unsigned acllen,
access_comm_level *out_level,
a2act_t *optout_actor);

The Remote Identity and Local Identity are fundamental to all Communication attempts. Under manual deployment, the opt_acl is supplied, along with the total lenght in acllen. The ACL is a Ruleset of concatenated Rules, where each ends in a NUL character. The Service Key in opt_svckey and svckeylen add no value in the manual deployment scenario. The input local domain is used as the Access Domain and its user or service name (without +aliases or +svcargs) is used as the Access Name; finally, Communication Access defines its own Access Type.

When an error is detected, the function returns false and sets errno to an error that may be decoded with the com_err framework.

The optout_actor is for detection of an Actor Identity of the remote through the =g attribute. It can be set to NULL by applications that want to treat groups like a normal identity. Otherwise, the access_comm() call may set it up for continued group processing or sender-aliased forwarding. Applications that are aware of groups will test optout_actor to see if it holds a group member; if so, the sender address changes from remote to the Group Member Identity in optout_actor and local is expanded to the destination Group Member Identities. The communication is forked to all these destination addresses.

When successful, the function returns true and the value in out_level reveals the level of access granted. Your application may treat access_comm_greylist and/or access_comm_honeypot if it can handle them; otherwise they can be considered as you would for access_comm_blacklist, the general rejection of the proposed communication. Only access_comm_whitelist is the acceptance without prejudice of the proposed communication.

When access_comm_whitelist is returned from a successful call, the local field may have been modified to reflect another userid/svcname, different aliases/svcargs and, perhaps one day, a different domain. Consider this ACL-driven redirection; it is one example where the general Policy Rules framework can help us define refined control over incoming communication. An example use might be where email sets a Delivered-To header and delivers accordingly to a local mailbox.

Example Rules and expected outputs can be found in test/access/CMakeLists.txt and a supporting example program is test/access/xs-comm.c.

Automated Deployments

A service with a scalable configuration calls another Access Control function with almost the same information – just not the Rules; these are separately stored in the database and can be found with the Access Domain, Type and Name. The same API call is used:

#include <stdint.h>
#include <stdbool.h>
#include <arpa2/identity.h>
#include <arpa2/access_comm.h>
bool access_comm (const a2id_t *remote, a2id_t *local,
const uint8_t *opt_svckey, unsigned svckeylen,
const char *opt_acl, unsigned acllen,
access_comm_level *out_level);

In this case however, the opt_acl is set to NULL and the acllen will be ignored. The Access Name and is derived from local as for manual deployment, but a digest of the Access Domain and Database Secret must be provided as the opt_svckey with svckeylen. Other than this, the function behaves as described for manual deployments.

The Service Key may be configured in the calling application as a hexadecimal string, but it must be supplied here in its binary form. The reason for not deriving this information here is that the Database Secret may be isolated from services if this "lower grade" and more specific Service Key is used. It is not possible to derive another Service Key from the one provided here. See Rules documentation for the functions rules_dbkey_domain() and rules_dbkey_service() that take the two steps down from the Database Secret to the Service Key needed here.

A few example objects in LDAP could look like this,

``` dn: uid=test,associatedDomain=example.com,ou=IdentityHub,o=arpa2.net,ou=InternetWide object: accessControl accessType: 84283358-8ee3-444a-be2e-81e69f50b7fa accessName: /some/identity/structure accessRule: ^service ~+. accessRule: ^tickle =lfool R ~. =xuser CWR ~