mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
630 lines
22 KiB
630 lines
22 KiB
<?xml version='1.0'?>
|
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
|
"http://www.oasis-open.org/docbookid/id/g/4.5/docbookx.dtd">
|
|
|
|
|
|
<refentry xml:id="module.auth_identity"
|
|
xmlns:xi="http://www.w3.org/2001/XInclude"
|
|
xmlns:serdoc="http://sip-router.org/xml/serdoc">
|
|
<refmeta>
|
|
<refentrytitle>auth_identity</refentrytitle>
|
|
<manvolnum>7</manvolnum>
|
|
</refmeta>
|
|
<refnamediv>
|
|
<refname>auth_identity</refname>
|
|
<refpurpose>Securely identify originator of SIP messages.</refpurpose>
|
|
</refnamediv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
<para>
|
|
The <command>auth_identity</command> SER module provides
|
|
functionalities for securely identifying originators of SIP
|
|
messages by implementing the mechanism described in RFC 4474
|
|
and known as SIP Identity framework.
|
|
</para>
|
|
<para>
|
|
The module provides two services:
|
|
The <emphasis>authorizer</emphasis> authorizes a message and adds
|
|
Identity and Identity-Info headers to forwarded requests.
|
|
The <emphasis>verifier</emphasis> verifies the identity of a
|
|
received message.
|
|
</para>
|
|
<para>
|
|
In order to use the <command>auth_identity</command> module you
|
|
have to provide a certificate. More information can be found in
|
|
the section
|
|
<serdoc:link linkend="module.auth_identity.certificates">Certificates
|
|
</serdoc:link> below.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1 xml:id="module.auth_identity.functions">
|
|
<title>Functions</title>
|
|
|
|
<refsect2 xml:id="function.auth_add_identity">
|
|
<title>
|
|
<function>auth_add_identity</function>
|
|
()
|
|
</title>
|
|
<para>
|
|
Allowed in request processing only.
|
|
</para>
|
|
<para>
|
|
The <function>auth_add_identity()</function> function authorizes
|
|
a request by adding identity information to it.
|
|
</para>
|
|
<para>
|
|
It calculates a SHA1 hash over certain components of the message
|
|
and encrypts it using the private key given through the
|
|
<serdoc:modparam
|
|
module="auth_identity">privatekey_path</serdoc:modparam>
|
|
parameter. The resulting cyphertext is appended to the message
|
|
as the content of the Identity header field.
|
|
</para>
|
|
<para>
|
|
To allow the receiver to decypher the identity information, it adds
|
|
the URL where the receiver may find the certificate in the
|
|
Indentity-Info header field. This URL is set through the
|
|
<serdoc:modparam
|
|
module="auth_identity">certificate_url</serdoc:modparam>
|
|
parameter.
|
|
</para>
|
|
<para>
|
|
<emphasis>Note:</emphasis> After the function has been called,
|
|
the following header fields must not be modified:
|
|
From, To, Call-ID, CSeq, Date, Contact. Additionally, the
|
|
message body must remain unmodified, too.
|
|
</para>
|
|
</refsect2>
|
|
|
|
<refsect2 xml:id="function.auth_date_proc">
|
|
<title>
|
|
<function>auth_date_proc</function>
|
|
()
|
|
</title>
|
|
<para>
|
|
Allowed in request processing only.
|
|
</para>
|
|
<para>
|
|
The <function>auth_date_proc()</function> checks the age of a
|
|
request to be authroized. If the time given in the Date header
|
|
field of the request differs by more than the amount of seconds
|
|
given by the
|
|
<serdoc:modparam module="auth_identity">msg_timeout</serdoc:modparam>
|
|
parameter, the function returns <literal>false</literal>. It also
|
|
returns <literal>false</literal> if the certificate used by the
|
|
authorizer has expired.
|
|
</para>
|
|
</refsect2>
|
|
|
|
<refsect2 xml:id="function.vrfy_check_callid">
|
|
<title>
|
|
<function>vrfy_check_callid</function>
|
|
()
|
|
</title>
|
|
<para>
|
|
Allowed in request processing only.
|
|
</para>
|
|
<para>
|
|
The <function>vrfy_check_callid()</function> checks whether a
|
|
request for this call has been processed within the
|
|
time given by the
|
|
<serdoc:modparam
|
|
module="auth_identity">auth_validity_time</serdoc:modparam>
|
|
parameter.
|
|
</para>
|
|
<para>
|
|
The function generates a call identifier from the Call-ID and CSqe
|
|
header fields and the Tag parameter of the From header field and
|
|
compares it with the values stored in the Call-ID cache.
|
|
</para>
|
|
<para>
|
|
It returns <literal>false</literal> if the value is found and thus
|
|
the request is replayed or <literal>true</literal> otherwise.
|
|
</para>
|
|
</refsect2>
|
|
|
|
<refsect2 xml:id="function.vrfy_check_certificate">
|
|
<title>
|
|
<function>vrfy_check_certificate</function>
|
|
()
|
|
</title>
|
|
<para>
|
|
Allowed in request processing only.
|
|
</para>
|
|
<para>
|
|
The <function>vrfy_check_certificate()</function> function
|
|
checks the downloaded certificate and returns <literal>true</literal>
|
|
if it is valid or <literal>false</literal> otherwise.
|
|
</para>
|
|
<para>
|
|
A certificate is considered valid if it has not yet expired and
|
|
if its subject is identical to the domain part of the URL.
|
|
</para>
|
|
<!-- XXX Er, which URL? -->
|
|
<para>
|
|
Before <function>vrfy_check_certificate()</function> can be called,
|
|
the function <function>vrfy_check_date()</function> must have been
|
|
called and returned <literal>true</literal>.
|
|
</para>
|
|
</refsect2>
|
|
|
|
<refsect2 xml:id="function.vrfy_check_date">
|
|
<title>
|
|
<function>vrfy_check_date</function>
|
|
()
|
|
</title>
|
|
<para>
|
|
Allowed in request processing only.
|
|
</para>
|
|
<para>
|
|
The <function>vrfy_check_date()</function> function checks
|
|
the date of the request currently being processed. It returns
|
|
<literal>false</literal> if the time in the Date header field
|
|
of the request differs from the current system time by more than
|
|
the number of seconds given by the
|
|
<serdoc:modparam
|
|
module="auth_identity">auth_validity_time</serdoc:modparam>
|
|
parameter.
|
|
</para>
|
|
</refsect2>
|
|
|
|
<refsect2 xml:id="function.vrfy_check_msgvalidity">
|
|
<title>
|
|
<function>vrfy_check_msgvalidity</function>
|
|
()
|
|
</title>
|
|
<para>
|
|
Allowed in request processing only.
|
|
</para>
|
|
<para>
|
|
The <function>vrfy_check_msgvalidity()</function> function
|
|
checks the integrity of the request currently being processed.
|
|
</para>
|
|
<para>
|
|
It does so by calculating a SHA1 hash over certain parts of the
|
|
message and comparing it with the hash value that results from
|
|
decrypting the content of the Identity header field using the
|
|
certificate previously retrieved using the
|
|
<function>vrfy_get_certificate()</function> function.
|
|
</para>
|
|
<para>
|
|
The function returns <literal>true</literal> if the two hashes
|
|
match.
|
|
</para>
|
|
</refsect2>
|
|
|
|
<refsect2 xml:id="function.vrfy_get_certificate">
|
|
<title>
|
|
<function>vrfy_get_certificate</function>
|
|
()
|
|
</title>
|
|
<para>
|
|
Allowed in request processing only.
|
|
</para>
|
|
<para>
|
|
The <function>vrfy_get_certificate()</function> tries to get
|
|
the certificate from the URL given in the Identity-Info header
|
|
field of the currently processed request.
|
|
</para>
|
|
<para>
|
|
It returns <literal>true</literal> if the certifcate was
|
|
successfully loaded in a format that the module can process or
|
|
<literal>false</literal> otherwise.
|
|
</para>
|
|
</refsect2>
|
|
|
|
</refsect1>
|
|
|
|
|
|
<refsect1 xml:id="module.auth_identity.parameters">
|
|
<title>Module Parameters</title>
|
|
|
|
<refsect2 xml:id="module.auth_identity.accept_pem_certs">
|
|
<title><parameter>accept_pem_certs</parameter></title>
|
|
<serdoc:paraminfo>
|
|
<serdoc:paramtype>boolean</serdoc:paramtype>
|
|
<serdoc:paramdefault>no</serdoc:paramdefault>
|
|
</serdoc:paraminfo>
|
|
<para>
|
|
The <parameter>accept_pem_certs</parameter> parameter defines,
|
|
whether the verifier should process certificates in PEM format.
|
|
</para>
|
|
</refsect2>
|
|
|
|
<refsect2 xml:id="module.auth_identity.auth_validity_time">
|
|
<title><parameter>auth_validity_time</parameter></title>
|
|
<serdoc:paraminfo>
|
|
<serdoc:paramtype>integer</serdoc:paramtype>
|
|
<serdoc:paramdefault>3600</serdoc:paramdefault>
|
|
</serdoc:paraminfo>
|
|
<para>
|
|
The <parameter>auth_validity_time</parameter> parameter
|
|
sets the maximum age of a verified message.
|
|
</para>
|
|
</refsect2>
|
|
|
|
<refsect2 xml:id="module.auth_identity.cainfo_path">
|
|
<title><parameter>cainfo_path</parameter></title>
|
|
<serdoc:paraminfo>
|
|
<serdoc:paramtype>string</serdoc:paramtype>
|
|
<serdoc:paramdefault>""</serdoc:paramdefault>
|
|
</serdoc:paraminfo>
|
|
<para>
|
|
The <parameter>cainfo_path</parameter> paramter contains the
|
|
path and name of a file that contains trusted certificates.
|
|
</para>
|
|
<para>
|
|
The file should contain one or more certificates in PEM format
|
|
concatenated together. It is necessary if the verifier should
|
|
accept self-signed certifcates.
|
|
</para>
|
|
</refsect2>
|
|
|
|
<refsect2 xml:id="module.auth_identity.callid_cache_limit">
|
|
<title><parameter>callid_cache_limit</parameter></title>
|
|
<serdoc:paraminfo>
|
|
<serdoc:paramtype>integer</serdoc:paramtype>
|
|
<serdoc:paramdefault>262144</serdoc:paramdefault>
|
|
</serdoc:paraminfo>
|
|
<para>
|
|
The <parameter>callid_cache_limit</parameter> parameter
|
|
limits the number of entries in the Call-ID cache.
|
|
</para>
|
|
<para>
|
|
The Call-IDs of previously verified messages are stored in the
|
|
Call-ID cache for some time in order to recognize call
|
|
replay attacks. The cache uses shared memory. Each entry is
|
|
about 100 bytes in size.
|
|
</para>
|
|
</refsect2>
|
|
|
|
<refsect2 xml:id="module.auth_identity.certificate_cache_limit">
|
|
<title><parameter>certificate_cache_limit</parameter></title>
|
|
<serdoc:paraminfo>
|
|
<serdoc:paramtype>integer</serdoc:paramtype>
|
|
<serdoc:paramdefault>32768</serdoc:paramdefault>
|
|
</serdoc:paraminfo>
|
|
<para>
|
|
The <parameter>certificate_cache_limit</parameter> parameter
|
|
limits the number of entries stored in the certificate cache.
|
|
</para>
|
|
<para>
|
|
Each retrieved certificate is placed in the certificate cache
|
|
to speed up processing should it be needed again.
|
|
</para>
|
|
<para>
|
|
The cahce uses shared memory. Each entry is approximately 600
|
|
bytes in size.
|
|
</para>
|
|
</refsect2>
|
|
|
|
<refsect2 xml:id="module.auth_identity.certificate_path">
|
|
<title><parameter>certificate_path</parameter></title>
|
|
<serdoc:paraminfo>
|
|
<serdoc:paramtype>string</serdoc:paramtype>
|
|
<serdoc:paramdefault>""</serdoc:paramdefault>
|
|
</serdoc:paraminfo>
|
|
<para>
|
|
The <parameter>certificate_path</parameter> parameter must be
|
|
set to path and name of the file that contains the certificate
|
|
of the authentication service in PEM format.
|
|
</para>
|
|
<para>
|
|
The parameter is required for the authentication service to work.
|
|
</para>
|
|
</refsect2>
|
|
|
|
<refsect2 xml:id="module.auth_identity.certificate_url">
|
|
<title><parameter>certificate_url</parameter></title>
|
|
<serdoc:paraminfo>
|
|
<serdoc:paramtype>string</serdoc:paramtype>
|
|
<serdoc:paramdefault>""</serdoc:paramdefault>
|
|
</serdoc:paraminfo>
|
|
<para>
|
|
The <parameter>certificate_url</parameter> parameter must be
|
|
set to the URL where a verifier can retrieve the certificate.
|
|
The URL will be stored in the Identity-Info header of any
|
|
authorized request.
|
|
</para>
|
|
<para>
|
|
The certificate must be available at the given URL in DER
|
|
format.
|
|
</para>
|
|
<para>
|
|
The parameter is required for the authentication service to work.
|
|
</para>
|
|
</refsect2>
|
|
|
|
<refsect2 xml:id="module.auth_identity.msg_timeout">
|
|
<title><parameter>msg_timeout</parameter></title>
|
|
<serdoc:paraminfo>
|
|
<serdoc:paramtype>int</serdoc:paramtype>
|
|
<serdoc:paramdefault>600</serdoc:paramdefault>
|
|
</serdoc:paraminfo>
|
|
<para>
|
|
The <parameter>msg_timeout</parameter> parameter contains the
|
|
maximum age of a request to be authorized in seconds.
|
|
</para>
|
|
<para>
|
|
The authorizer will compare the time given in the Date header field
|
|
of the request with its own current time.
|
|
</para>
|
|
</refsect2>
|
|
|
|
<refsect2 xml:id="module.auth_identity.privatekey_path">
|
|
<title><parameter>privatekey_path</parameter></title>
|
|
<serdoc:paraminfo>
|
|
<serdoc:paramtype>string</serdoc:paramtype>
|
|
<serdoc:paramdefault>""</serdoc:paramdefault>
|
|
</serdoc:paraminfo>
|
|
<para>
|
|
The <parameter>privatekey_path</parameter> must be set to the paht
|
|
and name of the file that contains the private key of the
|
|
authentication service in PEM format.
|
|
</para>
|
|
<para>
|
|
The parameter is required for the authentication service to work.
|
|
</para>
|
|
</refsect2>
|
|
|
|
</refsect1>
|
|
|
|
<refsect1 id="modules.auth_identity.examples">
|
|
<title>Examples</title>
|
|
<para>
|
|
The <emphasis>authentifier</emphasis> is typically included in the
|
|
part of the routing
|
|
logic that sends a request to a foreign domain. In the
|
|
<filename>ser-oob.cfg</filename> configuration, this is the
|
|
<varname>route[OUTBOUND]</varname>. With an authentifier included,
|
|
it looks like this:
|
|
</para>
|
|
<programlisting><![CDATA[
|
|
route[OUTBOUND]
|
|
{
|
|
if ($f.did && !$t.did) {
|
|
# Authentication service
|
|
if (method=="INVITE" || method=="OPTION") {
|
|
# Identity and Identity-info headers must not exist
|
|
if (@identity) {
|
|
sl_reply("403", "Invalid Identity header");
|
|
drop;
|
|
}
|
|
if (@identity_info) {
|
|
sl_reply("403", "Invalid Identity-info header");
|
|
drop;
|
|
}
|
|
|
|
if (!auth_date_proc()) {
|
|
sl_reply("403", "Invalid Date value");
|
|
drop;
|
|
}
|
|
|
|
if (!auth_add_identity()) {
|
|
sl_reply("480", "Authentication error");
|
|
drop;
|
|
}
|
|
}
|
|
route(FORWARD);
|
|
}
|
|
}
|
|
]]></programlisting>
|
|
<para>
|
|
The <emphasis>verifier</emphasis> should be run after you discovered
|
|
that a request originates from a foreign domain (for your own domains,
|
|
you should be doing digest authentication instead).
|
|
</para>
|
|
<para>
|
|
While you should reject any request that does contain an Identity
|
|
header but does not verify, it is up to your local policy, what to
|
|
do with messages that do not contain an Identity header at all.
|
|
You could reject them or divert them to voice mail or any of a number
|
|
of other options.
|
|
</para>
|
|
<para>
|
|
The following config snippet rejects any message that does not have
|
|
an Identity header.
|
|
</para>
|
|
<programlisting><![CDATA[
|
|
if (method=="INVITE" || method=="OPTIONS") {
|
|
if (!@identity) {
|
|
sl_reply("428", "Use Identity Header");
|
|
drop;
|
|
}
|
|
if (!@identity_info) {
|
|
sl_reply("436", "Bad Identity-Info");
|
|
drop;
|
|
}
|
|
|
|
if (!vrfy_check_date()) {
|
|
sl_reply("403", "Outdated Date header value");
|
|
drop;
|
|
}
|
|
|
|
if (!vrfy_get_certificate()) {
|
|
sl_reply("436", "Bad Identity-Info");
|
|
drop;
|
|
}
|
|
|
|
if (!vrfy_check_certificate()) {
|
|
sl_reply("437", "Unsupported Certificate");
|
|
drop;
|
|
}
|
|
|
|
if (!vrfy_check_msgvalidity()) {
|
|
sl_reply("438", "Invalid Identity Header");
|
|
drop;
|
|
}
|
|
|
|
if (!vrfy_check_callid()) {
|
|
sl_reply("403", "Message is replayed");
|
|
drop;
|
|
}
|
|
}
|
|
]]></programlisting>
|
|
</refsect1>
|
|
|
|
<refsect1 id="mdoule.auth_identity.how-it-works">
|
|
<title>The SIP Identity Mechanism</title>
|
|
<para>
|
|
The SIP Identity Mechanism is defined in RFC 4474 "Enhancements for
|
|
Authenticated Identity Management in the Session Initiation Protocol
|
|
(SIP)". Its main purpose is to affirm the identity of the originator
|
|
of a request as stated in the From header field of the request.
|
|
While basic SIP provides a mechanism for a user agent to proof its
|
|
authenticity to the proxy serving the domain of the address used
|
|
by the user agent, no such mechanism exists to proof the authenticity
|
|
to other proxies or end points. The SIP Identity Mechanism mends this
|
|
oversight.
|
|
</para>
|
|
<para>
|
|
The mechanism allows a proxy to cryptographically sign a message as
|
|
authentic before sending it to another proxy. It does so after
|
|
making sure the sender actually is who he claims and is allowed to
|
|
use the address in the context of the message.
|
|
</para>
|
|
<para>
|
|
If the proxy is satisfied, it creates two header fields: Identity and
|
|
Identity-Info. The Identity header field contains a signed hash over
|
|
the following components of the message:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
the address given in the From header field,
|
|
</listitem>
|
|
<listitem>
|
|
the address given in the To header field,
|
|
</listitem>
|
|
<listitem>
|
|
the Call-ID,
|
|
</listitem>
|
|
<listitem>
|
|
the content of the CSeq header field,
|
|
</listitem>
|
|
<listitem>
|
|
the content of the Date header field,
|
|
</listitem>
|
|
<listitem>
|
|
the address given in the Contact header field if present, and
|
|
</listitem>
|
|
<listitem>
|
|
the body of the message.
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
The hash is signed with a certificate for the domain. A URL pointing
|
|
to a place where an interested party can download a copy of the
|
|
certificate is placed into the Identity-Info header field.
|
|
</para>
|
|
<para>
|
|
If the message arrives at a proxy or user agent that wishes to verify
|
|
the authenticity, this device downloads the certificate and itself
|
|
forms the hash over the above components. If both hashes match, the
|
|
message has been authenticated by the proxy of the domain of the
|
|
certificate and has not been tempered with on the way.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1 id="modules.auth_identity.credentials">
|
|
<title>Certificates</title>
|
|
<para>
|
|
In order to use the <command>auth_identity</command> module, you need a
|
|
certificate for your domain. There is two options, how to get one: you
|
|
buy one from a certification authority or you create your own
|
|
certification authority and use a self-signed certificate. If you plan
|
|
to provide real inter-domain calls for your domain, you should pick the
|
|
first option. Although it is more expensive, it guarantees proper
|
|
interaction between domains.
|
|
</para>
|
|
<para>
|
|
Either way, you will end up with a private key and a certificate which
|
|
includes the public key for that private key. You can use the same key
|
|
and certificate as for the TLS encrypted SIP transport. Because of
|
|
this, details on the process of acquiring them can be found in
|
|
<serdoc:module>tls</serdoc:module>.
|
|
</para>
|
|
<para>
|
|
Once you have the certificate and private key, you set the module
|
|
parameter
|
|
<serdoc:modparam module="auth_identity">certificate_path</serdoc:modparam>
|
|
to point to the file containing the certificate and
|
|
<serdoc:modparam module="auth_identity">privatekey_path</serdoc:modparam>
|
|
to point to the file with the private key.
|
|
</para>
|
|
<para>
|
|
Finally, you have to put a public version of your certificate onto
|
|
a web server somewhere. This version must be DER encoded and,
|
|
obviously, must not contain the private key. You can create this
|
|
by issuing
|
|
</para>
|
|
<programlisting><![CDATA[
|
|
# openssl x509 -in your_certificate.crt -outform der -out your_certificate.der
|
|
]]></programlisting>
|
|
<para>
|
|
You then place the DER encoded certificate into a publicly
|
|
available directory on your webserver and state the URL to the
|
|
file in the parameter
|
|
<serdoc:modparam module="auth_identity">certificate_url</serdoc:modparam>.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<!--
|
|
Compilation sections only go into the Admin Guide since we assume
|
|
that if you read a manpage you already have installed the module.
|
|
-->
|
|
<refsect1 role="admin-guide">
|
|
<title>Compilation</title>
|
|
<para>
|
|
This <command>auth_identity</command> module needs the following
|
|
headers and libraries:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<emphasis>OpenSSL</emphasis> (version 0.9.8 or higher) for
|
|
cryptographic functions,
|
|
</listitem>
|
|
<listitem>
|
|
<emphasis>libcURL</emphasis> for HTTP, HTTPS functions.
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
If you'd like to use the <emphasis>TLS</emphasis> module, too,
|
|
you will have to change <varname>LIB</varname> variable in the
|
|
Makefile to the value that is by default commented out.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Known Limitations</title>
|
|
<para>
|
|
Both authorizer and verifier currently only support SIP requests
|
|
except for responses to CANCEL and REGISTER requests.
|
|
</para>
|
|
<para>
|
|
The verifier does not support the subjectAltName extension of
|
|
certificates.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1 role="manpage">
|
|
<title>Authors</title>
|
|
<para>
|
|
Written by Gergely Kovacs and Martin Hoffmann.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1 role="manpage">
|
|
<title>See Also</title>
|
|
<simplelist type="inline">
|
|
<member><serdoc:sbin>ser</serdoc:sbin></member>
|
|
<member><serdoc:file>ser.cfg</serdoc:file></member>
|
|
</simplelist>
|
|
</refsect1>
|
|
|
|
</refentry>
|
|
|
|
<!-- vim:sw=2 sta et sts=2 ai
|
|
-->
|