ldap_mod.c

Go to the documentation of this file.
00001 /*
00002  * $Id: ldap_mod.c 4657 2008-08-10 22:51:44Z henningw $
00003  *
00004  * Kamailio LDAP Module
00005  *
00006  * Copyright (C) 2007 University of North Carolina
00007  *
00008  * Original author: Christian Schlatter, cs@unc.edu
00009  *
00010  *
00011  * This file is part of Kamailio, a free SIP server.
00012  *
00013  * Kamailio is free software; you can redistribute it and/or modify
00014  * it under the terms of the GNU General Public License as published by
00015  * the Free Software Foundation; either version 2 of the License, or
00016  * (at your option) any later version
00017  *
00018  * Kamailio is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License
00024  * along with this program; if not, write to the Free Software
00025  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026  *
00027  * History:
00028  * --------
00029  * 2007-02-18: Initial version
00030  */
00031 
00032 
00033 #include <stdio.h>
00034 #include <string.h>
00035 #include <sys/time.h>
00036 
00037 #include "../../ut.h"
00038 #include "../../parser/hf.h"
00039 #include "../../sr_module.h"
00040 #include "../../pvar.h"
00041 #include "../../mem/mem.h"
00042 
00043 #include "ld_session.h"
00044 #include "ldap_exp_fn.h"
00045 #include "api.h"
00046 #include "ldap_connect.h"
00047 #include "ldap_api_fn.h"
00048 #include "iniparser.h"
00049 
00050 MODULE_VERSION
00051 
00052 /*
00053 * Module management function prototypes
00054 */
00055 static int mod_init(void);
00056 static void destroy(void);
00057 static int child_init(int rank);
00058 
00059 /*
00060 * fixup functions
00061 */
00062 static int ldap_search_fixup(void** param, int param_no);
00063 static int ldap_result_fixup(void** param, int param_no);
00064 static int ldap_filter_url_encode_fixup(void** param, int param_no);
00065 static int ldap_result_check_fixup(void** param, int param_no);
00066 
00067 /*
00068 * exported functions
00069 */
00070 
00071 static int w_ldap_search(struct sip_msg* msg, char* ldap_url, char* param);
00072 static int w_ldap_result1(struct sip_msg* msg, char* src, char* param);
00073 static int w_ldap_result2(struct sip_msg* msg, char* src, char* subst);
00074 static int w_ldap_result_next(struct sip_msg* msg, char* foo, char *bar);
00075 static int w_ldap_filter_url_encode(struct sip_msg* msg, 
00076       char* filter_component, char* dst_avp_name);
00077 static int w_ldap_result_check_1(struct sip_msg* msg, 
00078       char* attr_name_check_str, char* param);
00079 static int w_ldap_result_check_2(struct sip_msg* msg,
00080       char* attr_name_check_str, char* attr_val_re);
00081 
00082 
00083 /* 
00084 * Default module parameter values 
00085 */
00086 #define DEF_LDAP_CONFIG "/usr/local/etc/kamailio/ldap.cfg"
00087 
00088 /*
00089 * Module parameter variables
00090 */
00091 str ldap_config = str_init(DEF_LDAP_CONFIG);
00092 static dictionary* config_vals = NULL;
00093 
00094 /*
00095 * Exported functions
00096 */
00097 static cmd_export_t cmds[] = {
00098    {"ldap_search",            (cmd_function)w_ldap_search,            1, 
00099       ldap_search_fixup, 0,
00100       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00101    {"ldap_result",            (cmd_function)w_ldap_result1,           1, 
00102       ldap_result_fixup, 0,
00103       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00104    {"ldap_result",            (cmd_function)w_ldap_result2,           2, 
00105       ldap_result_fixup, 0,
00106       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00107    {"ldap_result_next",       (cmd_function)w_ldap_result_next,       0, 
00108       0, 0,
00109       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00110    {"ldap_result_check",      (cmd_function)w_ldap_result_check_1,    1, 
00111       ldap_result_check_fixup, 0,
00112       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00113    {"ldap_result_check",      (cmd_function)w_ldap_result_check_2,    2, 
00114       ldap_result_check_fixup, 0,
00115       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00116    {"ldap_filter_url_encode", (cmd_function)w_ldap_filter_url_encode, 2, 
00117       ldap_filter_url_encode_fixup, 0,
00118       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00119    {"load_ldap",              (cmd_function)load_ldap,  0,
00120       0, 0,
00121       0},
00122    {0, 0, 0, 0, 0, 0}
00123 };
00124 
00125 
00126 /*
00127 * Exported parameters
00128 */
00129 static param_export_t params[] = {
00130 
00131    {"config_file",          STR_PARAM, &ldap_config},
00132    {0, 0, 0}
00133 };
00134 
00135 
00136 /*
00137 * Module interface
00138 */
00139 struct module_exports exports = {
00140    "ldap", 
00141    DEFAULT_DLFLAGS, /* dlopen flags */
00142    cmds,       /* Exported functions */
00143    params,     /* Exported parameters */
00144    0,          /* exported statistics */
00145    0,          /* exported MI functions */
00146    0,          /* exported pseudo-variables */
00147    0,          /* extra processes */
00148    mod_init,   /* module initialization function */
00149    0,          /* response function */
00150    destroy,    /* destroy function */
00151    child_init  /* child initialization function */
00152 };
00153 
00154 
00155 static int child_init(int rank)
00156 {
00157    int i = 0, ld_count = 0;
00158    char* ld_name;
00159    
00160    /* don't do anything for non-worker process */
00161    if (rank < 1) {
00162       return 0;
00163    }
00164 
00165    /*
00166    * build ld_sessions and connect all sessions
00167    */
00168    ld_count = iniparser_getnsec(config_vals);
00169    for (i = 0; i < ld_count; i++)
00170    {
00171       ld_name = iniparser_getsecname(config_vals, i);
00172       if (add_ld_session(ld_name,
00173                NULL,
00174                config_vals)
00175             != 0)
00176       {
00177          LM_ERR("[%s]: add_ld_session failed\n", ld_name);
00178          return -1;
00179       }
00180 
00181       if (ldap_connect(ld_name) != 0)
00182       {
00183          LM_ERR("[%s]: failed to connect to LDAP host(s)\n", ld_name);
00184          ldap_disconnect(ld_name);
00185          return -1;
00186       }
00187       
00188    }
00189    
00190    return 0;
00191 }
00192 
00193 
00194 static int mod_init(void)
00195 {
00196    int ld_count = 0, i = 0;
00197    char* section_name;
00198    char* ldap_version;
00199    
00200    /*
00201    * read config file
00202    */
00203    if (strlen(ldap_config.s) == 0)
00204    {
00205       LM_ERR("config_file is empty - this module param is mandatory\n");
00206       return -2;
00207    }
00208    if ((config_vals = iniparser_new(ldap_config.s)) == NULL)
00209    {
00210       LM_ERR("failed to read config_file [%s]\n", ldap_config.s);
00211       return -2;
00212    }
00213    if ((ld_count = iniparser_getnsec(config_vals)) < 1)
00214    {
00215       LM_ERR("no section found in config_file [%s]\n", ldap_config.s);
00216       return -2;
00217    }
00218    /* check if mandatory settings are present */
00219    for (i = 0; i < ld_count; i++)
00220    {
00221       section_name = iniparser_getsecname(config_vals, i);
00222       if (strlen(section_name) > 255)
00223       {
00224          LM_ERR(  "config_file section name [%s]"
00225             " longer than allowed 255 characters",
00226             section_name);
00227          return -2;
00228       }
00229       if (!iniparser_find_entry(config_vals,
00230                get_ini_key_name(section_name, CFG_N_LDAP_HOST)))
00231       {
00232          LM_ERR(  "mandatory %s not defined in [%s]\n", 
00233             CFG_N_LDAP_HOST, 
00234             section_name);
00235          return -2;
00236       }
00237    }  
00238    
00239    /*
00240    * print ldap version string
00241    */
00242    if (ldap_get_vendor_version(&ldap_version) != 0)
00243    {
00244       LM_ERR("ldap_get_vendor_version failed\n");
00245       return -2;
00246    }
00247    LM_INFO("%s\n", ldap_version);
00248 
00249    return 0;
00250 }
00251 
00252 
00253 static void destroy(void)
00254 {
00255    /* ldap_unbind */
00256    free_ld_sessions();
00257 
00258    /* free config file memory */
00259    iniparser_free(config_vals);
00260 }
00261 
00262 
00263 /*
00264 * EXPORTED functions
00265 */
00266 
00267 static int w_ldap_search(struct sip_msg* msg, char* ldap_url, char* param)
00268 {
00269    return ldap_search_impl(msg, (pv_elem_t*)ldap_url);
00270 }
00271 
00272 static int w_ldap_result1(struct sip_msg* msg, char* src, char* param)
00273 {
00274    return ldap_write_result(msg, (struct ldap_result_params*)src, NULL);
00275 }
00276 
00277 static int w_ldap_result2(struct sip_msg* msg, char* src, char* subst)
00278 {
00279    return ldap_write_result(msg, (struct ldap_result_params*)src,
00280          (struct subst_expr*)subst);
00281 }
00282 
00283 static int w_ldap_result_next(struct sip_msg* msg, char* foo, char *bar)
00284 {
00285    return ldap_result_next();
00286 }
00287 
00288 static int w_ldap_filter_url_encode(struct sip_msg* msg,
00289       char* filter_component, char* dst_avp_name)
00290 {
00291    return ldap_filter_url_encode(msg, (pv_elem_t*)filter_component,
00292          (pv_spec_t*)dst_avp_name);
00293 }
00294 
00295 static int w_ldap_result_check_1(struct sip_msg* msg,
00296       char* attr_name_check_str, char* param)
00297 {
00298    return ldap_result_check(msg,
00299          (struct ldap_result_check_params*)attr_name_check_str, NULL);
00300 }
00301 
00302 static int w_ldap_result_check_2(struct sip_msg* msg,
00303       char* attr_name_check_str, char* attr_val_re)
00304 {
00305    return ldap_result_check( msg, 
00306       (struct ldap_result_check_params*)attr_name_check_str, 
00307       (struct subst_expr*)attr_val_re);
00308 }
00309 
00310 /*
00311 * FIXUP functions
00312 */
00313 
00314 static int ldap_search_fixup(void** param, int param_no)
00315 {
00316    pv_elem_t *model;
00317    str s;
00318 
00319    if (param_no == 1) {
00320       s.s = (char*)*param;
00321       s.len = strlen(s.s);
00322       if (s.len==0) {
00323          LM_ERR("ldap url is empty string!\n");
00324          return E_CFG;
00325       }
00326       if ( pv_parse_format(&s,&model) || model==NULL) {
00327          LM_ERR("wrong format [%s] for ldap url!\n", s.s);
00328          return E_CFG;
00329       }
00330       *param = (void*)model;
00331    }
00332 
00333    return 0;
00334 }
00335 
00336 static int ldap_result_fixup(void** param, int param_no)
00337 {
00338    struct ldap_result_params* lp;
00339    struct subst_expr* se;
00340    str subst;
00341    char *arg_str, *dst_avp_str, *dst_avp_val_type_str;
00342    char *p;
00343    str s;
00344    int dst_avp_val_type = 0;
00345    
00346    if (param_no == 1) {
00347       arg_str = (char*)*param;
00348       if ((dst_avp_str = strchr(arg_str, '/')) == 0) 
00349       {
00350          /* no / found in arg_str */
00351          LM_ERR("invalid first argument [%s]\n", arg_str);
00352          return E_UNSPEC;
00353       }
00354       *(dst_avp_str++) = 0;
00355 
00356       if ((dst_avp_val_type_str = strchr(dst_avp_str, '/')))
00357       {
00358          *(dst_avp_val_type_str++) = 0;
00359          if (!strcmp(dst_avp_val_type_str, "int"))
00360          {
00361             dst_avp_val_type = 1;
00362          }
00363          else if (strcmp(dst_avp_val_type_str, "str"))
00364          {
00365             LM_ERR(  "invalid avp_type [%s]\n",
00366                dst_avp_val_type_str);
00367             return E_UNSPEC;
00368          }
00369       }
00370 
00371       lp = (struct ldap_result_params*)pkg_malloc(sizeof(struct ldap_result_params));
00372       if (lp == NULL) {
00373          LM_ERR("no memory\n");
00374          return E_OUT_OF_MEM;
00375       }
00376       memset(lp, 0, sizeof(struct ldap_result_params));
00377       
00378       lp->ldap_attr_name.s = arg_str;
00379       lp->ldap_attr_name.len = strlen(arg_str);
00380 
00381       lp->dst_avp_val_type = dst_avp_val_type;
00382       s.s = dst_avp_str; s.len = strlen(s.s);
00383       p = pv_parse_spec(&s, &lp->dst_avp_spec);
00384       if (p == 0) {
00385          pkg_free(lp);
00386          LM_ERR("parse error for [%s]\n",
00387                dst_avp_str);
00388          return E_UNSPEC;
00389       }
00390       if (lp->dst_avp_spec.type != PVT_AVP) {
00391          pkg_free(lp);
00392          LM_ERR(  "bad attribute name [%s]\n",
00393             dst_avp_str);
00394          return E_UNSPEC;
00395       }
00396       *param = (void*)lp;
00397       
00398    } else if (param_no == 2) {
00399       subst.s = *param;
00400       subst.len = strlen(*param);
00401       se = subst_parser(&subst);
00402       if (se == 0) {
00403          LM_ERR("bad subst re [%s]\n",
00404          (char*)*param);
00405          return E_BAD_RE;
00406       }
00407       *param = (void*)se;
00408    }
00409 
00410    return 0;
00411 }
00412 
00413 static int ldap_result_check_fixup(void** param, int param_no)
00414 {
00415    struct ldap_result_check_params *lp;
00416    struct subst_expr *se;
00417    str subst;
00418    str s;
00419    char *arg_str, *check_str;
00420    int arg_str_len;
00421    
00422    if (param_no == 1)
00423    {
00424       arg_str = (char*)*param;
00425       arg_str_len = strlen(arg_str);
00426       if ((check_str = strchr(arg_str, '/')) == 0)
00427       {
00428          /* no / found in arg_str */
00429          LM_ERR(  "invalid first argument [%s] (no '/' found)\n",
00430             arg_str);
00431          return E_UNSPEC;
00432       }
00433       *(check_str++) = 0;
00434       
00435       lp = (struct ldap_result_check_params*)pkg_malloc(sizeof(struct ldap_result_check_params));
00436       if (lp == NULL) {
00437          LM_ERR("no memory\n");
00438          return E_OUT_OF_MEM;
00439       }
00440       memset(lp, 0, sizeof(struct ldap_result_check_params));
00441 
00442       lp->ldap_attr_name.s = arg_str;
00443       lp->ldap_attr_name.len = strlen(arg_str);
00444 
00445       if (lp->ldap_attr_name.len + 1 == arg_str_len)
00446       {
00447          /* empty check_str */
00448          lp->check_str_elem_p = 0;
00449       }
00450       else
00451       {
00452          s.s = check_str; s.len = strlen(s.s);
00453          if (pv_parse_format(&s, &(lp->check_str_elem_p)) < 0)
00454          {
00455             LM_ERR("pv_parse_format failed\n");
00456             return E_OUT_OF_MEM;
00457          }
00458       }  
00459       *param = (void*)lp;
00460    }
00461    else if (param_no == 2)
00462    {
00463       subst.s = *param;
00464       subst.len = strlen(*param);
00465       se = subst_parser(&subst);
00466       if (se == 0) {
00467          LM_ERR(  "bad subst re [%s]\n",
00468             (char*)*param);
00469          return E_BAD_RE;
00470       }
00471       *param = (void*)se;
00472    }
00473 
00474    return 0;   
00475 }
00476 
00477 static int ldap_filter_url_encode_fixup(void** param, int param_no)
00478 {
00479    pv_elem_t *elem_p;
00480    pv_spec_t *spec_p;
00481    str s;
00482 
00483    if (param_no == 1) {
00484       s.s = (char*)*param;
00485       if (s.s==0 || s.s[0]==0) {
00486          elem_p = 0;
00487       } else {
00488          s.len = strlen(s.s);
00489          if (pv_parse_format(&s, &elem_p) < 0) {
00490             LM_ERR("pv_parse_format failed\n");
00491             return E_OUT_OF_MEM;
00492          }
00493       }
00494       *param = (void*)elem_p;
00495    }
00496    else if (param_no == 2)
00497    {
00498       spec_p = (pv_spec_t*)pkg_malloc(sizeof(pv_spec_t));
00499       if (spec_p == NULL) {
00500          LM_ERR("no memory\n");
00501          return E_OUT_OF_MEM;
00502       }
00503       s.s = (char*)*param; s.len = strlen(s.s);
00504       if (pv_parse_spec(&s, spec_p)
00505             == 0)
00506       {
00507          pkg_free(spec_p);
00508          LM_ERR("parse error for [%s]\n",
00509             (char*)*param);
00510          return E_UNSPEC;
00511       }
00512       if (spec_p->type != PVT_AVP) {
00513          pkg_free(spec_p);
00514          LM_ERR("bad attribute name"
00515             " [%s]\n", (char*)*param);
00516          return E_UNSPEC;
00517       }
00518       *param = (void*)spec_p;
00519    }
00520 
00521    return 0;
00522 }

Generated on Wed May 23 18:00:28 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6