re_group.c

Go to the documentation of this file.
00001 /*
00002  * $Id$ 
00003  *
00004  * Copyright (C) 2005-2007 Voice Sistem SRL
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  *  2005-10-06 - created by bogdan
00025  */
00026 
00034 #include <sys/types.h>
00035 #include <regex.h>
00036 
00037 #include "../../str.h"
00038 #include "../../mem/mem.h"
00039 #include "../../route_struct.h"
00040 #include "../../lvalue.h"
00041 #include "group_mod.h"
00042 #include "re_group.h"
00043 #include "group.h"
00044 
00046 struct re_grp {
00047         regex_t       re;
00048         int_str       gid;
00049         struct re_grp *next;
00050 };
00051 
00053 static struct re_grp *re_list = 0;
00054 
00055 
00062 static int add_re(const char *re, int gid)
00063 {
00064         struct re_grp *rg;
00065 
00066         LM_DBG("adding <%s> with %d\n",re, gid);
00067 
00068         rg = (struct re_grp*)pkg_malloc(sizeof(struct re_grp));
00069         if (rg==0) {
00070                 LM_ERR("no more pkg mem\n");
00071                 goto error;
00072         }
00073         memset( rg, 0, sizeof(struct re_grp));
00074 
00075         if (regcomp(&rg->re, re, REG_EXTENDED|REG_ICASE|REG_NEWLINE) ) {
00076                 LM_ERR("bad re %s\n", re);
00077                 pkg_free(rg);
00078                 goto error;
00079         }
00080 
00081         rg->gid.n = gid;
00082 
00083         rg->next = re_list;
00084         re_list = rg;
00085 
00086         return 0;
00087 error:
00088         return -1;
00089 }
00090 
00091 
00097 int load_re( str *table )
00098 {
00099         db_key_t cols[2];
00100         db1_res_t* res = NULL;
00101         db_row_t* row;
00102         int n;
00103 
00104         cols[0] = &re_exp_column;
00105         cols[1] = &re_gid_column;
00106 
00107         if (group_dbf.use_table(group_dbh, table) < 0) {
00108                 LM_ERR("failed to set table <%s>\n", table->s);
00109                 goto error;
00110         }
00111 
00112         if (group_dbf.query(group_dbh, 0, 0, 0, cols, 0, 2, 0, &res) < 0) {
00113                 LM_ERR("failed to query database\n");
00114                 goto error;
00115         }
00116 
00117         for( n=0 ; n<RES_ROW_N(res) ; n++) {
00118                 row = &res->rows[n];
00119                 /* validate row */
00120                 if (row->values[0].nul || row->values[0].type!=DB1_STRING) {
00121                         LM_ERR("empty or non-string "
00122                                 "value for <%s>(re) column\n",re_exp_column.s);
00123                         goto error1;
00124                 }
00125                 if (row->values[1].nul || row->values[1].type!=DB1_INT) {
00126                         LM_ERR("empty or non-integer "
00127                                 "value for <%s>(gid) column\n",re_gid_column.s);
00128                         goto error1;
00129                 }
00130 
00131                 if ( add_re( row->values[0].val.string_val,
00132                 row->values[1].val.int_val)!=0 ) {
00133                         LM_ERR("failed to add row\n");
00134                         goto error1;
00135                 }
00136         }
00137         LM_DBG("%d rules were loaded\n", n);
00138 
00139         group_dbf.free_result(group_dbh, res);
00140         return 0;
00141 error1:
00142         group_dbf.free_result(group_dbh, res);
00143 error:
00144         return -1;
00145 }
00146 
00147 
00155 int get_user_group(struct sip_msg *req, char *user, char *avp)
00156 {
00157         static char uri_buf[MAX_URI_SIZE];
00158         str  username;
00159         str  domain;
00160         pv_spec_t *pvs;
00161         pv_value_t val;
00162         struct re_grp *rg;
00163         regmatch_t pmatch;
00164         char *c;
00165         int n;
00166         int* pi;
00167 
00168         if (get_username_domain( req, (group_check_p)user, &username, &domain)!=0){
00169                 LM_ERR("failed to get username@domain\n");
00170                 goto error;
00171         }
00172 
00173         if (username.s==NULL || username.len==0 ) {
00174                 LM_DBG("no username part\n");
00175                 return -1;
00176         }
00177 
00178         if ( 4 + username.len + 1 + domain.len + 1 > MAX_URI_SIZE ) {
00179                 LM_ERR("URI to large!!\n");
00180                 goto error;
00181         }
00182 
00183         pi=(int*)uri_buf;
00184         *pi = htonl(('s'<<24) + ('i'<<16) + ('p'<<8) + ':');
00185         c = uri_buf + 4;
00186         memcpy( c, username.s, username.len);
00187         c += username.len;
00188         *(c++) = '@';
00189         memcpy( c, domain.s, domain.len);
00190         c += domain.len;
00191         *c = 0;
00192 
00193         LM_DBG("getting groups for <%s>\n",uri_buf);
00194         pvs = (pv_spec_t*)avp;
00195         memset(&val, 0, sizeof(pv_value_t));
00196         val.flags = PV_VAL_INT|PV_TYPE_INT;
00197 
00198         /* check against all re groups */
00199         for( rg=re_list,n=0 ; rg ; rg=rg->next ) {
00200                 if (regexec( &rg->re, uri_buf, 1, &pmatch, 0)==0) {
00201                         LM_DBG("user matched to group %d!\n", rg->gid.n);
00202 
00203                         /* match -> add the gid as AVP */
00204                         val.ri = rg->gid.n;
00205                         if(pvs->setf(req, &pvs->pvp, (int)EQ_T, &val)<0)
00206                         {
00207                                 LM_ERR("setting PV AVP failed\n");
00208                                 goto error;
00209                         }
00210                         n++;
00211                         /* continue? */
00212                         if (multiple_gid==0)
00213                                 break;
00214                 }
00215         }
00216 
00217         return n?n:-1;
00218 error:
00219         return -1;
00220 }
00221 
00222