Annotation of embedaddon/miniupnpd/upnppermissions.c, revision 1.1.1.2

1.1.1.2 ! misho       1: /* $Id: upnppermissions.c,v 1.17 2012/02/15 22:43:34 nanard Exp $ */
1.1       misho       2: /* MiniUPnP project
                      3:  * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
1.1.1.2 ! misho       4:  * (c) 2006-2012 Thomas Bernard
1.1       misho       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>
1.1.1.2 ! misho      13: #include <netinet/in.h>
1.1       misho      14: #include <arpa/inet.h>
                     15: #include <unistd.h>
                     16: #include "config.h"
                     17: #include "upnppermissions.h"
                     18: 
1.1.1.2 ! misho      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:  */
1.1       misho      24: int
                     25: read_permission_line(struct upnpperm * perm,
                     26:                      char * p)
                     27: {
                     28:        char * q;
                     29:        int n_bits;
1.1.1.2 ! misho      30:        int i;
1.1       misho      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++;
1.1.1.2 ! misho      51: 
        !            52:        /* second token: eport or eport_min-eport_max */
1.1       misho      53:        if(!isdigit(*p))
                     54:                return -1;
                     55:        for(q = p; isdigit(*q); q++);
                     56:        if(*q=='-')
                     57:        {
                     58:                *q = '\0';
1.1.1.2 ! misho      59:                i = atoi(p);
        !            60:                if(i > 65535)
        !            61:                        return -1;
        !            62:                perm->eport_min = (u_short)i;
1.1       misho      63:                q++;
                     64:                p = q;
                     65:                while(isdigit(*q))
                     66:                        q++;
                     67:                *q = '\0';
1.1.1.2 ! misho      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;
1.1       misho      74:        }
1.1.1.2 ! misho      75:        else if(isspace(*q))
1.1       misho      76:        {
                     77:                *q = '\0';
1.1.1.2 ! misho      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;
1.1       misho      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++;
1.1.1.2 ! misho     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:                }
1.1       misho     124:        }
1.1.1.2 ! misho     125:        else if(isspace(*q))
1.1       misho     126:        {
                    127:                *q = '\0';
                    128:                if(!inet_aton(p, &perm->address))
                    129:                        return -1;
1.1.1.2 ! misho     130:                perm->mask.s_addr = 0xffffffffu;
        !           131:        }
        !           132:        else
        !           133:        {
        !           134:                return -1;
1.1       misho     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';
1.1.1.2 ! misho     147:                i = atoi(p);
        !           148:                if(i > 65535)
        !           149:                        return -1;
        !           150:                perm->iport_min = (u_short)i;
1.1       misho     151:                q++;
                    152:                p = q;
                    153:                while(isdigit(*q))
                    154:                        q++;
                    155:                *q = '\0';
1.1.1.2 ! misho     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;
1.1       misho     162:        }
1.1.1.2 ! misho     163:        else if(isspace(*q) || *q == '\0')
1.1       misho     164:        {
                    165:                *q = '\0';
1.1.1.2 ! misho     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;
1.1       misho     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>