Table of Contents
XCAP is a HTTP based protocol for access remote configuration data. Data is stored in XML format and XCAP protocol allows to query, modify or delete parts of such data. This is in detail described in [xcap]. XCAP server is server able to handle XCAP requests.
XCAP server may be used for storing “presence interesting” data. From the SER's point of view are interesting:
authorization data
“buddy lists”
Definition of authorization documents and theirs usage is specified in [common auth] and especially for presence purposes in [presence auth]. Both documents are quite common and in SER's presence modules implemented only partialy.
XCAP server may be used for storing lists of users too. These lists may be used for presence subscriptions - subscription to such list means subscription to all users at once. This reduces number of created subscriptions and may reduce data transfers between server and client too; but presence documents for lists of users may be very big.
There may be not only lists for individual users with their contacts but there may be other sort of lists representing some “logical entities” such “businessmen”, “technical support”, ... which are used in cases like if some customer needs someone from technical support department and doesn't want to remeber all people there. Such customer may simply watch presence state of “technical-support@somewhere.net” if he needs help from them.
Lists of users - more common resource lists - are defined in [rls] and their usage with SIP in [sip rls]. These lists are partialy implemented in RLS module.
Manipulating with XCAP documents is quite simple because XCAP uses standard HTTP methods like GET, PUT or DELETE. Every web browser may be used to read XCAP data and it is quite simple to write utility to write data to XCAP server. These features allow to use XCAP with SER although there are is not much client software supporting it.
Authorization documents are read for presentities according to their presentity URIs. Presentity URI is AOR of SUBSCRIBE request. Resulting URI will be:
<xcap-root>/pres-rules/users/<username>/presence-rules.xml
where <xcap-root> is set in configuration and
<username> is username from presentity URI.
One of the worst disadvantages of XCAP authorization is slowness of XCAP queries compared to - for example - data stored in local database. This is the reason for caching XCAP queries and responses, but there is a problem - how to detect changes in data stored on XCAP server. One of possible solutions is to implement client for “XCAP change notifications” described in [xcap_diff] and [xcap_profiles] (planned in future versions).
There is a problem of resource lists usage: The draft [rls] describes that a Resource Lists Server operates with “rls-services” document - NOT directly with the user's buddy list, but tested client software doesn't store “rls-services” documents, only “resource list documents” (buddy lists).
It is possible now to change mode of processing subscriptions (see RLS module parameters so it works directly with resource list documents published by client instead of rls-services document.
The construction of rls-services document URI is described in [rls]. Only in short: the AOR from SIP SUBSCRIBE request is combined with XCAP root given in configuration like this:
<xcap-root>/rls-services/global/index/~~/rls-services/service[@uri=%22<AOR>%22].
This URI doesn't not specify namespaces as mentioned in definition, but this is due to problems with XCAP server used for tests (problems querying parts of documents with namespaces).
Example 2. rls-services uri example
xcap-root = http://localhost/xcap-root
AOR = sip:smith-list@iptel.org
Resulting rls-services document describing the list will be get from URI:
http://localhost/xcap-root/rls-services/global/index/~~/rls-services/service[@uri=%22<smith-list@iptel.org>%22],
which means the service element with
uri parameter value
smith-list@iptel.org stored in rls-services document named
index.
Working with URIs presented in this section have one big disadvantage - it needs full XCAP server which is able to work with partial documents and able to process XPointer expressions in XCAP queries.
Due to unavailability of free XCAP servers is there a possibility to
use SER's RLS server in mode of reduced XCAP server needs
(see RLS module parameters). If operating
in this mode, RLS requests full rls-service document from uri
<xcap-root>/rls-services/global/index, inspects it
and finds requested resource list according to URI and AOR by itself.
(Only if possible! There can't be links
to partial documents in rls-services document.)
XCAP documents examples published there doesn't use correct XML namespaces due to problems with XCAP server used for tests (probles querying partial documents with namespaces).
Example 3. Storing XCAP documents
There is a sample script in Python which stores XCAP documents onto a XCAP server. Documents are:
rls-services document stored
under name index
buddy list for user Smith
stored under name smith
presence authorization
document for user Smith stored under name
presence-rules.xml
#!/usr/bin/python
import httplib, urllib
machine = "localhost"
#
# store rls-services document
#
uri = "/xcap-root/rls-services/global/index"
headers = {"Content-Type": "application/rls-services+xml"}
bf = file("rls.xml", "r")
body = bf.read(65536);
conn = httplib.HTTPConnection(machine)
conn.request("PUT", uri, body, headers)
response = conn.getresponse()
print "Storing rls-services document: ", response.status, response.reason
data = response.read()
conn.close()
#
# store resource-list document for user
#
uri = "/xcap-root/resource-lists/users/smith/resource-list.xml"
headers = {"Content-Type": "application/resource-lists+xml"}
bf = file("list.xml", "r")
body = bf.read(65536);
conn = httplib.HTTPConnection(machine)
conn.request("PUT", uri, body, headers)
response = conn.getresponse()
print "Storing resource-lists document: ", response.status, response.reason
data = response.read()
conn.close()
#
# store presence authorization rules
#
uri = "/xcap-root/pres-rules/users/smith/presence-rules.xml"
headers = {"Content-Type": "application/pres-rules+xml"}
bf = file("presence-rules.xml", "r")
body = bf.read(65536);
conn = httplib.HTTPConnection(machine)
conn.request("PUT", uri, body, headers)
response = conn.getresponse()
print "Storing pres-rules document: ", response.status, response.reason
data = response.read()
conn.close()
Example 4. Example resource list document (list.xml)
Simple buddy lists which shows the possibility of nested lists.
<?xml version="1.0" ?> <resource-lists> <list name="default"> <list name="work"> <entry uri="sip:someone@iptel.org"> <display-name>Someone</display-name> </entry> <entry uri="sip:smith@iptel.org"> <display-name>Jonathan Smith</display-name> </entry> </list> <entry uri="sip:vasek@iptel.org"> <display-name>Vasek</display-name> </entry> <entry uri="sip:vaclav.kubart@iptel.org"> <display-name>Vaclav Kubart</display-name> </entry> </list> </resource-lists>
Example 5. Example rls-services document (rls.xml)
Example document which is processed by Resource List Server (RLS module). This document can contain references to users buddy lists like “smith-list@iptel.org” which points to buddy list for user smith named “default” and can contain such lists directly.
<?xml version="1.0" encoding="UTF-8"?> <rls-services> <service uri="sip:smith-list@iptel.org"> <resource-list>http://localhost/xcap-root/resource-lists/users/smith/resource-list.xml/~~/resource-lists/list[@name=%22default%22]</resource-list> <packages> <package>presence</package> </packages> </service> <service uri="sip:cz@iptel.org"> <list name="czech iptel"> <entry uri="sip:abc@iptel.org"> <display-name>A B</display-name> </entry> <entry uri="sip:cde@iptel.org"> <display-name>C D</display-name> </entry> <entry uri="sip:efg@iptel.org"> <display-name>Ef Ge</display-name> </entry> </list> <packages> <package>presence</package> <package>email</package> </packages> </service> </rls-services>
Example 6. Example presence authorization document (presence-rules.xml)
This document contains two rules:
“white list”, which allows access to presence information from all from domain iptel.org
“black list”, which denies access for user nemo@somewhere.net
<?xml version="1.0" ?> <ruleset xmlns="urn:ietf:params:xml:ns:common-policy" xmlns:pr="urn:ietf:params:xml:ns:pres-rules"> <rule id="blacklist"> <conditions> <identity> <id>sip:nemo@somewhere.net</id> </identity> </conditions> <actions> <pr:sub-handling>block</pr:sub-handling> </actions> <transformations/> </rule> <rule id="whitelist"> <conditions> <identity> <domain domain="iptel.org"/> </identity> </conditions> <actions> <pr:sub-handling>allow</pr:sub-handling> </actions> <transformations/> </rule> </ruleset>
XCAP server is a HTTP server with some features like document validation or ability of working with parts of stored documents. If you have no XCAP server, you can simulate it using standard web server. There are not many XCAP servers available today, thus the simulation may be interesting for - at least - demonstration or testing purposes.
Depending on your needs you can
create hierarchical directory structure of XML documents according to [xcap]
allow upload (handle HTTP PUT method) which stores documents into the directory structure
improve upload to validate documents according to schema (every sort of XCAP document should have their XSD published)
allow document removing (handle DELETE method)
process HTTP GET requests with a CGI-script so it processes queries for partial documents
Presence modules use XCAP documents stored in structure like this:
xcap-root
pres-rules
users
smith
presence-rules.xml (file
containg presence authorization rules for user smith)
joe
presence-rules.xml (file containing
presence authorization rules for user joe)
... (directories for other users)
resource-lists
users
smith
resource-list.xml (file
containing resources lists for user smith)
joe
resource-list.xml (file
containing resource lists for user joe)
... (directories for other users)
rls-services
global
index (file containing global
rls-services documents)
You don't need a full XCAP server for presence authorization documents - these are read as standalone documents from directories of standalone users.
For resource lists you have to set RLS module
parameters mode and/or
reduce_xcap_needs
to work as much as possible with XCAP server simulation.
Examples presented here can be used as simple XCAP server simulation. It is able to handle PUT method (for whole XML documents).
Example 7. Apache2 configuration
... Alias /xcap-root /var/simulated-xcap-root <Directory /var/simulated-xcap-root> Options Indexes FollowSymLinks MultiViews Script PUT /cgi-bin/upload <Limit PUT DELETE GET> Order Allow,Deny Deny from none Allow from all </Limit> </Directory> ...
If apache is running on machine with SER, you can use as xcap-root
http://localhost/xcap-root.
Example 8. Simple (and dangerous) cgi-script for upload
This code is written in C and it is able to create directories if needed, but its usage in presented form is realy unsafe! You have to compile it and put into directory with other CGI scripts.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
void copy_file(const char *filename)
{
char buf[2048];
int r;
FILE *f;
f = fopen(filename, "wb");
if (f) {
while (!feof(stdin)) {
r = fread(buf, 1, sizeof(buf), stdin);
fwrite(buf, 1, r, f);
}
fclose(f);
}
}
int main(int argc, char **argv)
{
char *filename, *x;
char tmp[1024];
int res = 0;
filename = getenv ("PATH_TRANSLATED");
strcpy(tmp, filename);
x = strrchr(tmp, '/');
if (x) {
*x = 0;
res = mkdir(tmp, 0755); /* ! dangerous ! */
}
else {
printf("Status: 500\n");
printf("Content-Type: text/html\n\n");
printf("<html><head/>\n<body>Incorrect filename</body></html>\n");
return -1;
}
copy_file(filename); /* ! dangerous ! */
printf("Status: 200\n");
printf("Content-Type: text/html\n\n");
printf("<html><head><title>Upload</title>\n</head>\n<body>Finished...</body></html>\n");
return 0;
}
Presence modules use some dynamic libraries distributed with SER and the
compilation procedure and running is a bit more difficult than usual. For detailed
description of libraries see their separate documentation (stored in
lib/doc subdirectory of main SER directory).
Presence module dependecies may be found in sections PA module dependencies and RLS module dependencies. These modules depend on common libraries which have their own dependencies as mentioned below.
This library depends only on standard C libraries and needs no other external libraries.
libcds (distributed with SER)
libxml2 (external library for parsing XML documents)
libcurl3 (external library for HTTP operations)
There is an example of steps which need to be done while installing SER with these libraries into directory /base/ser/directory (if no directory specified - no prefix parameter given - default value is used: /usr/local/)
Download current ser sources:
cvs -d :pserver:anonymous@cvs.berlios.de:/cvsroot/ser checkout sip_router
Compile and install libraries for usage with SER:
cd sip_router/lib
make -f Makefile.ser install prefix=/base/ser/directory
This procedure may fail in the case of unsatisfied library dependencies. You need to install all external libraries introduced in the section called “Dependencies”
Compile and install SER with presence modules
cd ..
make install include_modules="pa rls mysql" prefix=/base/ser/directory
This module implements a presence server, i.e. entity that receives SUBSCRIBE messages and sends NOTIFY when presence status of a user changes. Currently the presence server can be connected to registrar and jabber module so SIP users can see presence of jabber users.
This module currently cannot work as a B2BUA, i.e. it cannot subscribe to presence of users using SIP. We are currently working on that feature.
Default expires value to be used when the client doesn't supply one (in seconds).
Default value is 3600.
This variable specifies authorization type for presence watchers (event package is “presence”). Value can be one of:
All watchers are always authorized. This is not recommended because it ignores user's wish.
All watchers are always pending. This is not recommended because it means, that no presence data is sent to all watchers.
This type of authorization means, that authorization rules
are read from XCAP server and processed [presence auth].
In this case the auth_xcap_root must be set.
Default value is empty. In this case “implict” authorization is used with an error message.
This parameter holds value of XCAP root URI used for reading authorization rules. Value must be set to nonempty value if “xcap” authorization is used.
Authorization document is loaded using HTTP GET method from URI composed
from auth_xcap_root and user's name as follows:
auth_xcap_root/pres-rules/users/username/presence-rules.xml.
This variable specifies authorization type for watcher info watchers (event package is “presence.winfo”). Value can be one of:
All watcher info watchers are always authorized. This is not recommended.
This value means, that presentity can subscribe to its own watcher info data and nobody else. This is done via comparing watcher's and presentity's uri. If these values equals, the subscription is allowed. In other cases is the subscription rejected.
Default value is “implict”
Resource lists server is a server which allows subscriptions to lists of users. Its behaviour is defined in [rls] and [sip rls]. As described there, it uses XCAP server for storing data about lists of users. These data can be manipulated in any way by user's client software.
There is a few of standard incompliances:
only internal subscriptions - at this moment are supported only internal subscriptions to PA module. Module can not handle subscriptions to external presence servers.
nested lists (lists in list) are not possible
min_expiration (integer)
Minimal subscription expiration timeout in seconds.
If client supplies
value, which is less than value of min_expiration,
the server returns response "423 Interval too small" as described
in [events].
Default value is 60.
max_expiration (integer)
Maximal subscription expiration timeout in seconds.
If client supplies
value, which is more than value of max_expiration,
the server shortens this value to value of this variable as described
in [events].
Default value is 7200.
default_expiration (integer)
Default subscription expiration timeout in seconds.
If client doesn't supply subscription expiration timeout this value is used.
Default value is 3761.
auth (string)
This variable specifies authorization type for list watchers. Value can be one of:
All watchers are always authorized. This is not recommended because it ignores user's wish.
In this case is implicit authorization done. This means,
that for list URIs in the form
“<username>-list@domain” is subscription allowed
only for user with username <username>,
rejected for others.
If the URI is not in the form presented above, the subscription is marked as pending.
Default value is empty. In this case “implict” authorization is used with an error message.
mode (string)
Mode of processing subscriptions:
full
If set to this value, the resource-list is read according to [rls] from “index” rls-services document.
simple
In this case is supposed that list uri is in the form of
<username>-list@domain and the list is
taken as resource-lists document from XCAP URI
<xcap-root>/resource-lists/users/<username>/resource-list.xml
This allows usage of standard web server instead of XCAP server (querying only full documents, not using xpointer expressions) and direct usage with clients which don't set rls-services documents (eyeBeam).
reduce_xcap_needs (int)
If set to 1 the module tries to do simplify XCAP queries - queries will be done for whole documents, not partial, thus the XCAP server may be simulated using standard web server. It has influence only on querying resource lists and it will work correctly only if there are no links to resource lists containg partial documents URIs (lists should be contained directly in main rls-services document).
Default value is 0.
xcap_root (string)
Globaly defined XCAP root. This parameter was added due to simplification of configuration. Previous versions were able to work with more XCAP servers (given as parameter to handle_rls_subscription, but this may lead to problems with nested lists, thus it was removed).
Default value: not set.
handle_rls_subscription(create_error_response)
Handle subscription to resource list uri.
Parameters:
If set to 0 error responses are not sent to the client. This may be useful, if used together with PA module.
Modules
tm
pa
Libraries
libcds (internal)
libxcap (internal) - XCAP queries
libpresence (internal) - used for internal subscriptions ta PA
XCAP authorization
DB authorization (presence rules like in XCAP stored in local DB)
separate authorization settings (type, server) for each XCAP server
combination of XCAP and implicit authorization (no XCAP rules, try implicit)
reaction on failed NOTIFY (408, ...) as soon as will be
corrected req_within
remote subscriptions (SIP events client)
BUG: long run (kphone) => stops process resubscriptions so they start to be processed by PA
pending subscriptions should return 202 on SUBSCRIBE instead of 200 (but 202 kills eyeBeam!)
Example 13. ser.cfg
There is a sample config file containing simple usage of PA and RLS module without authentication.
# ----------- global configuration parameters ------------------------
check_via=no # (cmd. line: -v)
dns=no # (cmd. line: -r)
rev_dns=no # (cmd. line: -R)
fifo="/tmp/ser_fifo"
alias="test-domain.com"
# ------------------ module loading ----------------------------------
# Uncomment this if you want to use SQL database
loadmodule "/home/kubartv/current/lib/ser/modules/sl.so"
loadmodule "/home/kubartv/current/lib/ser/modules/tm.so"
loadmodule "/home/kubartv/current/lib/ser/modules/rr.so"
loadmodule "/home/kubartv/current/lib/ser/modules/maxfwd.so"
loadmodule "/home/kubartv/current/lib/ser/modules/usrloc.so"
loadmodule "/home/kubartv/current/lib/ser/modules/registrar.so"
loadmodule "/home/kubartv/current/lib/ser/modules/textops.so"
loadmodule "/home/kubartv/current/lib/ser/modules/mysql.so"
loadmodule "/home/kubartv/current/lib/ser/modules/dialog.so"
loadmodule "/home/kubartv/current/lib/ser/modules/pa.so"
loadmodule "/home/kubartv/current/lib/ser/modules/rls.so"
loadmodule "/home/kubartv/current/lib/ser/modules/auth.so"
loadmodule "/home/kubartv/current/lib/ser/modules/auth_db.so"
# ----------------- setting module-specific parameters ---------------
# -- usrloc params --
#?cvs: modparam("usrloc|registrar", "use_domain", 1)
modparam("auth_db", "calculate_ha1", yes)
modparam("auth_db", "password_column", "password")
# -- rr params --
# add value to ;lr param to make some broken UAs happy
modparam("rr", "enable_full_lr", 1)
modparam("rls", "min_expiration", 60)
modparam("rls", "max_expiration", 3600)
modparam("rls", "default_expiration", 600)
modparam("rls", "auth", "none")
modparam("rls", "xcap_root", "http://localhost/xcap")
modparam("rls", "mode", "simple")
# simplified XCAP queries if reduce_xcap_needs set
modparam("rls", "reduce_xcap_needs", 1)
modparam("usrloc|rls", "db_mode", 1)
modparam("pa", "use_db", 1)
modparam("domain|uri|acc|auth_db|usrloc|pa|rls", "db_url", "mysql://ser:heslo@127.0.0.1:3306/ser")
# mode of PA authorization: none, implicit or xcap
modparam("pa", "auth", "xcap")
modparam("pa", "auth_xcap_root", "http://localhost/xcap")
modparam("pa", "winfo_auth", "none")
# ------------------------- request routing logic -------------------
# main routing logic
route{
# initial sanity checks -- messages with
# max_forwards==0, or excessively long requests
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483","Too Many Hops");
break;
};
if (msg:len >= max_len ) {
sl_send_reply("513", "Message too big");
break;
};
# we record-route all messages -- to make sure that
# subsequent messages will go through our proxy; that's
# particularly good if upstream and downstream entities
# use different transport protocol
if (!method=="REGISTER") record_route();
# subsequent messages withing a dialog should take the
# path determined by record-routing
if (loose_route()) {
# mark routing logic in request
append_hf("P-hint: rr-enforced\r\n");
route(1);
break;
};
if (!uri==myself) {
# mark routing logic in request
append_hf("P-hint: outbound\r\n");
route(1);
break;
};
# if the request is for other domain use UsrLoc
# (in case, it does not work, use the following command
# with proper names and addresses in it)
if (uri==myself) {
if (method=="REGISTER") {
# Uncomment this if you want to use digest authentication
# if (!www_authorize("iptel.org", "subscriber")) {
# www_challenge("iptel.org", "0");
# break;
# };
save("location");
break;
};
if (method=="SUBSCRIBE") {
if (!t_newtran()) {
sl_reply_error();
};
if (!handle_rls_subscription("0")) {
# message is not for RLS but for PA ?
# log(1, "SUBSCRIBE not handled by RLS");
handle_subscription("registrar");
}
break;
};
if (method=="PUBLISH") {
if (!t_newtran()) {
log(1, "newtran error\n");
sl_reply_error();
};
handle_publish("registrar");
break;
};
# native SIP destinations are handled using our USRLOC DB
if (!lookup("location")) {
sl_send_reply("404", "Not Found");
break;
};
};
append_hf("P-hint: usrloc applied\r\n");
route(1);
}
route[1]
{
# send it out now; use stateful forwarding as it works reliably
# even for UDP2TCP
if (!t_relay()) {
sl_reply_error();
};
}
Example 14. cfg with authentication
There is a modification of ser.cfg shown above with
user authentication of SUBSCRIBE requests.
...
if (method=="SUBSCRIBE") {
if (!proxy_authorize("iptel.org", "subscriber")) {
proxy_challenge( "iptel.org", "0");
break;
};
if (!t_newtran()) {
sl_reply_error();
};
if (!handle_subscription("0")) {
# message is not for RLS but for PA ?
# log(1, "SUBSCRIBE not handled by RLS");
handle_subscription("registrar");
}
break;
};
...
There might be new versions of internet drafts and thus links to them my be obsolete. In such case try increment version in link or find the draft on IETF by name.
[xcap] draft-ietf-simple-xcap-07.txt - XCAP specification.
[xcap_diff] draft-ietf-simple-xcap-diff-01.txt - XCAP changes notifications format.
[xcap_profiles] draft-ietf-sipping-config-framework-07.txt -XCAP user profiles.
[events] RFC 3265 - SIP Events.
[presence] RFC 3856 - Presence Event package.
[winfo_doc] RFC 3858 - Data Format for watcher info.
[reg] RFC 3680 - SIP Reg Events.
[common auth] draft-ietf-geopriv-common-policy-05.txt.
[presence auth] draft-ietf-simple-presence-rules-03.txt - presence authorization XML based data format and usage with XCAP.
[rls] draft-ietf-simple-xcap-list-usage-05.txt - XML formats for representing resource lists.
[sip rls] draft-ietf-simple-event-list-07.txt - Event Notification Extension for Resource Lists.