The Auth Module

Jan Janak

   FhG Fokus
   <jan@iptel.org>

Juha Heinanen

   TutPro Inc
   <jh@song.fi>

Daniel-Constantin Mierla

   asipto.com
   <miconda@gmail.com>

   Copyright © 2002, 2003 FhG FOKUS
     __________________________________________________________________

   Table of Contents

   1. Admin Guide

        1. Overview
        2. Dependencies
        3. Parameters

              3.1. auth_checks_register (flags)
              3.2. auth_checks_no_dlg (flags)
              3.3. auth_checks_in_dlg (flags)
              3.4. qop (string)
              3.5. nonce_count (boolean)
              3.6. one_time_nonce (boolean)
              3.7. nid_pool_no (integer)
              3.8. nc_array_size (integer)
              3.9. nc_array_order (integer)
              3.10. otn_in_flight_no (integer)
              3.11. otn_in_flight_order (integer)
              3.12. secret (string)
              3.13. nonce_expire (integer)
              3.14. nonce_auth_max_drift (integer)
              3.15. force_stateless_reply (boolean)
              3.16. realm_prefix (string)
              3.17. use_domain (boolean)
              3.18. algorithm (string)
              3.19. add_authinfo_hdr (boolean)

        4. Functions

              4.1. consume_credentials()
              4.2. has_credentials(realm)
              4.3. www_challenge(realm, flags)
              4.4. proxy_challenge(realm, flags)
              4.5. auth_challenge(realm, flags)
              4.6. pv_www_authenticate(realm, passwd, flags [, method])
              4.7. pv_proxy_authenticate(realm, passwd, flags)
              4.8. pv_auth_check(realm, passwd, flags, checks)
              4.9. auth_get_www_authenticate(realm, flags, pvdest)
              4.10. auth_algorithm(algorithm)

   List of Examples

   1.1. Setting the auth_checks_register module parameter
   1.2. qop example
   1.3. nonce_count example
   1.4. one_time_nonce example
   1.5. nid_pool_no example
   1.6. nc_array_size example
   1.7. nc_array_order example
   1.8. otn_in_flight_no example
   1.9. otn_in_flight_order example
   1.10. Setting secret module parameter
   1.11. nonce_expire example
   1.12. nonce_auth_max_drift example
   1.13. force_stateless_reply example
   1.14. realm_prefix parameter example
   1.15. force_stateless_reply example
   1.16. algorithm example
   1.17. add Authentication-Info header example
   1.18. consume_credentials example
   1.19. consume_credentials example
   1.20. www_challenge usage
   1.21. proxy_challenge usage
   1.22. auth_challenge usage
   1.23. pv_www_authenticate usage
   1.24. pv_proxy_authenticate usage
   1.25. pv_auth_check usage
   1.26. auth_get_www_authenticate usage
   1.27. auth_algorithm example

Chapter 1. Admin Guide

   Table of Contents

   1. Overview
   2. Dependencies
   3. Parameters

        3.1. auth_checks_register (flags)
        3.2. auth_checks_no_dlg (flags)
        3.3. auth_checks_in_dlg (flags)
        3.4. qop (string)
        3.5. nonce_count (boolean)
        3.6. one_time_nonce (boolean)
        3.7. nid_pool_no (integer)
        3.8. nc_array_size (integer)
        3.9. nc_array_order (integer)
        3.10. otn_in_flight_no (integer)
        3.11. otn_in_flight_order (integer)
        3.12. secret (string)
        3.13. nonce_expire (integer)
        3.14. nonce_auth_max_drift (integer)
        3.15. force_stateless_reply (boolean)
        3.16. realm_prefix (string)
        3.17. use_domain (boolean)
        3.18. algorithm (string)
        3.19. add_authinfo_hdr (boolean)

   4. Functions

        4.1. consume_credentials()
        4.2. has_credentials(realm)
        4.3. www_challenge(realm, flags)
        4.4. proxy_challenge(realm, flags)
        4.5. auth_challenge(realm, flags)
        4.6. pv_www_authenticate(realm, passwd, flags [, method])
        4.7. pv_proxy_authenticate(realm, passwd, flags)
        4.8. pv_auth_check(realm, passwd, flags, checks)
        4.9. auth_get_www_authenticate(realm, flags, pvdest)
        4.10. auth_algorithm(algorithm)

1. Overview

   This is a generic module that itself doesn't provide all functions
   necessary for authentication but provides functions that are needed by
   all other authentication related modules (so called authentication
   backends).

   We decided to divide the authentication code into several modules
   because there are now more than one backends (currently database
   authentication and radius are supported). This allows us to create
   separate packages so users can install and load only the required
   functionality. This also allows us to avoid unnecessary dependencies in
   the binary packages.

2. Dependencies

   The following modules must be loaded before this module:
     * sl - stateless reply.

3. Parameters

   3.1. auth_checks_register (flags)
   3.2. auth_checks_no_dlg (flags)
   3.3. auth_checks_in_dlg (flags)
   3.4. qop (string)
   3.5. nonce_count (boolean)
   3.6. one_time_nonce (boolean)
   3.7. nid_pool_no (integer)
   3.8. nc_array_size (integer)
   3.9. nc_array_order (integer)
   3.10. otn_in_flight_no (integer)
   3.11. otn_in_flight_order (integer)
   3.12. secret (string)
   3.13. nonce_expire (integer)
   3.14. nonce_auth_max_drift (integer)
   3.15. force_stateless_reply (boolean)
   3.16. realm_prefix (string)
   3.17. use_domain (boolean)
   3.18. algorithm (string)
   3.19. add_authinfo_hdr (boolean)

3.1. auth_checks_register (flags)

   See description of parameter auth_checks_in_dlg.

3.2. auth_checks_no_dlg (flags)

   See description of parameter auth_checks_in_dlg.

3.3. auth_checks_in_dlg (flags)

   These three module parameters control which optional integrity checks
   will be performed on the SIP message carrying digest response during
   SIP MD5 digest authentication. auth_checks_register controls integrity
   checks to be performed on REGISTER messages, auth_checks_no_dlg
   controls which optional integrity checks will be performed on SIP
   requests that have no To header field or no To tag (in other words the
   requests either establishing or outside dialogs). auth_checks_in_dlg
   controls which integrity checks will be performed on SIP requests
   within dialogs, such as BYE or re-INVITE. The default value for all
   three parameters is 0 (old behaviour, no extra checks). The set of
   integrity checks that can be performed on REGISTERs is typically
   different from sets of integrity checks that can be performed for other
   SIP request types, hence we have three independent module parameters.

   Without the extra checks the nonce will protect only against expired
   values. Some reply attacks are still possible in the expire "window". A
   possible workaround is to always force qop authentication and always
   check the uri from the authorization header, but this would not work if
   an upstream proxy rewrites the uri and it will also not work with a lot
   of UA implementations.

   In this case the nonce value will be used only to hold the expire time
   (see nonce_expire) and an MD5 over it and some secret (the MD5 is used
   to make sure that nobody tampers with the nonce expire time).

   When the extra checks are enabled, the nonce will include an extra MD5
   over the selected part/parts of the message (see below) and some other
   secret. This will be used to check if the selected part of the message
   is the same when an UA tries to reuse the nonce, thus protecting or
   severely limiting reply attacks.

   The possible flag values for all three parameters are:
     * 1 for checking if the message URI changed (uses the whole URI)
     * 2 for checking the callid
     * 4 for checking the From tag
     * 8 for checking the source IP address (see nonce.h).

   As an example setting auth_checks_register to 3 would check if the
   callid or the request uri changed from the REGISTER message for which
   the original nonce was generated (this would allow nonce reuse only
   within the same UA and for the expire time). Note that enabling the
   extra checks will limit nonce caching by UAs, requiring extra
   challenges and roundtrips, but will provide much better protection.

Warning

   Do not enable the from tag check (4) for REGISTERs
   (auth_checks_register) and out-of-dialog messages (auth_checks_no_dlg)
   unless you are sure that all your user agents do not change the from
   tag when challenged. Some user agents will also change the callid when
   the challenged request is not in-dialog, so avoid enabling the callid
   check (2) for messages that are not part of a dialog
   (auth_checks_no_dlg). In some rare case this will also have to be done
   for REGISTERs.

   When the secret parameter is set and the extra checks are enabled, the
   first half of the secret will be used for the expire time MD5 and the
   other half for the extra checks MD5, so make sure you have a long
   secret (32 chars or longer are recommended).

   Example 1.1. Setting the auth_checks_register module parameter
...
# For REGISTER requests we hash the Request-URI, Call-ID, and source IP of the
# request into the nonce string. This ensures that the generated credentials
# cannot be used with another registrar, user agent with another source IP
# address or Call-ID. Note that user agents that change Call-ID with every
# REGISTER message will not be able to register if you enable this.
modparam("auth", "auth_checks_register", 11)

# For dialog-establishing requests (such as the original INVITE, OPTIONS, etc)
# we hash the Request-URI and source IP. Hashing Call-ID and From tags takes
# some extra precaution, because these checks could render some UA unusable.
modparam("auth", "auth_checks_no_dlg", 9)

# For mid-dialog requests, such as re-INVITE, we can hash source IP and
# Request-URI just like in the previous case. In addition to that we can hash
# Call-ID and From tag because these are fixed within a dialog and are
# guaranteed not to change. This settings effectively restrict the usage of
# generated credentials to a single user agent within a single dialog.
modparam("auth", "auth_checks_in_dlg", 15)

...

3.4. qop (string)

   If set, enable qop for challenges: each challenge will include a qop
   parameter. This is the recommended way, but some older non rfc3261
   compliant UAs might get confused and might not authenticate properly if
   qop is enabled.

   Enabling qop together with nonce_count will provide extra-security
   (protection against replay attacks) while still allowing credentials
   caching at the UA side and thus not compromising performance.

   The possible values are: "auth", "auth-int" and "" (unset).

   The default value is not-set ("").

   See also: nonce_count.

   Example 1.2. qop example
...
modparam("auth", "qop", "auth")   # set qop=auth
...

3.5. nonce_count (boolean)

   If enabled the received nc value is remembered and checked against the
   older value (for a successful authentication the received nc must be
   greater than the previously received one, see rfc2617 for more
   details). This will provide protection against replay attacks while
   still allowing credentials caching at the UA side.

   It depends on qop being enabled (if qop is not enabled, the challenges
   won't include qop and so the UA will probably not include the qop or nc
   parameters in its response).

   If a response doesn't include qop or nc (for example obsolete UAs that
   don't support them) the response will be checked according to the other
   enabled nonce checks, in this order: one_time_nonce and auth_checks_*.
   If a response includes nc only the normal nonce_expire checks and the
   nonce_count checks will be performed, all the other checks will be
   ignored.

   The nonce_count checks work by tracking a limited number of nonces. The
   maximum number of tracked nonces is set using the nc_array_size or
   nc_array_order parameters. If this number is exceeded, older entries
   will be overwritten. As long as the maximum rate of challengeable
   messages per average response time is lower than nc_array_size, the
   nonce_count checks should work flawlessly. For optimum performance
   (maximum reuse of cache credentials) nc_array_size divided by
   nid_pool_no should be lower than the message rate multiplied by the
   desired nonce_expire.

   The maximum accepted nc value is 255. If nc becomes greater than this,
   the nonce will be considered stale and the UA will be re-challenged.

   Note: nonce_count should be enabled only in stateful mode (a
   transaction should be created prior to the authentication check to
   absorb possible retransmissions and all the replies should be sent
   statefully, using t_reply()). If nonce_count and the authentication
   checks are used in the stateless mode then all retransmissions will be
   challenged.

   The default value is 0 (off).

   See also: qop, nc_array_size, nc_array_order, nid_pool_no,
   nonce_expire. one_time_nonce.

   Example 1.3. nonce_count example
...
modparam("auth", "nonce_count", 1) # enable nonce_count support
modparam("auth", "qop", "auth")    # enable qop=auth

....
route{
...
        # go stateful and catch retransmissions
        if (!t_newtran()) {
            xlog("L_NOTICE", "Failed to create new transaction\n");
            drop;
        };
        if (method=="REGISTER"){
                if (!www_authenticate("test", "credentials")){
                        # reply must be sent with t_reply because the
                        # transaction is already created at this point
                        # (we are in "stateful" mode)
                        if ($? == -2){
                                t_reply("500", "Internal Server Error");
                        }else if ($? == -3){
                                t_reply("400", "Bad Request");
                        }else{
                                if ($digest_challenge)
                                        append_to_reply("%$digest_challenge");
                                t_reply("401", "Unauthorized");
                        }
                        drop;
                }
                if (!save_noreply("location")) {
                        t_reply("400", "Invalid REGISTER Request");
                        drop;
                }
                append_to_reply("%$contact");
                t_reply("$code", "$reason"); # no %, avps are used directly
                drop;
        }else{
                if (!proxy_authenticate("my_realm", "credentials")){
                        if ($? == -2){
                                t_reply("500", "Internal Server Error");
                        }else if ($? == -3){
                                t_reply("400", "Bad Request");
                        }else{
                                if ($digest_challenge)
                                        append_to_reply("%$digest_challenge");
                                t_reply("401", "Unauthorized");
                        }
                        drop;
                }
        }
...

3.6. one_time_nonce (boolean)

   If set to 1 nonce reuse is disabled: each nonce is allowed only once,
   in the first response to a challenge. All the messages will be
   challenged, even retransmissions. Stateful mode should be used, to
   catch retransmissions before the authentication checks (using
   t_newtran() before the authentication checks and sending all the
   replies with t_reply()).

   one_time_nonce provides enhanced replay protections at the cost of
   invalidating UA side credentials caching, challenging every message
   (and thus generating extra messages and extra round-trips) and
   requiring stateful mode. In general qop and nonce_count should be
   prefered (if possible) with fallback to auth_checks_*. Due to the
   disadvantages listed above, one_time_nonce should be used only if the
   extra checks provided by auth_checks_register, auth_checks_no_dlg and
   auth_checks_in_dlg are deemed insufficient for a specific setup.

   Compared to nonce_count, one_time_nonce provides the same protection,
   but at a higher message cost. The only advantages are that it works
   with user agents that do not support qop and nc and that it uses less
   memory for the same supported number of maximum in-flight nonces (by a
   factor of 8). one_time_nonce can be used as fallback from nonce_count,
   when the UA doesn't support nc (it happens automatically when both of
   them are enabled).

   Like nonce_count, one_time_nonce works by tracking a limited number of
   nonces. The maximum number of tracked nonces is set using the
   otn_in_flight_no or otn_in_flight_order parameters. If this number is
   exceeded, older entries will be overwritten. As long as the maximum
   rate of challengeable messages per average response time is lower than
   otn_in_flight_no, the one_time_nonce checks should work flawlessly.

   The default value is 0 (off).

   See also: otn_in_flight_no, otn_in_flight_order, nid_pool_no and
   nonce_count.

   Example 1.4. one_time_nonce example
...
modparam("auth", "one_time_nonce", 1)
# Note: stateful mode should be used, see the nonce_count example
...

3.7. nid_pool_no (integer)

   Controls the number of partitions for the nonce_count and
   one_time_nonce arrays (it's common to both of them to reduce the nonce
   size).

   Instead of using single arrays for keeping nonce state, these arrays
   can be divided into more partitions. Each Kamailio process is assigned
   to one of these partitions, allowing for higher concurrency on
   multi-CPU machines. Besides increasing performance, increasing
   nid_pool_no has also a negative effect: it could decrease the maximum
   supported in-flight nonces in certain conditions. In the worst case,
   when only one Kamailio process receives most of the traffic (e.g. very
   busy tcp connection between two proxies), the in-flight nonces could be
   limited to the array size (nc_array_size for nonce_count or
   otn_in_flight_no for one_time_nonce) divided by the partitions number
   (nid_pool_no). However for normal traffic, when the process receiving a
   message is either random or chosen in a round-robin fashion the maximum
   in-flight nonces number will be very little influenced by nid_pool_no
   (the messages will be close to equally distributed to processes using
   different partitions).

   nid_pool_no value should be one of: 1, 2, 4, 8, 16, 32 or 64 (the
   maximum value is 64 and all values should be of the form 2^k or else
   they will be rounded down to 2^k).

   The default value is 1.

   See also: nonce_count, one_time_nonce, nc_array_size and
   otn_in_flight_no.

   Example 1.5. nid_pool_no example
...
modparam("auth", "nid_pool_no", 4)
...

3.8. nc_array_size (integer)

   Maximum number of in-flight nonces for nonce_count. It represents the
   maximum nonces for which state will be kept. When this number is
   exceeded, state for the older nonces will be discarded to make space
   for new ones (see nonce_count for more details).

   The value should be of the form 2^k. If it's not it will be rounded
   down to 2^k (for example a value of 1000000 will be rounded down to
   2^19=524288). nc_array_order can be used to directly specify the power
   of 2 (e.g. nc_array_order set to 20 is equivalent to nc_array_size set
   to 1048576).

   The memory used to keep the nonce state will be nc_array_size in bytes.

   The default value is 1048576 (1M in-flight nonces, using 1Mb memory).

   See also: nonce_count and nid_pool_no.

   Example 1.6. nc_array_size example
...
modparam("auth", "nc_array_size", 4194304)   # 4Mb
...

3.9. nc_array_order (integer)

   Equivalent to nc_array_size, but instead of directly specifying the
   size, its value is the power at which 2 should be raised
   (log2(nc_array_size)).

   nc_array_size = 2^nc_array_order. For more details see nc_array_size.

   The default value is 20 (1M in-flight nonces, using 1Mb memory).

   See also: nonce_count, nc_array_size and nid_pool_no.

   Example 1.7. nc_array_order example
...
modparam("auth", "nc_array_order", 22)   # 4Mb
...

3.10. otn_in_flight_no (integer)

   Maximum number of in-flight nonces for one_time_nonce. It represents
   the maximum number of nonces remembered for the one-time-nonce check.
   When this number is exceeded, information about older nonces will be
   discarded and overwritten with information about the new generated ones
   (see one_time_nonce for more details).

   The value should be of the form 2^k. If it's not it will be rounded
   down to 2^k (for example a value of 1000000 will be rounded down to
   2^19=524288). otn_in_flight_no can be used to directly specify the
   power of 2 (e.g. otn_in_flight_order set to 19 is equivalent to
   otn_in_fligh_number set to 524288).

   The memory used to keep the nonce information will be the
   otn_in_flight_no divided by 8 (only 1 bit of state is kept per nonce).

   The default value is 1048576 (1M in-flight nonces, using 128Kb memory).

   See also: one_time_nonce and nid_pool_no.

   Example 1.8. otn_in_flight_no example
...
modparam("auth", "otn_in_flight_no", 8388608)   # 8 Mb (1Mb memory)
...

3.11. otn_in_flight_order (integer)

   Equivalent to otn_in_flight_no, but instead of directly specifying the
   size, its value is the power at which 2 should be raised
   (log2(otn_in_flight_no)).

   otn_in_flight_no = 2^otn_in_flight_order. For more details see
   otn_in_flight_order.

   The default value is 20 (1M in-flight nonces, using 128Kb memory).

   See also: one_time_nonce, otn_in_flight_no and nid_pool_no.

   Example 1.9. otn_in_flight_order example
...
modparam("auth", "otn_in_flight_order", 23)   # 8 Mb (1Mb memory)
...

3.12. secret (string)

   Secret phrase used to calculate the nonce value used to challenge the
   client for authentication.

   If you use multiple servers in your installation, and would like to
   authenticate on the second server against the nonce generated at the
   first one, it is necessary to explicitly set the secret to the same
   value on all servers. However, as the use of a shared (and fixed)
   secret as nonce is insecure, it is much better is to stay with the
   default. Any clients should send the authenticated request to the
   server that issued the challenge.

   Default value is randomly generated string.

   Example 1.10. Setting secret module parameter
...
modparam("auth", "secret", "johndoessecretphrase")
...

3.13. nonce_expire (integer)

   Nonces have limited lifetime. After a given period of time nonces will
   be considered invalid. This is to protect replay attacks. Credentials
   containing a stale nonce will be not authorized, but the user agent
   will be challenged again. This time the challenge will contain stale
   parameter which will indicate to the client that it doesn't have to
   disturb user by asking for username and password, it can recalculate
   credentials using existing username and password.

   The value is in seconds and default value is 300 seconds.

   Example 1.11. nonce_expire example
...
modparam("auth", "nonce_expire", 600)   # Set nonce_expire to 600s
...

3.14. nonce_auth_max_drift (integer)

   Maximum difference in seconds between a nonce creation time and the
   current time, if the nonce creation time appears to be in the future.

   In some cases, like shortly after a system time backward adjustment or
   when the current proxy is part of a cluster which is not
   time-synchronized, it's possible to receive a nonce with creation time
   in the future. In this case if the difference is greater than
   nonce_auth_max_drift seconds, consider the nonce stale and re-challenge
   (otherwise after a dramatic time change backwards, it might happen that
   some previously generated nonces will be valid for too much time).

   The default value is 3 seconds

   See also: nonce_expire.

   Example 1.12. nonce_auth_max_drift example
...
modparam("auth", "nonce_auth_max_drift", 1)   # set max drift to 1 s
...

3.15. force_stateless_reply (boolean)

   If set to 1, www_challenge() and proxy_challenge() functions send reply
   statelessly no matter if transaction exists or not. If set to 0
   (default), reply is sent statefully if transaction exists and
   statelessly otherwise.

   Example 1.13. force_stateless_reply example
...
modparam("auth", "force_stateless_reply", 1)
...

3.16. realm_prefix (string)

   Prefix to be automatically stripped from the realm. As an alternative
   to SRV records (not all SIP clients support SRV lookup), a subdomain of
   the master domain can be defined for SIP purposes (like
   sip.mydomain.net pointing to same IP address as the SRV record for
   mydomain.net). By ignoring the realm_prefix “sip.”, at authentication,
   sip.example.com will be equivalent to example.com .

   Default value is empty string.

   Example 1.14. realm_prefix parameter example
modparam("auth", "realm_prefix", "sip.")

3.17. use_domain (boolean)

   If set to 1, pv_auth_check() uses domain parts of the URIs to check
   user identity.

   Example 1.15. force_stateless_reply example
...
modparam("auth", "use_domain", 1)
...

3.18. algorithm (string)

   Configure hash algorithm used for digest authentication. Possible
   values are "MD5", "SHA-256", "SHA-512" or "SHA-512-256". If left empty
   MD5 is used. If specified, the specified algorithm is used and is also
   put in the 'algorithm' field of the challenge header.

   Warning: SHA-256/512 hash values take twice or more the space of MD5
   hash values. So a buffer overflow might occur if this option is used in
   combination with another auth_* module that does not allocate at least
   enough (65 or 129) bytes to store hash values. SHA-256/512 can safely
   be used with the module auth_db as it allocates 256 bytes to store HA1
   values.

   Example 1.16. algorithm example
...
modparam("auth", "algorithm", "SHA-256")
...

3.19. add_authinfo_hdr (boolean)

   Should an Authentication-Info header be added on 200 OK responses? The
   Authentication-Info header offers mutual authentication. The server
   proves to the client that it knows the user's secret.

   The header also includes the next nonce which may be used by the client
   in a future request. If one_time_nonce is enabled, a new nonce is
   calculated for the next nonce. Otherwise the current nonce is used for
   the next nonce.

   The default value is 0 (no).

   Example 1.17. add Authentication-Info header example
...
modparam("auth", "add_authinfo_hdr", yes)
...

4. Functions

   4.1. consume_credentials()
   4.2. has_credentials(realm)
   4.3. www_challenge(realm, flags)
   4.4. proxy_challenge(realm, flags)
   4.5. auth_challenge(realm, flags)
   4.6. pv_www_authenticate(realm, passwd, flags [, method])
   4.7. pv_proxy_authenticate(realm, passwd, flags)
   4.8. pv_auth_check(realm, passwd, flags, checks)
   4.9. auth_get_www_authenticate(realm, flags, pvdest)
   4.10. auth_algorithm(algorithm)

4.1. consume_credentials()

   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 www_authorize,
   proxy_authorize, www_authenticate or proxy_authenticate.

   Example 1.18. consume_credentials example
...
if (www_authenticate("realm", "subscriber")) {
    consume_credentials();
}
...

4.2. has_credentials(realm)

   This function returns true if the request has Authorization or
   Proxy-Authorization header with provided realm. The parameter can be
   string with pseudo-variables.

   Example 1.19. consume_credentials example
...
if (has_credentials("myrealm")) {
    ...
}
...

4.3.  www_challenge(realm, flags)

   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.

   Meaning of the parameters is as follows:
     * realm - 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.
       It must not be empty string “”. 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).
       The string may contain pseudo variables.
     * flags - Value of this parameter can be a bitmask of following:
          + 1 - build challenge header with qop=auth
          + 2 - build challenge header with qop=auth-int
          + 4 - do not send '500 Internal Server Error' reply
            automatically in failure cases (error code is returned to
            config)
          + 16 - build challenge header with stale=true

   This function can be used from REQUEST_ROUTE.

   Example 1.20. www_challenge usage
...
if (!www_authenticate("$td", "subscriber")) {
        www_challenge("$td", "1");
        exit;
}
...

4.4.  proxy_challenge(realm, flags)

   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.

   Meaning of the parameters is the same as for function
   www_challenge(realm, flags)

   This function can be used from REQUEST_ROUTE.

   Example 1.21. proxy_challenge usage
...
if (!proxy_authenticate("$fd", "subscriber")) {
        proxy_challenge("$fd", "1");
        exit;
}
...

4.5.  auth_challenge(realm, flags)

   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.

   Meaning of the parameters the same as for function www_challenge(realm,
   flags)

   This function can be used from REQUEST_ROUTE.

   Example 1.22. auth_challenge usage
...
if (!auth_check("$fd", "subscriber", "1")) {
        auth_challenge("$fd", "1");
        exit;
}
...

4.6.  pv_www_authenticate(realm, passwd, flags [, method])

   The function verifies credentials according to RFC2617. 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 www_challenge which will challenge the user again.

   Negative codes may be interpreted as follows:
     * -1 (generic error) - some generic error occurred and no reply was
       sent out
     * -2 (invalid password) - wrong password
     * -4 (nonce expired) - the nonce has expired
     * -5 (no credentials) - request does not contain an Authorization
       header with the correct realm
     * -6 (nonce reused) - the nonce has already been used to authenticate
       a previous request

   Meaning of the parameters is as follows:
     * realm - 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.
       It must not be empty string “”. 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).
       The string may contain pseudo variables.
     * passwd - the password to be used for authentication. Can contain
       config variables. The Username is taken from Auth header.
     * flags - the value of this parameter can be a bitmask of following:
          + 1 - the value of password parameter is HA1 format
          + 2 - build challenge header with no qop and add it to avp
          + 4 - build challenge header with qop=auth and add it to avp
          + 8 - build challenge header with qop=auth-int and add it to avp
          + 16 - build challenge header with stale=true
          + 32 - don't invalidate nc on authentication failure
     * method - the method to be used for authentication. This parameter
       is optional and if not set is the first "word" on the request-line.

   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.

   This function can be used from REQUEST_ROUTE.

   Example 1.23. pv_www_authenticate usage
...
if (!pv_www_authenticate("$td", "123abc", "0")) {
        www_challenge("$td", "1");
        exit;
}
...

4.7.  pv_proxy_authenticate(realm, passwd, flags)

   The function verifies credentials according to RFC2617. 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 proxy_challenge which will challenge the user again. For more
   about the negative return codes, see the above function.

   Meaning of the parameters is the same as for pv_www_authenticate(realm,
   passwd, flags)

   This function can be used from REQUEST_ROUTE.

   Example 1.24. pv_proxy_authenticate usage
...
$avp(password)="xyz";
if (!pv_proxy_authenticate("$fd", "$avp(password)", "0")) {
        proxy_challenge("$fd", "1");
        exit;
}
...

4.8.  pv_auth_check(realm, passwd, flags, checks)

   The function combines the functionalities of pv_www_authenticate and
   pv_proxy_authenticate, first being executed if the SIP request is a
   REGISTER, the second for the rest.

   Meaning of the first three parameters is the same as for
   pv_www_authenticate(realm, passwd, flags).

   Parameter checks 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.

   The set of possible return codes is the same than
   pv_{www,proxy}_authenticate, with one more possible value:

   -8 (auth user mismatch) - the auth user is different than the From/To
   user

   This function can be used from REQUEST_ROUTE.

   Example 1.25. pv_auth_check usage
...
$avp(password)="xyz";
if (!pv_auth_check("$fd", "$avp(password)", "0", "1")) {
        auth_challenge("$fd", "1");
        exit;
}
...

4.9.  auth_get_www_authenticate(realm, flags, pvdest)

   Build WWW-Authentication header and set the resulting value in 'pvdest'
   pseudo-variable parameter.

   Meaning of the realm and flags parameters is the same as for
   pv_www_authenticate(realm, passwd, flags)

   This function can be used from ANY_ROUTE.

   Example 1.26. auth_get_www_authenticate usage
...
if (auth_get_www_authenticate("$fd", "0", "$var(wauth)")) {
        xlog("www authenticate header is [$var(wauth)]\n");
}
...

4.10. auth_algorithm(algorithm)

   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.

   Example 1.27. auth_algorithm example
...
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;
}
...
