re_group.c

Go to the documentation of this file.
00001 /*
00002  * $Id: re_group.c 5210 2008-11-17 19:52:43Z henningw $ 
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 
00027 /**
00028  * \file
00029  * \brief Group membership module
00030  * \ingroup group
00031  * - Module: \ref group
00032  */
00033 
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 "group_mod.h"
00041 #include "re_group.h"
00042 #include "group.h"
00043 
00044 /*! regular expression for groups */
00045 struct re_grp {
00046    regex_t       re;
00047    int_str       gid;
00048    struct re_grp *next;
00049 };
00050 
00051 /*! global regexp list */
00052 static struct re_grp *re_list = 0;
00053 
00054 
00055 /*!
00056  * \brief Create a group regexp and add it to the list
00057  * \param re regular expression string
00058  * \param gid group ID
00059  * \return 0 on success, -1 on failure
00060  */
00061 static int add_re(const char *re, int gid)
00062 {
00063    struct re_grp *rg;
00064 
00065    LM_DBG("adding <%s> with %d\n",re, gid);
00066 
00067    rg = (struct re_grp*)pkg_malloc(sizeof(struct re_grp));
00068    if (rg==0) {
00069       LM_ERR("no more pkg mem\n");
00070       goto error;
00071    }
00072    memset( rg, 0, sizeof(struct re_grp));
00073 
00074    if (regcomp(&rg->re, re, REG_EXTENDED|REG_ICASE|REG_NEWLINE) ) {
00075       LM_ERR("bad re %s\n", re);
00076       pkg_free(rg);
00077       goto error;
00078    }
00079 
00080    rg->gid.n = gid;
00081 
00082    rg->next = re_list;
00083    re_list = rg;
00084 
00085    return 0;
00086 error:
00087    return -1;
00088 }
00089 
00090 
00091 /*!
00092  * \brief Load regular expression rules from a database
00093  * \param table DB table
00094  * \return 0 on success, -1 on failure
00095  */
00096 int load_re( str *table )
00097 {
00098    db_key_t cols[2];
00099    db_res_t* res = NULL;
00100    db_row_t* row;
00101    int n;
00102 
00103    cols[0] = &re_exp_column;
00104    cols[1] = &re_gid_column;
00105 
00106    if (group_dbf.use_table(group_dbh, table) < 0) {
00107       LM_ERR("failed to set table <%s>\n", table->s);
00108       goto error;
00109    }
00110 
00111    if (group_dbf.query(group_dbh, 0, 0, 0, cols, 0, 2, 0, &res) < 0) {
00112       LM_ERR("failed to query database\n");
00113       goto error;
00114    }
00115 
00116    for( n=0 ; n<RES_ROW_N(res) ; n++) {
00117       row = &res->rows[n];
00118       /* validate row */
00119       if (row->values[0].nul || row->values[0].type!=DB_STRING) {
00120          LM_ERR("empty or non-string "
00121             "value for <%s>(re) column\n",re_exp_column.s);
00122          goto error1;
00123       }
00124       if (row->values[1].nul || row->values[1].type!=DB_INT) {
00125          LM_ERR("empty or non-integer "
00126             "value for <%s>(gid) column\n",re_gid_column.s);
00127          goto error1;
00128       }
00129 
00130       if ( add_re( row->values[0].val.string_val,
00131       row->values[1].val.int_val)!=0 ) {
00132          LM_ERR("failed to add row\n");
00133          goto error1;
00134       }
00135    }
00136    LM_DBG("%d rules were loaded\n", n);
00137 
00138    group_dbf.free_result(group_dbh, res);
00139    return 0;
00140 error1:
00141    group_dbf.free_result(group_dbh, res);
00142 error:
00143    return -1;
00144 }
00145 
00146 
00147 /*!
00148  * \brief Get the user group and compare to the regexp list
00149  * \param req SIP message
00150  * \param user user string
00151  * \param avp AVP value
00152  * \return number of all matches (positive), -1 on errors or when not found
00153  */
00154 int get_user_group(struct sip_msg *req, char *user, char *avp)
00155 {
00156    static char uri_buf[MAX_URI_SIZE];
00157    str  username;
00158    str  domain;
00159    pv_spec_t *pvs;
00160    pv_value_t val;
00161    struct re_grp *rg;
00162    regmatch_t pmatch;
00163    char *c;
00164    int n;
00165 
00166    if (get_username_domain( req, (group_check_p)user, &username, &domain)!=0){
00167       LM_ERR("failed to get username@domain\n");
00168       goto error;
00169    }
00170 
00171    if (username.s==NULL || username.len==0 ) {
00172       LM_DBG("no username part\n");
00173       return -1;
00174    }
00175 
00176    if ( 4 + username.len + 1 + domain.len + 1 > MAX_URI_SIZE ) {
00177       LM_ERR("URI to large!!\n");
00178       goto error;
00179    }
00180 
00181    *(int*)uri_buf = htonl(('s'<<24) + ('i'<<16) + ('p'<<8) + ':');
00182    c = uri_buf + 4;
00183    memcpy( c, username.s, username.len);
00184    c += username.len;
00185    *(c++) = '@';
00186    memcpy( c, domain.s, domain.len);
00187    c += domain.len;
00188    *c = 0;
00189 
00190    LM_DBG("getting groups for <%s>\n",uri_buf);
00191    pvs = (pv_spec_t*)avp;
00192    memset(&val, 0, sizeof(pv_value_t));
00193    val.flags = PV_VAL_INT|PV_TYPE_INT;
00194 
00195    /* check against all re groups */
00196    for( rg=re_list,n=0 ; rg ; rg=rg->next ) {
00197       if (regexec( &rg->re, uri_buf, 1, &pmatch, 0)==0) {
00198          LM_DBG("user matched to group %d!\n", rg->gid.n);
00199 
00200          /* match -> add the gid as AVP */
00201          val.ri = rg->gid.n;
00202          if(pvs->setf(req, &pvs->pvp, (int)EQ_T, &val)<0)
00203          {
00204             LM_ERR("setting PV AVP failed\n");
00205             goto error;
00206          }
00207          n++;
00208          /* continue? */
00209          if (multiple_gid==0)
00210             break;
00211       }
00212    }
00213 
00214    return n?n:-1;
00215 error:
00216    return -1;
00217 }
00218 
00219 

Generated on Thu May 24 10:00:29 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6