# Parameters

## `auth_checks_register` (flags)

See description of parameter `auth_checks_in_dlg`.

## `auth_checks_no_dlg` (flags)

See description of parameter `auth_checks_in_dlg`.

## `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.

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).

### 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)

    ...

## `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`.

### qop example

    ...
    modparam("auth", "qop", "auth")   # set qop=auth
    ...

## `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`.

### 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;
    		}
    	}
    ...

## `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`.

### one_time_nonce example

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

## `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`.

### nid_pool_no example

    ...
    modparam("auth", "nid_pool_no", 4)
    ...

## `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`.

### nc_array_size example

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

## `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`.

### nc_array_order example

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

## `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`.

### otn_in_flight_no example

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

## `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`.

### otn_in_flight_order example

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

## `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.

### Setting secret module parameter

    ...
    modparam("auth", "secret", "johndoessecretphrase")
    ...

## `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.

### nonce_expire example

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

## `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`.

### nonce_auth_max_drift example

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

## `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.

### force_stateless_reply example

    ...
    modparam("auth", "force_stateless_reply", 1)
    ...

## `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.

### realm_prefix parameter example

    modparam("auth", "realm_prefix", "sip.")

## `use_domain` (boolean)

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

### force_stateless_reply example

    ...
    modparam("auth", "use_domain", 1)
    ...

## `algorithm` (string)

Configure hash algorithm used for digest authentication. Possible values are "MD5" or "SHA-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 hash values take twice 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 65 bytes to store hash values. SHA-256 can safely be used with the module auth_db as it allocates 256 bytes to store HA1 values.

### use SHA-256 example

    ...
    modparam("auth", "algorithm", "SHA-256")
    ...

## `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).

### add Authentication-Info header example

    ...
    modparam("auth", "add_authinfo_hdr", yes)
    ...