Improve code for WANIPv6FirewallControl
This commit is contained in:
parent
8148acc55c
commit
c9cf40633d
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: upnpredirect.c,v 1.66 2012/04/20 14:38:38 nanard Exp $ */
|
/* $Id: upnpredirect.c,v 1.67 2012/04/20 21:52:57 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-2012 Thomas Bernard
|
* (c) 2006-2012 Thomas Bernard
|
||||||
|
@ -634,7 +634,7 @@ upnp_add_inboundpinhole(const char * raddr,
|
||||||
unsigned short rport,
|
unsigned short rport,
|
||||||
const char * iaddr,
|
const char * iaddr,
|
||||||
unsigned short iport,
|
unsigned short iport,
|
||||||
const char * protocol,
|
int proto,
|
||||||
unsigned int leasetime,
|
unsigned int leasetime,
|
||||||
int * uid)
|
int * uid)
|
||||||
{
|
{
|
||||||
|
@ -646,15 +646,12 @@ upnp_add_inboundpinhole(const char * raddr,
|
||||||
time_t current;
|
time_t current;
|
||||||
unsigned int timestamp;
|
unsigned int timestamp;
|
||||||
struct in6_addr address; /* IPv6 Modification*/
|
struct in6_addr address; /* IPv6 Modification*/
|
||||||
int proto;
|
|
||||||
|
|
||||||
if(inet_pton(AF_INET6, iaddr, &address) < 0) /* IPv6 Modification */
|
if(inet_pton(AF_INET6, iaddr, &address) < 0) /* IPv6 Modification */
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "inet_pton(%s) : %m", iaddr);
|
syslog(LOG_ERR, "inet_pton(%s) : %m", iaddr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
proto = atoi(protocol); /* for WANIPv6FirewallControl AddPinhole, the protocol argument
|
|
||||||
* is passed as an integer, not a string */
|
|
||||||
current = time(NULL);
|
current = time(NULL);
|
||||||
timestamp = current + leasetime;
|
timestamp = current + leasetime;
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -673,7 +670,7 @@ upnp_add_inboundpinhole(const char * raddr,
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
syslog(LOG_INFO, "Adding pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with protocol %s and %u lease time.", raddr, rport, iaddr, iport, protocol, leasetime);
|
syslog(LOG_INFO, "Adding pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with proto %d and %u lease time.", raddr, rport, iaddr, iport, proto, leasetime);
|
||||||
#ifdef USE_PF
|
#ifdef USE_PF
|
||||||
*uid = add_pinhole (0/*ext_if_name*/, raddr, rport, iaddr, iport, proto, timestamp);
|
*uid = add_pinhole (0/*ext_if_name*/, raddr, rport, iaddr, iport, proto, timestamp);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* $Id: upnpredirect.h,v 1.24 2011/06/22 20:34:39 nanard Exp $ */
|
/* $Id: upnpredirect.h,v 1.27 2012/04/20 21:52:58 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-2011 Thomas Bernard
|
* (c) 2006-2012 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 */
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ upnp_check_outbound_pinhole(int proto, int * timeout);
|
||||||
int
|
int
|
||||||
upnp_add_inboundpinhole(const char * raddr, unsigned short rport,
|
upnp_add_inboundpinhole(const char * raddr, unsigned short rport,
|
||||||
const char * iaddr, unsigned short iport,
|
const char * iaddr, unsigned short iport,
|
||||||
const char * protocol, const char * leaseTime, int * uid);
|
int proto, unsigned int leasetime, int * uid);
|
||||||
|
|
||||||
int
|
int
|
||||||
upnp_add_inboundpinhole_internal(const char * raddr, unsigned short rport,
|
upnp_add_inboundpinhole_internal(const char * raddr, unsigned short rport,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: upnpsoap.c,v 1.96 2012/04/20 14:38:39 nanard Exp $ */
|
/* $Id: upnpsoap.c,v 1.97 2012/04/20 21:52:58 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-2012 Thomas Bernard
|
* (c) 2006-2012 Thomas Bernard
|
||||||
|
@ -8,6 +8,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
@ -1144,62 +1145,6 @@ CheckStatus(struct upnphttp * h)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
DataVerification(struct upnphttp * h, char * int_ip, unsigned short * int_port, const char * protocol, char * leaseTime)
|
|
||||||
{
|
|
||||||
/* ** Internal IP can't be wildcarded */
|
|
||||||
if (!int_ip)
|
|
||||||
{
|
|
||||||
SoapError(h, 708, "WildCardNotPermittedInSrcIP");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strchr(int_ip, ':'))
|
|
||||||
{
|
|
||||||
SoapError(h, 402, "Invalid Args");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ** Internal port can't be wilcarded. */
|
|
||||||
/* printf("\tint_port: *%d*\n", *int_port); */
|
|
||||||
if (*int_port == 0)
|
|
||||||
{
|
|
||||||
SoapError(h, 706, "InternalPortWilcardingNotAllowed");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ** Protocol can't be wilcarded and can't be an unknown port
|
|
||||||
* (here deal with only UDP, TCP, UDPLITE) */
|
|
||||||
/* printf("\tprotocol: *%s*\n", protocol); */
|
|
||||||
if (atoi(protocol) == 65535)
|
|
||||||
{
|
|
||||||
SoapError(h, 707, "ProtocolWilcardingNotAllowed");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (atoi(protocol) != IPPROTO_UDP
|
|
||||||
&& atoi(protocol) != IPPROTO_TCP
|
|
||||||
#ifdef IPPROTO_UDPITE
|
|
||||||
&& atoi(protocol) != IPPROTO_UDPLITE
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
SoapError(h, 705, "ProtocolNotSupported");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ** Lease Time can't be wilcarded nor >86400. */
|
|
||||||
/* printf("\tlease time: %s\n", leaseTime); */
|
|
||||||
if(!leaseTime || !atoi(leaseTime) || atoi(leaseTime)>86400)
|
|
||||||
{
|
|
||||||
/* lease duration is never infinite, nor wilcarded. In this case, use default value */
|
|
||||||
syslog(LOG_WARNING, "LeaseTime=%s not supported, (ip=%s)", leaseTime, int_ip);
|
|
||||||
SoapError(h, 402, "Invalid Args");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static int connecthostport(const char * host, unsigned short port, char * result)
|
static int connecthostport(const char * host, unsigned short port, char * result)
|
||||||
{
|
{
|
||||||
|
@ -1256,18 +1201,12 @@ static int connecthostport(const char * host, unsigned short port, char * result
|
||||||
|
|
||||||
/* Check the security policy right */
|
/* Check the security policy right */
|
||||||
static int
|
static int
|
||||||
PinholeVerification(struct upnphttp * h, char * int_ip, unsigned short * int_port)
|
PinholeVerification(struct upnphttp * h, char * int_ip, unsigned short int_port)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
char senderAddr[INET6_ADDRSTRLEN]="";
|
char senderAddr[INET6_ADDRSTRLEN]="";
|
||||||
#if 0
|
|
||||||
//char str[INET6_ADDRSTRLEN]="";
|
|
||||||
//connecthostport(int_ip, *int_port, str);
|
|
||||||
//printf("int_ip: %s / str: %s\n", int_ip, str);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct addrinfo hints, *ai, *p;
|
struct addrinfo hints, *ai, *p;
|
||||||
struct in6_addr result_ip;/*unsigned char result_ip[16];*/ /* inet_pton() */
|
struct in6_addr result_ip;
|
||||||
|
|
||||||
/* Pinhole InternalClient address must correspond to the action sender */
|
/* Pinhole InternalClient address must correspond to the action sender */
|
||||||
syslog(LOG_INFO, "Checking internal IP@ and port (Security policy purpose)");
|
syslog(LOG_INFO, "Checking internal IP@ and port (Security policy purpose)");
|
||||||
|
@ -1276,17 +1215,16 @@ PinholeVerification(struct upnphttp * h, char * int_ip, unsigned short * int_por
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
|
||||||
/* if ip not valid assume hostname and convert */
|
/* if ip not valid assume hostname and convert */
|
||||||
if (inet_pton(AF_INET6, int_ip, &result_ip) <= 0) /*IPv6 Modification*/
|
if (inet_pton(AF_INET6, int_ip, &result_ip) <= 0)
|
||||||
{
|
{
|
||||||
|
n = getaddrinfo(int_ip, NULL, &hints, &ai);
|
||||||
n = getaddrinfo(int_ip, NULL, &hints, &ai);/*hp = gethostbyname(int_ip);*/
|
if(!n && ai->ai_family == AF_INET6)
|
||||||
if(!n && ai->ai_family == AF_INET6) /*IPv6 Modification*/
|
|
||||||
{
|
{
|
||||||
for(p = ai; p; p = p->ai_next)/*ptr = hp->h_addr_list; ptr && *ptr; ptr++)*/
|
for(p = ai; p; p = p->ai_next)
|
||||||
{
|
{
|
||||||
inet_ntop(AF_INET6, (struct in6_addr *) p, int_ip, sizeof(struct in6_addr)); /*IPv6 Modification*/
|
inet_ntop(AF_INET6, (struct in6_addr *) p, int_ip, sizeof(struct in6_addr));
|
||||||
result_ip = *((struct in6_addr *) p);
|
result_ip = *((struct in6_addr *) p);
|
||||||
fprintf(stderr, "upnpsoap / AddPinhole: assuming int addr = %s", int_ip);
|
/* fprintf(stderr, "upnpsoap / AddPinhole: assuming int addr = %s", int_ip); */
|
||||||
/* TODO : deal with more than one ip per hostname */
|
/* TODO : deal with more than one ip per hostname */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1317,7 +1255,7 @@ PinholeVerification(struct upnphttp * h, char * int_ip, unsigned short * int_por
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pinhole InternalPort must be greater than or equal to 1024 */
|
/* Pinhole InternalPort must be greater than or equal to 1024 */
|
||||||
if (*int_port < 1024)
|
if (int_port < 1024)
|
||||||
{
|
{
|
||||||
syslog(LOG_INFO, "Client %s tried to access pinhole with port < 1024 and is not authorized to do it",
|
syslog(LOG_INFO, "Client %s tried to access pinhole with port < 1024 and is not authorized to do it",
|
||||||
senderAddr);
|
senderAddr);
|
||||||
|
@ -1343,6 +1281,7 @@ AddPinhole(struct upnphttp * h, const char * action)
|
||||||
int uid = 0;
|
int uid = 0;
|
||||||
unsigned short iport, rport;
|
unsigned short iport, rport;
|
||||||
int ltime;
|
int ltime;
|
||||||
|
long proto;
|
||||||
|
|
||||||
if(CheckStatus(h)==0)
|
if(CheckStatus(h)==0)
|
||||||
return;
|
return;
|
||||||
|
@ -1357,7 +1296,19 @@ AddPinhole(struct upnphttp * h, const char * action)
|
||||||
|
|
||||||
rport = (unsigned short)(rem_port ? atoi(rem_port) : 0);
|
rport = (unsigned short)(rem_port ? atoi(rem_port) : 0);
|
||||||
iport = (unsigned short)(int_port ? atoi(int_port) : 0);
|
iport = (unsigned short)(int_port ? atoi(int_port) : 0);
|
||||||
ltime = atoi(leaseTime);
|
ltime = leaseTime ? atoi(leaseTime) : -1;
|
||||||
|
errno = 0;
|
||||||
|
proto = protocol ? strtol(protocol, NULL, 0) : -1;
|
||||||
|
if(errno != 0 || proto > 65535 || proto < 0)
|
||||||
|
{
|
||||||
|
SoapError(h, 402, "Invalid Args");
|
||||||
|
goto clear_and_exit;
|
||||||
|
}
|
||||||
|
if(iport == 0)
|
||||||
|
{
|
||||||
|
SoapError(h, 706, "InternalPortWilcardingNotAllowed");
|
||||||
|
goto clear_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
/* In particular, [IGD2] RECOMMENDS that unauthenticated and
|
/* In particular, [IGD2] RECOMMENDS that unauthenticated and
|
||||||
* unauthorized control points are only allowed to invoke
|
* unauthorized control points are only allowed to invoke
|
||||||
|
@ -1366,37 +1317,59 @@ AddPinhole(struct upnphttp * h, const char * action)
|
||||||
* - InternalClient value equals to the control point's IP address.
|
* - InternalClient value equals to the control point's IP address.
|
||||||
* It is REQUIRED that InternalClient cannot be one of IPv6
|
* It is REQUIRED that InternalClient cannot be one of IPv6
|
||||||
* addresses used by the gateway. */
|
* addresses used by the gateway. */
|
||||||
/* ** As there is no security policy, InternalClient must be equal
|
if(!int_ip || 0 == strlen(int_ip) || 0 == strcmp(int_ip, "*"))
|
||||||
* to the CP's IP address. */
|
|
||||||
if(DataVerification(h, int_ip, &iport, protocol, leaseTime) == 0
|
|
||||||
|| PinholeVerification(h, int_ip, &iport) <= 0)
|
|
||||||
{
|
{
|
||||||
ClearNameValueList(&data);
|
SoapError(h, 708, "WildCardNotPermittedInSrcIP");
|
||||||
return ;
|
goto clear_and_exit;
|
||||||
}
|
}
|
||||||
|
/* TODO : convert int_ip to literal ipv6 address ? */
|
||||||
|
/* TODO : rem_host should be converted to literal ipv6 ? */
|
||||||
|
|
||||||
/* ** RemoteHost can be wilcarded or an IDN. */
|
if(proto == 65535)
|
||||||
/*printf("\trem_host: %s\n", rem_host);*/
|
|
||||||
if (rem_host!=NULL && !strchr(rem_host, ':'))
|
|
||||||
{
|
{
|
||||||
ClearNameValueList(&data);
|
SoapError(h, 707, "ProtocolWilcardingNotAllowed");
|
||||||
|
goto clear_and_exit;
|
||||||
|
}
|
||||||
|
if(proto != IPPROTO_UDP && proto != IPPROTO_TCP
|
||||||
|
#ifdef IPPROTO_UDPITE
|
||||||
|
&& atoi(protocol) != IPPROTO_UDPLITE
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SoapError(h, 705, "ProtocolNotSupported");
|
||||||
|
goto clear_and_exit;
|
||||||
|
}
|
||||||
|
if(ltime < 1 || ltime > 86400)
|
||||||
|
{
|
||||||
|
syslog(LOG_WARNING, "%s: LeaseTime=%d not supported, (ip=%s)",
|
||||||
|
action, ltime, int_ip);
|
||||||
SoapError(h, 402, "Invalid Args");
|
SoapError(h, 402, "Invalid Args");
|
||||||
return;
|
goto clear_and_exit;
|
||||||
}
|
}
|
||||||
/*printf("\tAddr check passed.\n");*/
|
|
||||||
|
|
||||||
syslog(LOG_INFO, "%s: (inbound) from [%s]:%hu to [%s]:%hu with protocol %s during %ssec", action, rem_host?rem_host:"anywhere", rport, int_ip, iport, protocol, leaseTime);
|
if(PinholeVerification(h, int_ip, iport) <= 0)
|
||||||
|
{
|
||||||
|
goto clear_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
syslog(LOG_INFO, "%s: (inbound) from [%s]:%hu to [%s]:%hu with proto %ld during %d sec",
|
||||||
|
action, rem_host?rem_host:"any",
|
||||||
|
rport, int_ip, iport,
|
||||||
|
proto, ltime);
|
||||||
|
|
||||||
/* In cases where the RemoteHost, RemotePort, InternalPort,
|
/* In cases where the RemoteHost, RemotePort, InternalPort,
|
||||||
* InternalClient and Protocol are the same than an existing pinhole,
|
* InternalClient and Protocol are the same than an existing pinhole,
|
||||||
* but LeaseTime is different, the device MUST extend the existing
|
* but LeaseTime is different, the device MUST extend the existing
|
||||||
* pinhole's lease time and return the UniqueID of the existing pinhole. */
|
* pinhole's lease time and return the UniqueID of the existing pinhole. */
|
||||||
r = upnp_add_inboundpinhole(rem_host, rport, int_ip, iport, protocol, ltime, &uid);
|
r = upnp_add_inboundpinhole(rem_host, rport, int_ip, iport, proto, ltime, &uid);
|
||||||
|
|
||||||
switch(r)
|
switch(r)
|
||||||
{
|
{
|
||||||
case 1: /* success */
|
case 1: /* success */
|
||||||
bodylen = snprintf(body, sizeof(body), resp, action, "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1", uid, action);
|
bodylen = snprintf(body, sizeof(body),
|
||||||
|
resp, action,
|
||||||
|
"urn:schemas-upnp-org:service:WANIPv6FirewallControl:1",
|
||||||
|
uid, action);
|
||||||
BuildSendAndCloseSoapResp(h, body, bodylen);
|
BuildSendAndCloseSoapResp(h, body, bodylen);
|
||||||
break;
|
break;
|
||||||
case -1: /* not permitted */
|
case -1: /* not permitted */
|
||||||
|
@ -1406,6 +1379,15 @@ AddPinhole(struct upnphttp * h, const char * action)
|
||||||
SoapError(h, 501, "ActionFailed");
|
SoapError(h, 501, "ActionFailed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* 606 Action not authorized
|
||||||
|
* 701 PinholeSpaceExhausted
|
||||||
|
* 702 FirewallDisabled
|
||||||
|
* 703 InboundPinholeNotAllowed
|
||||||
|
* 705 ProtocolNotSupported
|
||||||
|
* 706 InternalPortWildcardingNotAllowed
|
||||||
|
* 707 ProtocolWildcardingNotAllowed
|
||||||
|
* 708 WildCardNotPermittedInSrcIP */
|
||||||
|
clear_and_exit:
|
||||||
ClearNameValueList(&data);
|
ClearNameValueList(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1444,7 +1426,7 @@ UpdatePinhole(struct upnphttp * h, const char * action)
|
||||||
n = upnp_get_pinhole_info(0, 0, iaddr, &iport, proto, uid, lt);
|
n = upnp_get_pinhole_info(0, 0, iaddr, &iport, proto, uid, lt);
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
{
|
{
|
||||||
if(PinholeVerification(h, iaddr, &iport)==0)
|
if(PinholeVerification(h, iaddr, iport)==0)
|
||||||
{
|
{
|
||||||
ClearNameValueList(&data);
|
ClearNameValueList(&data);
|
||||||
return ;
|
return ;
|
||||||
|
@ -1556,7 +1538,7 @@ DeletePinhole(struct upnphttp * h, const char * action)
|
||||||
n = upnp_get_pinhole_info(0, 0, iaddr, &iport, proto, uid, lt);
|
n = upnp_get_pinhole_info(0, 0, iaddr, &iport, proto, uid, lt);
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
{
|
{
|
||||||
if(PinholeVerification(h, iaddr, &iport)==0)
|
if(PinholeVerification(h, iaddr, iport)==0)
|
||||||
{
|
{
|
||||||
ClearNameValueList(&data);
|
ClearNameValueList(&data);
|
||||||
return ;
|
return ;
|
||||||
|
@ -1620,7 +1602,7 @@ CheckPinholeWorking(struct upnphttp * h, const char * action)
|
||||||
r = upnp_get_pinhole_info(eaddr, eport, iaddr, &iport, proto, uid, lt);
|
r = upnp_get_pinhole_info(eaddr, eport, iaddr, &iport, proto, uid, lt);
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
{
|
{
|
||||||
if(PinholeVerification(h, iaddr, &iport)==0)
|
if(PinholeVerification(h, iaddr, iport)==0)
|
||||||
{
|
{
|
||||||
ClearNameValueList(&data);
|
ClearNameValueList(&data);
|
||||||
return ;
|
return ;
|
||||||
|
@ -1719,7 +1701,7 @@ GetPinholePackets(struct upnphttp * h, const char * action)
|
||||||
r = upnp_get_pinhole_info(0, 0, iaddr, &iport, proto, uid, lt);
|
r = upnp_get_pinhole_info(0, 0, iaddr, &iport, proto, uid, lt);
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
{
|
{
|
||||||
if(PinholeVerification(h, iaddr, &iport)==0)
|
if(PinholeVerification(h, iaddr, iport)==0)
|
||||||
{
|
{
|
||||||
ClearNameValueList(&data);
|
ClearNameValueList(&data);
|
||||||
return ;
|
return ;
|
||||||
|
|
Loading…
Reference in New Issue