File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / miniupnpd / upnppermissions.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 00:32:35 2013 UTC (11 years, 5 months ago) by misho
Branches: miniupnpd, elwix, MAIN
CVS tags: v1_8p0, v1_8, HEAD
1.8

    1: /* $Id: upnppermissions.c,v 1.1.1.2 2013/07/22 00:32:35 misho Exp $ */
    2: /* MiniUPnP project
    3:  * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
    4:  * (c) 2006-2012 Thomas Bernard
    5:  * This software is subject to the conditions detailed
    6:  * in the LICENCE file provided within the distribution */
    7: 
    8: #include <ctype.h>
    9: #include <string.h>
   10: #include <stdlib.h>
   11: #include <stdio.h>
   12: #include <syslog.h>
   13: #include <netinet/in.h>
   14: #include <arpa/inet.h>
   15: #include <unistd.h>
   16: #include "config.h"
   17: #include "upnppermissions.h"
   18: 
   19: /* read_permission_line()
   20:  * parse the a permission line which format is :
   21:  * (deny|allow) [0-9]+(-[0-9]+) ip/mask [0-9]+(-[0-9]+)
   22:  * ip/mask is either 192.168.1.1/24 or 192.168.1.1/255.255.255.0
   23:  */
   24: int
   25: read_permission_line(struct upnpperm * perm,
   26:                      char * p)
   27: {
   28: 	char * q;
   29: 	int n_bits;
   30: 	int i;
   31: 
   32: 	/* first token: (allow|deny) */
   33: 	while(isspace(*p))
   34: 		p++;
   35: 	if(0 == memcmp(p, "allow", 5))
   36: 	{
   37: 		perm->type = UPNPPERM_ALLOW;
   38: 		p += 5;
   39: 	}
   40: 	else if(0 == memcmp(p, "deny", 4))
   41: 	{
   42: 		perm->type = UPNPPERM_DENY;
   43: 		p += 4;
   44: 	}
   45: 	else
   46: 	{
   47: 		return -1;
   48: 	}
   49: 	while(isspace(*p))
   50: 		p++;
   51: 
   52: 	/* second token: eport or eport_min-eport_max */
   53: 	if(!isdigit(*p))
   54: 		return -1;
   55: 	for(q = p; isdigit(*q); q++);
   56: 	if(*q=='-')
   57: 	{
   58: 		*q = '\0';
   59: 		i = atoi(p);
   60: 		if(i > 65535)
   61: 			return -1;
   62: 		perm->eport_min = (u_short)i;
   63: 		q++;
   64: 		p = q;
   65: 		while(isdigit(*q))
   66: 			q++;
   67: 		*q = '\0';
   68: 		i = atoi(p);
   69: 		if(i > 65535)
   70: 			return -1;
   71: 		perm->eport_max = (u_short)i;
   72: 		if(perm->eport_min > perm->eport_max)
   73: 			return -1;
   74: 	}
   75: 	else if(isspace(*q))
   76: 	{
   77: 		*q = '\0';
   78: 		i = atoi(p);
   79: 		if(i > 65535)
   80: 			return -1;
   81: 		perm->eport_min = perm->eport_max = (u_short)i;
   82: 	}
   83: 	else
   84: 	{
   85: 		return -1;
   86: 	}
   87: 	p = q + 1;
   88: 	while(isspace(*p))
   89: 		p++;
   90: 
   91: 	/* third token:  ip/mask */
   92: 	if(!isdigit(*p))
   93: 		return -1;
   94: 	for(q = p; isdigit(*q) || (*q == '.'); q++);
   95: 	if(*q=='/')
   96: 	{
   97: 		*q = '\0';
   98: 		if(!inet_aton(p, &perm->address))
   99: 			return -1;
  100: 		q++;
  101: 		p = q;
  102: 		while(isdigit(*q))
  103: 			q++;
  104: 		if(*q == '.')
  105: 		{
  106: 			while(*q == '.' || isdigit(*q))
  107: 				q++;
  108: 			if(!isspace(*q))
  109: 				return -1;
  110: 			*q = '\0';
  111: 			if(!inet_aton(p, &perm->mask))
  112: 				return -1;
  113: 		}
  114: 		else if(!isspace(*q))
  115: 			return -1;
  116: 		else
  117: 		{
  118: 			*q = '\0';
  119: 			n_bits = atoi(p);
  120: 			if(n_bits > 32)
  121: 				return -1;
  122: 			perm->mask.s_addr = htonl(n_bits ? (0xffffffffu << (32 - n_bits)) : 0);
  123: 		}
  124: 	}
  125: 	else if(isspace(*q))
  126: 	{
  127: 		*q = '\0';
  128: 		if(!inet_aton(p, &perm->address))
  129: 			return -1;
  130: 		perm->mask.s_addr = 0xffffffffu;
  131: 	}
  132: 	else
  133: 	{
  134: 		return -1;
  135: 	}
  136: 	p = q + 1;
  137: 
  138: 	/* fourth token: iport or iport_min-iport_max */
  139: 	while(isspace(*p))
  140: 		p++;
  141: 	if(!isdigit(*p))
  142: 		return -1;
  143: 	for(q = p; isdigit(*q); q++);
  144: 	if(*q=='-')
  145: 	{
  146: 		*q = '\0';
  147: 		i = atoi(p);
  148: 		if(i > 65535)
  149: 			return -1;
  150: 		perm->iport_min = (u_short)i;
  151: 		q++;
  152: 		p = q;
  153: 		while(isdigit(*q))
  154: 			q++;
  155: 		*q = '\0';
  156: 		i = atoi(p);
  157: 		if(i > 65535)
  158: 			return -1;
  159: 		perm->iport_max = (u_short)i;
  160: 		if(perm->iport_min > perm->iport_max)
  161: 			return -1;
  162: 	}
  163: 	else if(isspace(*q) || *q == '\0')
  164: 	{
  165: 		*q = '\0';
  166: 		i = atoi(p);
  167: 		if(i > 65535)
  168: 			return -1;
  169: 		perm->iport_min = perm->iport_max = (u_short)i;
  170: 	}
  171: 	else
  172: 	{
  173: 		return -1;
  174: 	}
  175: #ifdef DEBUG
  176: 	printf("perm rule added : %s %hu-%hu %08x/%08x %hu-%hu\n",
  177: 	       (perm->type==UPNPPERM_ALLOW)?"allow":"deny",
  178: 	       perm->eport_min, perm->eport_max, ntohl(perm->address.s_addr),
  179: 	       ntohl(perm->mask.s_addr), perm->iport_min, perm->iport_max);
  180: #endif
  181: 	return 0;
  182: }
  183: 
  184: #ifdef USE_MINIUPNPDCTL
  185: void
  186: write_permlist(int fd, const struct upnpperm * permary,
  187:                int nperms)
  188: {
  189: 	int l;
  190: 	const struct upnpperm * perm;
  191: 	int i;
  192: 	char buf[128];
  193: 	write(fd, "Permissions :\n", 14);
  194: 	for(i = 0; i<nperms; i++)
  195: 	{
  196: 		perm = permary + i;
  197: 		l = snprintf(buf, sizeof(buf), "%02d %s %hu-%hu %08x/%08x %hu-%hu\n",
  198: 	       i,
  199:     	   (perm->type==UPNPPERM_ALLOW)?"allow":"deny",
  200: 	       perm->eport_min, perm->eport_max, ntohl(perm->address.s_addr),
  201: 	       ntohl(perm->mask.s_addr), perm->iport_min, perm->iport_max);
  202: 		if(l<0)
  203: 			return;
  204: 		write(fd, buf, l);
  205: 	}
  206: }
  207: #endif
  208: 
  209: /* match_permission()
  210:  * returns: 1 if eport, address, iport matches the permission rule
  211:  *          0 if no match */
  212: static int
  213: match_permission(const struct upnpperm * perm,
  214:                  u_short eport, struct in_addr address, u_short iport)
  215: {
  216: 	if( (eport < perm->eport_min) || (perm->eport_max < eport))
  217: 		return 0;
  218: 	if( (iport < perm->iport_min) || (perm->iport_max < iport))
  219: 		return 0;
  220: 	if( (address.s_addr & perm->mask.s_addr)
  221: 	   != (perm->address.s_addr & perm->mask.s_addr) )
  222: 		return 0;
  223: 	return 1;
  224: }
  225: 
  226: int
  227: check_upnp_rule_against_permissions(const struct upnpperm * permary,
  228:                                     int n_perms,
  229:                                     u_short eport, struct in_addr address,
  230:                                     u_short iport)
  231: {
  232: 	int i;
  233: 	for(i=0; i<n_perms; i++)
  234: 	{
  235: 		if(match_permission(permary + i, eport, address, iport))
  236: 		{
  237: 			syslog(LOG_DEBUG,
  238: 			       "UPnP permission rule %d matched : port mapping %s",
  239: 			       i, (permary[i].type == UPNPPERM_ALLOW)?"accepted":"rejected"
  240: 			       );
  241: 			return (permary[i].type == UPNPPERM_ALLOW);
  242: 		}
  243: 	}
  244: 	syslog(LOG_DEBUG, "no permission rule matched : accept by default (n_perms=%d)", n_perms);
  245: 	return 1;	/* Default : accept */
  246: }
  247: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>