... | ... |
@@ -25,7 +25,7 @@ Gergely Kovacs |
25 | 25 |
5.6. callid_cache_limit (integer) |
26 | 26 |
5.7. certificate_cache_limit (integer) |
27 | 27 |
5.8. cainfo_path (string) |
28 |
- 5.9. accept_pem_certs ([0|1]) |
|
28 |
+ 5.9. accept_pem_certs (int) |
|
29 | 29 |
|
30 | 30 |
6. Functions |
31 | 31 |
|
... | ... |
@@ -91,7 +91,7 @@ Chapter 1. Admin Guide |
91 | 91 |
5.6. callid_cache_limit (integer) |
92 | 92 |
5.7. certificate_cache_limit (integer) |
93 | 93 |
5.8. cainfo_path (string) |
94 |
- 5.9. accept_pem_certs ([0|1]) |
|
94 |
+ 5.9. accept_pem_certs (int) |
|
95 | 95 |
|
96 | 96 |
6. Functions |
97 | 97 |
|
... | ... |
@@ -174,7 +174,7 @@ Chapter 1. Admin Guide |
174 | 174 |
5.6. callid_cache_limit (integer) |
175 | 175 |
5.7. certificate_cache_limit (integer) |
176 | 176 |
5.8. cainfo_path (string) |
177 |
- 5.9. accept_pem_certs ([0|1]) |
|
177 |
+ 5.9. accept_pem_certs (int) |
|
178 | 178 |
|
179 | 179 |
5.1. privatekey_path (string) |
180 | 180 |
|
... | ... |
@@ -296,11 +296,12 @@ modparam("auth_identity","certificate_cache_limit",4096) |
296 | 296 |
modparam("auth_identity","cainfo_path","/etc/ssl/certs/ca-certificates.crt") |
297 | 297 |
... |
298 | 298 |
|
299 |
-5.9. accept_pem_certs ([0|1]) |
|
299 |
+5.9. accept_pem_certs (int) |
|
300 | 300 |
|
301 | 301 |
Note: this parameter is for verifier service. |
302 | 302 |
|
303 | 303 |
Enables the acquired certificate processing if it is in PEM format. |
304 |
+ Value can be 0 or 1. |
|
304 | 305 |
|
305 | 306 |
This parameter is optional. The default value is "0". |
306 | 307 |
|
307 | 308 |
deleted file mode 100644 |
... | ... |
@@ -1,629 +0,0 @@ |
1 |
-<?xml version='1.0'?> |
|
2 |
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" |
|
3 |
- "http://www.oasis-open.org/docbookid/id/g/4.5/docbookx.dtd"> |
|
4 |
- |
|
5 |
- |
|
6 |
-<refentry xml:id="module.auth_identity" |
|
7 |
- xmlns:xi="http://www.w3.org/2001/XInclude" |
|
8 |
- xmlns:serdoc="http://sip-router.org/xml/serdoc"> |
|
9 |
- <refmeta> |
|
10 |
- <refentrytitle>auth_identity</refentrytitle> |
|
11 |
- <manvolnum>7</manvolnum> |
|
12 |
- </refmeta> |
|
13 |
- <refnamediv> |
|
14 |
- <refname>auth_identity</refname> |
|
15 |
- <refpurpose>Securely identify originator of SIP messages.</refpurpose> |
|
16 |
- </refnamediv> |
|
17 |
- |
|
18 |
- <refsect1> |
|
19 |
- <title>Description</title> |
|
20 |
- <para> |
|
21 |
- The <command>auth_identity</command> SER module provides |
|
22 |
- functionalities for securely identifying originators of SIP |
|
23 |
- messages by implementing the mechanism described in RFC 4474 |
|
24 |
- and known as SIP Identity framework. |
|
25 |
- </para> |
|
26 |
- <para> |
|
27 |
- The module provides two services: |
|
28 |
- The <emphasis>authorizer</emphasis> authorizes a message and adds |
|
29 |
- Identity and Identity-Info headers to forwarded requests. |
|
30 |
- The <emphasis>verifier</emphasis> verifies the identity of a |
|
31 |
- received message. |
|
32 |
- </para> |
|
33 |
- <para> |
|
34 |
- In order to use the <command>auth_identity</command> module you |
|
35 |
- have to provide a certificate. More information can be found in |
|
36 |
- the section |
|
37 |
- <serdoc:link linkend="module.auth_identity.certificates">Certificates |
|
38 |
- </serdoc:link> below. |
|
39 |
- </para> |
|
40 |
- </refsect1> |
|
41 |
- |
|
42 |
- <refsect1 xml:id="module.auth_identity.functions"> |
|
43 |
- <title>Functions</title> |
|
44 |
- |
|
45 |
- <refsect2 xml:id="function.auth_add_identity"> |
|
46 |
- <title> |
|
47 |
- <function>auth_add_identity</function> |
|
48 |
- () |
|
49 |
- </title> |
|
50 |
- <para> |
|
51 |
- Allowed in request processing only. |
|
52 |
- </para> |
|
53 |
- <para> |
|
54 |
- The <function>auth_add_identity()</function> function authorizes |
|
55 |
- a request by adding identity information to it. |
|
56 |
- </para> |
|
57 |
- <para> |
|
58 |
- It calculates a SHA1 hash over certain components of the message |
|
59 |
- and encrypts it using the private key given through the |
|
60 |
- <serdoc:modparam |
|
61 |
- module="auth_identity">privatekey_path</serdoc:modparam> |
|
62 |
- parameter. The resulting cyphertext is appended to the message |
|
63 |
- as the content of the Identity header field. |
|
64 |
- </para> |
|
65 |
- <para> |
|
66 |
- To allow the receiver to decypher the identity information, it adds |
|
67 |
- the URL where the receiver may find the certificate in the |
|
68 |
- Indentity-Info header field. This URL is set through the |
|
69 |
- <serdoc:modparam |
|
70 |
- module="auth_identity">certificate_url</serdoc:modparam> |
|
71 |
- parameter. |
|
72 |
- </para> |
|
73 |
- <para> |
|
74 |
- <emphasis>Note:</emphasis> After the function has been called, |
|
75 |
- the following header fields must not be modified: |
|
76 |
- From, To, Call-ID, CSeq, Date, Contact. Additionally, the |
|
77 |
- message body must remain unmodified, too. |
|
78 |
- </para> |
|
79 |
- </refsect2> |
|
80 |
- |
|
81 |
- <refsect2 xml:id="function.auth_date_proc"> |
|
82 |
- <title> |
|
83 |
- <function>auth_date_proc</function> |
|
84 |
- () |
|
85 |
- </title> |
|
86 |
- <para> |
|
87 |
- Allowed in request processing only. |
|
88 |
- </para> |
|
89 |
- <para> |
|
90 |
- The <function>auth_date_proc()</function> checks the age of a |
|
91 |
- request to be authroized. If the time given in the Date header |
|
92 |
- field of the request differs by more than the amount of seconds |
|
93 |
- given by the |
|
94 |
- <serdoc:modparam module="auth_identity">msg_timeout</serdoc:modparam> |
|
95 |
- parameter, the function returns <literal>false</literal>. It also |
|
96 |
- returns <literal>false</literal> if the certificate used by the |
|
97 |
- authorizer has expired. |
|
98 |
- </para> |
|
99 |
- </refsect2> |
|
100 |
- |
|
101 |
- <refsect2 xml:id="function.vrfy_check_callid"> |
|
102 |
- <title> |
|
103 |
- <function>vrfy_check_callid</function> |
|
104 |
- () |
|
105 |
- </title> |
|
106 |
- <para> |
|
107 |
- Allowed in request processing only. |
|
108 |
- </para> |
|
109 |
- <para> |
|
110 |
- The <function>vrfy_check_callid()</function> checks whether a |
|
111 |
- request for this call has been processed within the |
|
112 |
- time given by the |
|
113 |
- <serdoc:modparam |
|
114 |
- module="auth_identity">auth_validity_time</serdoc:modparam> |
|
115 |
- parameter. |
|
116 |
- </para> |
|
117 |
- <para> |
|
118 |
- The function generates a call identifier from the Call-ID and CSqe |
|
119 |
- header fields and the Tag parameter of the From header field and |
|
120 |
- compares it with the values stored in the Call-ID cache. |
|
121 |
- </para> |
|
122 |
- <para> |
|
123 |
- It returns <literal>false</literal> if the value is found and thus |
|
124 |
- the request is replayed or <literal>true</literal> otherwise. |
|
125 |
- </para> |
|
126 |
- </refsect2> |
|
127 |
- |
|
128 |
- <refsect2 xml:id="function.vrfy_check_certificate"> |
|
129 |
- <title> |
|
130 |
- <function>vrfy_check_certificate</function> |
|
131 |
- () |
|
132 |
- </title> |
|
133 |
- <para> |
|
134 |
- Allowed in request processing only. |
|
135 |
- </para> |
|
136 |
- <para> |
|
137 |
- The <function>vrfy_check_certificate()</function> function |
|
138 |
- checks the downloaded certificate and returns <literal>true</literal> |
|
139 |
- if it is valid or <literal>false</literal> otherwise. |
|
140 |
- </para> |
|
141 |
- <para> |
|
142 |
- A certificate is considered valid if it has not yet expired and |
|
143 |
- if its subject is identical to the domain part of the URL. |
|
144 |
- </para> |
|
145 |
- <!-- XXX Er, which URL? --> |
|
146 |
- <para> |
|
147 |
- Before <function>vrfy_check_certificate()</function> can be called, |
|
148 |
- the function <function>vrfy_check_date()</function> must have been |
|
149 |
- called and returned <literal>true</literal>. |
|
150 |
- </para> |
|
151 |
- </refsect2> |
|
152 |
- |
|
153 |
- <refsect2 xml:id="function.vrfy_check_date"> |
|
154 |
- <title> |
|
155 |
- <function>vrfy_check_date</function> |
|
156 |
- () |
|
157 |
- </title> |
|
158 |
- <para> |
|
159 |
- Allowed in request processing only. |
|
160 |
- </para> |
|
161 |
- <para> |
|
162 |
- The <function>vrfy_check_date()</function> function checks |
|
163 |
- the date of the request currently being processed. It returns |
|
164 |
- <literal>false</literal> if the time in the Date header field |
|
165 |
- of the request differs from the current system time by more than |
|
166 |
- the number of seconds given by the |
|
167 |
- <serdoc:modparam |
|
168 |
- module="auth_identity">auth_validity_time</serdoc:modparam> |
|
169 |
- parameter. |
|
170 |
- </para> |
|
171 |
- </refsect2> |
|
172 |
- |
|
173 |
- <refsect2 xml:id="function.vrfy_check_msgvalidity"> |
|
174 |
- <title> |
|
175 |
- <function>vrfy_check_msgvalidity</function> |
|
176 |
- () |
|
177 |
- </title> |
|
178 |
- <para> |
|
179 |
- Allowed in request processing only. |
|
180 |
- </para> |
|
181 |
- <para> |
|
182 |
- The <function>vrfy_check_msgvalidity()</function> function |
|
183 |
- checks the integrity of the request currently being processed. |
|
184 |
- </para> |
|
185 |
- <para> |
|
186 |
- It does so by calculating a SHA1 hash over certain parts of the |
|
187 |
- message and comparing it with the hash value that results from |
|
188 |
- decrypting the content of the Identity header field using the |
|
189 |
- certificate previously retrieved using the |
|
190 |
- <function>vrfy_get_certificate()</function> function. |
|
191 |
- </para> |
|
192 |
- <para> |
|
193 |
- The function returns <literal>true</literal> if the two hashes |
|
194 |
- match. |
|
195 |
- </para> |
|
196 |
- </refsect2> |
|
197 |
- |
|
198 |
- <refsect2 xml:id="function.vrfy_get_certificate"> |
|
199 |
- <title> |
|
200 |
- <function>vrfy_get_certificate</function> |
|
201 |
- () |
|
202 |
- </title> |
|
203 |
- <para> |
|
204 |
- Allowed in request processing only. |
|
205 |
- </para> |
|
206 |
- <para> |
|
207 |
- The <function>vrfy_get_certificate()</function> tries to get |
|
208 |
- the certificate from the URL given in the Identity-Info header |
|
209 |
- field of the currently processed request. |
|
210 |
- </para> |
|
211 |
- <para> |
|
212 |
- It returns <literal>true</literal> if the certifcate was |
|
213 |
- successfully loaded in a format that the module can process or |
|
214 |
- <literal>false</literal> otherwise. |
|
215 |
- </para> |
|
216 |
- </refsect2> |
|
217 |
- |
|
218 |
- </refsect1> |
|
219 |
- |
|
220 |
- |
|
221 |
- <refsect1 xml:id="module.auth_identity.parameters"> |
|
222 |
- <title>Module Parameters</title> |
|
223 |
- |
|
224 |
- <refsect2 xml:id="module.auth_identity.accept_pem_certs"> |
|
225 |
- <title><parameter>accept_pem_certs</parameter></title> |
|
226 |
- <serdoc:paraminfo> |
|
227 |
- <serdoc:paramtype>boolean</serdoc:paramtype> |
|
228 |
- <serdoc:paramdefault>no</serdoc:paramdefault> |
|
229 |
- </serdoc:paraminfo> |
|
230 |
- <para> |
|
231 |
- The <parameter>accept_pem_certs</parameter> parameter defines, |
|
232 |
- whether the verifier should process certificates in PEM format. |
|
233 |
- </para> |
|
234 |
- </refsect2> |
|
235 |
- |
|
236 |
- <refsect2 xml:id="module.auth_identity.auth_validity_time"> |
|
237 |
- <title><parameter>auth_validity_time</parameter></title> |
|
238 |
- <serdoc:paraminfo> |
|
239 |
- <serdoc:paramtype>integer</serdoc:paramtype> |
|
240 |
- <serdoc:paramdefault>3600</serdoc:paramdefault> |
|
241 |
- </serdoc:paraminfo> |
|
242 |
- <para> |
|
243 |
- The <parameter>auth_validity_time</parameter> parameter |
|
244 |
- sets the maximum age of a verified message. |
|
245 |
- </para> |
|
246 |
- </refsect2> |
|
247 |
- |
|
248 |
- <refsect2 xml:id="module.auth_identity.cainfo_path"> |
|
249 |
- <title><parameter>cainfo_path</parameter></title> |
|
250 |
- <serdoc:paraminfo> |
|
251 |
- <serdoc:paramtype>string</serdoc:paramtype> |
|
252 |
- <serdoc:paramdefault>""</serdoc:paramdefault> |
|
253 |
- </serdoc:paraminfo> |
|
254 |
- <para> |
|
255 |
- The <parameter>cainfo_path</parameter> paramter contains the |
|
256 |
- path and name of a file that contains trusted certificates. |
|
257 |
- </para> |
|
258 |
- <para> |
|
259 |
- The file should contain one or more certificates in PEM format |
|
260 |
- concatenated together. It is necessary if the verifier should |
|
261 |
- accept self-signed certifcates. |
|
262 |
- </para> |
|
263 |
- </refsect2> |
|
264 |
- |
|
265 |
- <refsect2 xml:id="module.auth_identity.callid_cache_limit"> |
|
266 |
- <title><parameter>callid_cache_limit</parameter></title> |
|
267 |
- <serdoc:paraminfo> |
|
268 |
- <serdoc:paramtype>integer</serdoc:paramtype> |
|
269 |
- <serdoc:paramdefault>262144</serdoc:paramdefault> |
|
270 |
- </serdoc:paraminfo> |
|
271 |
- <para> |
|
272 |
- The <parameter>callid_cache_limit</parameter> parameter |
|
273 |
- limits the number of entries in the Call-ID cache. |
|
274 |
- </para> |
|
275 |
- <para> |
|
276 |
- The Call-IDs of previously verified messages are stored in the |
|
277 |
- Call-ID cache for some time in order to recognize call |
|
278 |
- replay attacks. The cache uses shared memory. Each entry is |
|
279 |
- about 100 bytes in size. |
|
280 |
- </para> |
|
281 |
- </refsect2> |
|
282 |
- |
|
283 |
- <refsect2 xml:id="module.auth_identity.certificate_cache_limit"> |
|
284 |
- <title><parameter>certificate_cache_limit</parameter></title> |
|
285 |
- <serdoc:paraminfo> |
|
286 |
- <serdoc:paramtype>integer</serdoc:paramtype> |
|
287 |
- <serdoc:paramdefault>32768</serdoc:paramdefault> |
|
288 |
- </serdoc:paraminfo> |
|
289 |
- <para> |
|
290 |
- The <parameter>certificate_cache_limit</parameter> parameter |
|
291 |
- limits the number of entries stored in the certificate cache. |
|
292 |
- </para> |
|
293 |
- <para> |
|
294 |
- Each retrieved certificate is placed in the certificate cache |
|
295 |
- to speed up processing should it be needed again. |
|
296 |
- </para> |
|
297 |
- <para> |
|
298 |
- The cahce uses shared memory. Each entry is approximately 600 |
|
299 |
- bytes in size. |
|
300 |
- </para> |
|
301 |
- </refsect2> |
|
302 |
- |
|
303 |
- <refsect2 xml:id="module.auth_identity.certificate_path"> |
|
304 |
- <title><parameter>certificate_path</parameter></title> |
|
305 |
- <serdoc:paraminfo> |
|
306 |
- <serdoc:paramtype>string</serdoc:paramtype> |
|
307 |
- <serdoc:paramdefault>""</serdoc:paramdefault> |
|
308 |
- </serdoc:paraminfo> |
|
309 |
- <para> |
|
310 |
- The <parameter>certificate_path</parameter> parameter must be |
|
311 |
- set to path and name of the file that contains the certificate |
|
312 |
- of the authentication service in PEM format. |
|
313 |
- </para> |
|
314 |
- <para> |
|
315 |
- The parameter is required for the authentication service to work. |
|
316 |
- </para> |
|
317 |
- </refsect2> |
|
318 |
- |
|
319 |
- <refsect2 xml:id="module.auth_identity.certificate_url"> |
|
320 |
- <title><parameter>certificate_url</parameter></title> |
|
321 |
- <serdoc:paraminfo> |
|
322 |
- <serdoc:paramtype>string</serdoc:paramtype> |
|
323 |
- <serdoc:paramdefault>""</serdoc:paramdefault> |
|
324 |
- </serdoc:paraminfo> |
|
325 |
- <para> |
|
326 |
- The <parameter>certificate_url</parameter> parameter must be |
|
327 |
- set to the URL where a verifier can retrieve the certificate. |
|
328 |
- The URL will be stored in the Identity-Info header of any |
|
329 |
- authorized request. |
|
330 |
- </para> |
|
331 |
- <para> |
|
332 |
- The certificate must be available at the given URL in DER |
|
333 |
- format. |
|
334 |
- </para> |
|
335 |
- <para> |
|
336 |
- The parameter is required for the authentication service to work. |
|
337 |
- </para> |
|
338 |
- </refsect2> |
|
339 |
- |
|
340 |
- <refsect2 xml:id="module.auth_identity.msg_timeout"> |
|
341 |
- <title><parameter>msg_timeout</parameter></title> |
|
342 |
- <serdoc:paraminfo> |
|
343 |
- <serdoc:paramtype>int</serdoc:paramtype> |
|
344 |
- <serdoc:paramdefault>600</serdoc:paramdefault> |
|
345 |
- </serdoc:paraminfo> |
|
346 |
- <para> |
|
347 |
- The <parameter>msg_timeout</parameter> parameter contains the |
|
348 |
- maximum age of a request to be authorized in seconds. |
|
349 |
- </para> |
|
350 |
- <para> |
|
351 |
- The authorizer will compare the time given in the Date header field |
|
352 |
- of the request with its own current time. |
|
353 |
- </para> |
|
354 |
- </refsect2> |
|
355 |
- |
|
356 |
- <refsect2 xml:id="module.auth_identity.privatekey_path"> |
|
357 |
- <title><parameter>privatekey_path</parameter></title> |
|
358 |
- <serdoc:paraminfo> |
|
359 |
- <serdoc:paramtype>string</serdoc:paramtype> |
|
360 |
- <serdoc:paramdefault>""</serdoc:paramdefault> |
|
361 |
- </serdoc:paraminfo> |
|
362 |
- <para> |
|
363 |
- The <parameter>privatekey_path</parameter> must be set to the paht |
|
364 |
- and name of the file that contains the private key of the |
|
365 |
- authentication service in PEM format. |
|
366 |
- </para> |
|
367 |
- <para> |
|
368 |
- The parameter is required for the authentication service to work. |
|
369 |
- </para> |
|
370 |
- </refsect2> |
|
371 |
- |
|
372 |
- </refsect1> |
|
373 |
- |
|
374 |
- <refsect1 id="modules.auth_identity.examples"> |
|
375 |
- <title>Examples</title> |
|
376 |
- <para> |
|
377 |
- The <emphasis>authentifier</emphasis> is typically included in the |
|
378 |
- part of the routing |
|
379 |
- logic that sends a request to a foreign domain. In the |
|
380 |
- <filename>ser-oob.cfg</filename> configuration, this is the |
|
381 |
- <varname>route[OUTBOUND]</varname>. With an authentifier included, |
|
382 |
- it looks like this: |
|
383 |
- </para> |
|
384 |
- <programlisting><![CDATA[ |
|
385 |
-route[OUTBOUND] |
|
386 |
-{ |
|
387 |
- if ($f.did && !$t.did) { |
|
388 |
- # Authentication service |
|
389 |
- if (method=="INVITE" || method=="OPTION") { |
|
390 |
- # Identity and Identity-info headers must not exist |
|
391 |
- if (@identity) { |
|
392 |
- sl_reply("403", "Invalid Identity header"); |
|
393 |
- drop; |
|
394 |
- } |
|
395 |
- if (@identity_info) { |
|
396 |
- sl_reply("403", "Invalid Identity-info header"); |
|
397 |
- drop; |
|
398 |
- } |
|
399 |
- |
|
400 |
- if (!auth_date_proc()) { |
|
401 |
- sl_reply("403", "Invalid Date value"); |
|
402 |
- drop; |
|
403 |
- } |
|
404 |
- |
|
405 |
- if (!auth_add_identity()) { |
|
406 |
- sl_reply("480", "Authentication error"); |
|
407 |
- drop; |
|
408 |
- } |
|
409 |
- } |
|
410 |
- route(FORWARD); |
|
411 |
- } |
|
412 |
-} |
|
413 |
-]]></programlisting> |
|
414 |
- <para> |
|
415 |
- The <emphasis>verifier</emphasis> should be run after you discovered |
|
416 |
- that a request originates from a foreign domain (for your own domains, |
|
417 |
- you should be doing digest authentication instead). |
|
418 |
- </para> |
|
419 |
- <para> |
|
420 |
- While you should reject any request that does contain an Identity |
|
421 |
- header but does not verify, it is up to your local policy, what to |
|
422 |
- do with messages that do not contain an Identity header at all. |
|
423 |
- You could reject them or divert them to voice mail or any of a number |
|
424 |
- of other options. |
|
425 |
- </para> |
|
426 |
- <para> |
|
427 |
- The following config snippet rejects any message that does not have |
|
428 |
- an Identity header. |
|
429 |
- </para> |
|
430 |
- <programlisting><![CDATA[ |
|
431 |
- if (method=="INVITE" || method=="OPTIONS") { |
|
432 |
- if (!@identity) { |
|
433 |
- sl_reply("428", "Use Identity Header"); |
|
434 |
- drop; |
|
435 |
- } |
|
436 |
- if (!@identity_info) { |
|
437 |
- sl_reply("436", "Bad Identity-Info"); |
|
438 |
- drop; |
|
439 |
- } |
|
440 |
- |
|
441 |
- if (!vrfy_check_date()) { |
|
442 |
- sl_reply("403", "Outdated Date header value"); |
|
443 |
- drop; |
|
444 |
- } |
|
445 |
- |
|
446 |
- if (!vrfy_get_certificate()) { |
|
447 |
- sl_reply("436", "Bad Identity-Info"); |
|
448 |
- drop; |
|
449 |
- } |
|
450 |
- |
|
451 |
- if (!vrfy_check_certificate()) { |
|
452 |
- sl_reply("437", "Unsupported Certificate"); |
|
453 |
- drop; |
|
454 |
- } |
|
455 |
- |
|
456 |
- if (!vrfy_check_msgvalidity()) { |
|
457 |
- sl_reply("438", "Invalid Identity Header"); |
|
458 |
- drop; |
|
459 |
- } |
|
460 |
- |
|
461 |
- if (!vrfy_check_callid()) { |
|
462 |
- sl_reply("403", "Message is replayed"); |
|
463 |
- drop; |
|
464 |
- } |
|
465 |
- } |
|
466 |
-]]></programlisting> |
|
467 |
- </refsect1> |
|
468 |
- |
|
469 |
- <refsect1 id="mdoule.auth_identity.how-it-works"> |
|
470 |
- <title>The SIP Identity Mechanism</title> |
|
471 |
- <para> |
|
472 |
- The SIP Identity Mechanism is defined in RFC 4474 "Enhancements for |
|
473 |
- Authenticated Identity Management in the Session Initiation Protocol |
|
474 |
- (SIP)". Its main purpose is to affirm the identity of the originator |
|
475 |
- of a request as stated in the From header field of the request. |
|
476 |
- While basic SIP provides a mechanism for a user agent to proof its |
|
477 |
- authenticity to the proxy serving the domain of the address used |
|
478 |
- by the user agent, no such mechanism exists to proof the authenticity |
|
479 |
- to other proxies or end points. The SIP Identity Mechanism mends this |
|
480 |
- oversight. |
|
481 |
- </para> |
|
482 |
- <para> |
|
483 |
- The mechanism allows a proxy to cryptographically sign a message as |
|
484 |
- authentic before sending it to another proxy. It does so after |
|
485 |
- making sure the sender actually is who he claims and is allowed to |
|
486 |
- use the address in the context of the message. |
|
487 |
- </para> |
|
488 |
- <para> |
|
489 |
- If the proxy is satisfied, it creates two header fields: Identity and |
|
490 |
- Identity-Info. The Identity header field contains a signed hash over |
|
491 |
- the following components of the message: |
|
492 |
- </para> |
|
493 |
- <itemizedlist> |
|
494 |
- <listitem> |
|
495 |
- the address given in the From header field, |
|
496 |
- </listitem> |
|
497 |
- <listitem> |
|
498 |
- the address given in the To header field, |
|
499 |
- </listitem> |
|
500 |
- <listitem> |
|
501 |
- the Call-ID, |
|
502 |
- </listitem> |
|
503 |
- <listitem> |
|
504 |
- the content of the CSeq header field, |
|
505 |
- </listitem> |
|
506 |
- <listitem> |
|
507 |
- the content of the Date header field, |
|
508 |
- </listitem> |
|
509 |
- <listitem> |
|
510 |
- the address given in the Contact header field if present, and |
|
511 |
- </listitem> |
|
512 |
- <listitem> |
|
513 |
- the body of the message. |
|
514 |
- </listitem> |
|
515 |
- </itemizedlist> |
|
516 |
- <para> |
|
517 |
- The hash is signed with a certificate for the domain. A URL pointing |
|
518 |
- to a place where an interested party can download a copy of the |
|
519 |
- certificate is placed into the Identity-Info header field. |
|
520 |
- </para> |
|
521 |
- <para> |
|
522 |
- If the message arrives at a proxy or user agent that wishes to verify |
|
523 |
- the authenticity, this device downloads the certificate and itself |
|
524 |
- forms the hash over the above components. If both hashes match, the |
|
525 |
- message has been authenticated by the proxy of the domain of the |
|
526 |
- certificate and has not been tempered with on the way. |
|
527 |
- </para> |
|
528 |
- </refsect1> |
|
529 |
- |
|
530 |
- <refsect1 id="modules.auth_identity.credentials"> |
|
531 |
- <title>Certificates</title> |
|
532 |
- <para> |
|
533 |
- In order to use the <command>auth_identity</command> module, you need a |
|
534 |
- certificate for your domain. There is two options, how to get one: you |
|
535 |
- buy one from a certification authority or you create your own |
|
536 |
- certification authority and use a self-signed certificate. If you plan |
|
537 |
- to provide real inter-domain calls for your domain, you should pick the |
|
538 |
- first option. Although it is more expensive, it guarantees proper |
|
539 |
- interaction between domains. |
|
540 |
- </para> |
|
541 |
- <para> |
|
542 |
- Either way, you will end up with a private key and a certificate which |
|
543 |
- includes the public key for that private key. You can use the same key |
|
544 |
- and certificate as for the TLS encrypted SIP transport. Because of |
|
545 |
- this, details on the process of acquiring them can be found in |
|
546 |
- <serdoc:module>tls</serdoc:module>. |
|
547 |
- </para> |
|
548 |
- <para> |
|
549 |
- Once you have the certificate and private key, you set the module |
|
550 |
- parameter |
|
551 |
- <serdoc:modparam module="auth_identity">certificate_path</serdoc:modparam> |
|
552 |
- to point to the file containing the certificate and |
|
553 |
- <serdoc:modparam module="auth_identity">privatekey_path</serdoc:modparam> |
|
554 |
- to point to the file with the private key. |
|
555 |
- </para> |
|
556 |
- <para> |
|
557 |
- Finally, you have to put a public version of your certificate onto |
|
558 |
- a web server somewhere. This version must be DER encoded and, |
|
559 |
- obviously, must not contain the private key. You can create this |
|
560 |
- by issuing |
|
561 |
- </para> |
|
562 |
- <programlisting><![CDATA[ |
|
563 |
-# openssl x509 -in your_certificate.crt -outform der -out your_certificate.der |
|
564 |
-]]></programlisting> |
|
565 |
- <para> |
|
566 |
- You then place the DER encoded certificate into a publicly |
|
567 |
- available directory on your webserver and state the URL to the |
|
568 |
- file in the parameter |
|
569 |
- <serdoc:modparam module="auth_identity">certificate_url</serdoc:modparam>. |
|
570 |
- </para> |
|
571 |
- </refsect1> |
|
572 |
- |
|
573 |
- <!-- |
|
574 |
- Compilation sections only go into the Admin Guide since we assume |
|
575 |
- that if you read a manpage you already have installed the module. |
|
576 |
- --> |
|
577 |
- <refsect1 role="admin-guide"> |
|
578 |
- <title>Compilation</title> |
|
579 |
- <para> |
|
580 |
- This <command>auth_identity</command> module needs the following |
|
581 |
- headers and libraries: |
|
582 |
- </para> |
|
583 |
- <itemizedlist> |
|
584 |
- <listitem> |
|
585 |
- <emphasis>OpenSSL</emphasis> (version 0.9.8 or higher) for |
|
586 |
- cryptographic functions, |
|
587 |
- </listitem> |
|
588 |
- <listitem> |
|
589 |
- <emphasis>libcURL</emphasis> for HTTP, HTTPS functions. |
|
590 |
- </listitem> |
|
591 |
- </itemizedlist> |
|
592 |
- <para> |
|
593 |
- If you'd like to use the <emphasis>TLS</emphasis> module, too, |
|
594 |
- you will have to change <varname>LIB</varname> variable in the |
|
595 |
- Makefile to the value that is by default commented out. |
|
596 |
- </para> |
|
597 |
- </refsect1> |
|
598 |
- |
|
599 |
- <refsect1> |
|
600 |
- <title>Known Limitations</title> |
|
601 |
- <para> |
|
602 |
- Both authorizer and verifier currently only support SIP requests |
|
603 |
- except for responses to CANCEL and REGISTER requests. |
|
604 |
- </para> |
|
605 |
- <para> |
|
606 |
- The verifier does not support the subjectAltName extension of |
|
607 |
- certificates. |
|
608 |
- </para> |
|
609 |
- </refsect1> |
|
610 |
- |
|
611 |
- <refsect1 role="manpage"> |
|
612 |
- <title>Authors</title> |
|
613 |
- <para> |
|
614 |
- Written by Gergely Kovacs and Martin Hoffmann. |
|
615 |
- </para> |
|
616 |
- </refsect1> |
|
617 |
- |
|
618 |
- <refsect1 role="manpage"> |
|
619 |
- <title>See Also</title> |
|
620 |
- <simplelist type="inline"> |
|
621 |
- <member><serdoc:sbin>ser</serdoc:sbin></member> |
|
622 |
- <member><serdoc:file>ser.cfg</serdoc:file></member> |
|
623 |
- </simplelist> |
|
624 |
- </refsect1> |
|
625 |
- |
|
626 |
-</refentry> |
|
627 |
- |
|
628 |
-<!-- vim:sw=2 sta et sts=2 ai |
|
629 |
- --> |
... | ... |
@@ -190,11 +190,11 @@ modparam("auth_identity","cainfo_path","/etc/ssl/certs/ca-certificates.crt") |
190 | 190 |
</section> |
191 | 191 |
|
192 | 192 |
<section id="accept_pem_certs"> |
193 |
- <title><varname>accept_pem_certs</varname> ([0|1])</title> |
|
193 |
+ <title><varname>accept_pem_certs</varname> (int)</title> |
|
194 | 194 |
<para>Note: this parameter is for verifier service.</para> |
195 | 195 |
<para> |
196 | 196 |
Enables the acquired certificate processing if it is in PEM |
197 |
- format. |
|
197 |
+ format. Value can be 0 or 1. |
|
198 | 198 |
</para> |
199 | 199 |
<para> |
200 | 200 |
This parameter is optional. The default value is "0". |
... | ... |
@@ -51,6 +51,8 @@ Tsvetomir Dimitrov |
51 | 51 |
3.6. ipsec_reuse_server_port (int) |
52 | 52 |
3.7. ipsec_spi_id_start (int) |
53 | 53 |
3.8. ipsec_spi_id_range (int) |
54 |
+ 3.9. ipsec_preferred_alg (string) |
|
55 |
+ 3.10. ipsec_preferred_ealg (string) |
|
54 | 56 |
|
55 | 57 |
4. Functions |
56 | 58 |
|
... | ... |
@@ -68,9 +70,11 @@ Tsvetomir Dimitrov |
68 | 70 |
1.6. ipsec_reuse_server_port parameter usage |
69 | 71 |
1.7. ipsec_spi_id_start parameter usage |
70 | 72 |
1.8. ipsec_spi_id_range parameter usage |
71 |
- 1.9. ipsec_create |
|
72 |
- 1.10. ipsec_forward |
|
73 |
- 1.11. ipsec_destroy |
|
73 |
+ 1.9. ipsec_preferred_alg parameter usage |
|
74 |
+ 1.10. ipsec_preferred_ealg parameter usage |
|
75 |
+ 1.11. ipsec_create |
|
76 |
+ 1.12. ipsec_forward |
|
77 |
+ 1.13. ipsec_destroy |
|
74 | 78 |
|
75 | 79 |
Chapter 1. Admin Guide |
76 | 80 |
|
... | ... |
@@ -92,6 +96,8 @@ Chapter 1. Admin Guide |
92 | 96 |
3.6. ipsec_reuse_server_port (int) |
93 | 97 |
3.7. ipsec_spi_id_start (int) |
94 | 98 |
3.8. ipsec_spi_id_range (int) |
99 |
+ 3.9. ipsec_preferred_alg (string) |
|
100 |
+ 3.10. ipsec_preferred_ealg (string) |
|
95 | 101 |
|
96 | 102 |
4. Functions |
97 | 103 |
|
... | ... |
@@ -130,6 +136,8 @@ Chapter 1. Admin Guide |
130 | 136 |
3.6. ipsec_reuse_server_port (int) |
131 | 137 |
3.7. ipsec_spi_id_start (int) |
132 | 138 |
3.8. ipsec_spi_id_range (int) |
139 |
+ 3.9. ipsec_preferred_alg (string) |
|
140 |
+ 3.10. ipsec_preferred_ealg (string) |
|
133 | 141 |
|
134 | 142 |
3.1. ipsec_listen_addr (string) |
135 | 143 |
|
... | ... |
@@ -159,8 +167,7 @@ modparam("ims_ipsec_pcscf", "ipsec_listen_addr6", "") |
159 | 167 |
|
160 | 168 |
3.3. ipsec_client_port (int) |
161 | 169 |
|
162 |
- Start port number which will be bound for incoming (server) IPSec |
|
163 |
- traffic. |
|
170 |
+ Port number which will be bound for incoming (server) IPSec traffic. |
|
164 | 171 |
|
165 | 172 |
Default value is 5062. |
166 | 173 |
|
... | ... |
@@ -171,8 +178,7 @@ modparam("ims_ipsec_pcscf", "ipsec_client_port", 5062) |
171 | 178 |
|
172 | 179 |
3.4. ipsec_server_port (int) |
173 | 180 |
|
174 |
- Start port number which will be bound for incoming (server) IPSec |
|
175 |
- traffic. |
|
181 |
+ Port number which will be bound for incoming (server) IPSec traffic. |
|
176 | 182 |
|
177 | 183 |
Default value is 5063. |
178 | 184 |
|
... | ... |
@@ -183,11 +189,7 @@ modparam("ims_ipsec_pcscf", "ipsec_server_port", 5063) |
183 | 189 |
|
184 | 190 |
3.5. ipsec_max_connections (int) |
185 | 191 |
|
186 |
- Maximum IPSec connections for the process. E.g. if |
|
187 |
- ipsec_client_port=5100, ipsec_server_port=6100 and |
|
188 |
- ipsec_max_connections=10, all client ports between 5100 and 5109 and |
|
189 |
- all server ports between 6100 and 6109 will be used for maximum to 10 |
|
190 |
- IPSec connections. |
|
192 |
+ Maximum simultanious IPSec connections |
|
191 | 193 |
|
192 | 194 |
Default value is 2. |
193 | 195 |
|
... | ... |
@@ -198,11 +200,10 @@ modparam("ims_ipsec_pcscf", "ipsec_max_connections", 10) |
198 | 200 |
|
199 | 201 |
3.6. ipsec_reuse_server_port (int) |
200 | 202 |
|
201 |
- Reuse (1) or not (0) the P-CSCF Server port for Re-registration for one |
|
202 |
- UA. When set to 0 - During Re-registration P-CSCF will distribute new |
|
203 |
- P-CSCF client and P-CSCF server ports. When set to 1 - During |
|
204 |
- Re-registration P-CSCF will reuse the old P-CSCF server port and will |
|
205 |
- distribute a new P-CSCF client port. |
|
203 |
+ Reuse (1) or not (0) the P-CSCF IPSec information for Re-registration |
|
204 |
+ for one UA. When set to 0 - During Re-registration P-CSCF will create |
|
205 |
+ new IPSec tunnels. When set to 1 - During Re-registration P-CSCF will |
|
206 |
+ reuse the old IPSec tunnels. |
|
206 | 207 |
|
207 | 208 |
Default value is 1. |
208 | 209 |
|
... | ... |
@@ -238,6 +239,33 @@ modparam("ims_ipsec_pcscf", "ipsec_spi_id_start", 100) |
238 | 239 |
modparam("ims_ipsec_pcscf", "ipsec_spi_id_range", 1000) |
239 | 240 |
... |
240 | 241 |
|
242 |
+3.9. ipsec_preferred_alg (string) |
|
243 |
+ |
|
244 |
+ A name of an authentication algorithm which the Proxy-CSCF will prefer |
|
245 |
+ when creating IPSec tunnels. |
|
246 |
+ |
|
247 |
+ Default value is empty string (null) - the last algorithm in the |
|
248 |
+ Sec-Agree header will be used. |
|
249 |
+ |
|
250 |
+ Example 1.9. ipsec_preferred_alg parameter usage |
|
251 |
+... |
|
252 |
+modparam("ims_ipsec_pcscf", "ipsec_preferred_alg", "hmac-sha-1-96") |
|
253 |
+... |
|
254 |
+ |
|
255 |
+3.10. ipsec_preferred_ealg (string) |
|
256 |
+ |
|
257 |
+ A name of an encrytion algorithm which the Proxy-CSCF will prefer when |
|
258 |
+ creating IPSec tunnels. |
|
259 |
+ |
|
260 |
+ Default value is empty string (null) - the last algorithm in the |
|
261 |
+ Sec-Agree header will be used. Note that the possibility of it being |
|
262 |
+ the "null" algorithm is not insignificant. |
|
263 |
+ |
|
264 |
+ Example 1.10. ipsec_preferred_ealg parameter usage |
|
265 |
+... |
|
266 |
+modparam("ims_ipsec_pcscf", "ipsec_preferred_ealg", "aes-cbc") |
|
267 |
+... |
|
268 |
+ |
|
241 | 269 |
4. Functions |
242 | 270 |
|
243 | 271 |
4.1. ipsec_create(domain) |
... | ... |
@@ -258,7 +286,7 @@ modparam("ims_ipsec_pcscf", "ipsec_spi_id_range", 1000) |
258 | 286 |
every registration. This is an optional parameter, default value - |
259 | 287 |
0. |
260 | 288 |
|
261 |
- Example 1.9. ipsec_create |
|
289 |
+ Example 1.11. ipsec_create |
|
262 | 290 |
... |
263 | 291 |
ipsec_create("location"); |
264 | 292 |
# or |
... | ... |
@@ -278,7 +306,7 @@ ipsec_create("location", "1"); |
278 | 306 |
the memory. Useful when contact alias is disabled. This is an |
279 | 307 |
optional parameter, default value - 0. |
280 | 308 |
|
281 |
- Example 1.10. ipsec_forward |
|
309 |
+ Example 1.12. ipsec_forward |
|
282 | 310 |
... |
283 | 311 |
ipsec_forward("location"); |
284 | 312 |
# or |
... | ... |
@@ -293,7 +321,7 @@ ipsec_forward("location", "1"); |
293 | 321 |
* domain - Logical domain within the registrar. If a database is used |
294 | 322 |
then this must be name of the table which stores the contacts. |
295 | 323 |
|
296 |
- Example 1.11. ipsec_destroy |
|
324 |
+ Example 1.13. ipsec_destroy |
|
297 | 325 |
... |
298 | 326 |
ipsec_destroy("location"); |
299 | 327 |
... |
... | ... |
@@ -50,7 +50,6 @@ |
50 | 50 |
|
51 | 51 |
#include "ipsec.h" |
52 | 52 |
#include "spi_gen.h" |
53 |
-#include "port_gen.h" |
|
54 | 53 |
#include "cmd.h" |
55 | 54 |
#include "sec_agree.h" |
56 | 55 |
|
... | ... |
@@ -351,57 +350,26 @@ static int update_contact_ipsec_params(ipsec_t* s, const struct sip_msg* m, ipse |
351 | 350 |
s->ik.len = ik.len; |
352 | 351 |
|
353 | 352 |
// Generate SPI |
354 |
- if((s->spi_pc = acquire_spi()) == 0) { |
|
355 |
- LM_ERR("Error generating client SPI for IPSEC tunnel creation\n"); |
|
356 |
- shm_free(s->ck.s); |
|
357 |
- s->ck.s = NULL; s->ck.len = 0; |
|
358 |
- shm_free(s->ik.s); |
|
359 |
- s->ik.s = NULL; s->ik.len = 0; |
|
360 |
- return -1; |
|
353 |
+ if(s_old) { |
|
354 |
+ if(s_old->spi_pc && s_old->spi_ps && s_old->port_pc && s_old->port_ps) { |
|
355 |
+ LM_INFO("Reusing IPSEC tunnel\n"); |
|
356 |
+ s->spi_pc = s_old->spi_pc; |
|
357 |
+ s->spi_ps = s_old->spi_ps; |
|
358 |
+ s->port_pc = s_old->port_pc; |
|
359 |
+ s->port_ps = s_old->port_ps; |
|
360 |
+ return 0; |
|
361 |
+ } |
|
361 | 362 |
} |
362 | 363 |
|
363 |
- if((s->spi_ps = acquire_spi()) == 0) { |
|
364 |
- LM_ERR("Error generating server SPI for IPSEC tunnel creation\n"); |
|
364 |
+ if(acquire_spi(&s->spi_pc, &s->spi_ps, &s->port_pc, &s->port_ps) == 0) { |
|
365 |
+ LM_ERR("Error generating client SPI for IPSEC tunnel creation\n"); |
|
365 | 366 |
shm_free(s->ck.s); |
366 | 367 |
s->ck.s = NULL; s->ck.len = 0; |
367 | 368 |
shm_free(s->ik.s); |
368 | 369 |
s->ik.s = NULL; s->ik.len = 0; |
369 |
- |
|
370 |
- release_spi(s->spi_pc); |
|
371 | 370 |
return -1; |
372 | 371 |
} |
373 | 372 |
|
374 |
- if((s->port_pc = acquire_cport()) == 0){ |
|
375 |
- LM_ERR("No free client port for IPSEC tunnel creation\n"); |
|
376 |
- shm_free(s->ck.s); |
|
377 |
- s->ck.s = NULL; s->ck.len = 0; |
|
378 |
- shm_free(s->ik.s); |
|
379 |
- s->ik.s = NULL; s->ik.len = 0; |
|
380 |
- |
|
381 |
- release_spi(s->spi_pc); |
|
382 |
- release_spi(s->spi_ps); |
|
383 |
- return -1; |
|
384 |
- } |
|
385 |
- |
|
386 |
- // use the same P-CSCF server port if it is present |
|
387 |
- if(s_old){ |
|
388 |
- s->port_ps = s_old->port_ps; |
|
389 |
- }else{ |
|
390 |
- if((s->port_ps = acquire_sport()) == 0){ |
|
391 |
- LM_ERR("No free server port for IPSEC tunnel creation\n"); |
|
392 |
- shm_free(s->ck.s); |
|
393 |
- s->ck.s = NULL; s->ck.len = 0; |
|
394 |
- shm_free(s->ik.s); |
|
395 |
- s->ik.s = NULL; s->ik.len = 0; |
|
396 |
- |
|
397 |
- release_cport(s->port_pc); |
|
398 |
- |
|
399 |
- release_spi(s->spi_pc); |
|
400 |
- release_spi(s->spi_ps); |
|
401 |
- return -1; |
|
402 |
- } |
|
403 |
- } |
|
404 |
- |
|
405 | 373 |
return 0; |
406 | 374 |
} |
407 | 375 |
|
... | ... |
@@ -508,12 +476,7 @@ static int destroy_ipsec_tunnel(str remote_addr, ipsec_t* s, unsigned short rece |
508 | 476 |
remove_policy(sock, remote_addr, ipsec_addr, s->port_us, s->port_pc, s->spi_pc, ip_addr.af, IPSEC_POLICY_DIRECTION_IN); |
509 | 477 |
|
510 | 478 |
// Release SPIs |
511 |
- release_spi(s->spi_pc); |
|
512 |
- release_spi(s->spi_ps); |
|
513 |
- |
|
514 |
- // Release the client and the server ports |
|
515 |
- release_cport(s->port_pc); |
|
516 |
- release_sport(s->port_ps); |
|
479 |
+ release_spi(s->spi_pc, s->spi_ps, s->port_pc, s->port_ps); |
|
517 | 480 |
|
518 | 481 |
close_mnl_socket(sock); |
519 | 482 |
return 0; |
... | ... |
@@ -692,74 +655,69 @@ int ipsec_create(struct sip_msg* m, udomain_t* d, int _cflags) |
692 | 655 |
|
693 | 656 |
struct sip_msg* req = t->uas.request; |
694 | 657 |
|
658 |
+ // Parse security parameters from the REGISTER request and get some data for the new tunnels |
|
659 |
+ security_t* req_sec_params = cscf_get_security(req); |
|
660 |
+ ipsec_t* s; |
|
661 |
+ ipsec_t* old_s = NULL; |
|
662 |
+ |
|
695 | 663 |
// Update contacts only for initial registration, for re-registration the existing contacts shouldn't be updated. |
696 | 664 |
if(ci.via_port == SIP_PORT){ |
697 | 665 |
LM_DBG("Registration for contact with AOR [%.*s], VIA [%d://%.*s:%d], received_host [%d://%.*s:%d]\n", |
698 | 666 |
ci.aor.len, ci.aor.s, ci.via_prot, ci.via_host.len, ci.via_host.s, ci.via_port, |
699 | 667 |
ci.received_proto, ci.received_host.len, ci.received_host.s, ci.received_port); |
700 | 668 |
|
701 |
- ipsec_t* s = pcontact->security_temp->data.ipsec; |
|
669 |
+ if(req_sec_params == NULL) |
|
670 |
+ s = pcontact->security_temp->data.ipsec; |
|
671 |
+ else |
|
672 |
+ s = req_sec_params->data.ipsec; |
|
673 |
+ }else{ |
|
674 |
+ LM_DBG("RE-Registration for contact with AOR [%.*s], VIA [%d://%.*s:%d], received_host [%d://%.*s:%d]\n", |
|
675 |
+ ci.aor.len, ci.aor.s, ci.via_prot, ci.via_host.len, ci.via_host.s, ci.via_port, |
|
676 |
+ ci.received_proto, ci.received_host.len, ci.received_host.s, ci.received_port); |
|
702 | 677 |
|
703 |
- // for initial Registration use a new P-CSCF server port |
|
704 |
- if(update_contact_ipsec_params(s, m, NULL) != 0) { |
|
678 |
+ if(req_sec_params == NULL) { |
|
679 |
+ LM_CRIT("No security parameters in REGISTER request\n"); |
|
705 | 680 |
goto cleanup; |
706 | 681 |
} |
707 | 682 |
|
708 |
- if(create_ipsec_tunnel(&req->rcv.src_ip, s) != 0){ |
|
709 |
- goto cleanup; |
|
710 |
- } |
|
683 |
+ s = req_sec_params->data.ipsec; |
|
684 |
+ old_s = (ipsec_reuse_server_port && pcontact->security_temp) ? pcontact->security_temp->data.ipsec : NULL; |
|
685 |
+ } |
|
711 | 686 |
|
712 |
- if (ul.update_pcontact(d, &ci, pcontact) != 0){ |
|
713 |
- LM_ERR("Error updating contact\n"); |
|
714 |
- goto cleanup; |
|
715 |
- } |
|
687 |
+ if(update_contact_ipsec_params(s, m, old_s) != 0) { |
|
688 |
+ goto cleanup; |
|
689 |
+ } |
|
716 | 690 |
|
691 |
+ if(create_ipsec_tunnel(&req->rcv.src_ip, s) != 0){ |
|
692 |
+ goto cleanup; |
|
693 |
+ } |
|
694 |
+ |
|
695 |
+ if (ul.update_pcontact(d, &ci, pcontact) != 0){ |
|
696 |
+ LM_ERR("Error updating contact\n"); |
|
697 |
+ goto cleanup; |
|
698 |
+ } |
|
699 |
+ |
|
700 |
+ if(ci.via_port == SIP_PORT){ |
|
717 | 701 |
// Update temp security parameters |
718 | 702 |
if(ul.update_temp_security(d, pcontact->security_temp->type, pcontact->security_temp, pcontact) != 0){ |
719 | 703 |
LM_ERR("Error updating temp security\n"); |
720 | 704 |
} |
705 |
+ } |
|
721 | 706 |
|
722 |
- if(add_supported_secagree_header(m) != 0) { |
|
723 |
- goto cleanup; |
|
724 |
- } |
|
725 | 707 |
|
726 |
- if(add_security_server_header(m, s) != 0) { |
|
727 |
- goto cleanup; |
|
728 |
- } |
|
708 |
+ if(add_supported_secagree_header(m) != 0) { |
|
709 |
+ goto cleanup; |
|
710 |
+ } |
|
729 | 711 |
|
712 |
+ if(add_security_server_header(m, s) != 0) { |
|
713 |
+ goto cleanup; |
|
714 |
+ } |
|
715 |
+ |
|
716 |
+ if(ci.via_port == SIP_PORT){ |
|
730 | 717 |
if(ul.register_ulcb(pcontact, PCSCF_CONTACT_EXPIRE|PCSCF_CONTACT_DELETE, ipsec_on_expire, (void*)&pcontact->received_port) != 1) { |
731 | 718 |
LM_ERR("Error subscribing for contact\n"); |
732 | 719 |
goto cleanup; |
733 | 720 |
} |
734 |
- }else{ |
|
735 |
- LM_DBG("RE-Registration for contact with AOR [%.*s], VIA [%d://%.*s:%d], received_host [%d://%.*s:%d]\n", |
|
736 |
- ci.aor.len, ci.aor.s, ci.via_prot, ci.via_host.len, ci.via_host.s, ci.via_port, |
|
737 |
- ci.received_proto, ci.received_host.len, ci.received_host.s, ci.received_port); |
|
738 |
- |
|
739 |
- security_t* req_sec_params = NULL; |
|
740 |
- |
|
741 |
- // Parse security parameters from the REGISTER request and get some data for the new tunnels |
|
742 |
- if((req_sec_params = cscf_get_security(req)) == NULL) { |
|
743 |
- LM_CRIT("No security parameters in REGISTER request\n"); |
|
744 |
- goto cleanup; |
|
745 |
- } |
|
746 |
- |
|
747 |
- // for Re-Registration use the same P-CSCF server port if 'ipsec reuse server port' is enabled |
|
748 |
- if(update_contact_ipsec_params(req_sec_params->data.ipsec, m, ipsec_reuse_server_port ? pcontact->security_temp->data.ipsec : NULL) != 0) { |
|
749 |
- goto cleanup; |
|
750 |
- } |
|
751 |
- |
|
752 |
- if(create_ipsec_tunnel(&req->rcv.src_ip, req_sec_params->data.ipsec) != 0){ |
|
753 |
- goto cleanup; |
|
754 |
- } |
|
755 |
- |
|
756 |
- if(add_supported_secagree_header(m) != 0) { |
|
757 |
- goto cleanup; |
|
758 |
- } |
|
759 |
- |
|
760 |
- if(add_security_server_header(m, req_sec_params->data.ipsec) != 0) { |
|
761 |
- goto cleanup; |
|
762 |
- } |
|
763 | 721 |
} |
764 | 722 |
|
765 | 723 |
ret = IPSEC_CMD_SUCCESS; // all good, set ret to SUCCESS, and exit |
... | ... |
@@ -1004,10 +962,9 @@ int ipsec_reconfig() |
1004 | 962 |
return 0; |
1005 | 963 |
} |
1006 | 964 |
|
1007 |
- clean_spi_list(); |
|
1008 |
- clean_port_lists(); |
|
1009 |
- |
|
1010 |
- LM_DBG("Clean all ipsec tunnels\n"); |
|
965 |
+ if(clean_spi_list() != 0) { |
|
966 |
+ return 1; |
|
967 |
+ } |
|
1011 | 968 |
|
1012 | 969 |
return ipsec_cleanall(); |
1013 | 970 |
} |
... | ... |
@@ -82,7 +82,7 @@ modparam("ims_ipsec_pcscf", "ipsec_listen_addr6", "") |
82 | 82 |
<section> |
83 | 83 |
<title><varname>ipsec_client_port</varname> (int)</title> |
84 | 84 |
|
85 |
- <para>Start port number which will be bound for incoming (server) IPSec traffic.</para> |
|
85 |
+ <para>Port number which will be bound for incoming (server) IPSec traffic.</para> |
|
86 | 86 |
|
87 | 87 |
<para><emphasis>Default value is 5062.</emphasis></para> |
88 | 88 |
|
... | ... |
@@ -100,7 +100,7 @@ modparam("ims_ipsec_pcscf", "ipsec_client_port", 5062) |
100 | 100 |
<section> |
101 | 101 |
<title><varname>ipsec_server_port</varname> (int)</title> |
102 | 102 |
|
103 |
- <para>Start port number which will be bound for incoming (server) IPSec traffic.</para> |
|
103 |
+ <para>Port number which will be bound for incoming (server) IPSec traffic.</para> |
|
104 | 104 |
|
105 | 105 |
<para><emphasis>Default value is 5063.</emphasis></para> |
106 | 106 |
|
... | ... |
@@ -118,9 +118,7 @@ modparam("ims_ipsec_pcscf", "ipsec_server_port", 5063) |
118 | 118 |
<section> |
119 | 119 |
<title><varname>ipsec_max_connections</varname> (int)</title> |
120 | 120 |
|
121 |
- <para>Maximum IPSec connections for the process. E.g. if ipsec_client_port=5100, ipsec_server_port=6100 and |
|
122 |
- ipsec_max_connections=10, all client ports between 5100 and 5109 and all server ports between 6100 and 6109 |
|
123 |
- will be used for maximum to 10 IPSec connections.</para> |
|
121 |
+ <para>Maximum simultanious IPSec connections</para> |
|
124 | 122 |
|
125 | 123 |
<para><emphasis>Default value is 2.</emphasis></para> |
126 | 124 |
|
... | ... |
@@ -138,11 +136,9 @@ modparam("ims_ipsec_pcscf", "ipsec_max_connections", 10) |
138 | 136 |
<section> |
139 | 137 |
<title><varname>ipsec_reuse_server_port</varname> (int)</title> |
140 | 138 |
|
141 |
- <para>Reuse (1) or not (0) the P-CSCF Server port for Re-registration for one UA. |
|
142 |
- When set to 0 - During Re-registration P-CSCF will distribute new P-CSCF client and |
|
143 |
- P-CSCF server ports. |
|
144 |
- When set to 1 - During Re-registration P-CSCF will reuse the old P-CSCF server port and |
|
145 |
- will distribute a new P-CSCF client port.</para> |
|
139 |
+ <para>Reuse (1) or not (0) the P-CSCF IPSec information for Re-registration for one UA. |
|
140 |
+ When set to 0 - During Re-registration P-CSCF will create new IPSec tunnels. |
|
141 |
+ When set to 1 - During Re-registration P-CSCF will reuse the old IPSec tunnels.</para> |
|
146 | 142 |
|
147 | 143 |
<para><emphasis>Default value is 1.</emphasis></para> |
148 | 144 |
|
... | ... |
@@ -192,6 +188,40 @@ modparam("ims_ipsec_pcscf", "ipsec_spi_id_start", 100) |
192 | 188 |
<programlisting format="linespecific"> |
193 | 189 |
... |
194 | 190 |
modparam("ims_ipsec_pcscf", "ipsec_spi_id_range", 1000) |
191 |
+... |
|
192 |
+ </programlisting> |
|
193 |
+ </example> |
|
194 |
+ </section> |
|
195 |
+ |
|
196 |
+ <section> |
|
197 |
+ <title><varname>ipsec_preferred_alg</varname> (string)</title> |
|
198 |
+ |
|
199 |
+ <para>A name of an authentication algorithm which the Proxy-CSCF will <emphasis>prefer</emphasis> when creating IPSec tunnels.</para> |
|
200 |
+ <para><emphasis>Default value is empty string (null) - the last algorithm in the Sec-Agree header will be used.</emphasis></para> |
|
201 |
+ |
|
202 |
+ <example> |
|
203 |
+ <title><varname>ipsec_preferred_alg</varname> parameter usage</title> |
|
204 |
+ |
|
205 |
+ <programlisting format="linespecific"> |
|
206 |
+... |
|
207 |
+modparam("ims_ipsec_pcscf", "ipsec_preferred_alg", "hmac-sha-1-96") |
|
208 |
+... |
|
209 |
+ </programlisting> |
|
210 |
+ </example> |
|
211 |
+ </section> |
|
212 |
+ |
|
213 |
+ <section> |
|
214 |
+ <title><varname>ipsec_preferred_ealg</varname> (string)</title> |
|
215 |
+ |
|
216 |
+ <para>A name of an encrytion algorithm which the Proxy-CSCF will <emphasis>prefer</emphasis> when creating IPSec tunnels.</para> |
|
217 |
+ <para><emphasis>Default value is empty string (null) - the last algorithm in the Sec-Agree header will be used. Note that the possibility of it being the "null" algorithm is not insignificant.</emphasis></para> |
|
218 |
+ |
|
219 |
+ <example> |
|
220 |
+ <title><varname>ipsec_preferred_ealg</varname> parameter usage</title> |
|
221 |
+ |
|
222 |
+ <programlisting format="linespecific"> |
|
223 |
+... |
|
224 |
+modparam("ims_ipsec_pcscf", "ipsec_preferred_ealg", "aes-cbc") |
|
195 | 225 |
... |
196 | 226 |
</programlisting> |
197 | 227 |
</example> |
... | ... |
@@ -28,8 +28,6 @@ |
28 | 28 |
|
29 | 29 |
#include "cmd.h" |
30 | 30 |
#include "spi_gen.h" |
31 |
-#include "port_gen.h" |
|
32 |
- |
|
33 | 31 |
|
34 | 32 |
MODULE_VERSION |
35 | 33 |
|
... | ... |
@@ -45,6 +43,8 @@ int ipsec_reuse_server_port = 1; |
45 | 43 |
int ipsec_max_connections = 2; |
46 | 44 |
int spi_id_start = 100; |
47 | 45 |
int spi_id_range = 1000; |
46 |
+str ipsec_preferred_alg= STR_NULL; |
|
47 |
+str ipsec_preferred_ealg= STR_NULL; |
|
48 | 48 |
int xfrm_user_selector = 143956232; |
49 | 49 |
|
50 | 50 |
ip_addr_t ipsec_listen_ip_addr; |
... | ... |
@@ -92,6 +92,8 @@ static param_export_t params[] = { |
92 | 92 |
{"ipsec_max_connections", INT_PARAM, &ipsec_max_connections }, |
93 | 93 |
{"ipsec_spi_id_start", INT_PARAM, &spi_id_start }, |
94 | 94 |
{"ipsec_spi_id_range", INT_PARAM, &spi_id_range }, |
95 |
+ {"ipsec_preferred_alg", PARAM_STR, &ipsec_preferred_alg }, |
|
96 |
+ {"ipsec_preferred_ealg", PARAM_STR, &ipsec_preferred_ealg }, |
|
95 | 97 |
{0, 0, 0} |
96 | 98 |
}; |
97 | 99 |
|
... | ... |
@@ -302,16 +304,11 @@ static int mod_init(void) { |
302 | 304 |
} |
303 | 305 |
|
304 | 306 |
int res = 0; |
305 |
- if((res = init_spi_gen(spi_id_start, spi_id_range)) != 0) { |
|
307 |
+ if((res = init_spi_gen(spi_id_start, spi_id_range, ipsec_server_port, ipsec_client_port, ipsec_max_connections)) != 0) { |
|
306 | 308 |
LM_ERR("Error initialising spi generator. Error: %d\n", res); |
307 | 309 |
return -1; |
308 | 310 |
} |
309 | 311 |
|
310 |
- if((res = init_port_gen(ipsec_server_port, ipsec_client_port, ipsec_max_connections)) != 0) { |
|
311 |
- LM_ERR("Error initialising port generator. Error: %d\n", res); |
|
312 |
- return -1; |
|
313 |
- } |
|
314 |
- |
|
315 | 312 |
init_flag = 1; |
316 | 313 |
|
317 | 314 |
return 0; |
... | ... |
@@ -327,9 +324,6 @@ static void mod_destroy(void) |
327 | 324 |
LM_ERR("Error destroying spi generator\n"); |
328 | 325 |
} |
329 | 326 |
|
330 |
- if(destroy_port_gen() != 0){ |
|
331 |
- LM_ERR("Error destroying port generator\n"); |
|
332 |
- } |
|
333 | 327 |
} |
334 | 328 |
|
335 | 329 |
static int child_init(int rank) |
... | ... |
@@ -24,7 +24,6 @@ |
24 | 24 |
|
25 | 25 |
#include "ipsec.h" |
26 | 26 |
#include "spi_gen.h" |
27 |
-#include "port_gen.h" |
|
28 | 27 |
|
29 | 28 |
#include "../../core/dprint.h" |
30 | 29 |
#include "../../core/mem/pkg.h" |
... | ... |
@@ -205,7 +204,6 @@ int add_sa(struct mnl_socket* nl_sock, const struct ip_addr *src_addr_param, con |
205 | 204 |
return -1; |
206 | 205 |
} |
207 | 206 |
|
208 |
- |
|
209 | 207 |
mnl_attr_put(l_nlh, XFRMA_ALG_AUTH, sizeof(struct xfrm_algo) + l_auth_algo->alg_key_len, l_auth_algo); |
210 | 208 |
|
211 | 209 |
// add encription algorithm for this SA |
... | ... |
@@ -830,13 +828,7 @@ static int delete_unused_sa_cb(const struct nlmsghdr *nlh, void *data) |
830 | 828 |
|
831 | 829 |
// NOTE: Release the Proxy SPIs and Ports only here. Do not release the same SPIs and ports in delete unsused policy callback. |
832 | 830 |
// Release SPIs |
833 |
- release_spi(ipsec.spi_pc); |
|
834 |
- release_spi(ipsec.spi_ps); |
|
835 |
- |
|
836 |
- // Release the client and the server ports |
|
837 |
- release_cport(ipsec.port_pc); |
|
838 |
- release_sport(ipsec.port_ps); |
|
839 |
- |
|
831 |
+ release_spi(ipsec.spi_pc, ipsec.spi_ps, ipsec.port_pc, ipsec.port_ps); |
|
840 | 832 |
return MNL_CB_OK; |
841 | 833 |
} |
842 | 834 |
|
843 | 835 |
deleted file mode 100644 |
... | ... |
@@ -1,227 +0,0 @@ |
1 |
-/* |
|
2 |
- * IMS IPSEC PCSCF module |
|
3 |
- * |
|
4 |
- * Copyright (C) 2018 Tsvetomir Dimitrov |
|
5 |
- * Copyright (C) 2019 Aleksandar Yosifov |
|
6 |
- * |
|
7 |
- * This file is part of Kamailio, a free SIP server. |
|
8 |
- * |
|
9 |
- * Kamailio is free software; you can redistribute it and/or modify |
|
10 |
- * it under the terms of the GNU General Public License as published by |
|
11 |
- * the Free Software Foundation; either version 2 of the License, or |
|
12 |
- * (at your option) any later version |
|
13 |
- * |
|
14 |
- * Kamailio is distributed in the hope that it will be useful, |
|
15 |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
17 |
- * GNU General Public License for more details. |
|
18 |
- * |
|
19 |
- * You should have received a copy of the GNU General Public License |
|
20 |
- * along with this program; if not, write to the Free Software |
|
21 |
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
22 |
- * |
|
23 |
- */ |
|
24 |
- |
|
25 |
-#include "spi_gen.h" |
|
26 |
-#include "spi_list.h" |
|
27 |
-#include <pthread.h> |
|
28 |
-#include "../../core/mem/shm_mem.h" |
|
29 |
- |
|
30 |
-typedef struct port_generator{ |
|
31 |
- pthread_mutex_t sport_mut; // server port mutex |
|
32 |
- pthread_mutex_t cport_mut; // client port mutex |
|
33 |
- spi_list_t used_sports; // list with used server ports |
|
34 |
- spi_list_t used_cports; // list with used client ports |
|
35 |
- uint32_t sport_val; // the last acquired server port |
|
36 |
- uint32_t cport_val; // the last acquired client port |
|
37 |
- uint32_t min_sport; |
|
38 |
- uint32_t min_cport; |
|
39 |
- uint32_t max_sport; |
|
40 |
- uint32_t max_cport; |
|
41 |
-} port_generator_t; |
|
42 |
- |
|
43 |
-port_generator_t* port_data = NULL; |
|
44 |
- |
|
45 |
-int init_port_gen(uint32_t sport_start_val, uint32_t cport_start_val, uint32_t range) |
|
46 |
-{ |
|
47 |
- if(sport_start_val < 1 || cport_start_val < 1){ |
|
48 |
- return 1; |
|
49 |
- } |
|
50 |
- |
|
51 |
- if((UINT32_MAX - range < sport_start_val) || (UINT32_MAX - range < cport_start_val)){ |
|
52 |
- return 2; |
|
53 |
- } |
|
54 |
- |
|
55 |
- if(port_data){ |
|
56 |
- return 3; |
|
57 |
- } |
|
58 |
- |
|
59 |
- port_data = shm_malloc(sizeof(port_generator_t)); |
|
60 |
- if(port_data == NULL){ |
|
61 |
- return 4; |
|
62 |
- } |
|
63 |
- |
|
64 |
- if(pthread_mutex_init(&port_data->sport_mut, NULL)){ |
|
65 |
- shm_free(port_data); |
|
66 |
- return 5; |
|
67 |
- } |
|
68 |
- |
|
69 |
- if(pthread_mutex_init(&port_data->cport_mut, NULL)){ |
|
70 |
- pthread_mutex_destroy(&port_data->sport_mut); |
|
71 |
- shm_free(port_data); |
|
72 |
- return 6; |
|
73 |
- } |
|
74 |
- |
|
75 |
- port_data->used_sports = create_list(); |
|
76 |
- port_data->used_cports = create_list(); |
|
77 |
- |
|
78 |
- port_data->sport_val = port_data->min_sport = sport_start_val; |
|
79 |
- port_data->cport_val = port_data->min_cport = cport_start_val; |
|
80 |
- port_data->max_sport = sport_start_val + range; |
|
81 |
- port_data->max_cport = cport_start_val + range; |
|
82 |
- |
|
83 |
- return 0; |
|
84 |
-} |
|
85 |
- |
|
86 |
-uint32_t acquire_port(spi_list_t* used_ports, pthread_mutex_t* port_mut, uint32_t* port_val, uint32_t min_port, uint32_t max_port) |
|
87 |
-{ |
|
88 |
- //save the initial value for the highly unlikely case where there are no free PORTs |
|
89 |
- uint32_t initial_val = *port_val; |
|
90 |
- uint32_t ret = 0; // by default return invalid port |
|
91 |
- |
|
92 |
- if(pthread_mutex_lock(port_mut) != 0) { |
|
93 |
- return ret; |
|
94 |
- } |
|
95 |
- |
|
96 |
- while(1){ |
|
97 |
- if(spi_in_list(used_ports, *port_val) == 0) { |
|
98 |
- ret = *port_val; |
|
99 |
- (*port_val)++; |
|
100 |
- |
|
101 |
- if(*port_val >= max_port) { //reached the top of the range - reset |
|
102 |
- *port_val = min_port; |
|
103 |
- } |
|
104 |
- |
|
105 |
- break; |
|
106 |
- } |
|
107 |
- |
|
108 |
- (*port_val)++; //the current server port is not available - increment |
|
109 |
- |
|
110 |
- if(*port_val >= max_port) { //reached the top of the range - reset |
|
111 |
- *port_val = min_port; |
|
112 |
- } |
|
113 |
- |
|
114 |
- if(*port_val == initial_val) { //there are no free server ports |
|
115 |
- pthread_mutex_unlock(port_mut); |
|
116 |
- return ret; |
|
117 |
- } |
|
118 |
- } |
|
119 |
- |
|
120 |
- // found unused server port - add it to the used list |
|
121 |
- if(spi_add(used_ports, ret) != 0) { |
|
122 |
- ret = 0; |
|
123 |
- } |
|
124 |
- |
|
125 |
- pthread_mutex_unlock(port_mut); |
|
126 |
- return ret; |
|
127 |
-} |
|
128 |
- |
|
129 |
-uint32_t acquire_sport() |
|
130 |
-{ |
|
131 |
- if(!port_data){ |
|
132 |
- return 0; |
|
133 |
- } |
|
134 |
- |
|
135 |
- return acquire_port(&port_data->used_sports, &port_data->sport_mut, &port_data->sport_val, port_data->min_sport, port_data->max_sport); |
|
136 |
-} |
|
137 |
- |
|
138 |
-uint32_t acquire_cport() |
|
139 |
-{ |
|
140 |
- if(!port_data){ |
|
141 |
- return 0; |
|
142 |
- } |
|
143 |
- |
|
144 |
- return acquire_port(&port_data->used_cports, &port_data->cport_mut, &port_data->cport_val, port_data->min_cport, port_data->max_cport); |
|
145 |
-} |
|
146 |
- |
|
147 |
-int release_sport(uint32_t port) |
|
148 |
-{ |
|
149 |
- if(!port_data){ |
|
150 |
- return 1; |
|
151 |
- } |
|
152 |
- |
|
153 |
- if(pthread_mutex_lock(&port_data->sport_mut) != 0){ |
|
154 |
- return 1; |
|
155 |
- } |
|
156 |
- |
|
157 |
- spi_remove(&port_data->used_sports, port); |
|
158 |
- |
|
159 |
- pthread_mutex_unlock(&port_data->sport_mut); |
|
160 |
- return 0; |
|
161 |
-} |
|
162 |
- |
|
163 |
-int release_cport(uint32_t port) |
|
164 |
-{ |
|
165 |
- if(!port_data){ |
|
166 |
- return 1; |
|
167 |
- } |
|
168 |
- |
|
169 |
- if(pthread_mutex_lock(&port_data->cport_mut) != 0){ |
|
170 |
- return 1; |
|
171 |
- } |
|
172 |
- |
|
173 |
- spi_remove(&port_data->used_cports, port); |
|
174 |
- |
|
175 |
- pthread_mutex_unlock(&port_data->cport_mut); |
|
176 |
- return 0; |
|
177 |
-} |
|
178 |