group_mod.c

Go to the documentation of this file.
00001 /*
00002  * $Id$ 
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  * History:
00023  * --------
00024  *  2003-02-25 - created by janakj
00025  *  2003-03-11 - New module interface (janakj)
00026  *  2003-03-16 - flags export parameter added (janakj)
00027  *  2003-03-19  all mallocs/frees replaced w/ pkg_malloc/pkg_free
00028  *  2003-04-05  default_uri #define used (jiri)
00029  *  2004-06-07  updated to the new DB api: calls to group_db_* (andrei)
00030  *  2005-10-06 - added support for regexp-based groups (bogdan)
00031  */
00032 
00047 #include <stdio.h>
00048 #include <stdlib.h>
00049 #include <string.h>
00050 #include "../../sr_module.h"
00051 #include "../../dprint.h"
00052 #include "../../ut.h"
00053 #include "../../error.h"
00054 #include "../../mem/mem.h"
00055 #include "../../usr_avp.h"
00056 #include "group_mod.h"
00057 #include "group.h"
00058 #include "re_group.h"
00059 
00060 MODULE_VERSION
00061 
00062 #define TABLE_VERSION    2
00063 #define RE_TABLE_VERSION 1
00064 
00068 static void destroy(void);
00069 
00070 
00074 static int child_init(int rank);
00075 
00076 
00080 static int mod_init(void);
00081 
00083 static int hf_fixup(void** param, int param_no);
00084 
00086 static int get_gid_fixup(void** param, int param_no);
00087 
00088 
00089 #define TABLE "grp"
00090 #define TABLE_LEN (sizeof(TABLE) - 1)
00091 
00092 #define USER_COL "username"
00093 #define USER_COL_LEN (sizeof(USER_COL) - 1)
00094 
00095 #define DOMAIN_COL "domain"
00096 #define DOMAIN_COL_LEN (sizeof(DOMAIN_COL) - 1)
00097 
00098 #define GROUP_COL "grp"
00099 #define GROUP_COL_LEN (sizeof(GROUP_COL) - 1)
00100 
00101 #define RE_TABLE "re_grp"
00102 #define RE_TABLE_LEN (sizeof(TABLE) - 1)
00103 
00104 #define RE_EXP_COL "reg_exp"
00105 #define RE_EXP_COL_LEN (sizeof(USER_COL) - 1)
00106 
00107 #define RE_GID_COL "group_id"
00108 #define RE_GID_COL_LEN (sizeof(DOMAIN_COL) - 1)
00109 
00110 /*
00111  * Module parameter variables
00112  */
00113 static str db_url = {DEFAULT_RODB_URL, DEFAULT_RODB_URL_LEN};
00115 str table         = {TABLE, TABLE_LEN}; 
00116 str user_column   = {USER_COL, USER_COL_LEN};
00117 str domain_column = {DOMAIN_COL, DOMAIN_COL_LEN};
00118 str group_column  = {GROUP_COL, GROUP_COL_LEN};
00119 int use_domain    = 0;
00120 
00121 /* table and columns used for regular expression-based groups */
00122 str re_table      = {0, 0};
00123 str re_exp_column = {RE_EXP_COL, RE_EXP_COL_LEN};
00124 str re_gid_column = {RE_GID_COL, RE_GID_COL_LEN};
00125 int multiple_gid  = 1;
00126 
00127 /* DB functions and handlers */
00128 db_func_t group_dbf;
00129 db1_con_t* group_dbh = 0;
00130 
00131 
00135 static cmd_export_t cmds[] = {
00136         {"is_user_in",      (cmd_function)is_user_in,      2,  hf_fixup, 0,
00137                         REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00138         {"get_user_group",  (cmd_function)get_user_group,  2,  get_gid_fixup, 0,
00139                         REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00140         {0, 0, 0, 0, 0, 0}
00141 };
00142 
00143 
00147 static param_export_t params[] = {
00148         {"db_url",        STR_PARAM, &db_url.s       },
00149         {"table",         STR_PARAM, &table.s        },
00150         {"user_column",   STR_PARAM, &user_column.s  },
00151         {"domain_column", STR_PARAM, &domain_column.s},
00152         {"group_column",  STR_PARAM, &group_column.s },
00153         {"use_domain",    INT_PARAM, &use_domain     },
00154         {"re_table",      STR_PARAM, &re_table.s     },
00155         {"re_exp_column", STR_PARAM, &re_exp_column.s},
00156         {"re_gid_column", STR_PARAM, &re_gid_column.s},
00157         {"multiple_gid",  INT_PARAM, &multiple_gid   },
00158         {0, 0, 0}
00159 };
00160 
00161 
00165 struct module_exports exports = {
00166         "group", 
00167         DEFAULT_DLFLAGS, /* dlopen flags */
00168         cmds,       /* Exported functions */
00169         params,     /* Exported parameters */
00170         0,          /* exported statistics */
00171         0,          /* exported MI functions */
00172         0,          /* exported pseudo-variables */
00173         0,          /* extra processes */
00174         mod_init,   /* module initialization function */
00175         0,          /* response function */
00176         destroy,    /* destroy function */
00177         child_init  /* child initialization function */
00178 };
00179 
00180 
00181 static int child_init(int rank)
00182 {
00183         if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
00184                 return 0; /* do nothing for the main process */
00185 
00186         return group_db_init(&db_url);
00187 }
00188 
00189 
00190 static int mod_init(void)
00191 {
00192         /* Calculate lengths */
00193         db_url.len = strlen(db_url.s);
00194         table.len = strlen(table.s);
00195         user_column.len = strlen(user_column.s);
00196         domain_column.len = strlen(domain_column.s);
00197         group_column.len = strlen(group_column.s);
00198 
00199         re_table.len = (re_table.s && re_table.s[0])?strlen(re_table.s):0;
00200         re_exp_column.len = strlen(re_exp_column.s);
00201         re_gid_column.len = strlen(re_gid_column.s);
00202 
00203         /* Find a database module */
00204         if (group_db_bind(&db_url)) {
00205                 return -1;
00206         }
00207 
00208         if (group_db_init(&db_url) < 0 ){
00209                 LM_ERR("unable to open database connection\n");
00210                 return -1;
00211         }
00212 
00213         /* check version for group table */
00214         if (db_check_table_version(&group_dbf, group_dbh, &table, TABLE_VERSION) < 0) {
00215                         LM_ERR("error during group table version check.\n");
00216                         return -1;
00217         }
00218 
00219         if (re_table.len) {
00220                 /* check version for group re_group table */
00221                 if (db_check_table_version(&group_dbf, group_dbh, &re_table, RE_TABLE_VERSION) < 0) {
00222                         LM_ERR("error during re_group table version check.\n");
00223                         return -1;
00224                 }
00225                 if (load_re( &re_table )!=0 ) {
00226                         LM_ERR("failed to load <%s> table\n", re_table.s);
00227                         return -1;
00228                 }
00229         }
00230 
00231         group_db_close();
00232         return 0;
00233 }
00234 
00235 
00236 static void destroy(void)
00237 {
00238         group_db_close();
00239 }
00240 
00241 
00250 static group_check_p get_hf( char *str1)
00251 {
00252         group_check_p gcp=NULL;
00253         str s;
00254 
00255         gcp = (group_check_p)pkg_malloc(sizeof(group_check_t));
00256         if(gcp == NULL) {
00257                 LM_ERR("no pkg more memory\n");
00258                 return 0;
00259         }
00260         memset(gcp, 0, sizeof(group_check_t));
00261 
00262         if (!strcasecmp( str1, "Request-URI")) {
00263                 gcp->id = 1;
00264         } else if (!strcasecmp( str1, "To")) {
00265                 gcp->id = 2;
00266         } else if (!strcasecmp( str1, "From")) {
00267                 gcp->id = 3;
00268         } else if (!strcasecmp( str1, "Credentials")) {
00269                 gcp->id = 4;
00270         } else {
00271                 s.s = str1; s.len = strlen(s.s);
00272                 if(pv_parse_spec( &s, &gcp->sp)==NULL
00273                         || gcp->sp.type!=PVT_AVP)
00274                 {
00275                         LM_ERR("unsupported User Field identifier\n");
00276                         pkg_free( gcp );
00277                         return 0;
00278                 }
00279                 gcp->id = 5;
00280         }
00281 
00282         /* do not free all the time, needed by pseudo-variable spec */
00283         if(gcp->id!=5)
00284                 pkg_free(str1);
00285 
00286         return gcp;
00287 }
00288 
00289 
00296 static int hf_fixup(void** param, int param_no)
00297 {
00298         void* ptr;
00299         str* s;
00300 
00301         if (param_no == 1) {
00302                 ptr = *param;
00303                 if ( (*param = (void*)get_hf( ptr ))==0 )
00304                         return E_UNSPEC;
00305         } else if (param_no == 2) {
00306                 s = (str*)pkg_malloc(sizeof(str));
00307                 if (!s) {
00308                         LM_ERR("no pkg memory left\n");
00309                         return E_UNSPEC;
00310                 }
00311                 s->s = (char*)*param;
00312                 s->len = strlen(s->s);
00313                 *param = (void*)s;
00314         }
00315 
00316         return 0;
00317 }
00318 
00319 
00326 static int get_gid_fixup(void** param, int param_no)
00327 {
00328         pv_spec_t *sp;
00329         void *ptr;
00330         str  name;
00331 
00332         if (param_no == 1) {
00333                 ptr = *param;
00334                 if ( (*param = (void*)get_hf( ptr ))==0 )
00335                         return E_UNSPEC;
00336         } else if (param_no == 2) {
00337                 name.s = (char*)*param;
00338                 name.len = strlen(name.s);
00339                 sp = (pv_spec_t*)pkg_malloc(sizeof(pv_spec_t));
00340                 if (sp == NULL) {
00341                         LM_ERR("no more pkg memory\n");
00342                         return E_UNSPEC;
00343                 }
00344                 if(pv_parse_spec(&name, sp)==NULL || sp->type!=PVT_AVP)
00345                 {
00346                         LM_ERR("bad AVP spec <%s>\n", name.s);
00347                         pv_spec_free(sp);
00348                         return E_UNSPEC;
00349                 }
00350 
00351                 *param = sp;
00352         }
00353 
00354         return 0;
00355 }