Skip to content

Commit 63604ec

Browse files
committed
Add PJSIP Authentication configuration info
1 parent 0c14bb0 commit 63604ec

File tree

1 file changed

+265
-0
lines changed

1 file changed

+265
-0
lines changed
Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
# PJSIP Authentication
2+
3+
With the release of Asterisk 20.12.0, 21.7.0 and 22.2.0 and the associated release of PJProject 2.15.1, the chan_pjsip channel driver now supports the SHA-256 and SHA-512-256 authentication digest hash algorithms in addition to the base MD5 algorithm.
4+
5+
/// note | Supported Digest Hash Algorithms
6+
While the MD5 algorithm is universally supported, support for SHA-256 and SHA-512-256 is dependent on both the PJProject and OpenSSL versions installed on both the build and runtime systems. PJProject 2.15.1 (which is the version bundled with Asterisk 20.12.0, 21.7.0 and 22.2.0) is required to support both SHA algorithms. OpenSSL version > 1.0.0 is required to support SHA-256 and OpenSSL version >= 1.1.1 is required to support SHA-512-256.
7+
8+
On a running Asterisk system, you can execute the CLI command `pjproject show buildopts` to see the currently supported algorithms.
9+
///
10+
11+
## Authentication Process Refresher
12+
13+
We'll use 2 Asterisk systems as the UAS and UAC.
14+
15+
* When a PJSIP endpoint acting as a UAS receives a SIP request that requires authentication, Asterisk looks at the endpoint's `auth` parameter which should point to an auth object with the required credentials. It then creates one or more `WWW-Authenticate` headers containing the realm from the auth object, a nonce, and a digest hash algorithm name and sends them to the UAC in a 401 response. If more than one digest hash algorithm were supported, a header would be sent for each. Historically though, Asterisk only supported the MD5 algorithm so only one `WWW-Authenticate` header would be sent.
16+
17+
* The UAC receives the 401 response and looks for an auth object listed in the outgoing endpoint's `outbound_auth` parameter that has a realm that matches the realm in the response (or an object with no realm or a realm of `*`) and that can support the digest hash algorithm in the response. Again, only the MD5 algorithm was historically supported. It then constructs an `Authorization` header with, among other things, a `digest` parameter which contains the result of passing a string containing `<username>:<realm>:<password>` through the requested digest hash algorithm (the calculation is actually a bit more complicated than that but we don't need to worry about that here). The request is then retried with the `Authorization` header added.
18+
19+
* When the UAS receives the new request with the `Authorization` header, it constructs its own `<username>:<realm>:<password>` string using the values from its own auth object and passes that through the digest hash algorithm. If the resulting value matches the digest received in the `Authorzation` header, request processing continues. If not, another 401 response is sent.
20+
21+
Most of the time, passwords are specified in the configuration as plain-text. You can however also supply them "pre-hashed". This involves you manually passing a string composed of `<username>:<realm>:<password>` through a digest hash algorithm. For example:
22+
23+
```bash
24+
$ echo -n "myuser:asterisk:somepassword" | openssl dgst -md5
25+
MD5(stdin)= 1650345a24d9b5fdbc9c28e1f2321387
26+
```
27+
28+
The resulting value would then be used in the configuration. This is somewhat more secure because the password isn't stored in plain-text but if you're acting as a UAC, it requires that you know in advance the realm the UAS will be sending. See description for the [realm](#realm) parameter below for more information.
29+
30+
## Configuration Changes Required to Support the New Algorithms
31+
32+
Supporting more than one digest algorithm required changes to the PJSIP auth object configuration parameters. Some new ones were needed and some existing ones had to be changed (although they retain backwards compatibility).
33+
34+
### Changed Parameters
35+
36+
#### auth_type
37+
38+
* **Valid values**
39+
* **digest** - Standard [RFC 7616 HTTP/SIP digest authentication](https://datatracker.ietf.org/doc/html/rfc7616) whether using plain-text or pre-hashed passwords.
40+
* **google_oauth** - Google OAuth authentication used by Google Voice.
41+
* **Deprecated values**
42+
* **userpass** - This previously meant "plain-text password" but that is now determined automatically. If this value is used, it'll automatically be converted to "digest".
43+
* **md5** - This previously meant "pre-hashed MD5 password" but that is now also determined automatically. If this value is used, it'll automatically be converted to "digest".
44+
45+
#### md5_cred
46+
47+
Deprecated. Will be converted to a `password_digest` parameter with an MD5 digest hash algorithm. See [password_digest](#password_digest) below.
48+
49+
### Unchanged Parameters
50+
51+
#### realm
52+
53+
No change. For incoming authentication (Asterisk is the UAS), this is the realm to be sent on `WWW-Authenticate` headers. If not specified, the global object's `default_realm` will be used. `asterisk` is the final default if neither is specified.
54+
55+
For outgoing authentication (Asterisk is the UAC), this should be left empty, set to `*` or not specified at all unless you know the exact realm the UAS will be sending in the `WWW-Authenticate` headers.
56+
57+
/// warning | Realms & Using the same auth object for both UAS and UAC situations
58+
Although rare, some scenarios require that an endpoint configuration both send and respond to authentication challenges at the same time. In this case, you may be tempted to specify the same auth object in the endpoint's `auth` (UAS, send challenges (`WWW-Authenticate` headers) in a 401 SIP response) parameter and its `outbound_auth` (UAC, send challenge responses (`Authorization` headers) in a SIP request) parameter. This generally isn't good idea because when sending challenges as a UAS, you need to configure a specific realm in the auth object (or in the global `default_realm` parameter) to be placed in the `WWW-Authenticate` header. If you use this same auth object as a UAC however, it can only send challenge responses to a UAS that specified the same realm. Normally, when acting as a UAC, you'll want to leave the auth object's realm empty or set to `*` so it can be used to handle any realm sent by the remote UAS.
59+
60+
So, unless you know in advance the exact realm a UAS will send in challenges AND it's the same realm you want to use when you're sending challenges as a UAS, create two separate auth objects. for the endpoint.
61+
///
62+
63+
64+
#### username
65+
66+
No change. Username to use for account.
67+
68+
#### password
69+
70+
No change. A plain-text password.
71+
72+
#### nonce_lifetime
73+
74+
No change. Lifetime in seconds of a nonce associated with this authentication config (default: "32") See [RFC 7616](https://datatracker.ietf.org/doc/html/rfc7616) for more information on nonces.
75+
76+
#### refresh_token
77+
78+
No change. OAuth 2.0 refresh token
79+
80+
#### oauth_clientid
81+
82+
No change. OAuth 2.0 application's client id
83+
84+
#### oauth_secret
85+
86+
No change. OAuth 2.0 application's secret
87+
88+
### New Parameters
89+
90+
#### password_digest
91+
92+
This replaces the `md5_cred` parameter and provides the same capability of providing pre-hashed credentials for the SHA-256 and SHA-512-256 digest algorithms. The format is as follows:
93+
94+
```
95+
password_digest = <digest-spec>
96+
<digest_spec>: <digest-hash-algorithm>:<hashed-credential>
97+
<digest-hash-algorithm>: One of the 3 supported algorithms: MD5, SHA-256, SHA-512-256
98+
<hashed-credential>: The result of passing a string composed of <username>:<realm>:<password>
99+
through the algorithm.
100+
```
101+
102+
Examples:
103+
104+
```bash
105+
$ echo -n "myuser:somedomain:somepassword" | openssl dgst -md5
106+
MD5(stdin)= 1650345a24d9b5fdbc9c28e1f2321387
107+
# You'd then specify password_digest = MD5:1650345a24d9b5fdbc9c28e1f2321387
108+
109+
$ echo -n "myuser:somedomain:somepassword" | openssl dgst -SHA-256
110+
SHA2-256(stdin)= e8789f45d84aac27977eed41f3eec7572bb8ee81c6398715a04a51a7f9c68122
111+
# You'd then specify password_digest = SHA-256:e8789f45d84aac27977eed41f3eec7572bb8ee81c6398715a04a51a7f9c68122
112+
113+
$ echo -n "myuser:somedomain:somepassword" | openssl dgst -SHA512-256
114+
SHA2-512/256(stdin)= f8c3d34ce5ae6550740eaed0bff78a8aed354e87f2364813e4dbe9624bf06570
115+
# You'd then specify password_digest = SHA-512-256:f8c3d34ce5ae6550740eaed0bff78a8aed354e87f2364813e4dbe9624bf06570
116+
```
117+
118+
You can specify multiple `password_digest` parameters in an auth object but no more than one for each digest hash algorithm.
119+
120+
/// note | Line Endings
121+
Note that the examples show using the `-n` parameter in the `echo` command. This tells `echo` to not output any line endings after printing the string. This is important because you don't want those line endings included in the hash calculation.
122+
///
123+
124+
/// warning | Algorithm Names
125+
Asterisk uses the **case-insensitive** digest hash algorithm names as registered in the IANA by [RFC7616](https://datatracker.ietf.org/doc/html/rfc7616): `MD5`, `SHA-256`, `SHA-512-256` or their lower-case equivalents. OpenSSL digests aren't always referenced by the same names. For example, the IANA uses `SHA-512-256` but OpenSSL only recognizes `SHA512-256` (without the first dash) and `sha512-256` (without the first dash and lower case). Make sure you use the IANA names exactly as registered for all Asterisk configuration.
126+
///
127+
128+
#### supported_algorithms_uas
129+
130+
A comma-separated list of digest hash algorithm names to use when creating challenges in a 401 response. A separate `WWW-Authenticate` header will be added to the response for each algorithm, in the order specified. Order is important as, according to [RFC7616](https://datatracker.ietf.org/doc/html/rfc7616), the UAS _MUST_ order the `WWW-Authenticate` headers in order of most-preferred to least-preferred and the UAC _SHOULD_ respond to the first challenge it supports.
131+
132+
If this parameter isn't specified, the value of the global object's `default_auth_algorithms_uas` parameter will be used. `MD5` is the final default if neither is specified. This preserves backwards compatibility.
133+
134+
Example:
135+
136+
```
137+
supported_algorithms_uas = SHA-256, MD5
138+
```
139+
140+
#### supported_algorithms_uac
141+
142+
A comma-separated list of digest hash algorithm names to allow when creating an `Authorization` header for a request that previously failed with a 401 response. Only algorithms listed here will be considered for use so if the UAS responds with challenges for SHA-256 and SHA-512-256 and only MD5 is specified in this parameter, an `Authorization` header will not be created and the request will likely fail again. Order isn't important here as the UAS sets the preferred order.
143+
144+
If this parameter isn't specified, the value of the global object's `default_auth_algorithms_uac` parameter will be used. `MD5` is the final default if neither is specified. This preserves backwards compatibility.
145+
146+
Example:
147+
148+
```
149+
supported_algorithms_uac = SHA-256, MD5, SHA-512-256
150+
```
151+
152+
/// warning | Using `password` and `password_digest`
153+
Asterisk can only create challenges and challenge-responses if it has access to either the plain-text `password` parameter or a `password_digest` parameter that matches the digest hash algorithm desired. For instance, if your auth object only has a `password_digest` parameter for the MD5 algorithm and no plain-text `password` parameter but you specify `SHA-256` in either `supported_algorithms_uas` or `supported_algorithms_uac`, the configuration will fail to load and error messages will be printed. It's not possible for _any_ software to construct a valid hash for one algorithm using a hash created by another algorithm. You either have to provide a `password_digest` parameter that matches each algorithm listed in your `supported_algorithms_uas` and `supported_algorithms_uac` parameters OR provide a plain-text `password` parameter from which Asterisk can create the hash value. You _can_ provide both `password` and `password_digest` however. A matching `password_digest` will be preferred but if not found, the `password` will be used as a fallback.
154+
///
155+
156+
## Examples
157+
158+
### Typical Endpoint-to-Phone Scenario
159+
160+
```text
161+
[somephone-auth]
162+
type = auth
163+
auth_type = digest
164+
realm = myrealm
165+
username = myuser
166+
password = my-plain-text-password
167+
supported_algorithms_uas = SHA-256, MD5
168+
169+
[somephone]
170+
type = endpoint
171+
auth = somephone-auth
172+
```
173+
174+
In this example, the endpoint is configured as it would be to connect to a remote phone. When Asterisk needs to send a 401 response (to an incoming INVITE for example), it will create the response with two `WWW-Authenticate` headers, the first with SHA-256 as the digest algorithm and the second with MD5. The phone would then retry the request with a single `Authorization` header using the first of the two digest algorithms it supported.
175+
176+
### Alternate Endpoint-to-Phone Scenario
177+
178+
```text
179+
[somephone-auth]
180+
type = auth
181+
auth_type = digest
182+
realm = myrealm
183+
username = myuser
184+
password_digest = MD5:c3cffc6ef6f7c002a51d7f3fe2695ab4
185+
password_digest = SHA-256:c3cffc6ef6f7c002a51d7f3fe2695ab4
186+
password_digest = SHA-512-256:9468f16f3e37ac9c6e572e34533015e26d8b7b0b23a9f5953bd4be63a258ca60
187+
supported_algorithms_uas = SHA-256, SHA-512-256, MD5
188+
189+
[somephone]
190+
type = endpoint
191+
auth = somephone-auth
192+
```
193+
194+
In this example, the endpoint is configured as it would be to connect to a remote phone. When Asterisk needs to send a 401 response (to an incoming INVITE for example), it will create the response with three `WWW-Authenticate` headers, with the SHA-256, SHA-512-256 and MD5 digest algorithms in that order. The phone would then retry the request with a single `Authorization` header using the first of the three digest algorithms it supported. This keeps the plain-text password out of the configuration but it does require that the username and realm used when creating the pre-hashed credentials for the `password_digest` parameters be the exact same ones specified in the `username` and `realm` parameters in the auth object. The `realm` parameter in the auth object is used to set the `realm` parameter in the `WWW-Authenticate` header and that's what the phone will use when creating is's own digest to send back.
195+
196+
### Legacy Endpoint-to-Phone Scenario
197+
198+
```text
199+
[somephone-auth]
200+
type = auth
201+
auth_type = userpass
202+
realm = myrealm
203+
username = myuser
204+
password = my-plain-text-password
205+
206+
[somephone]
207+
type = endpoint
208+
auth = somephone-auth
209+
```
210+
211+
This scenario uses the legacy configuration parameters and is functionally equivalent to the [Typical Endpoint-to-Phone Scenario](#typical-endpoint-to-phone-scenario).
212+
213+
### Typical Endpoint-to-Provider Scenario
214+
215+
```text
216+
[someprovider-auth]
217+
type = auth
218+
auth_type = digest
219+
realm = * ; this is optional as the default for a UAC is '*' anyway.
220+
username = myuser
221+
password = my-plain-text-password
222+
supported_algorithms_uac = MD5
223+
224+
[myendpoint]
225+
type = endpoint
226+
outbound_auth = myauth
227+
```
228+
229+
In this example, the endpoint is configured as it would be to connect to a service provider that requires authentication. If the service provider responds to a request with a 401 that contains two `WWW-Authenticate` headers, the first with SHA-256 as the digest algorithm and the second with MD5, Asterisk would retry the request with an `Authorization` header for MD5 because even though the service provider preferred SHA-256, the auth object only supports MD5.
230+
231+
### Alternate Endpoint-to-Provider Scenario
232+
233+
```text
234+
[someprovider-auth]
235+
type = auth
236+
auth_type = digest
237+
realm = * ; this is optional as the default for a UAC is '*' anyway.
238+
username = myuser
239+
password_digest = MD5:c3cffc6ef6f7c002a51d7f3fe2695ab4
240+
password = my-plain-text-password
241+
supported_algorithms_uac = MD5, SHA-256
242+
243+
[myendpoint]
244+
type = endpoint
245+
outbound_auth = myauth
246+
```
247+
248+
In this example, the endpoint is configured as it would be to connect to a service provider that requires authentication. If the service provider responds to a request with a 401 that contains two `WWW-Authenticate` headers, the first with SHA-256 as the digest algorithm and the second with MD5, Asterisk would retry the request with an `Authorization` header for SHA-256 because it's the algorithm the service provider preferred and there's a plain-text password available that can be used to create the necessary digest. If the service provider had responded with MD5 first and SHA-256 second, Asterisk would have responded with MD5 using the pre-hashed credentials. HOWEVER!! For this to work, the Asterisk admin would have to know ahead of time the realm the service provider would specify in the `WWW-Authenticate` headers. You can't create a pre-hashed credential with an empty or wildcard `*` realm.
249+
250+
### Legacy Endpoint-to-Provider Scenario
251+
252+
```text
253+
[someprovider-auth]
254+
type = auth
255+
auth_type = md5
256+
realm = * ; this is optional as the default for a UAC is '*' anyway.
257+
username = myuser
258+
md5_cred = c3cffc6ef6f7c002a51d7f3fe2695ab4
259+
260+
[myendpoint]
261+
type = endpoint
262+
outbound_auth = myauth
263+
```
264+
265+
This scenario is _almost_ functionally equivalent to the [Alternate Endpoint-to-Provider Scenario](#alternate-endpoint-to-provider-scenario). While it supports MD5 pre-hased credentials, it can't support SHA-256 at all.

0 commit comments

Comments
 (0)