Installation

This documentation is split in multiple sections that deal with the installation and configuration of several components:

  • OpenXCAP, the XCAP server itself
  • opensips-mi-proxy, an optional component that replaces the need for the standard OpenSIPS xml-rpc module, is required to issue the refreshWatchers command in OpenSIPS when the the policy stored in the pres-rules XCAP document for a given presentity has been changed. The proxy has also more features like being able to listen on a custom IP address and provides an access list for the clients allowed to connect
  • soap-simple-proxy, an optional component that can access XCAP documents using SOAP/XML requests, it can be used to build a web page to perform XCAP requests for pres-rules and pidf-manipulation documents

Debian or Ubuntu Linux

Debian packages are available for Debian (unstable distribution) systems. To install the packages add the following lines to /etc/apt/sources.list:

deb	http://ag-projects.com/debian unstable main
deb-src http://ag-projects.com/debian unstable main

Install AG Projects debian repository signing key:

wget http://download.ag-projects.com/agp-debian-gpg.key
apt-key add agp-debian-gpg.key

To install the software on the designated XCAP server machine:

apt-get update
apt-get install openxcap soap-simple-proxy

To install the software on the designated SIP Proxy machine:

apt-get update
apt-get install opensips-mi-proxy

To install the xcap client library:

apt-get update
apt-get install python-xcaplib

Other Linux OS

You must perform the following steps:

  • Download and install OpenXCAP
  • Download and install opensips-mi-proxy (optional)
  • Download and install soap-simple-proxy (optional)

Download and install OpenXCAP

The software has the following dependencies, which you must install on your operating system:

OpenXCAP has been tested on Debian unstable with the following software versions:

  • libxml2: 2.6.32.dfsg-2
  • python: 2.5.2
  • python-application: 1.1.5
  • python-gnutls: 1.1.8
  • python-lxml: 2.0.7-1
  • python-sqlobject: 0.10.1
  • python-twisted-core: 8.1.0
  • python-twisted-web: 8.1.0
  • python-twisted-web2: 8.1.0
  • python-zopeinterface: 3.3.1-6

OpenXCAP can be downloaded as a tar archive from:

 http://download.ag-projects.com/XCAP/

Extract it using tar xzvf openxcap-version.tar.gz and change directory to the newly created openxcap directory.

Install the software:

cd openxcap
python setup.py install

Download and install opensips-mi-proxy

The software has the following dependencies, which you must install on your operating system:

The software can be downloaded as a tar archive from:

 http://download.ag-projects.com/XCAP/

Extract it using tar xzvf opensips-mi-proxy-version.tar.gz and change directory to the newly created opensips-mi-proxy directory.

Install the software:

cd opensips-mi-proxy
python setup.py install

Download and install soap-simple-proxy

The software can be downloaded as a tar archive from:

 http://download.ag-projects.com/XCAP/

Extract it using tar xzvf soap-simple-proxy-version.tar.gz and change directory to the newly created soap-simple-proxy directory.

Install the software:

cd soap-simple-proxy
python setup.py install

Downloading from the version control repository

The source code is managed using darcs version control tool. The darcs repository can be fetched with:

darcs get http://devel.ag-projects.com/repositories/openxcap

Other packages like python-xcaplib, soap-simple-proxy and opensips-mi-proxy can be obtained in the same way.

To obtain the incremental changes after the initial get:

cd openxcap
darcs pull -a

Configuration

Configure OpenXCAP server

If you have installed the debian package copy /etc/openxcap/config.ini.sample to /etc/openxcap/config.ini. For other Linux OS copy config.ini.sample from the tar archive to the same directory. Edit config.ini with your settings.

The specific settings for an installation must be set from the configuration file, which is split in several configuration sections.

The [Server] section contains global settings: the IP address and port where OpenXCAP listens for client requests.

The XCAP root is the context that contains all the documents across all applications and users that are managed by the server. Only the client requests that address the root defined here are accepted. If the root URI has the "https" scheme, the server will listen for requests in TLS mode. The X509 certificate and private key that will identify the server are loaded using the values in the [TLS] section.

OpenXCAP support multiple, interchangeable backend modules. Each backend knows where and how to authorize and authenticate XCAP users and where to store the XCAP documents. Currently, supported values are "Database" and "OpenSIPS", the specific settings will be taken the corresponding sections, [Database] or [OpenSIPS].

An XCAP request must be authenticated before it's handled, and the various settings are found in the [Authentication] section. The HTTP authentication algorithm can be chosen from 'basic' and 'digest'. A trusted peer IP list can be defined, requests matching this list will be accepted without authentication. Client requests must be authenticated in the context of a realm that is the same as the SIP domain. This realm is derived in real time for each request using the following logic:

  • if the user section of the XCAP URI (the section following the "users" path segment) is in the form of username@domain, the realm is taken from the domain part
  • some XCAP clients (e.g. CounterPath's Eyebeam), only put the username in the XCAP URI, so there is the need for a convention to determine the realm: it must be included in the XCAP root URI on the client side. For example, if the XCAP root of the server is  http://example.com/xcap-root, the client should be provisioned with  http://example.com/xcap-root@domain/
  • if the above logic does not provide the realm, the realm will be taken from the default_realm setting of [Authentication]

There are separate configuration settings for each backend. The current supported back-ends are Database and OpenSIPS.

The Database section contains the database connection URI to the database where the service subscribers are kept (authentication_db_uri) and the database connection URI to the database where XCAP documents are stored. Currently, only the MySQL database engine has been thoroughly tested.

The OpenSIPS section contains all the settings of the Database section, plus the URL where OpenSIPS's XMLRPC management interface is listening for commands. The refreshWatchers command is sent to OpenSIPS management interface to inform the server that the XCAP documents have been changed for a user so that OpenSIPS can send notifications out according to the new policy in real-time.

When using TLS you must generate an X.509 certificate and a key. Consult Internet resources for how to do this. The procedure is the same as for any other TLS server like Apache web server.

Database setup

Both OpenXCAP backends (Database and OpenSIPS) depend on a database engine to store service subscribers and XCAP resources. The database creation scripts are found in the scripts/ directory, and involve 2 tables: subscriber, which is used to authenticate XCAP requests, and xcap, where XCAP documents are stored. The subscriber table is a subset of the subscriber table from OpenSIPS, xcap table is the same as the one from OpenSIPS.

Sample OpenXCAP configuration file

Configure opensips-mi-proxy

If you have installed the debian package copy /etc/opensips-mi-proxy/config.ini.sample to /etc/opensips-mi-proxy/config.ini. For other Linux OS copy config.ini.sample from the tar archive to the same directory. Edit config.ini with your settings.

[OpenSIPS]
socket = /var/run/opensips/socket

[MIProxy]
;listen_url = http://<defaultIPAddress>:8080
;trusted = any

For more information see the README and INSTALL files that come together with the tar archive.

Configure soap-simple-proxy

If you have installed the debian package copy /etc/soap-simple-proxy/config.ini.sample to /etc/soap-simple-proxy/config.ini. For other Linux OS copy config.ini.sample from the tar archive to the same directory. Edit config.ini with your settings.

[SOAP Server]
address = 0.0.0.0
port = 9300
log_requests = Yes

[WSDL]
public_service_url = https://example.com/soap-simple-proxy/
internal_service_url = http://private-address:9200/

[XCAP]
root_uri = http://xcap.example.com/xcap-root

For more information see the README and INSTALL files that come together with the tar archive.

Configure OpenSIPS

The following OpenSIPS configuration example enables OpenSIPS to act like a dedicated SIP Presence server that accepts messages from a trusted SIP Proxy with XCAP authorization enabled using OpenXCAP as policy server. The SIP Proxies defined as trusted peers must be configured to authenticate and authorize the PUBLISH and SUBSCRIBE methods.

Is advisable to consult  http://opensips.org web site, documentation section for the up to date configuration and settings.

listen       = 10.0.0.1:5060

# --- module loading ---

mpath = "/usr/lib/opensips/modules"
loadmodule "mi_fifo.so"
loadmodule "mi_datagram.so"
loadmodule "mysql.so"
loadmodule "sl.so"
loadmodule "maxfwd.so"
loadmodule "tm.so"
loadmodule "rr.so"
loadmodule "xlog.so"

loadmodule "presence.so"
loadmodule "presence_xml.so"
loadmodule "presence_mwi.so"
loadmodule "presence_xcapdiff.so"
loadmodule "pua.so"
loadmodule "pua_mi.so"
loadmodule "rls.so"


# ----------------- setting module-specific parameters ---------------

# -- rr params --
# add value to ;lr param to make some broken UAs happy
modparam("rr", "enable_full_lr", 1)

modparam("mi_datagram", "socket_name",       "/var/run/opensips/socket")
modparam("mi_datagram", "unix_socket_user",  "opensips")
modparam("mi_datagram", "unix_socket_group", "opensips")

modparam("mi_fifo", "fifo_name", "/var/run/opensips/fifo")
modparam("mi_fifo", "fifo_user",  "opensips")
modparam("mi_fifo", "fifo_group", "opensips")

# -- presence params --
modparam("presence", "db_url", "mysql://opensips:password@db/opensips")
modparam("presence", "server_address", "sip:presence@10.0.0.1")
modparam("presence", "fallback2db", 1)
modparam("presence", "clean_period",  30)

# -- xcap params --
modparam("presence_xml", "db_url", "mysql://opensips:password@db/opensips")
modparam("presence_xml", "force_active", 0)
modparam("presence_xml", "pidf_manipulation", 1)
modparam("presence_xml", "integrated_xcap_server", 1)

# -- rls params --

modparam("rls", "db_url", "mysql://opensips:password@db/opensips")
modparam("rls", "server_address",         "sip:rls@10.0.0.1")
modparam("rls", "to_presence_code", 5)
modparam("rls", "integrated_xcap_server", 1)


# -------------------------  request routing logic -------------------
 
# main routing logic
 
route {
    xlog("L_INFO", "----- Start routing");

    if ((method=="PUBLISH" || method=="SUBSCRIBE" || method=="NOTIFY")) {
        xlog("L_INFO", "Presence event: $hdr(Event)\n");
    }

    if(is_method("PUBLISH")) {
        if ((src_ip==10.0.0.1 && src_port==5060)) {  
            sl_send_reply("404", "Domain not served here");
            return;
        }
        if (is_from_local()) {
            if (avp_check("$hdr(Event)", "fm/presence*/i") && ($au != $rU || $ar != $rd)) {
                xlog("L_WARN", "Account $au@$ar tried to publish $hdr(Event) event for $ru\n");
                sl_send_reply("403", "Publishing $hdr(Event) events for others is forbidden");
               return; 
            }
       } else {
            sl_send_reply("403", "PUBLISH forbidden for outside domains");
            return;
        }

        if (t_newtran()) {  
            handle_publish();
            t_release();
        } else {
            sl_reply_error();
        }
        exit;
    } else if( is_method("NOTIFY"))
        if (has_totag()) {
            if (!loose_route()) {
                if (!t_newtran()) {
                    sl_reply_error();
                    exit;
                }
                rls_handle_notify();
                switch ($retcode) {
                case 1:
                    # Notify processed by rls
                    xlog("L_INFO", "$rm processed by RLS\n");
                    t_release();
                    exit;
                    break;
                case -1:
                    # Error
                    xlog("L_INFO", "$rm processed by RLS but has error\n");
                    t_reply("500", "Server error while processing RLS NOTIFY");
                    exit;
                    break;
                default:
                    if (uri == "sip:rls@10.0.0.1") {
                        xlog("L_ERR", "$rm should be processed by RLS but was not recognized\n");
                        xlog("L_INFO", "Dropping $rm because it will loop\n");
                        t_reply("500", "Server error while processing RLS NOTIFY");
                        exit;  
                    } else {   
                        xlog("L_INFO", "$rm handled by presence\n");
                        t_release();
                    }
                }
            }
        } else {
            # Out-of-dialog NOTIFY
            sl_send_reply("405", "Method Not Allowed");
            exit;
        }

    } else if( is_method("SUBSCRIBE")) {
        if (!has_totag()) {
            if (loose_route()) {
                xlog("L_ERR", "Incorrectly formatted $rm request. Rejected.\n");
                sl_send_reply("400", "Incorrectly formatted request");
                return;
            }

            if ((src_ip==10.0.0.1 && src_port==5060) && is_present_hf("Record-Route")) {
                sl_send_reply("404", "Domain not served here");
                return;
            }

            if (is_from_local()) {
                   if (!(src_ip==10.0.0.1 && src_port==5060)) {
                       xlog("L_INFO", "Request came directly from the subscriber\n");
                        setflag(18);
                   }

                    if ((avp_check("$hdr(Event)", "fm/*.winfo/i") || avp_check("$hdr(Event)", "eq/message-summary/i")) &&
                        ($au != $rU || $ar != $rd)) {
                        xlog("L_WARN", "Account $au@$ar tried to subscribe to $ru for $hdr(Event)\n");
                        sl_send_reply("403", "Subscription to others $hdr(Event) is forbidden");
                        return;
                    }
                }
            }

            # Internal presence handling
            if (!t_newtran()) {
                sl_reply_error();
                exit;
            }

            rls_handle_subscribe();

            switch ($retcode) {
            case 5:
                # RLS indicated that message should be processed by presence

                if (is_uri_host_local()) {
                    if (does_uri_exist()) {
                        handle_subscribe();
                        t_release();
                    } else {   
                        t_reply("404", "User not found");
                    }
                    exit;
                }
                break;
            default:
                t_release();   
                exit;
            }
        } else {
            # In-dialog SUBSCRIBE
            if (uri=="sip:presence@10.0.0.1" || uri=="sip:rls@10.0.0.1" || !loose_route()) {
                # Internal presence handling
                if (t_newtran()) {
                    rls_handle_subscribe();
                    if ($retcode==5) {
                        handle_subscribe();
                    }
                    t_release();
                } else {
                    sl_reply_error();
                }
                exit;
            }
        }
    } else {
        xlog("L_INFO", "Method $rm Not Acceptable Here");
        sl_send_reply("488", "Not Acceptable Here");
        exit;
    };
}

Running the server

For non Debian systems copy openxcap, soap-simple-proxy and opensips-mi-proxy startup scripts from their debian directory present in each tar file to /etc/init.d/ and edit them to match your system.

Start OpenXCAP server:

/etc/init.d/openxcap start

Start opensips-mi-proxy:

/etc/init.d/opensips-mi-proxy start

Start soap-simple-proxy:

/etc/init.d/soap-simple-proxy start

OpenXCAP logs its messages to /var/log/openxcap/. All other servers log their messages to the system syslog. Check the log files for any startup or runtime errors.

Creating user accounts

The user accounts are stored in OpenSIPS subscriber table. You can add subscribers by using your favorite OpenSIPS subscriber management tool.