Browse code

initial import of new H350 module

git-svn-id: https://openser.svn.sourceforge.net/svnroot/openser/trunk@2591 689a6050-402a-0410-94f2-e92a70836424

Cristian Schlatter authored on 10/08/2007 13:38:03
Showing 11 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,13 @@
1
+# $Id: $
2
+#
3
+# H350
4
+#
5
+# 
6
+# WARNING: do not run this directly, it should be run by the master Makefile
7
+
8
+include ../../Makefile.defs
9
+
10
+auto_gen=
11
+NAME=h350.so
12
+
13
+include ../../Makefile.modules
0 14
new file mode 100644
... ...
@@ -0,0 +1,695 @@
1
+
2
+H350 Module
3
+
4
+Christian Schlatter
5
+
6
+   University of North Carolina
7
+
8
+   Copyright � 2007 University of North Carolina
9
+     _________________________________________________________
10
+
11
+   Table of Contents
12
+   1. User's Guide
13
+
14
+        1.1. Overview
15
+
16
+              1.1.1. Example H.350 commObject LDAP Entry
17
+
18
+        1.2. Dependencies
19
+
20
+              1.2.1. OpenSER Modules
21
+              1.2.2. External Libraries or Applications
22
+
23
+        1.3. Exported Parameters
24
+
25
+              1.3.1. ldap_session (string)
26
+              1.3.2. base_dn (string)
27
+              1.3.3. search_scope (string)
28
+
29
+        1.4. Exported Functions
30
+
31
+              1.4.1. h350_sipuri_lookup(sip_uri)
32
+              1.4.2. h350_auth_lookup(auth_username,
33
+                      "username_avp_spec/pwd_avp_spec")
34
+
35
+              1.4.3.
36
+                      h350_result_call_preferences(avp_name_prefix)
37
+
38
+              1.4.4. h350_result_service_level(avp_name_prefix)
39
+
40
+   2. Developer's Guide
41
+   3. Frequently Asked Questions
42
+   Resources
43
+
44
+   List of Examples
45
+   1-1. Example H.350 commObject storing SIP account data
46
+   1-2. ldap_session parameter usage
47
+   1-3. base_dn parameter usage
48
+   1-4. search_scope parameter usage
49
+   1-5. Example Usage
50
+   1-6. Example Usage
51
+   1-7. Example H.350 callPreferenceURI simple call forwarding
52
+          rules
53
+
54
+   1-8. Example Usage
55
+   1-9. Example SIPIdentityServiceLevel values and resulting AVPs
56
+   1-10. Example Usage
57
+     _________________________________________________________
58
+
59
+Chapter 1. User's Guide
60
+
61
+1.1. Overview
62
+
63
+   The OpenSER H350 module enables an OpenSER SIP proxy server to
64
+   access SIP account data stored in an LDAP [RFC4510] directory
65
+   containing H.350 [H.350] commObjects. ITU-T Recommendation
66
+   H.350 standardizes LDAP object classes to store Real-Time
67
+   Communication (RTC) account data. In particular, H.350.4
68
+   [H.350.4] defines an object class called sipIdentity that
69
+   includes attribute specifications for SIP account data like
70
+   SIP URI, SIP digest username/password, or service level. This
71
+   allows to store SIP account data in a vendor neutral way and
72
+   lets different entities, like SIP proxies, provisioning, or
73
+   billing applications, access the data in a standardized
74
+   format.
75
+
76
+   The ViDe H.350 Cookbook [vide-h.350-cb] is a good reference
77
+   for deploying an H.350 directory. Besides general information
78
+   on H.350, LDAP, and related standards, this document explains
79
+   how to set up an H.350/LDAP directory and discusses different
80
+   deployment scenarios.
81
+
82
+   The H350 module uses the OpenSER LDAP module to import H.350
83
+   attribute values into the OpenSER routing script variable
84
+   space. The module exports functions to parse and store the
85
+   H.350 attribute values from the OpenSER routing script. It
86
+   allows a script writer to implement H.350 based SIP digest
87
+   authentication, call forwarding, SIP URI alias to AOR
88
+   rewriting, and service level parsing.
89
+     _________________________________________________________
90
+
91
+1.1.1. Example H.350 commObject LDAP Entry
92
+
93
+   The following example shows a typical H.350 commObject LDAP
94
+   entry storing SIP account data.
95
+
96
+   Example 1-1. Example H.350 commObject storing SIP account data
97
+Attribute Name                Attribute Value(s)
98
+--------------                -----------------
99
+
100
+# LDAP URI identifying the owner of this commObject, typically
101
+# points to an entry in the enterprise directory
102
+commOwner       ldap://dir.example.com/dc=example,dc=com??one?(uid=bob)
103
+
104
+
105
+# Unique identifier for this commObject, used for referencing
106
+# this object e.g. from the enterprise directory
107
+commUniqueId                  298217asdjgj213
108
+
109
+# Determines if this commObject should be listed on white pages
110
+commPrivate                   false
111
+
112
+# Valid SIP URIs for this account (can be used to store alias SIP URIs
113
+# like DIDs as well)
114
+SIPIdentitySIPURI             sip:bob@example.com
115
+                              sip:bob@alias.example.com
116
+                              sip:+1919123456@alias.example.com
117
+# SIP digest username
118
+SIPIdentityUserName           bob
119
+
120
+# SIP digest password
121
+SIPIdentityPassword           pwd
122
+
123
+# SIP proxy address
124
+SIPIdentityProxyAddress       sip.example.com
125
+
126
+# SIP registrar address
127
+SIPIdentityRegistrarAddress   sip.example.com
128
+
129
+# Call preferences: Forward to voicemail on no response
130
+# after 20 seconds and on busy
131
+callPreferenceURI             sip:bob@voicemail.example.com n:20000
132
+                              sip:bob@voicemail.example.com b
133
+
134
+# Account service level(s)
135
+SIPIdentityServiceLevel       long_distance
136
+                              conferencing
137
+
138
+# H.350 object classes
139
+objectClass                   top
140
+                              commObject
141
+                              SIPIdentity
142
+                              callPreferenceURIObject
143
+
144
+     _________________________________________________________
145
+
146
+1.2. Dependencies
147
+
148
+1.2.1. OpenSER Modules
149
+
150
+   The module depends on the following modules (the listed
151
+   modules must be loaded before this module):
152
+
153
+     * LDAP
154
+     _________________________________________________________
155
+
156
+1.2.2. External Libraries or Applications
157
+
158
+   The following libraries or applications must be installed
159
+   before running OpenSER with this module loaded:
160
+
161
+     * OpenLDAP library (libldap), libldap header files
162
+       (libldap-dev) are needed for compilation
163
+     _________________________________________________________
164
+
165
+1.3. Exported Parameters
166
+
167
+1.3.1. ldap_session (string)
168
+
169
+   Name of the LDAP session to be used for H.350 queries, as
170
+   defined in the LDAP module configuration file.
171
+
172
+   Default value: ""
173
+
174
+   Example 1-2. ldap_session parameter usage
175
+modparam("h350", "ldap_session", "h350");
176
+
177
+     _________________________________________________________
178
+
179
+1.3.2. base_dn (string)
180
+
181
+   Base LDAP DN to start LDAP search for H.350 entries. For best
182
+   performance, this should be set to the direct ancestor of the
183
+   H.350 objects.
184
+
185
+   Default value: ""
186
+
187
+   Example 1-3. base_dn parameter usage
188
+modparam("h350", "base_dn", "ou=h350,dc=example,dc=com");
189
+
190
+     _________________________________________________________
191
+
192
+1.3.3. search_scope (string)
193
+
194
+   LDAP search scope for H.350 queries, one of "one", "base", or
195
+   "sub".
196
+
197
+   Default value: "one"
198
+
199
+   Example 1-4. search_scope parameter usage
200
+modparam("h350", "search_scope", "sub");
201
+
202
+     _________________________________________________________
203
+
204
+1.4. Exported Functions
205
+
206
+1.4.1. h350_sipuri_lookup(sip_uri)
207
+
208
+   This function performs an LDAP search query for an H.350
209
+   commObject with a SIPIdentitySIPURI of sip_uri. The sip_uri
210
+   parameter first gets escaped according the rules for LDAP
211
+   filter strings. The result of the LDAP search is stored
212
+   internally and can be accessed either by one of the
213
+   h350_result* or one of the ldap_result* functions from the
214
+   OpenSER LDAP module.
215
+
216
+   The function returns -1 (FALSE) for internal errors, and -2
217
+   (FALSE) if no H.350 commObject was found with a matching
218
+   sip_uri. n > 0 (TRUE) is returned if n H.350 commObjects were
219
+   found.
220
+
221
+   This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
222
+   FAILURE_ROUTE and BRANCH_ROUTE.
223
+
224
+   Function Parameters:
225
+
226
+   sip_uri
227
+          H.350 SIPIdentitySIPURI to search for in directory.
228
+          Included OpenSER variables do get expanded.
229
+
230
+   Return Values:
231
+
232
+   n > 0 (TRUE):
233
+
234
+          + n H.350 commObjects found.
235
+
236
+   -1 (FALSE):
237
+
238
+          + Internal error occurred.
239
+
240
+   -2 (FALSE):
241
+
242
+          + No H.350 commObject found.
243
+
244
+   Example 1-5. Example Usage
245
+#
246
+# H.350 lookup for callee
247
+#
248
+
249
+if (!h350_sipuri_lookup("sip:$rU@$rd"))
250
+{
251
+    switch ($retcode)
252
+    {
253
+    case -2:
254
+        xlog("L_INFO",
255
+             "h350 callee lookup: no entry found in H.350 directory");
256
+        exit;
257
+    case -1:
258
+        sl_send_reply("500", "Internal server error");
259
+        exit;
260
+    }
261
+}
262
+
263
+# now h350_result* or ldap_result* functions can be used
264
+
265
+     _________________________________________________________
266
+
267
+1.4.2. h350_auth_lookup(auth_username,
268
+"username_avp_spec/pwd_avp_spec")
269
+
270
+   This function performs an LDAP search query for SIP digest
271
+   authentication credentials in an H.350 directory. The H.350
272
+   directory is searched for a commObject with
273
+   SIPIdentityUserName of auth_username. If such a commObject is
274
+   found, the SIP digest authentication username and password are
275
+   stored in AVPs username_avp_spec and pwd_avp_spec,
276
+   respectively. pv_*_authorize functions from AUTH module can
277
+   then be used to perform SIP digest authentication.
278
+
279
+   The function returns 1 (TRUE) if an H.350 commObject was
280
+   found, -1 (FALSE) in case of an internal error, and -2 (FALSE)
281
+   if no matching commObject was found.
282
+
283
+   This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
284
+   FAILURE_ROUTE and BRANCH_ROUTE.
285
+
286
+   Function Parameters:
287
+
288
+   auth_username
289
+          H.350 SIPIdentityUserName to search for in directory.
290
+          Included OpenSER variables do get expanded.
291
+
292
+   username_avp_spec
293
+          Specification for authentication username AVP, e.g.
294
+          $avp(s:username).
295
+
296
+   pwd_avp_spec
297
+          Specification for authentication password AVP, e.g.
298
+          $avp(s:pwd).
299
+
300
+   Return Values:
301
+
302
+   1 (TRUE):
303
+
304
+          + H.350 commObject found and SIP digest authentication
305
+            credentials stored in username_avp_spec and
306
+            pwd_avp_spec.
307
+
308
+   -1 (FALSE):
309
+
310
+          + Internal error occurred.
311
+
312
+   -2 (FALSE):
313
+
314
+          + No H.350 commObject found.
315
+
316
+   Example 1-6. Example Usage
317
+# -- auth params --
318
+modparam("auth", "username_spec", "$avp(s:auth_user)")
319
+modparam("auth", "password_spec", "$avp(s:auth_pwd)")
320
+modparam("auth", "calculate_ha1", 1)
321
+
322
+# -- h350 params --
323
+modparam("h350", "ldap_session", "h350")
324
+modparam("h350", "base_dn", "ou=h350,dc=example,dc=com")
325
+modparam("h350", "search_scope", "one")
326
+
327
+
328
+route[1]
329
+{
330
+    #
331
+    # H.350 based SIP digest authentication
332
+    #
333
+
334
+    # challenge all requests not including an Auth header
335
+    if (!(is_present_hf("Authorization") ||
336
+          is_present_hf("Proxy-Authorization")))
337
+    {
338
+        if (is_method("REGISTER"))
339
+        {
340
+            www_challenge("example.com", "0");
341
+            exit;
342
+        }
343
+        proxy_challenge("example.com", "0");
344
+        exit;
345
+    }
346
+
347
+    # get digest password from H.350 using auth username ($au)
348
+    if (!h350_auth_lookup("$au",
349
+                          "$avp(s:auth_user)/$avp(s:auth_pwd)"))
350
+    {
351
+        switch ($retcode)
352
+        {
353
+        case -2:
354
+            sl_send_reply("401", "Unauthorized");
355
+            exit;
356
+        case -1:
357
+            sl_send_reply("500", "Internal server error");
358
+            exit;
359
+        }
360
+    }
361
+
362
+    # REGISTER requests
363
+    if (is_method("REGISTER"))
364
+    {
365
+        if (!pv_www_authorize("example.com"))
366
+        {
367
+            if ($retcode == -5)
368
+            {
369
+                sl_send_reply("500", "Internal server error");
370
+                exit;
371
+            }
372
+            else {
373
+                www_challenge("example.com", "0");
374
+                exit;
375
+            }
376
+        }
377
+
378
+        consume_credentials();
379
+        xlog("L_INFO",
380
+             "REGISTER request successfully authenticated");
381
+        return(1);
382
+    }
383
+
384
+    # non-REGISTER requests
385
+    if (!pv_proxy_authorize("example.com"))
386
+    {
387
+        if ($retcode == -5)
388
+        {
389
+            sl_send_reply("500", "Internal server error");
390
+            exit;
391
+        }
392
+        else {
393
+            proxy_challenge("example.com", "0");
394
+            exit;
395
+        }
396
+    }
397
+
398
+    consume_credentials();
399
+    xlog("L_INFO", "$rm request successfully authenticated");
400
+    return(1);
401
+}
402
+
403
+     _________________________________________________________
404
+
405
+1.4.3. h350_result_call_preferences(avp_name_prefix)
406
+
407
+   This function parses the callPreferenceURI attribute of an
408
+   H.350 commObject, which must have been fetched through
409
+   h350_*_lookup or ldap_search. callPreferenceURI is a
410
+   multi-valued attribute that stores call preference rules like
411
+   e.g. forward-on-busy or forward-unconditionally. Directory
412
+   services architecture for call forwarding and preferences
413
+   [H.350.6] defines a format for simple call forwarding rules:
414
+
415
+     target_uri type[:argument]
416
+
417
+   In a SIP environment, target_uri is typically the call
418
+   forwarding rule's target SIP URI, although it could be any
419
+   type of URI, e.g. an HTTP pointer to a CPL script. Four
420
+   different values are specified for type: b for "forward on
421
+   busy", n for "forward on no answer", u for "forward
422
+   unconditionally", and f for "forward on destination not
423
+   found". The optional argument is a string indicating the time
424
+   in milliseconds after which the call forwarding should occur.
425
+
426
+   Example 1-7. Example H.350 callPreferenceURI simple call
427
+   forwarding rules
428
+# Example 1:
429
+# forward to sip:voicemail@example.com on no answer after 15 seconds:
430
+
431
+callPreferenceURI: sip:voicemail@example.com n:15000
432
+
433
+# Example 2:
434
+# unconditionally forward to sip:alice@example.com:
435
+
436
+callPreferenceURI: sip:alice@example.com u
437
+
438
+# Example 3:
439
+# forward to sip:bob@example.com and sip:alice@example.com
440
+# (forking) on destination not found:
441
+
442
+callPreferenceURI: sip:bob@example.com f
443
+callPreferenceURI: sip:alice@example.com f
444
+
445
+
446
+   h350_result_call_preferences stores these call forwarding
447
+   rules as AVPs according to the following rules:
448
+
449
+#
450
+# AVP storing a forwarding rule's target URI
451
+#
452
+
453
+AVP name  = avp_name_prefix + '_' + type
454
+AVP value = target_uri
455
+
456
+#
457
+# AVP storing a forwarding rule's argument
458
+#
459
+
460
+AVP name  = avp_name_prefix + '_' + type + '_t'
461
+AVP value = argument / 1000
462
+
463
+
464
+   Example 1 from above would result in two AVPs:
465
+   $avp("s:prefix_n") = "sip:voicemail@example.com" and
466
+   $avp("s:prefix_n_t") = 15.
467
+
468
+   Example 2: $avp("s:prefix_u") = "sip:alice@example.com".
469
+
470
+   Example 3: $avp("s:prefix_f[1]") = "sip:bob@example.com" and
471
+   $avp("s:prefix_f[2]]") = "sip:alice@example.com".
472
+
473
+   These AVPs can then be used to implement the desired behavior
474
+   in the OpenSER routing script.
475
+
476
+   This function returns the number of successfully parsed simple
477
+   call forwarding rules (TRUE), in case the H.350
478
+   callPreferenceURI attribute contained one or multiple values
479
+   matching the simple call forwarding rule syntax described
480
+   above. It returns -1 (FALSE) for internal errors, and -2
481
+   (FALSE) if none of the rules matched or if no
482
+   callPreferenceURI attribute was found.
483
+
484
+   This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
485
+   FAILURE_ROUTE and BRANCH_ROUTE.
486
+
487
+   Function Parameters:
488
+
489
+   avp_name_prefix
490
+          Name prefix for call forwarding rule AVPs, as described
491
+          above.
492
+
493
+   Return Values:
494
+
495
+   n > 0 (TRUE):
496
+
497
+          + n simple call forwarding rules found.
498
+
499
+   -1 (FALSE):
500
+
501
+          + Internal error occurred.
502
+
503
+   -2 (FALSE):
504
+
505
+          + No simple call forwarding rule found, or
506
+            callPreferenceURI not present.
507
+
508
+   Example 1-8. Example Usage
509
+#
510
+# H.350 lookup for callee
511
+#
512
+
513
+... h350_sipuri_lookup("sip:$rU@$rd") ...
514
+
515
+#
516
+# store H.350 call preferences in AVP
517
+#
518
+
519
+if (!h350_result_call_preferences("callee_pref_") && ($retcode == -1))
520
+{
521
+    sl_send_reply("500", "Internal server error");
522
+    exit;
523
+}
524
+
525
+# $avp(s:callee_pref_u)   == CFU URI(s)
526
+# $avp(s:callee_pref_n)   == CFNR URI(s)
527
+# $avp(s:callee_pref_n_t) == CFNR timeout in seconds
528
+# $avp(s:callee_pref_b)   == CFB URI(s)
529
+# $avp(s:callee_pref_f)   == CFOFFLINE URI(s)
530
+
531
+#
532
+# Example for forward-unconditionally (CFU)
533
+#
534
+
535
+if (is_avp_set("$avp(s:callee_pref_u)"))
536
+{
537
+    # replace R-URI with CFU URI, g will fetch all CFU URIs
538
+    # --> request can fork
539
+    if (avp_pushto("$ru", "$avp(s:callee_pref_u)/g"))
540
+    {
541
+            avp_delete("$avp(s:callee_pref_u)");
542
+    } else
543
+    {
544
+            sl_send_reply("500", "Internal server error");
545
+            exit;
546
+    }
547
+    sl_send_reply("181", "Call is being forwarded");
548
+    t_relay();
549
+    exit;
550
+}
551
+
552
+     _________________________________________________________
553
+
554
+1.4.4. h350_result_service_level(avp_name_prefix)
555
+
556
+   Directory services architecture for SIP [H.350.4] defines a
557
+   multi-valued LDAP attribute named SIPIdentityServiceLevel,
558
+   which can be used to store SIP account service level values in
559
+   an LDAP directory. This function parses the
560
+   SIPIdentityServiceLevel attribute and stores all service level
561
+   values as AVPs for later retrieval in the OpenSER routing
562
+   script. The function accesses the H.350 commObject fetched by
563
+   a call to h350_*_lookup or ldap_search.
564
+
565
+   The resulting AVPs have a name of the form avp_name_prefix +
566
+   SIPIdentityServiceLevel attribute value, and an integer value
567
+   of 1.
568
+
569
+   Example 1-9. Example SIPIdentityServiceLevel values and
570
+   resulting AVPs
571
+SIPIdentityServiceLevel: longdistance
572
+SIPIdentityServiceLevel: international
573
+SIPIdentityServiceLevel: 900
574
+
575
+after calling h350_result_service_level("sl_"), the following AVPs
576
+will be available in the routing script:
577
+
578
+$avp("s:sl_longdistance") = 1
579
+$avp("s:sl_international") = 1
580
+$avp("s:sl_900") = 1
581
+
582
+
583
+   This function returns the number of added AVPs (TRUE), -1
584
+   (FALSE)for internal errors, and -2 (FALSE)if no
585
+   SIPIdentityServiceLevel attribute was found.
586
+
587
+   The function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
588
+   FAILURE_ROUTE and BRANCH_ROUTE.
589
+
590
+   Function Parameters:
591
+
592
+   avp_name_prefix
593
+          Name prefix for service level AVPs, as described above.
594
+
595
+   Return Values:
596
+
597
+   n > 0 (TRUE):
598
+
599
+          + n AVPs added.
600
+
601
+   -1 (FALSE):
602
+
603
+          + Internal error occurred.
604
+
605
+   -2 (FALSE):
606
+
607
+          + No SIPIdentityServiceLevel attribute found.
608
+
609
+   Example 1-10. Example Usage
610
+#
611
+# H.350 SIP digest authentication for caller
612
+#
613
+
614
+... h350_auth_lookup("$au", ...) ...
615
+
616
+#
617
+# store caller's service level as AVP
618
+#
619
+
620
+if (!h350_result_service_level("caller_sl_") && ($retcode == -1))
621
+{
622
+    sl_send_reply("500", "Internal server error");
623
+    exit;
624
+}
625
+
626
+#
627
+# make routing decision based on service level AVPs
628
+#
629
+
630
+if (is_avp_set("$avp(s:caller_sl_international)"))
631
+{
632
+    t_relay();
633
+}
634
+else {
635
+    sl_send_reply("403", "Forbidden");
636
+}
637
+exit;
638
+
639
+     _________________________________________________________
640
+
641
+Chapter 2. Developer's Guide
642
+
643
+   The module does not provide any API to use in other OpenSER
644
+   modules.
645
+     _________________________________________________________
646
+
647
+Chapter 3. Frequently Asked Questions
648
+
649
+   3.1. Where can I find more about OpenSER?
650
+   3.2. Where can I post a question about this module?
651
+   3.3. How can I report a bug?
652
+
653
+   3.1. Where can I find more about OpenSER?
654
+
655
+   Take a look at http://openser.org/.
656
+
657
+   3.2. Where can I post a question about this module?
658
+
659
+   First at all check if your question was already answered on
660
+   one of our mailing lists:
661
+
662
+     * User Mailing List -
663
+       http://openser.org/cgi-bin/mailman/listinfo/users
664
+     * Developer Mailing List -
665
+       http://openser.org/cgi-bin/mailman/listinfo/devel
666
+
667
+   E-mails regarding any stable OpenSER release should be sent to
668
+   <users@openser.org> and e-mails regarding development versions
669
+   should be sent to <devel@openser.org>.
670
+
671
+   If you want to keep the mail private, send it to
672
+   <team@openser.org>.
673
+
674
+   3.3. How can I report a bug?
675
+
676
+   Please follow the guidelines provided at:
677
+   http://sourceforge.net/tracker/?group_id=139143.
678
+     _________________________________________________________
679
+
680
+Resources
681
+
682
+   [H.350] Directory Services Architecture for Multimedia
683
+   Conferencing, August 2003, ITU-T.
684
+
685
+   [H.350.4] Directory services architecture for SIP, August
686
+   2003, ITU-T.
687
+
688
+   [H.350.6] Directory services architecture for call forwarding
689
+   and preferences, March 2004, ITU-T.
690
+
691
+   [ViDe-H.350-Cookbook] ViDe H.350 Cookbook, 2005, ViDe.
692
+
693
+   [RFC4510] Lightweight Directory Access Protocol (LDAP):
694
+   Technical Specification Road Map, June 2006, Internet
695
+   Engineering Task Force.
0 696
new file mode 100644
... ...
@@ -0,0 +1,45 @@
1
+<!DOCTYPE Book PUBLIC "-//OASIS//DTD DocBook V4.2//EN" [
2
+
3
+<!ENTITY user SYSTEM "h350_user.sgml">
4
+<!ENTITY devel SYSTEM "h350_devel.sgml">
5
+<!ENTITY faq SYSTEM "h350_faq.sgml">
6
+<!ENTITY biblio SYSTEM "h350_biblio.sgml">
7
+
8
+<!-- Include general documentation entities -->
9
+<!ENTITY % docentities SYSTEM "../../../doc/entities.sgml">
10
+%docentities;
11
+
12
+]>
13
+
14
+<book>
15
+        <bookinfo>
16
+        <title>H350 Module</title>
17
+        <productname class="trade">&ser;</productname>
18
+        <authorgroup>
19
+                <author>
20
+                <firstname>Christian</firstname>
21
+                <surname>Schlatter</surname>
22
+                <affiliation><orgname>University of North Carolina</orgname></affiliation>
23
+                <email>cs@unc.edu</email>
24
+                </author>
25
+        </authorgroup>
26
+        <copyright>
27
+                <year>2007</year>
28
+                <holder>University of North Carolina</holder>
29
+        </copyright>
30
+        <revhistory>
31
+                <revision>
32
+                <revnumber>0.1</revnumber>
33
+                <date>05-17-2007</date>
34
+                </revision>
35
+        </revhistory>
36
+        </bookinfo>
37
+        <toc></toc>
38
+
39
+        &user;
40
+        &devel;
41
+        &faq;
42
+		&biblio;
43
+
44
+</book>
45
+
0 46
new file mode 100644
... ...
@@ -0,0 +1,77 @@
1
+
2
+  <bibliography>
3
+    <title>Resources</title>
4
+
5
+    <bibliodiv>
6
+      <biblioentry id="H350" xreflabel="[H.350]">
7
+        <abbrev>H.350</abbrev>
8
+
9
+        <title><ulink url="http://www.itu.int/rec/T-REC-H.350/en">Directory
10
+        Services Architecture for Multimedia Conferencing</ulink></title>
11
+
12
+        <date>August 2003</date>
13
+
14
+        <publisher>
15
+          <publishername>ITU-T</publishername>
16
+        </publisher>
17
+      </biblioentry>
18
+
19
+      <biblioentry id="H350-4" xreflabel="[H.350.4]">
20
+        <abbrev>H.350.4</abbrev>
21
+
22
+        <title><ulink url="http://www.itu.int/rec/T-REC-H.350.4/en">Directory
23
+        services architecture for SIP</ulink></title>
24
+
25
+        <date>August 2003</date>
26
+
27
+        <publisher>
28
+          <publishername>ITU-T</publishername>
29
+        </publisher>
30
+      </biblioentry>
31
+      
32
+      <biblioentry id="H350-6" xreflabel="[H.350.6]">
33
+        <abbrev>H.350.6</abbrev>
34
+
35
+        <title><ulink url="http://www.itu.int/rec/T-REC-H.350.6/en">Directory services architecture for call forwarding and preferences</ulink></title>
36
+
37
+        <date>March 2004</date>
38
+
39
+        <publisher>
40
+          <publishername>ITU-T</publishername>
41
+        </publisher>
42
+      </biblioentry>
43
+      
44
+      <biblioentry id="vide-H350-cookbook" xreflabel="[vide-h.350-cb]">
45
+        <abbrev>ViDe-H.350-Cookbook</abbrev>
46
+
47
+        <title><ulink url="http://www.vide.net/cookbookh350/">ViDe H.350 Cookbook</ulink></title>
48
+
49
+        <date>2005</date>
50
+
51
+        <publisher>
52
+          <publishername>ViDe</publishername>
53
+        </publisher>
54
+      </biblioentry>
55
+        
56
+      <biblioentry id="RFC4510" xreflabel="[RFC4510]">
57
+        <abbrev>RFC4510</abbrev>
58
+
59
+        <title><ulink url="http://tools.ietf.org/html/rfc4510">Lightweight
60
+        Directory Access Protocol (LDAP): Technical Specification Road
61
+        Map</ulink></title>
62
+
63
+        <date>June 2006</date>
64
+
65
+        <publisher>
66
+          <publishername>Internet Engineering Task Force</publishername>
67
+        </publisher>
68
+      </biblioentry>
69
+
70
+    </bibliodiv>
71
+  </bibliography>
72
+
73
+<!-- Keep this element at the end of the file
74
+Local Variables:
75
+sgml-parent-document: ("ldap_h350.sgml" "Book" "chapter")
76
+End:
77
+-->
0 78
new file mode 100644
... ...
@@ -0,0 +1,15 @@
1
+<!-- LDAP_H350 Module Developer's Guide -->
2
+
3
+<chapter>
4
+    <title>Developer's Guide</title>
5
+    <para>
6
+        The module does not provide any <acronym>API</acronym> to use in other &ser; modules.
7
+    </para>
8
+</chapter>
9
+
10
+<!-- Keep this element at the end of the file
11
+Local Variables:
12
+sgml-parent-document: ("ldap_h350.sgml" "book" "chapter")
13
+End:
14
+-->
15
+
0 16
new file mode 100644
... ...
@@ -0,0 +1,60 @@
1
+<chapter>
2
+    <title>Frequently Asked Questions</title>
3
+    <qandaset defaultlabel="number">
4
+        <qandaentry>
5
+            <question>
6
+                <para>Where can I find more about OpenSER?</para>
7
+            </question>
8
+            <answer>
9
+                <para>
10
+                        Take a look at &serhomelink;.
11
+                </para>
12
+            </answer>
13
+        </qandaentry>
14
+        <qandaentry>
15
+            <question>
16
+                <para>Where can I post a question about this module?</para>
17
+            </question>
18
+            <answer>
19
+                <para>
20
+                        First at all check if your question was already answered on one of
21
+                        our mailing lists:
22
+                </para>
23
+                <itemizedlist>
24
+                    <listitem>
25
+                        <para>User Mailing List - &seruserslink;</para>
26
+                    </listitem>
27
+                    <listitem>
28
+                        <para>Developer Mailing List - &serdevlink;</para>
29
+                    </listitem>
30
+                </itemizedlist>
31
+                <para>
32
+                        E-mails regarding any stable &ser; release should be sent to
33
+                        &serusersmail; and e-mails regarding development versions
34
+                        should be sent to &serdevmail;.
35
+                </para>
36
+                <para>
37
+                        If you want to keep the mail private, send it to
38
+                        &serhelpmail;.
39
+                </para>
40
+            </answer>
41
+        </qandaentry>
42
+        <qandaentry>
43
+            <question>
44
+                <para>How can I report a bug?</para>
45
+            </question>
46
+            <answer>
47
+                <para>
48
+                        Please follow the guidelines provided at:
49
+                        &serbugslink;.
50
+                </para>
51
+            </answer>
52
+        </qandaentry>
53
+    </qandaset>
54
+</chapter>
55
+
56
+<!-- Keep this element at the end of the file
57
+Local Variables:
58
+sgml-parent-document: ("ldap_h350.sgml" "Book" "chapter")
59
+End:
60
+-->
0 61
new file mode 100644
... ...
@@ -0,0 +1,802 @@
1
+<chapter>
2
+    <title>User's Guide</title>
3
+
4
+    <section>
5
+        <title>Overview</title>
6
+
7
+        <para>
8
+            The OpenSER H350 module enables an OpenSER SIP proxy server to access SIP account data stored in an LDAP <xref linkend="RFC4510" > directory containing H.350 <xref linkend="H350" > <emphasis>commObjects</emphasis>. ITU-T Recommendation H.350 standardizes LDAP object classes to store Real-Time Communication (RTC) account data. In particular, <emphasis>H.350.4</emphasis> <xref linkend="H350-4" > defines an object class called <emphasis>sipIdentity</emphasis> that includes attribute specifications for SIP account data like SIP URI, SIP digest username/password, or service level. This allows to store SIP account data in a vendor neutral way and lets different entities, like SIP proxies, provisioning, or billing applications, access the data in a standardized format.  
9
+        </para>
10
+        
11
+        <para>
12
+            The <emphasis>ViDe H.350 Cookbook</emphasis> <xref linkend="vide-H350-cookbook">  is a good reference for deploying an H.350 directory. Besides general information on H.350, LDAP, and related standards, this document explains how to set up an H.350/LDAP directory and discusses different deployment scenarios.    
13
+        </para>
14
+        
15
+        <para>
16
+            The H350 module uses the OpenSER LDAP module to import H.350 attribute values into the OpenSER routing script variable space. The module exports functions to parse and store the H.350 attribute values from the OpenSER routing script. It allows a script writer to implement H.350 based SIP digest authentication, call forwarding, SIP URI alias to AOR rewriting, and service level parsing. 
17
+        </para>
18
+
19
+    <section>
20
+        <title>Example H.350 commObject LDAP Entry</title>
21
+        
22
+        <para>
23
+            The following example shows a typical H.350 commObject LDAP entry storing SIP account data.
24
+        </para>
25
+        
26
+        <example>
27
+            <title>Example H.350 commObject storing SIP account data</title>
28
+
29
+            <programlisting>
30
+Attribute Name                Attribute Value(s)
31
+--------------                -----------------
32
+
33
+# LDAP URI identifying the owner of this commObject, typically 
34
+# points to an entry in the enterprise directory
35
+commOwner	ldap://dir.example.com/dc=example,dc=com??one?(uid=bob)	
36
+
37
+# Unique identifier for this commObject, used for referencing 
38
+# this object e.g. from the enterprise directory 
39
+commUniqueId                  298217asdjgj213	
40
+
41
+# Determines if this commObject should be listed on white pages
42
+commPrivate                   false
43
+
44
+# Valid SIP URIs for this account (can be used to store alias SIP URIs 
45
+# like DIDs as well)
46
+SIPIdentitySIPURI             sip:bob@example.com                 
47
+                              sip:bob@alias.example.com
48
+                              sip:+1919123456@alias.example.com
49
+# SIP digest username	
50
+SIPIdentityUserName           bob
51
+
52
+# SIP digest password
53
+SIPIdentityPassword           pwd
54
+
55
+# SIP proxy address
56
+SIPIdentityProxyAddress       sip.example.com
57
+
58
+# SIP registrar address
59
+SIPIdentityRegistrarAddress   sip.example.com
60
+
61
+# Call preferences: Forward to voicemail on no response 
62
+# after 20 seconds and on busy
63
+callPreferenceURI             sip:bob@voicemail.example.com n:20000
64
+                              sip:bob@voicemail.example.com b
65
+	
66
+# Account service level(s)
67
+SIPIdentityServiceLevel	      long_distance
68
+                              conferencing
69
+                              
70
+# H.350 object classes
71
+objectClass                   top
72
+                              commObject
73
+                              SIPIdentity
74
+                              callPreferenceURIObject
75
+            </programlisting>
76
+        </example>
77
+      </section>
78
+    </section>
79
+
80
+    <section>
81
+      <title>Dependencies</title>
82
+
83
+      <section>
84
+        <title>OpenSER Modules</title>
85
+
86
+        <para>The module depends on the following modules (the listed modules
87
+        must be loaded before this module):</para>
88
+
89
+        <itemizedlist>
90
+          <listitem>
91
+            <para>LDAP</para>
92
+          </listitem>
93
+        </itemizedlist>
94
+      </section>
95
+
96
+      <section>
97
+        <title>External Libraries or Applications</title>
98
+
99
+        <para>The following libraries or applications must be installed before
100
+        running OpenSER with this module loaded:</para>
101
+
102
+        <itemizedlist>
103
+          <listitem>
104
+            <para>OpenLDAP library (libldap), libldap header files
105
+            (libldap-dev) are needed for compilation</para>
106
+          </listitem>
107
+        </itemizedlist>
108
+      </section>
109
+</section>
110
+
111
+<section>
112
+    <title>Exported Parameters</title>
113
+
114
+    <section>
115
+        <title>ldap_session (string)</title>
116
+
117
+        <para>
118
+            Name of the LDAP session to be used for H.350 queries, as defined in the LDAP module configuration file.
119
+        </para>
120
+
121
+        <para>
122
+            Default value: ""
123
+        </para>
124
+
125
+        <example>
126
+            <title><varname>ldap_session</varname> parameter usage</title>
127
+
128
+            <programlisting>
129
+modparam("h350", "ldap_session", "h350");
130
+            </programlisting>
131
+        </example>
132
+    </section>
133
+    
134
+    <section>
135
+        <title>base_dn (string)</title>
136
+
137
+        <para>
138
+            Base LDAP DN to start LDAP search for H.350 entries. For best performance, this should be set to the direct ancestor of the H.350 objects.
139
+        </para>
140
+
141
+        <para>
142
+            Default value: ""
143
+        </para>
144
+
145
+        <example>
146
+            <title><varname>base_dn</varname> parameter usage</title>
147
+
148
+            <programlisting>
149
+modparam("h350", "base_dn", "ou=h350,dc=example,dc=com");
150
+            </programlisting>
151
+        </example>
152
+    </section>
153
+    
154
+    <section>
155
+        <title>search_scope (string)</title>
156
+
157
+        <para>
158
+            LDAP search scope for H.350 queries, one of "one", "base", or "sub".
159
+        </para>
160
+
161
+        <para>
162
+            Default value: "one"
163
+        </para>
164
+
165
+        <example>
166
+            <title><varname>search_scope</varname> parameter usage</title>
167
+
168
+            <programlisting>
169
+modparam("h350", "search_scope", "sub");
170
+            </programlisting>
171
+        </example>
172
+    </section>
173
+</section>
174
+
175
+<section>
176
+    <title>Exported Functions</title>
177
+
178
+    <section>
179
+        <title>h350_sipuri_lookup(sip_uri)</title>
180
+        
181
+        <para>
182
+            This function performs an LDAP search query for an H.350 commObject with a SIPIdentitySIPURI of <varname>sip_uri</varname>. The <varname>sip_uri</varname> parameter first gets escaped according the rules for LDAP filter strings. The result of the LDAP search is stored internally and can be accessed either by one of the <emphasis>h350_result*</emphasis> or one of the <emphasis>ldap_result*</emphasis> functions from the OpenSER LDAP module.
183
+        </para>
184
+        
185
+        <para>
186
+            The function returns <varname>-1</varname> (FALSE) for internal errors, and <varname>-2</varname> (FALSE) if no H.350 commObject was found with a matching <varname>sip_uri</varname>. <varname>n</varname> &gt; 0 (TRUE) is returned if <varname>n</varname> H.350 commObjects were found.
187
+        </para>
188
+        
189
+        <para>
190
+            This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE and BRANCH_ROUTE.
191
+        </para>
192
+
193
+        <variablelist>
194
+            <title>Function Parameters:</title>
195
+
196
+            <varlistentry>
197
+                <term>sip_uri</term>
198
+
199
+                <listitem>
200
+                    <para>
201
+                        H.350 SIPIdentitySIPURI to search for in directory. Included OpenSER variables do get expanded.
202
+                    </para>
203
+                </listitem>
204
+            </varlistentry>
205
+        </variablelist>
206
+
207
+        <variablelist>
208
+            <title>Return Values:</title>
209
+
210
+            <varlistentry>
211
+                <term><varname>n</varname> &gt; 0 (TRUE):</term>
212
+
213
+                <listitem>
214
+                    <itemizedlist>
215
+                        <listitem>
216
+                            <para>
217
+                                <varname>n</varname> H.350 commObjects found.
218
+                            </para>
219
+                        </listitem>
220
+                    </itemizedlist>
221
+                </listitem>
222
+            </varlistentry>
223
+
224
+            <varlistentry>
225
+                <term><constant>-1</constant> (FALSE):</term>
226
+
227
+                <listitem>
228
+                    <itemizedlist>
229
+                        <listitem>
230
+                            <para>
231
+                                Internal error occurred.
232
+                            </para>
233
+                        </listitem>
234
+                    </itemizedlist>
235
+                </listitem>
236
+            </varlistentry>
237
+            
238
+            <varlistentry>
239
+                <term><constant>-2</constant> (FALSE):</term>
240
+
241
+                <listitem>
242
+                    <itemizedlist>
243
+                        <listitem>
244
+                            <para>
245
+                                No H.350 commObject found.
246
+                            </para>
247
+                        </listitem>
248
+                    </itemizedlist>
249
+                </listitem>
250
+            </varlistentry>
251
+        </variablelist>
252
+
253
+        <example>
254
+            <title>Example Usage</title>
255
+
256
+            <programlisting>
257
+#
258
+# H.350 lookup for callee
259
+#
260
+
261
+if (!h350_sipuri_lookup("sip:$rU@$rd"))
262
+{
263
+    switch ($retcode)
264
+    {
265
+    case -2:
266
+        xlog("L_INFO", 
267
+             "h350 callee lookup: no entry found in H.350 directory");
268
+        exit;
269
+    case -1:
270
+        sl_send_reply("500", "Internal server error");
271
+        exit;
272
+    }
273
+}
274
+
275
+# now h350_result* or ldap_result* functions can be used
276
+            </programlisting>
277
+        </example>
278
+    </section>
279
+    
280
+    <section>
281
+        <title>h350_auth_lookup(auth_username, "username_avp_spec/pwd_avp_spec")</title>
282
+        
283
+        <para>
284
+            This function performs an LDAP search query for SIP digest authentication credentials in an H.350 directory. The H.350 directory is searched for a commObject with SIPIdentityUserName of <varname>auth_username</varname>. If such a commObject is found, the SIP digest authentication username and password are stored in AVPs <varname>username_avp_spec</varname> and <varname>pwd_avp_spec</varname>, respectively. <emphasis>pv_*_authorize</emphasis> functions from AUTH module can then be used to perform SIP digest authentication.
285
+        </para>
286
+        
287
+        <para>
288
+            The function returns <constant>1</constant> (TRUE) if an H.350 commObject was found, <constant>-1</constant> (FALSE) in case of an internal error, and <constant>-2</constant> (FALSE) if no matching commObject was found.
289
+        </para>
290
+        
291
+        <para>
292
+            This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE and BRANCH_ROUTE.
293
+        </para>
294
+        
295
+        <variablelist>
296
+            <title>Function Parameters:</title>
297
+
298
+            <varlistentry>
299
+                <term>auth_username</term>
300
+
301
+                <listitem>
302
+                    <para>
303
+                        H.350 SIPIdentityUserName to search for in directory. Included OpenSER variables do get expanded.
304
+                    </para>
305
+                </listitem>
306
+            </varlistentry>
307
+            
308
+            <varlistentry>
309
+                <term>username_avp_spec</term>
310
+
311
+                <listitem>
312
+                    <para>
313
+                        Specification for authentication username AVP, e.g. <varname>$avp(s:username)</varname>.
314
+                    </para>
315
+                </listitem>
316
+            </varlistentry>
317
+            
318
+            <varlistentry>
319
+                <term>pwd_avp_spec</term>
320
+
321
+                <listitem>
322
+                    <para>
323
+                        Specification for authentication password AVP, e.g. <varname>$avp(s:pwd)</varname>.
324
+                    </para>
325
+                </listitem>
326
+            </varlistentry>
327
+        </variablelist>
328
+
329
+        <variablelist>
330
+            <title>Return Values:</title>
331
+
332
+            <varlistentry>
333
+                <term><constant>1</constant> (TRUE):</term>
334
+
335
+                <listitem>
336
+                    <itemizedlist>
337
+                        <listitem>
338
+                            <para>
339
+                                H.350 commObject found and SIP digest authentication credentials stored in <varname>username_avp_spec</varname> and <varname>pwd_avp_spec</varname>.
340
+                            </para>
341
+                        </listitem>
342
+                    </itemizedlist>
343
+                </listitem>
344
+            </varlistentry>
345
+
346
+            <varlistentry>
347
+                <term><constant>-1</constant> (FALSE):</term>
348
+
349
+                <listitem>
350
+                    <itemizedlist>
351
+                        <listitem>
352
+                            <para>
353
+                                Internal error occurred.
354
+                            </para>
355
+                        </listitem>
356
+                    </itemizedlist>
357
+                </listitem>
358
+            </varlistentry>
359
+            
360
+            <varlistentry>
361
+                <term><constant>-2</constant> (FALSE):</term>
362
+
363
+                <listitem>
364
+                    <itemizedlist>
365
+                        <listitem>
366
+                            <para>
367
+                                No H.350 commObject found.
368
+                            </para>
369
+                        </listitem>
370
+                    </itemizedlist>
371
+                </listitem>
372
+            </varlistentry>
373
+        </variablelist>
374
+
375
+        <example>
376
+            <title>Example Usage</title>
377
+
378
+            <programlisting>
379
+# -- auth params --
380
+modparam("auth", "username_spec", "$avp(s:auth_user)")
381
+modparam("auth", "password_spec", "$avp(s:auth_pwd)")
382
+modparam("auth", "calculate_ha1", 1)
383
+
384
+# -- h350 params --
385
+modparam("h350", "ldap_session", "h350")
386
+modparam("h350", "base_dn", "ou=h350,dc=example,dc=com")
387
+modparam("h350", "search_scope", "one")
388
+
389
+
390
+route[1]
391
+{
392
+    #
393
+    # H.350 based SIP digest authentication 
394
+    #
395
+     
396
+    # challenge all requests not including an Auth header
397
+    if (!(is_present_hf("Authorization") || 
398
+          is_present_hf("Proxy-Authorization")))
399
+    {
400
+        if (is_method("REGISTER"))
401
+        {
402
+            www_challenge("example.com", "0");
403
+            exit;
404
+        }
405
+        proxy_challenge("example.com", "0");
406
+        exit;
407
+    }
408
+
409
+    # get digest password from H.350 using auth username ($au)
410
+    if (!h350_auth_lookup("$au", 
411
+                          "$avp(s:auth_user)/$avp(s:auth_pwd)"))
412
+    {
413
+        switch ($retcode)
414
+        {
415
+        case -2:
416
+            sl_send_reply("401", "Unauthorized");
417
+            exit;
418
+        case -1:
419
+            sl_send_reply("500", "Internal server error");
420
+            exit;
421
+        }
422
+    }
423
+
424
+    # REGISTER requests
425
+    if (is_method("REGISTER"))
426
+    {
427
+        if (!pv_www_authorize("example.com"))
428
+        {
429
+            if ($retcode == -5)
430
+            {
431
+                sl_send_reply("500", "Internal server error");
432
+                exit;    
433
+            }
434
+            else {
435
+                www_challenge("example.com", "0");
436
+                exit;
437
+            }
438
+        }
439
+
440
+        consume_credentials();
441
+        xlog("L_INFO", 
442
+             "REGISTER request successfully authenticated");
443
+        return(1);
444
+    }
445
+
446
+    # non-REGISTER requests
447
+    if (!pv_proxy_authorize("example.com"))
448
+    {
449
+        if ($retcode == -5)
450
+        {
451
+            sl_send_reply("500", "Internal server error");
452
+            exit;    
453
+        }
454
+        else {
455
+            proxy_challenge("example.com", "0");
456
+            exit;
457
+        }
458
+    }
459
+
460
+    consume_credentials();
461
+    xlog("L_INFO", "$rm request successfully authenticated");
462
+    return(1);
463
+}
464
+            </programlisting>
465
+        </example>
466
+    </section>
467
+    
468
+    <section>
469
+        <title>h350_result_call_preferences(avp_name_prefix)</title>
470
+        
471
+        <para>
472
+            This function parses the callPreferenceURI attribute of an H.350 commObject, which must have been fetched through <emphasis>h350_*_lookup</emphasis> or <emphasis>ldap_search</emphasis>. callPreferenceURI is a multi-valued attribute that stores call preference rules like e.g. forward-on-busy or forward-unconditionally. <emphasis>Directory services architecture for call forwarding and preferences</emphasis> <xref linkend="H350-6" > defines a format for simple call forwarding rules:
473
+        </para>
474
+        
475
+        <blockquote>
476
+            <para>
477
+                <literal>target_uri type[:argument]</literal>
478
+            </para>
479
+        </blockquote>
480
+        
481
+        <para>
482
+            In a SIP environment, <literal>target_uri</literal> is typically the call forwarding rule's target SIP URI, although it could be any type of URI, e.g. an HTTP pointer to a CPL script. Four different values are specified for <literal>type</literal>: <literal>b</literal> for "forward on busy", <literal>n</literal> for "forward on no answer", <literal>u</literal> for "forward unconditionally", and <literal>f</literal> for "forward on destination not found". The optional <literal>argument</literal> is a string indicating the time in milliseconds after which the call forwarding should occur.
483
+        </para>
484
+