📄 filters.c
字号:
#ifdef BINARY_FILTERS/* * Copyright (c) 1994 Ascend Communications, Inc. * All rights reserved. * * Permission to copy all or part of this material for any purpose is * granted provided that the above copyright notice and this paragraph * are duplicated in all copies. THIS SOFTWARE IS PROVIDED ``AS IS'' * AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. *//* * Copyright [C] The Regents of the University of Michigan and Merit Network, * Inc. 1992, 1993, 1994, 1995, 1996, 1997, 1998 All Rights Reserved * * Permission to use, copy, and modify this software and its documentation * for any purpose and without fee is hereby granted, provided: * * 1) that the above copyright notice and this permission notice appear in all * copies of the software and derivative works or modified versions thereof, * * 2) that both the copyright notice and this permission and disclaimer notice * appear in all supporting documentation, and * * 3) that all derivative works made from this material are returned to the * Regents of the University of Michigan and Merit Network, Inc. with * permission to copy, to display, to distribute, and to make derivative * works from the provided material in whole or in part for any purpose. * * Users of this code are requested to notify Merit Network, Inc. of such use * by sending email to aaa-admin@merit.edu * * Please also use aaa-admin@merit.edu to inform Merit Network, Inc of any * derivative works. * * Distribution of this software or derivative works or the associated * documentation is not allowed without an additional license. * * Licenses for other uses are available on an individually negotiated * basis. Contact aaa-license@merit.edu for more information. * * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF THE * UNIVERSITY OF MICHIGAN AND MERIT NETWORK, INC. DO NOT WARRANT THAT THE * FUNCTIONS CONTAINED IN THE SOFTWARE WILL MEET LICENSEE'S REQUIREMENTS OR * THAT OPERATION WILL BE UNINTERRUPTED OR ERROR FREE. The Regents of the * University of Michigan and Merit Network, Inc. shall not be liable for any * special, indirect, incidental or consequential damages with respect to any * claim by Licensee or any third party arising from use of the software. * * Merit AAA Server Support * Merit Network, Inc. * 4251 Plymouth Road, Suite C. * Ann Arbor, Michigan, USA 48105-2785 * * attn: John Vollbrecht * voice: 734-764-9430 * fax: 734-647-3185 * email: aaa-admin@merit.edu * */static char rcsid[] = "$Id: filters.c,v 1.1.1.1 2001/08/10 20:49:28 bonze Exp $";#include <sys/types.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <errno.h>#include <syslog.h>#include <netinet/in.h>#include <stdlib.h>#include <sys/time.h> /* gettimeofday() */#include <memory.h>#include "radius.h"extern int debug_flag;/* * Filter Port Type * * ASCII names of some well known TCP/UDP services. * Used for filtering on a port type. * */static keywordstruct filterporttype[] ={ { "ftp-data", 20 }, { "ftp", 21 }, { "telnet", 23 }, { "smtp", 25 }, { "nameserver", 42 }, { "domain", 53 }, { "tftp", 69 }, { "gopher", 70 }, { "finger", 79 }, { "www", 80 }, { "kerberos", 88 }, { "hostname", 101 }, { "nntp", 119 }, { "ntp", 123 }, { "exec", 512 }, { "login", 513 }, { "cmd", 514 }, { "talk", 517 }, { NULL, NO_TOKEN },};static keywordstruct filterkeywords[] ={ { "ip", FILTER_IP_TYPE }, { "generic", FILTER_GENERIC_TYPE }, { "in", FILTER_IN }, { "out", FILTER_OUT }, { "forward", FILTER_FORWARD }, { "drop", FILTER_DROP }, { "dstip", FILTER_IP_DST }, { "srcip", FILTER_IP_SRC }, { "dstport", FILTER_IP_DST_PORT }, { "srcport", FILTER_IP_SRC_PORT }, { "est", FILTER_EST }, { "more", FILTER_MORE }, { "!=", FILTER_GENERIC_COMPNEQ }, { "==", FILTER_GENERIC_COMPEQ }, { NULL, NO_TOKEN },};#define FILTER_DIRECTION 0#define FILTER_DISPOSITION 1#define IP_FILTER_COMPLETE 0x3 /* bits shifted by FILTER_DIRECTION, */ /* and by FILTER_DISPOSITION */#define GENERIC_FILTER_COMPLETE 0x1c3 /* bits shifted by FILTER_DIRECTION, */ /* and by FILTER_DISPOSITION, and by */ /* FILTER_GENERIC_OFFSET, and by */ /* FILTER_GENERIC_MASK, and by */ /* FILTER_GENERIC_VALUE *//* * Filter Protocol Name - ASCII names of protocols used for filtering. */static keywordstruct filterprotoname[] ={ { "tcp", 6 }, { "udp", 17 }, { "ospf", 89 }, { "icmp", 1 }, { NULL, NO_TOKEN },};keywordstruct filtercompare[] ={ { ">", RAD_COMPARE_GREATER }, { "=", RAD_COMPARE_EQUAL }, { "<", RAD_COMPARE_LESS }, { "!=", RAD_COMPARE_NOT_EQUAL }, { NULL, NO_TOKEN },};static char curstring[AUTH_STRING2_LEN];static char ip_address_digits[] = "1234567890./";static int find_key PROTO((char *, keywordstruct *));static int is_all_digit PROTO((char *));static short a2octet PROTO((char *, char *));static char default_netmask PROTO((UINT4));static int ipaddr_str2val PROTO((char *, UINT4 *, char *));static int parse_ip_filter PROTO((radfilter *));static int parse_gen_filter PROTO((radfilter *));/************************************************************************* * * Function: find_key * * Purpose: Given a table of keywords, try to match the given string * to an entry. If it matches, return that keyword value, * else NO_TOKEN is returned. A sanity check is made for * upper-case characters. * * Returns: Keyword value on a match, or NO_TOKEN. * *************************************************************************/static intfind_key (string, list)char *string; /* Pointer to the token to match. */keywordstruct *list; /* Point to the list of keywords. */{ short len; keywordstruct *entry; char *ptr; char buf[80]; static char *func = "find_key"; dprintf(2, (LOG_DAEMON, LOG_DEBUG, "%s: entered", func)); len = strlen ((char *) string); for (ptr = buf; len; len--, string++) { if (isupper(*string)) { *ptr++ = tolower(*string); } else { *ptr++ = *string; } } *ptr = 0; entry = list; while (entry->name) { if (strcmp (entry->name, buf) == 0) { break; } entry++; } return (entry->value);} /* end of find_key () *//************************************************************************* * * Function: is_all_digit * * Purpose: Checks a string to make sure all values are digits. * * Returns: TRUE if all digits, or FALSE. * *************************************************************************/static intis_all_digit (token)char *token; /* Pointer to sting to check. */{ int i; static char *func = "is_all_digit"; dprintf(2, (LOG_DAEMON, LOG_DEBUG, "%s: entered", func)); i = strlen ((char *) token); while (i--) { if (isdigit(*token)) { token++; } else { break; } } if (i > 0) { return (FALSE); } return (TRUE);} /* end of is_all_digit () *//************************************************************************* * * Function: a2octet * * Purpose: Converts the ASCII mask and value for generic filters * into octets. Also does a sanity check to see if the * string is greater than MAX_FILTER_LEN. * Assumes the sting is hexadecimal with NO leading "0x". * * Returns: Number of octets, or -1 for error. * *************************************************************************/static shorta2octet (tok, retBuf)char *tok; /* Pointer to the string. */char *retBuf; /* Pointer to place the octets. */{ short i; short len; short rc; short retlen; short val; char *octet; char buf[RAD_MAX_FILTER_LEN * 2]; static char *func = "a2octet"; dprintf(2, (LOG_DAEMON, LOG_DEBUG, "%s: entered", func)); octet = buf; rc = -1; retlen = 0; if ((len = strlen ((char *) tok)) <= (RAD_MAX_FILTER_LEN * 2)) { retlen = len / 2; if (len % 2) { retlen++; } memset (buf, '\0', RAD_MAX_FILTER_LEN * 2); for ( ; len ; len--) { if (*tok <= '9' && *tok >= '0') { val = '0'; *octet++ = *tok++ - val; } else if (isxdigit(*tok)) { if (*tok > 'Z') { val = 'a'; } else { val = 'A'; } *octet++ = (*tok++ - val) + 10; } else { break; } } if (!len) { /* merge the values */ for (i = 0; i < RAD_MAX_FILTER_LEN * 2; i += 2) { *retBuf++ = (buf[i] << 4) | buf[i + 1]; } } } if (len) { rc = -1; } else { rc = retlen; } return (rc);} /* end of a2octet () *//************************************************************************* * * Function: default_netmask * * Purpose: Given an IP address, calculate a default netmask. * * Returns: Number of bits for the netmask. * *************************************************************************/static chardefault_netmask (address)UINT4 address; /* The given IP address. */{ char netmask; static char *func = "default_netmask"; dprintf(2, (LOG_DAEMON, LOG_DEBUG, "%s: entered", func)); if (!address) { netmask = 0; } else if ((address & htonl(0x80000000)) == 0) { netmask = 8; } else if ((address & htonl(0xc0000000)) == htonl(0x80000000)) { netmask = 16; } else if ((address & htonl(0xe0000000)) == htonl(0xc0000000)) { netmask = 24; } else { netmask = 32; } return netmask;} /* end of default_netmask () *//************************************************************************* * * Function: ipaddr_str2val * * Purpose: Attempts to convert an IP address (in ASCII dotted quad * notation with an optional netmask part) to a pair of * IP addresses. Note: An IP address is always stored * in network byte order. * * * Returns: TRUE if valid conversion, FALSE otherwise. * *************************************************************************/static intipaddr_str2val (string, ipaddress, netmask)char *string; /* IP address string: xxx.xxx.xxx.xxx[/nn] */UINT4 *ipaddress; /* Resultant IP address to return to caller. */char *netmask; /* Resultant netmask to return to caller. */{ int i; int numdots; long value; u_char *dst; char *cp; static char *func = "ipaddr_str2val"; dprintf(2, (LOG_DAEMON, LOG_DEBUG, "%s: entered", func)); if (!string) { return (FALSE); } /* * Allow an IP address to be blanked instead of forcing * entry of 0.0.0.0 -- the user will like it. */ if (*string == 0) { *ipaddress = 0; *netmask = 0; return TRUE; } /* * First just count the number of dots in the address. * If there are more or less than three the address is invalid. */ cp = string; numdots = 0; while (*cp) { if (!strchr (ip_address_digits, *cp)) { return (FALSE); } if (*cp == '.') { numdots++; } cp++; } if (numdots != 3) { return (FALSE); } dst = (u_char *) ipaddress; cp = string; for (i = 0; i < sizeof (*ipaddress); i++) { value = strtol (cp, (char **) &cp, 10); if ((value < 0) || (value > 255)) { return (FALSE); } *dst++ = (u_char) value; if (*cp == '.') { cp += 1; } } /* * If there is a netmask part, parse it, otherwise figure out the * default netmask for this class of address. */ if (*cp == '/') { value = strtol (cp + 1, (char **) &cp, 10); if ((*cp != 0) || (value < 0) || (value > 32)) { return (FALSE); } *netmask = (char) value; } else { *netmask = default_netmask (*ipaddress); } return (TRUE);} /* end of ipaddr_str2val () *//************************************************************************* * * Function: parse_ip_filter * * Purpose: Parses an IP filter string from a RADIUS reply. * The format of the string is: * * ip dir action [ dstip n.n.n.n/nn ] [ srcip n.n.n.n/nn ] * [ proto [ dstport cmp value ] [ srcport cmd value ] [ est ] ] * * Fields in [...] are optional. Where: * * ip: Keyword to designate an IP filter. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -