mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
272 lines
5.9 KiB
272 lines
5.9 KiB
/*
|
|
* $Id$
|
|
*
|
|
* PERMISSIONS module
|
|
*
|
|
* Copyright (C) 2003 Miklós Tirpák (mtirpak@sztaki.hu)
|
|
*
|
|
* This file is part of Kamailio, a free SIP server.
|
|
*
|
|
* Kamailio is free software; you can redistribute it and/or modify
|
|
* 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
|
|
*
|
|
* Kamailio is distributed in the hope that it will be useful,
|
|
* 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
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include "../../sr_module.h"
|
|
#include "rule.h"
|
|
#include "parse_config.h"
|
|
|
|
|
|
/*
|
|
* parse a comma separated expression list like a, b, c
|
|
* return 0 on success, -1 on error
|
|
* parsed expressions are returned in **e
|
|
*/
|
|
static int parse_expression_list(char *str, expression **e)
|
|
{
|
|
int start=0, i=-1, j=-1, apost=0;
|
|
char str2[EXPRESSION_LENGTH];
|
|
expression *e1=NULL, *e2;
|
|
|
|
if (!str || !e) return -1;
|
|
|
|
*e = NULL;
|
|
do {
|
|
i++;
|
|
switch(str[i]) {
|
|
case '"': apost = !apost;
|
|
break;
|
|
case ',': if (apost) break;
|
|
case '\0': /* word found */
|
|
while ((str[start] == ' ') || (str[start] == '\t')) start++;
|
|
if (str[start] == '"') start++;
|
|
j = i-1;
|
|
while ((0 < j) && ((str[j] == ' ') || (str[j] == '\t'))) j--;
|
|
if ((0 < j) && (str[j] == '"')) j--;
|
|
if (start<=j) {
|
|
/* valid word */
|
|
if (j-start+1+1>EXPRESSION_LENGTH) {
|
|
LM_ERR("expression too long "
|
|
"<%.*s>(%d)\n",j-start+1,str+start,j-start+1);
|
|
goto error;
|
|
}
|
|
strncpy(str2, str+start, j-start+1);
|
|
str2[j-start+1] = '\0';
|
|
|
|
e2 = new_expression(str2);
|
|
if (!e2)
|
|
/* memory error */
|
|
goto error;
|
|
|
|
if (e1) {
|
|
/* it is not the first */
|
|
e1->next = e2;
|
|
e1 = e2;
|
|
} else {
|
|
/* it is the first */
|
|
*e = e1 = e2;
|
|
}
|
|
} else {
|
|
/* parsing error */
|
|
goto error;
|
|
}
|
|
/* for the next word */
|
|
start = i+1;
|
|
}
|
|
} while (str[i] != '\0');
|
|
|
|
return 0;
|
|
error:
|
|
if (*e) {
|
|
free_expression(*e);
|
|
*e = NULL;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
* parse a complex expression list like a, b, c EXCEPT d, e
|
|
* return 0 on success, -1 on error
|
|
* parsed expressions are returned in **e, and exceptions are returned in **e_exceptions
|
|
*/
|
|
static int parse_expression(char *str, expression **e, expression **e_exceptions)
|
|
{
|
|
char *except, str2[LINE_LENGTH+1];
|
|
int i,j;
|
|
|
|
if (!str || !e || !e_exceptions) return -1;
|
|
|
|
except = strstr(str, " EXCEPT ");
|
|
if (except) {
|
|
/* exception found */
|
|
strncpy(str2, str, except-str);
|
|
str2[except-str] = '\0';
|
|
/* except+8 points to the exception */
|
|
if (parse_expression_list(except+8, e_exceptions)) {
|
|
/* error */
|
|
*e = *e_exceptions = NULL;
|
|
return -1;
|
|
}
|
|
} else {
|
|
/* no exception */
|
|
strcpy(str2, str);
|
|
*e_exceptions = NULL;
|
|
}
|
|
|
|
for( i=0; isspace((int)str2[i]) ; i++);
|
|
for( j=strlen(str2)-1 ; isspace((int)str2[j]) ; str2[j--]=0);
|
|
|
|
if (strcmp("ALL", str2+i) == 0) {
|
|
*e = NULL;
|
|
} else {
|
|
if (parse_expression_list(str2+i, e)) {
|
|
/* error */
|
|
if (*e_exceptions) free_expression(*e_exceptions);
|
|
*e = *e_exceptions = NULL;
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* parse one line of the config file
|
|
* return the rule according to line
|
|
*/
|
|
static rule *parse_config_line(char *line)
|
|
{
|
|
rule *rule1;
|
|
expression *left, *left_exceptions, *right, *right_exceptions;
|
|
int i=-1, exit=0, apost=0, colon=-1, eval=0;
|
|
static char str1[LINE_LENGTH], str2[LINE_LENGTH+1];
|
|
|
|
if (!line) return 0;
|
|
|
|
rule1 = 0;
|
|
left = left_exceptions = right = right_exceptions = 0;
|
|
|
|
while (!exit) {
|
|
i++;
|
|
switch(line[i]) {
|
|
case '"': apost = !apost;
|
|
eval = 1;
|
|
break;
|
|
|
|
case ':': if (!apost) colon = i;
|
|
eval = 1;
|
|
break;
|
|
|
|
case '#': if (apost) break;
|
|
case '\0':
|
|
case '\n':
|
|
exit = 1;
|
|
break;
|
|
case ' ': break;
|
|
case '\t': break;
|
|
|
|
default: eval = 1;
|
|
|
|
}
|
|
}
|
|
|
|
if (eval) {
|
|
if ((0<colon) && (colon+1<i)) {
|
|
/* valid line */
|
|
|
|
/* left expression */
|
|
strncpy(str1, line, colon);
|
|
str1[colon] = '\0';
|
|
if (parse_expression(str1, &left, &left_exceptions)) {
|
|
/* error */
|
|
LM_ERR("failed to parse line-left: %s\n", line);
|
|
goto error;
|
|
}
|
|
|
|
/* right expression */
|
|
strncpy(str2, line+colon+1, i-colon-1);
|
|
str2[i-colon-1] = '\0';
|
|
if (parse_expression(str2, &right, &right_exceptions)) {
|
|
/* error */
|
|
LM_ERR("failed to parse line-right: %s\n", line);
|
|
goto error;
|
|
}
|
|
|
|
rule1 = new_rule();
|
|
if (!rule1) {
|
|
LM_ERR("can't create new rule\n");
|
|
goto error;
|
|
}
|
|
|
|
rule1->left = left;
|
|
rule1->left_exceptions = left_exceptions;
|
|
rule1->right = right;
|
|
rule1->right_exceptions = right_exceptions;
|
|
return rule1;
|
|
} else {
|
|
/* error */
|
|
LM_ERR("failed to parse line: %s\n", line);
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
error:
|
|
if (left) free_expression(left);
|
|
if (left_exceptions) free_expression(left_exceptions);
|
|
|
|
if (right) free_expression(right);
|
|
if (right_exceptions) free_expression(right_exceptions);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* parse a config file
|
|
* return a list of rules
|
|
*/
|
|
rule *parse_config_file(char *filename)
|
|
{
|
|
FILE *file;
|
|
char line[LINE_LENGTH+1];
|
|
rule *start_rule = NULL, *rule1 = NULL, *rule2 = NULL;
|
|
|
|
file = fopen(filename,"r");
|
|
if (!file) {
|
|
LM_INFO("file not found: %s\n", filename);
|
|
return NULL;
|
|
}
|
|
|
|
while (fgets(line, LINE_LENGTH, file)) {
|
|
rule2 = parse_config_line(line);
|
|
if (rule2) {
|
|
if (rule1) {
|
|
/* it is not the first rule */
|
|
rule1->next = rule2;
|
|
} else {
|
|
/* it is the first rule */
|
|
start_rule = rule2;
|
|
}
|
|
rule1 = rule2;
|
|
}
|
|
}
|
|
|
|
fclose(file);
|
|
return start_rule; /* returns the linked list */
|
|
}
|