<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [

<!-- Include general documentation entities -->
<!ENTITY % docentities SYSTEM "../../../../doc/docbook/entities.xml">
%docentities;

]>

<section id="auth.functions" xmlns:xi="http://www.w3.org/2001/XInclude">

    <title>Functions</title>

    <section id="auth.f.consume_credentials">
	<title><function>consume_credentials()</function></title>
	<para>
	    This function removes previously authorized credential headers from the
	    message being processed by the server. That means that the
	    downstream message will not contain credentials there were used by
	    this server. This ensures that the proxy will not reveal
	    information about credentials used to downstream elements and also
	    the message will be a little bit shorter. The function must be
	    called after <function>www_authorize</function>,
		<function>proxy_authorize</function>,
		<function>www_authenticate</function> or
	    <function>proxy_authenticate</function>.
	</para>
	<example>
	    <title>consume_credentials example</title>
	    <programlisting>
...
if (www_authenticate("realm", "subscriber")) {
    consume_credentials();
}
...
	    </programlisting>
	</example>
    </section>
    <section id="auth.f.has_credentials">
	<title><function>has_credentials(realm)</function></title>
	<para>
		This function returns true if the request has Authorization or
		Proxy-Authorization header with provided realm. The parameter
		can be string with pseudo-variables.
	</para>
	<example>
	    <title>consume_credentials example</title>
	    <programlisting>
...
if (has_credentials("myrealm")) {
    ...
}
...
	    </programlisting>
	</example>
    </section>
	<section id="auth.f.www_challenge">
		<title>
			<function moreinfo="none">www_challenge(realm, flags)</function>
		</title>
		<para>
		The function challenges a user agent. It will generate a
		WWW-Authorize header field containing a digest challenge, it will
		put the header field into a response generated from the request the
		server is processing and send the 401 reply. Upon reception of such a
		reply the user agent should compute credentials and retry the
		request. For more information regarding digest authentication
		see RFC2617. See module parameter force_stateless_reply
		regarding sending of the reply.
		</para>
		<para>Meaning of the parameters is as follows:</para>
		<itemizedlist>
		<listitem>
			<para><emphasis>realm</emphasis> - Realm is an opaque string that
			the user agent should present to the user so he can decide what
			username and password to use. Usually this is domain of the host
			the server is running on.
			</para>
			<para>
			It must not be empty string <quote></quote>. In case of REGISTER
			requests, the To header field domain (e.g., variable $td) can be used
			(because this header field represents the user being registered),
			for all other messages From header field domain can be used
			(e.g., variable $fd).
			</para>
			<para>
			The string may contain pseudo variables.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>flags</emphasis> - Value of this parameter can be
			a bitmask of following:</para>
			<itemizedlist>
			<listitem>
				<para><emphasis>1</emphasis> - build challenge header with
					qop=auth</para>
			</listitem>
			<listitem>
				<para><emphasis>2</emphasis> - build challenge header with
					qop=auth-int</para>
			</listitem>
			<listitem>
				<para><emphasis>4</emphasis> - do not send '500 Internal
					Server Error' reply automatically in failure cases
					(error code is returned to config)</para>
			</listitem>
			<listitem>
				<para><emphasis>16</emphasis> - build challenge header with
					stale=true</para>
			</listitem>
			</itemizedlist>
		</listitem>
		</itemizedlist>
		<para>
		This function can be used from REQUEST_ROUTE.
		</para>

		<example>
		<title>www_challenge usage</title>
		<programlisting format="linespecific">
...
if (!www_authenticate("$td", "subscriber")) {
	www_challenge("$td", "1");
	exit;
}
...
</programlisting>
		</example>
	</section>

	<section id="auth.f.proxy_challenge">
		<title>
			<function moreinfo="none">proxy_challenge(realm, flags)</function>
		</title>
		<para>
		The function challenges a user agent. It will generate a
		Proxy-Authorize header field containing a digest challenge, it will
		put the header field into a response generated from the request the
		server is processing and send the 407 reply. Upon reception of such a
		reply the user agent should compute credentials and retry the request.
		For more information regarding digest authentication see RFC2617.
		See module parameter force_stateless_reply regarding sending of the reply.
		</para>
		<para>Meaning of the parameters is the same as for function
		www_challenge(realm, flags)</para>
		<para>
		This function can be used from REQUEST_ROUTE.
		</para>
		<example>
		<title>proxy_challenge usage</title>
		<programlisting format="linespecific">
...
if (!proxy_authenticate("$fd", "subscriber")) {
	proxy_challenge("$fd", "1");
	exit;
}
...
</programlisting>
		</example>
	</section>

	<section id="auth.f.auth_challenge">
		<title>
			<function moreinfo="none">auth_challenge(realm, flags)</function>
		</title>
		<para>
		The function challenges a user agent for authentication. It combines
		the functions www_challenge() and proxy_challenge(), by calling
		internally the first one for REGISTER requests and the second one for
		the rest of other request types. In other words, it challenges for
		authentication by sending a 401 reply for REGISTER requests and 407
		reply for the other types of SIP requests.
		</para>
		<para>Meaning of the parameters the same as for function
		www_challenge(realm, flags)</para>
		<para>
		This function can be used from REQUEST_ROUTE.
		</para>
		<example>
		<title>auth_challenge usage</title>
		<programlisting format="linespecific">
...
if (!auth_check("$fd", "subscriber", "1")) {
	auth_challenge("$fd", "1");
	exit;
}
...
</programlisting>
		</example>
	</section>

	<section id="auth.f.pv_www_authenticate">
		<title>
		<function moreinfo="none">pv_www_authenticate(realm, passwd, flags [, method])</function>
		</title>
		<para>
		The function verifies credentials according to
		<ulink url="http://www.ietf.org/rfc/rfc2617.txt">RFC2617</ulink>.
		If the credentials are verified successfully then the function
		will succeed and mark the credentials as authorized (marked
		credentials can be later used by some other functions). If the
		function was unable to verify the credentials for some reason
		then it will fail and the script should
		call <function moreinfo="none">www_challenge</function> which will
		challenge the user again.
		</para>
		<para>Negative codes may be interpreted as follows:</para>
		<itemizedlist>
			<listitem><para>
			<emphasis>-1 (generic error)</emphasis> - some generic error
			occurred and no reply was sent out
			</para></listitem>
			<listitem><para>
			<emphasis>-2 (invalid password)</emphasis> - wrong password
			</para></listitem>
			<listitem><para>
			<emphasis>-4 (nonce expired)</emphasis> - the nonce has expired
			</para></listitem>
			<listitem><para>
			<emphasis>-5 (no credentials)</emphasis> - request does not contain
			an Authorization header with the correct realm
			</para></listitem>
			<listitem><para>
			<emphasis>-6 (nonce reused)</emphasis> - the nonce has already been
			used to authenticate a previous request
			</para></listitem>
		</itemizedlist>
		<para>Meaning of the parameters is as follows:</para>
		<itemizedlist>
		<listitem>
			<para><emphasis>realm</emphasis> - Realm is an opaque string that
			the user agent should present to the user so he can decide what
			username and password to use. Usually this is domain of the host
			the server is running on.
			</para>
			<para>
			It must not be empty string <quote></quote>. In case of REGISTER
			requests To header field domain (e.g., variable $td) can be used
			(because this header field represents a user being registered),
			for all other messages From header field domain can be used
			(e.g., variable $fd).
			</para>
			<para>
			The string may contain pseudo variables.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>passwd</emphasis> - the password to be used
			for authentication. Can contain config variables. The Username is
			taken from Auth header.</para>
		</listitem>
		<listitem>
			<para><emphasis>flags</emphasis> - the value of this parameter
				can be a bitmask of following:</para>
			<itemizedlist>
			<listitem>
				<para><emphasis>1</emphasis> - the value of password
					parameter is HA1 format</para>
			</listitem>
			<listitem>
				<para><emphasis>2</emphasis> - build challenge header with
					no qop and add it to avp</para>
			</listitem>
			<listitem>
				<para><emphasis>4</emphasis> - build challenge header with
					qop=auth and add it to avp</para>
			</listitem>
			<listitem>
				<para><emphasis>8</emphasis> - build challenge header with
					qop=auth-int and add it to avp</para>
			</listitem>
			<listitem>
				<para><emphasis>16</emphasis> - build challenge header with
					stale=true</para>
			</listitem>
			<listitem>
				<para><emphasis>32</emphasis> - don't invalidate nc on
					authentication failure</para>
			</listitem>

			</itemizedlist>
		</listitem>
		<listitem>
			<para><emphasis>method</emphasis> - the method to be used for
			authentication. This parameter is optional and if not set
			is the first "word" on the request-line.</para>
		</listitem>
		</itemizedlist>
		<para>
			When challenge header is built and stored in avp,
			append_to_reply() and the sl reply functions can be used to send
			appropriate SIP reply to challenge for authentication.
		</para>
		<para>
		This function can be used from REQUEST_ROUTE.
		</para>
		<example>
		<title><function moreinfo="none">pv_www_authenticate</function>
		usage</title>
		<programlisting format="linespecific">
...
if (!pv_www_authenticate("$td", "123abc", "0")) {
	www_challenge("$td", "1");
	exit;
}
...
</programlisting>
		</example>
	</section>

	<section id="auth.f.pv_proxy_authenticate">
		<title>
			<function moreinfo="none">pv_proxy_authenticate(realm, passwd, flags)</function>
		</title>
		<para>
		The function verifies credentials according to
		<ulink url="http://www.ietf.org/rfc/rfc2617.txt">RFC2617</ulink>. If
		the credentials are verified successfully then the function will
		succeed and mark the credentials as authorized (marked credentials can
		be later used by some other functions). If the function was unable to
		verify the credentials for some reason then it will fail and
		the script should call
		<function moreinfo="none">proxy_challenge</function> which will
		challenge the user again. For more about the negative return codes,
		see the above function.
		</para>
		<para>Meaning of the parameters is the same as for
		pv_www_authenticate(realm, passwd, flags)</para>
		<para>
		This function can be used from REQUEST_ROUTE.
		</para>
		<example>
		<title>pv_proxy_authenticate usage</title>
		<programlisting format="linespecific">
...
$avp(password)="xyz";
if (!pv_proxy_authenticate("$fd", "$avp(password)", "0")) {
	proxy_challenge("$fd", "1");
	exit;
}
...
</programlisting>
		</example>
	</section>

	<section id="auth.f.pv_auth_check">
		<title>
			<function moreinfo="none">pv_auth_check(realm, passwd, flags, checks)</function>
		</title>
		<para>
		The function combines the functionalities of
		<function moreinfo="none">pv_www_authenticate</function> and
		<function moreinfo="none">pv_proxy_authenticate</function>, first being
		executed if the SIP request is a REGISTER, the second for the rest.
		</para>
		<para>
		Meaning of the first three parameters is the same as for
		pv_www_authenticate(realm, passwd, flags).
		</para>
		<para>
		Parameter <emphasis>checks</emphasis> can be used to control the
		behaviour of the function. If it is 1, then the function will
		check to see if the authentication username matches either To or
		From header username, a matter of whether it is for a REGISTER
		request or not.	The parameter may be a pseudo variable.
		</para>
		<para>
		The set of possible return codes is the same than pv_{www,proxy}_authenticate, with
		one more possible value:
		    <para><emphasis>-8 (auth user mismatch)</emphasis> - the auth user is different
               than the From/To user
			</para>
		</para>
		<para>
		This function can be used from REQUEST_ROUTE.
		</para>
		<example>
		<title>pv_auth_check usage</title>
		<programlisting format="linespecific">
...
$avp(password)="xyz";
if (!pv_auth_check("$fd", "$avp(password)", "0", "1")) {
	auth_challenge("$fd", "1");
	exit;
}
...
</programlisting>
		</example>
	</section>

	<section id="auth.f.auth_get_www_authenticate">
		<title>
			<function moreinfo="none">auth_get_www_authenticate(realm, flags, pvdest)</function>
		</title>
		<para>
		Build WWW-Authentication header and set the resulting value in 'pvdest' pseudo-variable parameter.
		</para>
		<para>Meaning of the realm and flags parameters is the same as for
		pv_www_authenticate(realm, passwd, flags)</para>
		<para>
		This function can be used from ANY_ROUTE.
		</para>
		<example>
		<title>auth_get_www_authenticate usage</title>
		<programlisting format="linespecific">
...
if (auth_get_www_authenticate("$fd", "0", "$var(wauth)")) {
	xlog("www authenticate header is [$var(wauth)]\n");
}
...
</programlisting>
		</example>
	</section>
    <section id="auth.f.auth_algorithm">
	<title><function>auth_algorithm(algorithm)</function></title>
	<para>
	  Set hash algorithm used for digest authentication thus overriding
      algorithm parameter. Possible values are the same as those of
      algorithm parameter. The parameter may be a pseudo variable.
	</para>
	<example>
	    <title>auth_algorithm example</title>
	    <programlisting>
...
if($fU == "alice") {
    $var(alg) = "SHA-256";
} else {
    $var(alg) = "MD5";
}
auth_algorithm("$var(alg)");
if (!auth_check("$fd", "subscriber", "1")) {
    auth_challenge("$fd", "1");
    exit;
}
...
	    </programlisting>
	</example>
    </section>

</section>
