Merge branch 'issue-465' into master
This commit is contained in:
commit
1008ed1117
|
@ -1,7 +1,7 @@
|
||||||
/* $Id: upnppermissions.c,v 1.18 2014/03/07 10:43:29 nanard Exp $ */
|
/* $Id: upnppermissions.c,v 1.18 2014/03/07 10:43:29 nanard Exp $ */
|
||||||
/* MiniUPnP project
|
/* MiniUPnP project
|
||||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||||
* (c) 2006-2014 Thomas Bernard
|
* (c) 2006-2020 Thomas Bernard
|
||||||
* This software is subject to the conditions detailed
|
* This software is subject to the conditions detailed
|
||||||
* in the LICENCE file provided within the distribution */
|
* in the LICENCE file provided within the distribution */
|
||||||
|
|
||||||
|
@ -262,3 +262,44 @@ check_upnp_rule_against_permissions(const struct upnpperm * permary,
|
||||||
return 1; /* Default : accept */
|
return 1; /* Default : accept */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
get_permitted_ext_ports(uint32_t * allowed,
|
||||||
|
const struct upnpperm * permary, int n_perms,
|
||||||
|
in_addr_t addr, u_short iport)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
/* build allowed external ports array */
|
||||||
|
memset(allowed, 0xff, 65536 / 8); /* everything allowed by default */
|
||||||
|
|
||||||
|
for (i = n_perms - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if( (addr & permary[i].mask.s_addr)
|
||||||
|
!= (permary[i].address.s_addr & permary[i].mask.s_addr) )
|
||||||
|
continue;
|
||||||
|
if( (iport < permary[i].iport_min) || (permary[i].iport_max < iport))
|
||||||
|
continue;
|
||||||
|
for (j = (int)permary[i].eport_min ; j <= (int)permary[i].eport_max; )
|
||||||
|
{
|
||||||
|
if ((j % 32) == 0 && ((int)permary[i].eport_max >= (j + 31)))
|
||||||
|
{
|
||||||
|
/* 32bits at once */
|
||||||
|
allowed[j / 32] = (permary[i].type == UPNPPERM_ALLOW) ? 0xffffffff : 0;
|
||||||
|
j += 32;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* one bit at once */
|
||||||
|
if (permary[i].type == UPNPPERM_ALLOW)
|
||||||
|
allowed[j / 32] |= (1 << (j % 32));
|
||||||
|
else
|
||||||
|
allowed[j / 32] &= ~(1 << (j % 32));
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
while ((j % 32) != 0 && (j <= (int)permary[i].eport_max));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* $Id: upnppermissions.h,v 1.10 2014/03/07 10:43:29 nanard Exp $ */
|
/* $Id: upnppermissions.h,v 1.10 2014/03/07 10:43:29 nanard Exp $ */
|
||||||
/* MiniUPnP project
|
/* MiniUPnP project
|
||||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||||
* (c) 2006-2014 Thomas Bernard
|
* (c) 2006-2020 Thomas Bernard
|
||||||
* This software is subject to the conditions detailed
|
* This software is subject to the conditions detailed
|
||||||
* in the LICENCE file provided within the distribution */
|
* in the LICENCE file provided within the distribution */
|
||||||
|
|
||||||
|
@ -45,6 +45,14 @@ check_upnp_rule_against_permissions(const struct upnpperm * permary,
|
||||||
u_short eport, struct in_addr address,
|
u_short eport, struct in_addr address,
|
||||||
u_short iport);
|
u_short iport);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an array of all allowed external ports (for the address and internal port)
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
get_permitted_ext_ports(uint32_t * allowed,
|
||||||
|
const struct upnpperm * permary, int n_perms,
|
||||||
|
in_addr_t addr, u_short iport);
|
||||||
|
|
||||||
#ifdef USE_MINIUPNPDCTL
|
#ifdef USE_MINIUPNPDCTL
|
||||||
void
|
void
|
||||||
write_permlist(int fd, const struct upnpperm * permary,
|
write_permlist(int fd, const struct upnpperm * permary,
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "upnpsoap.h"
|
#include "upnpsoap.h"
|
||||||
#include "upnpreplyparse.h"
|
#include "upnpreplyparse.h"
|
||||||
#include "upnpredirect.h"
|
#include "upnpredirect.h"
|
||||||
|
#include "upnppermissions.h"
|
||||||
#include "upnppinhole.h"
|
#include "upnppinhole.h"
|
||||||
#include "getifaddr.h"
|
#include "getifaddr.h"
|
||||||
#include "getifstats.h"
|
#include "getifstats.h"
|
||||||
|
@ -586,7 +587,7 @@ AddAnyPortMapping(struct upnphttp * h, const char * action, const char * ns)
|
||||||
struct NameValueParserData data;
|
struct NameValueParserData data;
|
||||||
const char * int_ip, * int_port, * ext_port, * protocol, * desc;
|
const char * int_ip, * int_port, * ext_port, * protocol, * desc;
|
||||||
const char * r_host;
|
const char * r_host;
|
||||||
unsigned short iport, eport, eport_below, eport_above;
|
unsigned short iport, eport;
|
||||||
const char * leaseduration_str;
|
const char * leaseduration_str;
|
||||||
unsigned int leaseduration;
|
unsigned int leaseduration;
|
||||||
|
|
||||||
|
@ -674,26 +675,41 @@ AddAnyPortMapping(struct upnphttp * h, const char * action, const char * ns)
|
||||||
|
|
||||||
/* first try the port asked in request, then
|
/* first try the port asked in request, then
|
||||||
* try +1, -1, +2, -2, etc. */
|
* try +1, -1, +2, -2, etc. */
|
||||||
eport_above = eport_below = eport;
|
r = upnp_redirect(r_host, eport, int_ip, iport, protocol, desc, leaseduration);
|
||||||
for(;;) {
|
if (r != 0 && r != -1) {
|
||||||
r = upnp_redirect(r_host, eport, int_ip, iport, protocol, desc, leaseduration);
|
unsigned short eport_below, eport_above;
|
||||||
if (r == 0 || r == -1) {
|
struct in_addr address;
|
||||||
/* OK or failure : Stop */
|
uint32_t allowed_eports[65536 / 32];
|
||||||
break;
|
|
||||||
|
if(inet_aton(int_ip, &address) <= 0) {
|
||||||
|
syslog(LOG_ERR, "inet_aton(%s) FAILED", int_ip);
|
||||||
}
|
}
|
||||||
/* r : -2 / -4 already redirected or -3 permission check failed */
|
get_permitted_ext_ports(allowed_eports, upnppermlist, num_upnpperm,
|
||||||
if (eport_below <= 1 && eport_above == 65535) {
|
address.s_addr, iport);
|
||||||
/* all possible ports tried */
|
eport_above = eport_below = eport;
|
||||||
r = 1;
|
for(;;) {
|
||||||
break;
|
/* loop invariant
|
||||||
|
* eport is equal to either eport_below or eport_above (or both) */
|
||||||
|
if (eport_below <= 1 && eport_above == 65535) {
|
||||||
|
/* all possible ports tried */
|
||||||
|
r = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (eport_above == 65535 || (eport > eport_below && eport_below > 1)) {
|
||||||
|
eport = --eport_below;
|
||||||
|
} else {
|
||||||
|
eport = ++eport_above;
|
||||||
|
}
|
||||||
|
if (!(allowed_eports[eport / 32] & ((uint32_t)1U << (eport % 32))))
|
||||||
|
continue; /* not allowed */
|
||||||
|
r = upnp_redirect(r_host, eport, int_ip, iport, protocol, desc, leaseduration);
|
||||||
|
if (r == 0 || r == -1) {
|
||||||
|
/* OK or failure : Stop */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* r : -2 / -4 already redirected or -3 permission check failed :
|
||||||
|
* continue */
|
||||||
}
|
}
|
||||||
if (eport_above == 65535 || (eport > eport_below && eport_below > 1)) {
|
|
||||||
eport = --eport_below;
|
|
||||||
} else {
|
|
||||||
eport = ++eport_above;
|
|
||||||
}
|
|
||||||
/* loop invariant :
|
|
||||||
* eport is equal to either eport_below or eport_above (or both) */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearNameValueList(&data);
|
ClearNameValueList(&data);
|
||||||
|
|
Loading…
Reference in New Issue