Пример #1
0
/*
 * Test URI against Contact.
 */
int allow_test(char *file, char *uri, char *contact)
{
	char *pathname;
	int idx;

	pathname = get_pathname(file);
	if (!pathname) {
		LM_ERR("Cannot get pathname of <%s>\n", file);
		return 0;
	}

	idx = find_index(allow, pathname);
	if (idx == -1) {
		LM_ERR("File <%s> has not been loaded\n", pathname);
		pkg_free(pathname);
		return 0;
	}

	pkg_free(pathname);

	/* turn off control, allow any routing */
	if ((!allow[idx].rules) && (!deny[idx].rules)) {
		LM_DBG("No rules => Allowed\n");
		return 1;
	}

	LM_DBG("Looking for URI: %s, Contact: %s\n", uri, contact);

	/* rule exists in allow file */
	if (search_rule(allow[idx].rules, uri, contact)) {
		LM_DBG("Allow rule found => Allowed\n");
		return 1;
	}

	/* rule exists in deny file */
	if (search_rule(deny[idx].rules, uri, contact)) {
		LM_DBG("Deny rule found => Denied\n");
		return 0;
	}

	LM_DBG("Neither allow or deny rule found => Allowed\n");
	return 1;

}
Пример #2
0
static Char* parse_extra_rule(Char* read_ptr, Trace_Block* block)
{
   Char* name;

   tl_assert2(block, "the first group cannot be started by {");
   read_ptr++;
   name = read_ptr;

   while (*read_ptr != '}') {
      tl_assert2(*read_ptr && *read_ptr != '\n' && *read_ptr != '\r', "unterminated {");
      read_ptr++;
   }
   tl_assert2(name != read_ptr, "node has no name");

   search_rule(block, name, read_ptr - name);
   read_ptr++;

   while (*read_ptr == ' ')
      read_ptr++;
   tl_assert2(*read_ptr == '\n' || *read_ptr == '\r' || !*read_ptr, "Garbage at the end of the line");
   return read_ptr;
}
Пример #3
0
/*
 * determines the permission to an uri
 * return values:
 * -1:	deny
 * 1:	allow
 */
static int allow_uri(struct sip_msg* msg, char* _idx, char* _sp) 
{
	struct hdr_field *from;
	int idx, len;
	static char from_str[EXPRESSION_LENGTH+1];
	static char uri_str[EXPRESSION_LENGTH+1];
	pv_spec_t *sp;
	pv_value_t pv_val;

	idx = (int)(long)_idx;
	sp = (pv_spec_t *)_sp;

	/* turn off control, allow any uri */
	if ((!allow[idx].rules) && (!deny[idx].rules)) {
		LM_DBG("no rules => allow any uri\n");
		return 1;
	}

	/* looking for FROM HF */
	if ((!msg->from) && (parse_headers(msg, HDR_FROM_F, 0) == -1)) {
		LM_ERR("failed to parse message\n");
		return -1;
	}

	if (!msg->from) {
		LM_ERR("FROM header field not found\n");
		return -1;
	}

	/* we must call parse_from_header explicitly */
	if ((!(msg->from)->parsed) && (parse_from_header(msg) < 0)) {
		LM_ERR("failed to parse From body\n");
		return -1;
	}

	from = msg->from;
	len = ((struct to_body*)from->parsed)->uri.len;
	if (len > EXPRESSION_LENGTH) {
		LM_ERR("From header field is too long: %d chars\n", len);
		return -1;
	}
	strncpy(from_str, ((struct to_body*)from->parsed)->uri.s, len);
	from_str[len] = '\0';

	if (sp && (pv_get_spec_value(msg, sp, &pv_val) == 0)) {
		if (pv_val.flags & PV_VAL_STR) {
			if (pv_val.rs.len > EXPRESSION_LENGTH) {
				LM_ERR("pseudo variable value is too "
						"long: %d chars\n", pv_val.rs.len);
				return -1;
			}
			strncpy(uri_str, pv_val.rs.s, pv_val.rs.len);
			uri_str[pv_val.rs.len] = '\0';
		} else {
			LM_ERR("pseudo variable value is not string\n");
			return -1;
		}
	} else {
		LM_ERR("cannot get pseudo variable value\n");
		return -1;
	}

	LM_DBG("looking for From: %s URI: %s\n", from_str, uri_str);
	/* rule exists in allow file */
	if (search_rule(allow[idx].rules, from_str, uri_str)) {
		LM_DBG("allow rule found => URI is allowed\n");
		return 1;
	}

	/* rule exists in deny file */
	if (search_rule(deny[idx].rules, from_str, uri_str)) {
		LM_DBG("deny rule found => URI is denied\n");
		return -1;
	}

	LM_DBG("neither allow nor deny rule found => URI is allowed\n");

	return 1;
}
Пример #4
0
/*
 * Test of REGISTER messages. Creates To-Contact pairs and compares them
 * against rules in allow and deny files passed as parameters. The function
 * iterates over all Contacts and creates a pair with To for each contact 
 * found. That allows to restrict what IPs may be used in registrations, for
 * example
 */
static int check_register(struct sip_msg* msg, int idx)
{
	int len;
	static char to_str[EXPRESSION_LENGTH + 1];
	char* contact_str;
	contact_t* c;

	/* turn off control, allow any routing */
	if ((!allow[idx].rules) && (!deny[idx].rules)) {
		LM_DBG("no rules => allow any registration\n");
		return 1;
	}

	/*
	 * Note: We do not parse the whole header field here although the message can
	 * contain multiple Contact header fields. We try contacts one by one and if one
	 * of them causes reject then we don't look at others, this could improve performance
	 * a little bit in some situations
	 */
	if (parse_headers(msg, HDR_TO_F | HDR_CONTACT_F, 0) == -1) {
		LM_ERR("failed to parse headers\n");
		return -1;
	}

	if (!msg->to) {
		LM_ERR("To or Contact not found\n");
		return -1;
	}

	if (!msg->contact) {
		/* REGISTER messages that contain no Contact header field
		 * are allowed. Such messages do not modify the contents of
		 * the user location database anyway and thus are not harmful
		 */
		LM_DBG("no Contact found, allowing\n");
		return 1;
	}

	/* Check if the REGISTER message contains start Contact and if
	 * so then allow it
	 */
	if (parse_contact(msg->contact) < 0) {
		LM_ERR("failed to parse Contact HF\n");
		return -1;
	}

	if (((contact_body_t*)msg->contact->parsed)->star) {
		LM_DBG("* Contact found, allowing\n");
		return 1;
	}

	len = ((struct to_body*)msg->to->parsed)->uri.len;
	if (len > EXPRESSION_LENGTH) {
		LM_ERR("To header field is too long: %d chars\n", len);
		return -1;
	}
	strncpy(to_str, ((struct to_body*)msg->to->parsed)->uri.s, len);
	to_str[len] = '\0';

	if (contact_iterator(&c, msg, 0) < 0) {
		return -1;
	}

	while(c) {
		contact_str = get_plain_uri(&c->uri);
		if (!contact_str) {
			LM_ERR("can't extract plain Contact URI\n");
			return -1;
		}

		LM_DBG("looking for To: %s Contact: %s\n", to_str, contact_str);

		/* rule exists in allow file */
		if (search_rule(allow[idx].rules, to_str, contact_str)) {
			if (check_all_branches) goto skip_deny;
		}

		/* rule exists in deny file */
		if (search_rule(deny[idx].rules, to_str, contact_str)) {
			LM_DBG("deny rule found => Register denied\n");
			return -1;
		}

skip_deny:
		if (contact_iterator(&c, msg, c) < 0) {
			return -1;
		}
	}

	LM_DBG("no contact denied => Allowed\n");
	return 1;
}
Пример #5
0
/*
 * determines the permission of the call
 * return values:
 * -1:	deny
 * 1:	allow
 */
static int check_routing(struct sip_msg* msg, int idx) 
{
	struct hdr_field *from;
	int len, q;
	static char from_str[EXPRESSION_LENGTH+1];
	static char ruri_str[EXPRESSION_LENGTH+1];
	char* uri_str;
	str branch;
	int br_idx;

	/* turn off control, allow any routing */
	if ((!allow[idx].rules) && (!deny[idx].rules)) {
		LM_DBG("no rules => allow any routing\n");
		return 1;
	}

	/* looking for FROM HF */
	if ((!msg->from) && (parse_headers(msg, HDR_FROM_F, 0) == -1)) {
		LM_ERR("failed to parse message\n");
		return -1;
	}

	if (!msg->from) {
		LM_ERR("FROM header field not found\n");
		return -1;
	}

	/* we must call parse_from_header explicitly */
	if ((!(msg->from)->parsed) && (parse_from_header(msg) < 0)) {
		LM_ERR("failed to parse From body\n");
		return -1;
	}

	from = msg->from;
	len = ((struct to_body*)from->parsed)->uri.len;
	if (len > EXPRESSION_LENGTH) {
		LM_ERR("From header field is too long: %d chars\n", len);
		return -1;
	}
	strncpy(from_str, ((struct to_body*)from->parsed)->uri.s, len);
	from_str[len] = '\0';

	/* looking for request URI */
	if (parse_sip_msg_uri(msg) < 0) {
		LM_ERR("uri parsing failed\n");
		return -1;
	}

	len = msg->parsed_uri.user.len + msg->parsed_uri.host.len + 5;
	if (len > EXPRESSION_LENGTH) {
		LM_ERR("Request URI is too long: %d chars\n", len);
		return -1;
	}

	strcpy(ruri_str, "sip:");
	memcpy(ruri_str + 4, msg->parsed_uri.user.s, msg->parsed_uri.user.len);
	ruri_str[msg->parsed_uri.user.len + 4] = '@';
	memcpy(ruri_str + msg->parsed_uri.user.len + 5, msg->parsed_uri.host.s, msg->parsed_uri.host.len);
	ruri_str[len] = '\0';

	LM_DBG("looking for From: %s Request-URI: %s\n", from_str, ruri_str);
	/* rule exists in allow file */
	if (search_rule(allow[idx].rules, from_str, ruri_str)) {
		if (check_all_branches) goto check_branches;
		LM_DBG("allow rule found => routing is allowed\n");
		return 1;
	}

	/* rule exists in deny file */
	if (search_rule(deny[idx].rules, from_str, ruri_str)) {
		LM_DBG("deny rule found => routing is denied\n");
		return -1;
	}

	if (!check_all_branches) {
		LM_DBG("neither allow nor deny rule found => routing is allowed\n");
		return 1;
	}

check_branches:
	for( br_idx=0 ; (branch.s=get_branch(br_idx,&branch.len,&q,0,0,0,0,0,0,0))!=0 ;
			br_idx++ ) {
		uri_str = get_plain_uri(&branch);
		if (!uri_str) {
			LM_ERR("failed to extract plain URI\n");
			return -1;
		}
		LM_DBG("looking for From: %s Branch: %s\n", from_str, uri_str);

		if (search_rule(allow[idx].rules, from_str, uri_str)) {
			continue;
		}

		if (search_rule(deny[idx].rules, from_str, uri_str)) {
			LM_DBG("deny rule found for one of branches => routing"
					"is denied\n");
			return -1;
		}
	}

	LM_DBG("check of branches passed => routing is allowed\n");
	return 1;
}
Пример #6
0
static void fr_post_clo_init(void)
{
   Rule_List* last_rule_ptr = NULL;
   Char* read_ptr;
   Trace_Block* block = NULL;
   Trace_Block* parent = NULL;
   Int* indents = (int*)dir_buffer;
   Int indent;
   Int depth = -1;
   Bool is_group;
   SysRes sres;
   Int fd;
   OffT file_size;

   if (clo_mmap) {
#if VG_WORDSIZE == 4
      mmap_section.next = NULL;
      mmap_section.page_addr = 0;
      mmap_section.trace_blocks = VG_(calloc)("freya.fr_post_clo_init.2", PAGE_NUMBER, sizeof(Trace_Block*));
      mmap_section.used_blocks = VG_(calloc)("freya.fr_post_clo_init.3", PAGE_NUMBER, sizeof(Char));
#else
      mmap_sections = VG_(calloc)("freya.fr_post_clo_init.1", 1, sizeof(Mmap_Section));
      mmap_sections->next = NULL;
      mmap_sections->page_addr = 0;
      mmap_sections->trace_blocks = VG_(calloc)("freya.fr_post_clo_init.2", PAGE_NUMBER, sizeof(Trace_Block*));
      mmap_sections->used_blocks = VG_(calloc)("freya.fr_post_clo_init.3", PAGE_NUMBER, sizeof(Char));
      mmap_section_cache = mmap_sections;
#endif
   }

   read_ptr = NULL;
   if (clo_config) {
      sres = VG_(open)(clo_config, VKI_O_RDONLY, 0);
      if (!sr_isError(sres)) {
         fd = (Int) sr_Res(sres);

         file_size = VG_(lseek)(fd, 0, VKI_SEEK_END);
         VG_(lseek)(fd, 0, VKI_SEEK_SET);

         if (clo_fr_verb)
            VG_(printf)("File '%s' (size: %ld bytes) is successfully opened.\n", clo_config, file_size);

         read_ptr = VG_(malloc)("freya.fr_post_clo_init.3", (file_size + 1) * sizeof(Char));
         VG_(read)(fd, read_ptr, file_size);
         read_ptr[file_size] = '\0';

         VG_(close) (fd);
      }
      else if (clo_fr_verb)
         VG_(printf)("Cannot open '%s'. (Fallback to default config)\n", clo_config);
   }
   else if (clo_fr_verb)
      VG_(printf)("No config file provided. (Fallback to default config)\n");

   if (!read_ptr) {
      // Duplicate
      read_ptr = VG_(malloc)("freya.fr_post_clo_init.4", (VG_(strlen)(default_rule) + 1) * sizeof(Char));
      VG_(strcpy)(read_ptr, default_rule);
   }

   while (*read_ptr) {
      // Parsing the next line, first skip spaces
      indent = 0;
      while (*read_ptr == ' ') {
         indent++;
         read_ptr++;
      }

      // Skip comments and empty lines
      if (*read_ptr == '#' || *read_ptr == '\r' || *read_ptr == '\n') {
         while (*read_ptr != '\0' && *read_ptr != '\r' && *read_ptr != '\n')
            read_ptr++;

         if (*read_ptr) {
            read_ptr++;
            continue;
         }
      }

      if (*read_ptr == '{') {
         read_ptr = parse_extra_rule(read_ptr, block);
         continue;
      } else if (*read_ptr != '[' && *read_ptr != '(') {
         read_ptr = parse_rule(read_ptr, &last_rule_ptr);
         continue;
      }

      is_group = *read_ptr == '[';

      block = VG_(malloc)("freya.fr_post_clo_init.4", sizeof(Trace_Block));
      read_ptr++;
      block->name = read_ptr;

      while (!(!is_group && *read_ptr == ')') && !(is_group && *read_ptr == ']')) {
         tl_assert2(*read_ptr && *read_ptr != '\n' && *read_ptr != '\r', "unterminated ( or [");
         read_ptr++;
      }
      tl_assert2(block->name != read_ptr, "node has no name");

      *read_ptr = '\0';
      if (!is_group)
         search_rule(block, block->name, read_ptr - block->name);
      read_ptr++;

      if (*read_ptr == '+') {
         tl_assert2(default_parent == NULL, "Only one default node is allowed");
         default_parent = block;
         read_ptr++;
      }

      while (*read_ptr == ' ')
         read_ptr++;
      tl_assert2(*read_ptr == '\n' || *read_ptr == '\r' || !*read_ptr, "Garbage at the end of the line");

      if (clo_fr_verb)
         VG_(printf)("%s '%s' %s\n", is_group ? "Group:" : "Group & Attach:", block->name, default_parent == block ? "(Default)" : "");

      if (depth >= 0) {
         if (indents[depth] != indent) {
            if (indent > indents[depth]) {
               tl_assert2(depth < 63, "Maximum allowed depth is 63 for the tree");
               depth++;
               indents[depth] = indent;
               if (parent)
                  parent = parent->first;
               else
                  parent = trace_head;
            } else {
               do {
                  tl_assert2(depth != 0, "Wrong tree indentation");
                  depth--;
                  tl_assert(parent);
                  parent = parent->parent;
               } while (indent != indents[depth]);
               tl_assert((depth == 0 && !parent) || (depth > 0 && parent));
            }
         }
      } else {
         // The indentation of the top element
         tl_assert(!parent);
         indents[0] = indent;
         depth = 0;
      }

      block->parent = parent;
      if (parent) {
         block->next = parent->first;
         parent->first = block;
      } else {
         block->next = trace_head;
         trace_head = block;
      }
      block->first = NULL;

      block->hash_next = NULL;

      block->allocs = 0;
      block->total = 0;
      block->current = 0;
      block->peak = 0;
      block->ips = 0;
   }

   remove_unused_rules();
}