modules/group/group_mod.c
43d3bb92
 /*
31ccf6a2
  * Copyright (C) 2001-2003 FhG Fokus
  *
27642a08
  * This file is part of Kamailio, a free SIP server.
31ccf6a2
  *
27642a08
  * Kamailio is free software; you can redistribute it and/or modify
31ccf6a2
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
27642a08
  * Kamailio is distributed in the hope that it will be useful,
31ccf6a2
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
9e1ff448
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
31ccf6a2
  *
  */
 
9bcfe5d3
 /**
  * \file
  * \brief Group membership module
  * \ingroup group
  * - Module: \ref group
  */
 
 /*!
  * \defgroup group GROUP :: The Kamailio group Module
  * This module provides functions to check if a certain user belongs to a
  * group. This group definitions are read from a DB table.
  */
 
31ccf6a2
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "../../sr_module.h"
 #include "../../dprint.h"
 #include "../../ut.h"
 #include "../../error.h"
 #include "../../mem/mem.h"
43d3bb92
 #include "../../usr_avp.h"
31ccf6a2
 #include "group_mod.h"
 #include "group.h"
43d3bb92
 #include "re_group.h"
31ccf6a2
 
 MODULE_VERSION
 
43d3bb92
 #define TABLE_VERSION    2
 #define RE_TABLE_VERSION 1
31ccf6a2
 
9bcfe5d3
 /*!
  * \brief Module destroy function prototype
31ccf6a2
  */
 static void destroy(void);
 
 
9bcfe5d3
 /*!
  * \brief Module child-init function prototype
31ccf6a2
  */
 static int child_init(int rank);
 
 
9bcfe5d3
 /*!
  * \brief Module initialization function prototype
31ccf6a2
  */
 static int mod_init(void);
 
9bcfe5d3
 /*! Header field fixup */
31ccf6a2
 static int hf_fixup(void** param, int param_no);
 
9bcfe5d3
 /*! get user group ID fixup */
43d3bb92
 static int get_gid_fixup(void** param, int param_no);
 
 
31ccf6a2
 #define TABLE "grp"
 #define USER_COL "username"
 #define DOMAIN_COL "domain"
 #define GROUP_COL "grp"
43d3bb92
 #define RE_TABLE "re_grp"
 #define RE_EXP_COL "reg_exp"
 #define RE_GID_COL "group_id"
31ccf6a2
 
 /*
  * Module parameter variables
  */
fac14471
 static str db_url = str_init(DEFAULT_RODB_URL);
9bcfe5d3
 /*! Table name where group definitions are stored */
fac14471
 str table         = str_init(TABLE);
 str user_column   = str_init(USER_COL);
 str domain_column = str_init(DOMAIN_COL);
 str group_column  = str_init(GROUP_COL);
31ccf6a2
 int use_domain    = 0;
 
9bcfe5d3
 /* table and columns used for regular expression-based groups */
639a00c7
 str re_table      = {0, 0};
fac14471
 str re_exp_column = str_init(RE_EXP_COL);
 str re_gid_column = str_init(RE_GID_COL);
43d3bb92
 int multiple_gid  = 1;
 
 /* DB functions and handlers */
 db_func_t group_dbf;
de95faa4
 db1_con_t* group_dbh = 0;
31ccf6a2
 
 
9bcfe5d3
 /*!
31ccf6a2
  * Exported functions
  */
 static cmd_export_t cmds[] = {
c4d2e802
 	{"is_user_in",      (cmd_function)is_user_in,      2,  hf_fixup, 0,
d0d9d8f8
 			REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
c4d2e802
 	{"get_user_group",  (cmd_function)get_user_group,  2,  get_gid_fixup, 0,
d0d9d8f8
 			REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
80998a7f
 	{0, 0, 0, 0, 0, 0}
31ccf6a2
 };
 
 
9bcfe5d3
 /*!
31ccf6a2
  * Exported parameters
  */
 static param_export_t params[] = {
fac14471
 	{"db_url",        PARAM_STR, &db_url       },
 	{"table",         PARAM_STR, &table        },
 	{"user_column",   PARAM_STR, &user_column  },
 	{"domain_column", PARAM_STR, &domain_column},
 	{"group_column",  PARAM_STR, &group_column },
43d3bb92
 	{"use_domain",    INT_PARAM, &use_domain     },
fac14471
 	{"re_table",      PARAM_STR, &re_table     },
 	{"re_exp_column", PARAM_STR, &re_exp_column},
 	{"re_gid_column", PARAM_STR, &re_gid_column},
43d3bb92
 	{"multiple_gid",  INT_PARAM, &multiple_gid   },
31ccf6a2
 	{0, 0, 0}
 };
 
 
9bcfe5d3
 /*!
31ccf6a2
  * Module interface
  */
 struct module_exports exports = {
 	"group", 
51716422
 	DEFAULT_DLFLAGS, /* dlopen flags */
31ccf6a2
 	cmds,       /* Exported functions */
 	params,     /* Exported parameters */
739aec8b
 	0,          /* exported statistics */
de26de44
 	0,          /* exported MI functions */
71c26efd
 	0,          /* exported pseudo-variables */
3eee3a4e
 	0,          /* extra processes */
31ccf6a2
 	mod_init,   /* module initialization function */
 	0,          /* response function */
 	destroy,    /* destroy function */
 	child_init  /* child initialization function */
 };
 
 
 static int child_init(int rank)
 {
82a5ef65
 	if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
 		return 0; /* do nothing for the main process */
 
e2cf6343
 	return group_db_init(&db_url);
31ccf6a2
 }
 
 
 static int mod_init(void)
 {
43d3bb92
 	/* Find a database module */
e2cf6343
 	if (group_db_bind(&db_url)) {
31ccf6a2
 		return -1;
 	}
43d3bb92
 
e2cf6343
 	if (group_db_init(&db_url) < 0 ){
789504a6
 		LM_ERR("unable to open database connection\n");
43d3bb92
 		return -1;
 	}
 
 	/* check version for group table */
924f2089
 	if (db_check_table_version(&group_dbf, group_dbh, &table, TABLE_VERSION) < 0) {
 			LM_ERR("error during group table version check.\n");
 			return -1;
31ccf6a2
 	}
43d3bb92
 
 	if (re_table.len) {
924f2089
 		/* check version for group re_group table */
 		if (db_check_table_version(&group_dbf, group_dbh, &re_table, RE_TABLE_VERSION) < 0) {
 			LM_ERR("error during re_group table version check.\n");
43d3bb92
 			return -1;
 		}
 		if (load_re( &re_table )!=0 ) {
789504a6
 			LM_ERR("failed to load <%s> table\n", re_table.s);
43d3bb92
 			return -1;
 		}
 	}
 
 	group_db_close();
31ccf6a2
 	return 0;
 }
 
 
 static void destroy(void)
 {
 	group_db_close();
 }
 
 
9bcfe5d3
 /*!
  * \brief Convert HF description string to hdr_field pointer
31ccf6a2
  *
9bcfe5d3
  * Convert a header field description string to hdr_field structure
  * Supported strings: "Request-URI", "To", "From", "Credentials"
f7235964
  * \param str1 header field description string
9bcfe5d3
  * \return hdr_field structure on success, NULL on failure
31ccf6a2
  */
b0a7f212
 static group_check_p get_hf( char *str1)
43d3bb92
 {
 	group_check_p gcp=NULL;
b0a7f212
 	str s;
43d3bb92
 
 	gcp = (group_check_p)pkg_malloc(sizeof(group_check_t));
 	if(gcp == NULL) {
789504a6
 		LM_ERR("no pkg more memory\n");
43d3bb92
 		return 0;
 	}
 	memset(gcp, 0, sizeof(group_check_t));
 
b0a7f212
 	if (!strcasecmp( str1, "Request-URI")) {
43d3bb92
 		gcp->id = 1;
b0a7f212
 	} else if (!strcasecmp( str1, "To")) {
43d3bb92
 		gcp->id = 2;
b0a7f212
 	} else if (!strcasecmp( str1, "From")) {
43d3bb92
 		gcp->id = 3;
b0a7f212
 	} else if (!strcasecmp( str1, "Credentials")) {
43d3bb92
 		gcp->id = 4;
 	} else {
b0a7f212
 		s.s = str1; s.len = strlen(s.s);
 		if(pv_parse_spec( &s, &gcp->sp)==NULL
 			|| gcp->sp.type!=PVT_AVP)
43d3bb92
 		{
789504a6
 			LM_ERR("unsupported User Field identifier\n");
43d3bb92
 			pkg_free( gcp );
 			return 0;
 		}
 		gcp->id = 5;
 	}
 
 	/* do not free all the time, needed by pseudo-variable spec */
 	if(gcp->id!=5)
b0a7f212
 		pkg_free(str1);
43d3bb92
 
 	return gcp;
 }
 
 
9bcfe5d3
 /*!
  * \brief Header fixup function
  * \param param fixed parameter
  * \param param_no number of parameters
  * \return 0 on success, negative on failure
  */
31ccf6a2
 static int hf_fixup(void** param, int param_no)
 {
 	void* ptr;
 	str* s;
43d3bb92
 
31ccf6a2
 	if (param_no == 1) {
 		ptr = *param;
43d3bb92
 		if ( (*param = (void*)get_hf( ptr ))==0 )
 			return E_UNSPEC;
31ccf6a2
 	} else if (param_no == 2) {
 		s = (str*)pkg_malloc(sizeof(str));
 		if (!s) {
789504a6
 			LM_ERR("no pkg memory left\n");
31ccf6a2
 			return E_UNSPEC;
 		}
 		s->s = (char*)*param;
 		s->len = strlen(s->s);
 		*param = (void*)s;
 	}
 
 	return 0;
 }
 
43d3bb92
 
9bcfe5d3
 /*!
  * \brief Group ID fixup
  * \param param fixed parameter
  * \param param_no number of parameters
  * \return 0 on success, negative on failure
  */
43d3bb92
 static int get_gid_fixup(void** param, int param_no)
 {
6505c9d3
 	pv_spec_t *sp;
43d3bb92
 	void *ptr;
 	str  name;
 
 	if (param_no == 1) {
 		ptr = *param;
 		if ( (*param = (void*)get_hf( ptr ))==0 )
 			return E_UNSPEC;
 	} else if (param_no == 2) {
 		name.s = (char*)*param;
 		name.len = strlen(name.s);
6505c9d3
 		sp = (pv_spec_t*)pkg_malloc(sizeof(pv_spec_t));
 		if (sp == NULL) {
789504a6
 			LM_ERR("no more pkg memory\n");
43d3bb92
 			return E_UNSPEC;
 		}
6505c9d3
 		if(pv_parse_spec(&name, sp)==NULL || sp->type!=PVT_AVP)
 		{
789504a6
 			LM_ERR("bad AVP spec <%s>\n", name.s);
6505c9d3
 			pv_spec_free(sp);
43d3bb92
 			return E_UNSPEC;
 		}
6505c9d3
 
 		*param = sp;
43d3bb92
 	}
 
 	return 0;
 }