miniupnpd: improved permission checking for NAT-PMP
NAT-PMP now searches an allowed eport if the one from request is not, instead of returning an error
This commit is contained in:
parent
f49a70aab0
commit
e385db03b9
|
@ -1,4 +1,8 @@
|
|||
$Id: Changelog.txt,v 1.354 2014/02/28 12:14:29 nanard Exp $
|
||||
$Id: Changelog.txt,v 1.357 2014/03/07 10:43:29 nanard Exp $
|
||||
|
||||
2014/04/07:
|
||||
NAT-PMP search an allowed eport instead of returning an error
|
||||
if the original eport is not allowed.
|
||||
|
||||
2014/02/28:
|
||||
log message when shutting down
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: natpmp.c,v 1.36 2014/02/01 17:17:35 nanard Exp $ */
|
||||
/* $Id: natpmp.c,v 1.39 2014/03/07 10:43:30 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* (c) 2007-2014 Thomas Bernard
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
|
@ -263,14 +263,32 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
|
|||
}
|
||||
}
|
||||
eport = 0; /* to indicate correct removing of port mapping */
|
||||
} else if(iport==0
|
||||
|| !check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) {
|
||||
} else if(iport==0) {
|
||||
resp[3] = 2; /* Not Authorized/Refused */
|
||||
} else {
|
||||
} else { /* iport > 0 && lifetime > 0 */
|
||||
unsigned short eport_first;
|
||||
char desc[64];
|
||||
if(!check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) {
|
||||
/* if the mapping is forbidden because of eport only
|
||||
* (ie iaddr/iport are ok with another eport)
|
||||
* change eport value ! */
|
||||
if(!find_allowed_eport(upnppermlist, num_upnpperm, senderaddr->sin_addr, iport, &eport)) {
|
||||
/* no rule allow a mapping with this iaddr/iport */
|
||||
resp[3] = 2; /* Not Authorized/Refused */
|
||||
}
|
||||
}
|
||||
eport_first = eport;
|
||||
do {
|
||||
while(resp[3] == 0) {
|
||||
if(!check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) {
|
||||
eport++;
|
||||
if(eport == eport_first) { /* no external port available */
|
||||
syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu",
|
||||
eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport);
|
||||
resp[3] = 4; /* Out of resources */
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
r = get_redirect_rule(ext_if_name, eport, proto,
|
||||
iaddr_old, sizeof(iaddr_old),
|
||||
&iport_old, 0, 0, 0, 0,
|
||||
|
@ -314,16 +332,9 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
|
|||
syslog(LOG_ERR, "Failed to add NAT-PMP %hu %s->%s:%hu '%s'",
|
||||
eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport, desc);
|
||||
resp[3] = 3; /* Failure */
|
||||
#if 0
|
||||
} else if( !nextnatpmptoclean_eport
|
||||
|| timestamp < nextnatpmptoclean_timestamp) {
|
||||
nextnatpmptoclean_timestamp = timestamp;
|
||||
nextnatpmptoclean_eport = eport;
|
||||
nextnatpmptoclean_proto = proto;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
} while(r==0);
|
||||
}
|
||||
}
|
||||
*((uint16_t *)(resp+8)) = htons(iport); /* private port */
|
||||
*((uint16_t *)(resp+10)) = htons(eport); /* public port */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $Id: upnppermissions.c,v 1.17 2012/02/15 22:43:34 nanard Exp $ */
|
||||
/* $Id: upnppermissions.c,v 1.18 2014/03/07 10:43:29 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2012 Thomas Bernard
|
||||
* (c) 2006-2014 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
|
@ -223,6 +223,21 @@ match_permission(const struct upnpperm * perm,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* match_permission_internal()
|
||||
* returns: 1 if address, iport matches the permission rule
|
||||
* 0 if no match */
|
||||
static int
|
||||
match_permission_internal(const struct upnpperm * perm,
|
||||
struct in_addr address, u_short iport)
|
||||
{
|
||||
if( (iport < perm->iport_min) || (perm->iport_max < iport))
|
||||
return 0;
|
||||
if( (address.s_addr & perm->mask.s_addr)
|
||||
!= (perm->address.s_addr & perm->mask.s_addr) )
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
check_upnp_rule_against_permissions(const struct upnpperm * permary,
|
||||
int n_perms,
|
||||
|
@ -245,3 +260,21 @@ check_upnp_rule_against_permissions(const struct upnpperm * permary,
|
|||
return 1; /* Default : accept */
|
||||
}
|
||||
|
||||
int
|
||||
find_allowed_eport(const struct upnpperm * permary,
|
||||
int n_perms,
|
||||
struct in_addr address, u_short iport,
|
||||
u_short *allowed_eport)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<n_perms; i++)
|
||||
{
|
||||
if(permary[i].type == UPNPPERM_ALLOW
|
||||
&& match_permission_internal(permary + i, address, iport)) {
|
||||
*allowed_eport = permary[i].eport_min;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0; /* no eport found */
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $Id: upnppermissions.h,v 1.7 2007/02/28 18:13:18 nanard Exp $ */
|
||||
/* $Id: upnppermissions.h,v 1.10 2014/03/07 10:43:29 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006 Thomas Bernard
|
||||
* (c) 2006-2014 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
|
@ -45,6 +45,15 @@ check_upnp_rule_against_permissions(const struct upnpperm * permary,
|
|||
u_short eport, struct in_addr address,
|
||||
u_short iport);
|
||||
|
||||
/* find_allowed_eport()
|
||||
* returns: 0 if no allowed eport for (address, iport) was found
|
||||
* 1 and allowed_eport filled */
|
||||
int
|
||||
find_allowed_eport(const struct upnpperm * permary,
|
||||
int n_perms,
|
||||
struct in_addr address, u_short iport,
|
||||
u_short *allowed_eport);
|
||||
|
||||
#ifdef USE_MINIUPNPDCTL
|
||||
void
|
||||
write_permlist(int fd, const struct upnpperm * permary,
|
||||
|
|
Loading…
Reference in New Issue