modules_k/h350/README
38e2b05d
 H350 Module
 
 Christian Schlatter
 
    University of North Carolina
d77df08a
    <cs@unc.edu>
38e2b05d
 
    Copyright � 2007 University of North Carolina
d77df08a
    Revision History
    Revision 0.1 05-17-2007
989206bd
      __________________________________________________________
38e2b05d
 
    Table of Contents
d77df08a
 
9fc784c6
    1. Admin Guide
38e2b05d
 
         1.1. Overview
 
               1.1.1. Example H.350 commObject LDAP Entry
 
         1.2. Dependencies
 
9b64b9f3
               1.2.1. Kamailio Modules
38e2b05d
               1.2.2. External Libraries or Applications
 
         1.3. Exported Parameters
 
               1.3.1. ldap_session (string)
               1.3.2. base_dn (string)
               1.3.3. search_scope (string)
 
         1.4. Exported Functions
 
               1.4.1. h350_sipuri_lookup(sip_uri)
               1.4.2. h350_auth_lookup(auth_username,
                       "username_avp_spec/pwd_avp_spec")
 
989206bd
               1.4.3. h350_result_call_preferences(avp_name_prefix)
38e2b05d
               1.4.4. h350_result_service_level(avp_name_prefix)
 
    Resources
 
    List of Examples
d77df08a
 
    1.1. Example H.350 commObject storing SIP account data
    1.2. ldap_session parameter usage
    1.3. base_dn parameter usage
    1.4. search_scope parameter usage
    1.5. Example Usage
    1.6. Example Usage
    1.7. Example H.350 callPreferenceURI simple call forwarding
38e2b05d
           rules
 
d77df08a
    1.8. Example Usage
    1.9. Example SIPIdentityServiceLevel values and resulting AVPs
    1.10. Example Usage
38e2b05d
 
9fc784c6
 Chapter 1. Admin Guide
38e2b05d
 
 1.1. Overview
 
873d51d6
    The Kamailio H350 module enables an Kamailio SIP proxy server
    to access SIP account data stored in an LDAP [RFC4510]
    directory containing H.350 [H.350] commObjects. ITU-T
    Recommendation H.350 standardizes LDAP object classes to store
    Real-Time Communication (RTC) account data. In particular,
    H.350.4 [H.350.4] defines an object class called sipIdentity
    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
989206bd
    and lets different entities, like SIP proxies, provisioning, or
    billing applications, access the data in a standardized format.
 
    The ViDe H.350 Cookbook [vide-h.350-cb] 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
38e2b05d
    deployment scenarios.
 
9b64b9f3
    The H350 module uses the Kamailio LDAP module to import H.350
    attribute values into the Kamailio routing script variable
38e2b05d
    space. The module exports functions to parse and store the
9b64b9f3
    H.350 attribute values from the Kamailio routing script. It
38e2b05d
    allows a script writer to implement H.350 based SIP digest
    authentication, call forwarding, SIP URI alias to AOR
    rewriting, and service level parsing.
 
 1.1.1. Example H.350 commObject LDAP Entry
 
    The following example shows a typical H.350 commObject LDAP
    entry storing SIP account data.
 
d77df08a
    Example 1.1. Example H.350 commObject storing SIP account data
38e2b05d
 Attribute Name                Attribute Value(s)
 --------------                -----------------
 
 # LDAP URI identifying the owner of this commObject, typically
 # points to an entry in the enterprise directory
 commOwner       ldap://dir.example.com/dc=example,dc=com??one?(uid=bob)
 
 # Unique identifier for this commObject, used for referencing
 # this object e.g. from the enterprise directory
 commUniqueId                  298217asdjgj213
 
 # Determines if this commObject should be listed on white pages
 commPrivate                   false
 
 # Valid SIP URIs for this account (can be used to store alias SIP URIs
 # like DIDs as well)
 SIPIdentitySIPURI             sip:bob@example.com
                               sip:bob@alias.example.com
                               sip:+1919123456@alias.example.com
 # SIP digest username
 SIPIdentityUserName           bob
 
 # SIP digest password
 SIPIdentityPassword           pwd
 
 # SIP proxy address
 SIPIdentityProxyAddress       sip.example.com
 
 # SIP registrar address
 SIPIdentityRegistrarAddress   sip.example.com
 
 # Call preferences: Forward to voicemail on no response
 # after 20 seconds and on busy
 callPreferenceURI             sip:bob@voicemail.example.com n:20000
                               sip:bob@voicemail.example.com b
 
 # Account service level(s)
 SIPIdentityServiceLevel       long_distance
                               conferencing
 
 # H.350 object classes
 objectClass                   top
                               commObject
                               SIPIdentity
                               callPreferenceURIObject
 
 1.2. Dependencies
 
9b64b9f3
 1.2.1. Kamailio Modules
38e2b05d
 
989206bd
    The module depends on the following modules (the listed modules
    must be loaded before this module):
38e2b05d
      * LDAP
 
 1.2.2. External Libraries or Applications
 
    The following libraries or applications must be installed
9b64b9f3
    before running Kamailio with this module loaded:
38e2b05d
      * OpenLDAP library (libldap), libldap header files
        (libldap-dev) are needed for compilation
 
 1.3. Exported Parameters
 
 1.3.1. ldap_session (string)
 
    Name of the LDAP session to be used for H.350 queries, as
    defined in the LDAP module configuration file.
 
    Default value: ""
 
d77df08a
    Example 1.2. ldap_session parameter usage
38e2b05d
 modparam("h350", "ldap_session", "h350");
 
 1.3.2. base_dn (string)
 
    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.
 
    Default value: ""
 
d77df08a
    Example 1.3. base_dn parameter usage
38e2b05d
 modparam("h350", "base_dn", "ou=h350,dc=example,dc=com");
 
 1.3.3. search_scope (string)
 
    LDAP search scope for H.350 queries, one of "one", "base", or
    "sub".
 
    Default value: "one"
 
d77df08a
    Example 1.4. search_scope parameter usage
38e2b05d
 modparam("h350", "search_scope", "sub");
 
 1.4. Exported Functions
 
 1.4.1. h350_sipuri_lookup(sip_uri)
 
    This function performs an LDAP search query for an H.350
    commObject with a SIPIdentitySIPURI of sip_uri. The sip_uri
    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
    h350_result* or one of the ldap_result* functions from the
9b64b9f3
    Kamailio LDAP module.
38e2b05d
 
    The function returns -1 (FALSE) for internal errors, and -2
    (FALSE) if no H.350 commObject was found with a matching
    sip_uri. n > 0 (TRUE) is returned if n H.350 commObjects were
    found.
 
    This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
    FAILURE_ROUTE and BRANCH_ROUTE.
 
    Function Parameters:
 
    sip_uri
           H.350 SIPIdentitySIPURI to search for in directory.
9b64b9f3
           Included Kamailio variables do get expanded.
38e2b05d
 
    Return Values:
 
    n > 0 (TRUE):
 
           + n H.350 commObjects found.
 
    -1 (FALSE):
 
           + Internal error occurred.
 
    -2 (FALSE):
 
           + No H.350 commObject found.
 
719e7b81
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
    BRANCH_ROUTE, and ONREPLY_ROUTE.
 
d77df08a
    Example 1.5. Example Usage
38e2b05d
 #
 # H.350 lookup for callee
 #
 
 if (!h350_sipuri_lookup("sip:$rU@$rd"))
 {
     switch ($retcode)
     {
     case -2:
         xlog("L_INFO",
              "h350 callee lookup: no entry found in H.350 directory");
         exit;
     case -1:
         sl_send_reply("500", "Internal server error");
         exit;
     }
 }
 
 # now h350_result* or ldap_result* functions can be used
 
 1.4.2. h350_auth_lookup(auth_username,
 "username_avp_spec/pwd_avp_spec")
 
    This function performs an LDAP search query for SIP digest
    authentication credentials in an H.350 directory. The H.350
989206bd
    directory is searched for a commObject with SIPIdentityUserName
    of auth_username. If such a commObject is found, the SIP digest
    authentication username and password are stored in AVPs
    username_avp_spec and pwd_avp_spec, respectively.
    pv_*_authorize functions from AUTH module can then be used to
    perform SIP digest authentication.
38e2b05d
 
989206bd
    The function returns 1 (TRUE) if an H.350 commObject was found,
    -1 (FALSE) in case of an internal error, and -2 (FALSE) if no
    matching commObject was found.
38e2b05d
 
    This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
    FAILURE_ROUTE and BRANCH_ROUTE.
 
    Function Parameters:
 
    auth_username
           H.350 SIPIdentityUserName to search for in directory.
9b64b9f3
           Included Kamailio variables do get expanded.
38e2b05d
 
    username_avp_spec
           Specification for authentication username AVP, e.g.
           $avp(s:username).
 
    pwd_avp_spec
           Specification for authentication password AVP, e.g.
           $avp(s:pwd).
 
    Return Values:
 
    1 (TRUE):
 
           + H.350 commObject found and SIP digest authentication
             credentials stored in username_avp_spec and
             pwd_avp_spec.
 
    -1 (FALSE):
 
           + Internal error occurred.
 
    -2 (FALSE):
 
           + No H.350 commObject found.
 
719e7b81
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
    BRANCH_ROUTE, and ONREPLY_ROUTE.
 
d77df08a
    Example 1.6. Example Usage
38e2b05d
 # -- auth params --
 modparam("auth", "username_spec", "$avp(s:auth_user)")
 modparam("auth", "password_spec", "$avp(s:auth_pwd)")
 modparam("auth", "calculate_ha1", 1)
 
 # -- h350 params --
 modparam("h350", "ldap_session", "h350")
 modparam("h350", "base_dn", "ou=h350,dc=example,dc=com")
 modparam("h350", "search_scope", "one")
 
 
 route[1]
 {
     #
     # H.350 based SIP digest authentication
     #
 
     # challenge all requests not including an Auth header
     if (!(is_present_hf("Authorization") ||
           is_present_hf("Proxy-Authorization")))
     {
         if (is_method("REGISTER"))
         {
             www_challenge("example.com", "0");
             exit;
         }
         proxy_challenge("example.com", "0");
         exit;
     }
 
     # get digest password from H.350 using auth username ($au)
     if (!h350_auth_lookup("$au",
                           "$avp(s:auth_user)/$avp(s:auth_pwd)"))
     {
         switch ($retcode)
         {
         case -2:
             sl_send_reply("401", "Unauthorized");
             exit;
         case -1:
             sl_send_reply("500", "Internal server error");
             exit;
         }
     }
 
     # REGISTER requests
     if (is_method("REGISTER"))
     {
         if (!pv_www_authorize("example.com"))
         {
             if ($retcode == -5)
             {
                 sl_send_reply("500", "Internal server error");
                 exit;
             }
             else {
                 www_challenge("example.com", "0");
                 exit;
             }
         }
 
         consume_credentials();
         xlog("L_INFO",
              "REGISTER request successfully authenticated");
         return(1);
     }
 
     # non-REGISTER requests
     if (!pv_proxy_authorize("example.com"))
     {
         if ($retcode == -5)
         {
             sl_send_reply("500", "Internal server error");
             exit;
         }
         else {
             proxy_challenge("example.com", "0");
             exit;
         }
     }
 
     consume_credentials();
     xlog("L_INFO", "$rm request successfully authenticated");
     return(1);
 }
 
 1.4.3. h350_result_call_preferences(avp_name_prefix)
 
    This function parses the callPreferenceURI attribute of an
    H.350 commObject, which must have been fetched through
    h350_*_lookup or ldap_search. callPreferenceURI is a
    multi-valued attribute that stores call preference rules like
    e.g. forward-on-busy or forward-unconditionally. Directory
    services architecture for call forwarding and preferences
    [H.350.6] defines a format for simple call forwarding rules:
 
      target_uri type[:argument]
 
    In a SIP environment, target_uri is typically the call
989206bd
    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 type: b for "forward on busy", n for
    "forward on no answer", u for "forward unconditionally", and f
    for "forward on destination not found". The optional argument
    is a string indicating the time in milliseconds after which the
    call forwarding should occur.
38e2b05d
 
d77df08a
    Example 1.7. Example H.350 callPreferenceURI simple call
38e2b05d
    forwarding rules
d77df08a
 
38e2b05d
 # Example 1:
 # forward to sip:voicemail@example.com on no answer after 15 seconds:
 
 callPreferenceURI: sip:voicemail@example.com n:15000
 
 # Example 2:
 # unconditionally forward to sip:alice@example.com:
 
 callPreferenceURI: sip:alice@example.com u
 
 # Example 3:
 # forward to sip:bob@example.com and sip:alice@example.com
 # (forking) on destination not found:
 
 callPreferenceURI: sip:bob@example.com f
 callPreferenceURI: sip:alice@example.com f
 
989206bd
    h350_result_call_preferences stores these call forwarding rules
    as AVPs according to the following rules:
38e2b05d
 
 #
 # AVP storing a forwarding rule's target URI
 #
 
 AVP name  = avp_name_prefix + '_' + type
 AVP value = target_uri
 
 #
 # AVP storing a forwarding rule's argument
 #
 
 AVP name  = avp_name_prefix + '_' + type + '_t'
 AVP value = argument / 1000
 
    Example 1 from above would result in two AVPs:
    $avp("s:prefix_n") = "sip:voicemail@example.com" and
    $avp("s:prefix_n_t") = 15.
 
    Example 2: $avp("s:prefix_u") = "sip:alice@example.com".
 
    Example 3: $avp("s:prefix_f[1]") = "sip:bob@example.com" and
    $avp("s:prefix_f[2]]") = "sip:alice@example.com".
 
    These AVPs can then be used to implement the desired behavior
9b64b9f3
    in the Kamailio routing script.
38e2b05d
 
    This function returns the number of successfully parsed simple
    call forwarding rules (TRUE), in case the H.350
    callPreferenceURI attribute contained one or multiple values
    matching the simple call forwarding rule syntax described
    above. It returns -1 (FALSE) for internal errors, and -2
989206bd
    (FALSE) if none of the rules matched or if no callPreferenceURI
    attribute was found.
38e2b05d
 
    This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
    FAILURE_ROUTE and BRANCH_ROUTE.
 
    Function Parameters:
 
    avp_name_prefix
           Name prefix for call forwarding rule AVPs, as described
           above.
 
    Return Values:
 
    n > 0 (TRUE):
 
           + n simple call forwarding rules found.
 
    -1 (FALSE):
 
           + Internal error occurred.
 
    -2 (FALSE):
 
           + No simple call forwarding rule found, or
             callPreferenceURI not present.
 
719e7b81
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
    BRANCH_ROUTE, and ONREPLY_ROUTE.
 
d77df08a
    Example 1.8. Example Usage
38e2b05d
 #
 # H.350 lookup for callee
 #
 
 ... h350_sipuri_lookup("sip:$rU@$rd") ...
 
 #
 # store H.350 call preferences in AVP
 #
 
 if (!h350_result_call_preferences("callee_pref_") && ($retcode == -1))
 {
     sl_send_reply("500", "Internal server error");
     exit;
 }
 
 # $avp(s:callee_pref_u)   == CFU URI(s)
 # $avp(s:callee_pref_n)   == CFNR URI(s)
 # $avp(s:callee_pref_n_t) == CFNR timeout in seconds
 # $avp(s:callee_pref_b)   == CFB URI(s)
 # $avp(s:callee_pref_f)   == CFOFFLINE URI(s)
 
 #
 # Example for forward-unconditionally (CFU)
 #
 
 if (is_avp_set("$avp(s:callee_pref_u)"))
 {
     # replace R-URI with CFU URI, g will fetch all CFU URIs
     # --> request can fork
     if (avp_pushto("$ru", "$avp(s:callee_pref_u)/g"))
     {
             avp_delete("$avp(s:callee_pref_u)");
     } else
     {
             sl_send_reply("500", "Internal server error");
             exit;
     }
     sl_send_reply("181", "Call is being forwarded");
     t_relay();
     exit;
 }
 
 1.4.4. h350_result_service_level(avp_name_prefix)
 
    Directory services architecture for SIP [H.350.4] defines a
    multi-valued LDAP attribute named SIPIdentityServiceLevel,
    which can be used to store SIP account service level values in
    an LDAP directory. This function parses the
    SIPIdentityServiceLevel attribute and stores all service level
9b64b9f3
    values as AVPs for later retrieval in the Kamailio routing
989206bd
    script. The function accesses the H.350 commObject fetched by a
    call to h350_*_lookup or ldap_search.
38e2b05d
 
    The resulting AVPs have a name of the form avp_name_prefix +
    SIPIdentityServiceLevel attribute value, and an integer value
    of 1.
 
d77df08a
    Example 1.9. Example SIPIdentityServiceLevel values and
38e2b05d
    resulting AVPs
 SIPIdentityServiceLevel: longdistance
 SIPIdentityServiceLevel: international
 SIPIdentityServiceLevel: 900
 
 after calling h350_result_service_level("sl_"), the following AVPs
 will be available in the routing script:
 
 $avp("s:sl_longdistance") = 1
 $avp("s:sl_international") = 1
 $avp("s:sl_900") = 1
 
    This function returns the number of added AVPs (TRUE), -1
    (FALSE)for internal errors, and -2 (FALSE)if no
    SIPIdentityServiceLevel attribute was found.
 
    The function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
    FAILURE_ROUTE and BRANCH_ROUTE.
 
    Function Parameters:
 
    avp_name_prefix
           Name prefix for service level AVPs, as described above.
 
    Return Values:
 
    n > 0 (TRUE):
 
           + n AVPs added.
 
    -1 (FALSE):
 
           + Internal error occurred.
 
    -2 (FALSE):
 
           + No SIPIdentityServiceLevel attribute found.
 
719e7b81
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
    BRANCH_ROUTE, and ONREPLY_ROUTE.
 
d77df08a
    Example 1.10. Example Usage
38e2b05d
 #
 # H.350 SIP digest authentication for caller
 #
 
 ... h350_auth_lookup("$au", ...) ...
 
 #
 # store caller's service level as AVP
 #
 
 if (!h350_result_service_level("caller_sl_") && ($retcode == -1))
 {
     sl_send_reply("500", "Internal server error");
     exit;
 }
 
 #
 # make routing decision based on service level AVPs
 #
 
 if (is_avp_set("$avp(s:caller_sl_international)"))
 {
     t_relay();
 }
 else {
     sl_send_reply("403", "Forbidden");
 }
 exit;
d77df08a
 
38e2b05d
 Resources
 
    [H.350] Directory Services Architecture for Multimedia
d77df08a
    Conferencing. August 2003. ITU-T.
38e2b05d
 
989206bd
    [H.350.4] Directory services architecture for SIP. August 2003.
    ITU-T.
38e2b05d
 
    [H.350.6] Directory services architecture for call forwarding
d77df08a
    and preferences. March 2004. ITU-T.
38e2b05d
 
d77df08a
    [ViDe-H.350-Cookbook] ViDe H.350 Cookbook. 2005. ViDe.
38e2b05d
 
    [RFC4510] Lightweight Directory Access Protocol (LDAP):
d77df08a
    Technical Specification Road Map. June 2006. Internet
38e2b05d
    Engineering Task Force.