AddPinhole() and DeletePinhole() works ! (only with pf)

This commit is contained in:
Thomas Bernard 2012-04-20 16:53:34 +02:00
parent 82369d94e4
commit e0efe74a7c
3 changed files with 80 additions and 69 deletions

View File

@ -1,4 +1,8 @@
$Id: Changelog.txt,v 1.271 2012/04/18 23:44:35 nanard Exp $
$Id: Changelog.txt,v 1.272 2012/04/20 14:38:38 nanard Exp $
2012/04/20:
Enough WANIPv6FirewallControl is implemented on pf so that AddPinhole() and
DeletePinhole() works !
2012/04/19:
First working experiment of IPv6 "pinhole" with pf

View File

@ -1,4 +1,4 @@
/* $Id: upnpredirect.c,v 1.64 2012/04/14 22:12:09 nanard Exp $ */
/* $Id: upnpredirect.c,v 1.66 2012/04/20 14:38:38 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
@ -27,6 +27,7 @@
#endif
#if defined(USE_PF)
#include "pf/obsdrdr.h"
#include "pf/pfpinhole.h"
#endif
#if defined(USE_IPF)
#include "ipf/ipfrdr.h"
@ -626,6 +627,7 @@ upnp_check_outbound_pinhole(int proto, int * timeout)
* -1 failed to add pinhole
* -2 already created
* -3 inbound pinhole disabled
* TODO : return uid on success (positive) or error value (negative)
*/
int
upnp_add_inboundpinhole(const char * raddr,
@ -633,33 +635,34 @@ upnp_add_inboundpinhole(const char * raddr,
const char * iaddr,
unsigned short iport,
const char * protocol,
const char * leaseTime,
unsigned int leasetime,
int * uid)
{
int r, s, t, lt=0;
char iaddr_old[40]="", proto[6]="", idfound[5]="", leaseTmp[12]; /* IPv6 Modification*/
snprintf(proto, sizeof(proto), "%.5d", atoi(protocol));
unsigned short iport_old = 0;
time_t current = time(NULL);
int r;
#if 0
char iaddr_old[40]="", idfound[5]=""; /* IPv6 Modification*/
unsigned short iport_old = 0;
#endif
time_t current;
unsigned int timestamp;
struct in6_addr address; /* IPv6 Modification*/
int proto;
if(inet_pton(AF_INET6, iaddr, &address) < 0) /* IPv6 Modification */
{
syslog(LOG_ERR, "inet_pton(%s) : %m", iaddr);
return 0;
}
#endif
proto = atoi(protocol); /* for WANIPv6FirewallControl AddPinhole, the protocol argument
* is passed as an integer, not a string */
current = time(NULL);
timestamp = current + leasetime;
#if 0
r = get_rule_from_file(raddr, rport, iaddr_old, &iport_old, proto, 0, 0, idfound);
#endif
r = 0;
lt = (int) current + atoi(leaseTime);
snprintf(leaseTmp, sizeof(leaseTmp), "%d", lt);
printf("LeaseTime: %d / %d -> %s\n", atoi(leaseTime), (int)current, leaseTmp);
printf("\tCompare addr: %s // port: %d\n\t to addr: %s // port: %d\n", iaddr, iport, iaddr_old, iport_old);
#if 0
if(r == 1 && strcmp(iaddr, iaddr_old)==0 && iport==iport_old)
{
syslog(LOG_INFO, "Pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with protocol %s already done. Updating it.", raddr, rport, iaddr_old, iport_old, protocol);
@ -668,10 +671,17 @@ upnp_add_inboundpinhole(const char * raddr,
return t;
}
else
#endif
{
syslog(LOG_INFO, "Adding pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with protocol %s and %s lease time.", raddr, rport, iaddr, iport, protocol, leaseTime);
s = upnp_add_inboundpinhole_internal(raddr, rport, iaddr, iport, protocol, uid);
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);
#ifdef USE_PF
*uid = add_pinhole (0/*ext_if_name*/, raddr, rport, iaddr, iport, proto, timestamp);
return 1;
#else
return -42; /* not implemented */
#endif
#if 0
s = upnp_add_inboundpinhole_internal(raddr, rport, iaddr, iport, protocol, uid);
if(rule_file_add(raddr, rport, iaddr, iport, protocol, leaseTmp, uid)<0)
return -8;
else
@ -794,39 +804,15 @@ upnp_update_inboundpinhole(const char * uid, const char * leasetime)
int
upnp_delete_inboundpinhole(const char * uid)
{
/* TODO : to be implemented */
#if 0
/* this is a alpha implementation calling ip6tables via system(),
* it can be usefull as an example to code the netfilter version */
int r, s, linenum=0;
char cmd[256], cmd_raw[256];
syslog(LOG_INFO, "Removing pinhole for inbound traffic with ID: %s", uid);
r = check_rule_from_file(uid, &linenum);
if(r > 0)
{
s = rule_file_remove(uid, linenum);
if(s < 0)
return s;
else
{
snprintf(cmd, sizeof(cmd), "ip6tables -t filter -D %s %d", miniupnpd_forward_chain, linenum);
snprintf(cmd_raw, sizeof(cmd_raw), "ip6tables -t raw -D PREROUTING %d", linenum -1);
#ifdef DEBUG
syslog(LOG_INFO, "Deleting ip6tables rule:");
syslog(LOG_INFO, " -> %s", cmd);
syslog(LOG_INFO, " -> %s", cmd_raw);
#endif
// TODO Add a better checking error.
if(system(cmd) < 0 || system(cmd_raw) < 0)
{
return 0;
}
}
}
upnp_update_expiredpinhole();
return r;
unsigned short uid_s;
if(!uid)
return -1;
uid_s = (unsigned short)atoi(uid);
#ifdef USE_PF
return delete_pinhole(uid_s);
#else
return -1;
return -1;
#endif
}

View File

@ -1,4 +1,4 @@
/* $Id: upnpsoap.c,v 1.93 2012/04/19 22:04:48 nanard Exp $ */
/* $Id: upnpsoap.c,v 1.96 2012/04/20 14:38:39 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
@ -1259,8 +1259,6 @@ static int
PinholeVerification(struct upnphttp * h, char * int_ip, unsigned short * int_port)
{
int n;
/* Pinhole InternalClient address must correspond to the action sender */
syslog(LOG_INFO, "Checking internal IP@ and port (Security policy purpose)");
char senderAddr[INET6_ADDRSTRLEN]="";
#if 0
//char str[INET6_ADDRSTRLEN]="";
@ -1271,6 +1269,9 @@ PinholeVerification(struct upnphttp * h, char * int_ip, unsigned short * int_por
struct addrinfo hints, *ai, *p;
struct in6_addr result_ip;/*unsigned char result_ip[16];*/ /* inet_pton() */
/* Pinhole InternalClient address must correspond to the action sender */
syslog(LOG_INFO, "Checking internal IP@ and port (Security policy purpose)");
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_UNSPEC;
@ -1341,6 +1342,7 @@ AddPinhole(struct upnphttp * h, const char * action)
char * rem_host, * rem_port, * int_ip, * int_port, * protocol, * leaseTime;
int uid = 0;
unsigned short iport, rport;
int ltime;
if(CheckStatus(h)==0)
return;
@ -1353,9 +1355,17 @@ AddPinhole(struct upnphttp * h, const char * action)
protocol = GetValueFromNameValueList(&data, "Protocol");
leaseTime = GetValueFromNameValueList(&data, "LeaseTime");
rport = (unsigned short)atoi(rem_port);
iport = (unsigned short)atoi(int_port);
rport = (unsigned short)(rem_port ? atoi(rem_port) : 0);
iport = (unsigned short)(int_port ? atoi(int_port) : 0);
ltime = atoi(leaseTime);
/* In particular, [IGD2] RECOMMENDS that unauthenticated and
* unauthorized control points are only allowed to invoke
* this action with:
* - InternalPort value greater than or equal to 1024,
* - InternalClient value equals to the control point's IP address.
* It is REQUIRED that InternalClient cannot be one of IPv6
* addresses used by the gateway. */
/* ** As there is no security policy, InternalClient must be equal
* to the CP's IP address. */
if(DataVerification(h, int_ip, &iport, protocol, leaseTime) == 0
@ -1377,7 +1387,11 @@ AddPinhole(struct upnphttp * h, const char * action)
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);
r = upnp_add_inboundpinhole(rem_host, rport, int_ip, iport, protocol, leaseTime, &uid);
/* In cases where the RemoteHost, RemotePort, InternalPort,
* InternalClient and Protocol are the same than an existing pinhole,
* but LeaseTime is different, the device MUST extend the existing
* 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);
switch(r)
{
@ -1407,6 +1421,7 @@ UpdatePinhole(struct upnphttp * h, const char * action)
const char * uid, * leaseTime;
char iaddr[40], proto[6], lt[12];
unsigned short iport;
int ltime = -1;
if(CheckStatus(h)==0)
return;
@ -1414,8 +1429,10 @@ UpdatePinhole(struct upnphttp * h, const char * action)
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
uid = GetValueFromNameValueList(&data, "UniqueID");
leaseTime = GetValueFromNameValueList(&data, "NewLeaseTime");
if(leaseTime)
ltime = atoi(leaseTime);
if(!uid || !leaseTime || !atoi(leaseTime) || atoi(leaseTime) > 86400)
if(!uid || ltime <= 0 || ltime > 86400)
{
ClearNameValueList(&data);
SoapError(h, 402, "Invalid Args");
@ -1455,11 +1472,6 @@ UpdatePinhole(struct upnphttp * h, const char * action)
static void
GetOutboundPinholeTimeout(struct upnphttp * h, const char * action)
{
if (!ipv6fc_firewall_enabled)
{
SoapError(h, 702, "FirewallDisabed");
return;
}
int r;
static const char resp[] =
@ -1475,6 +1487,12 @@ GetOutboundPinholeTimeout(struct upnphttp * h, const char * action)
int opt=0, proto=0;
unsigned short iport, rport;
if (!ipv6fc_firewall_enabled)
{
SoapError(h, 702, "FirewallDisabed");
return;
}
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
int_ip = GetValueFromNameValueList(&data, "InternalClient");
int_port = GetValueFromNameValueList(&data, "InternalPort");
@ -1508,8 +1526,6 @@ GetOutboundPinholeTimeout(struct upnphttp * h, const char * action)
static void
DeletePinhole(struct upnphttp * h, const char * action)
{
if(CheckStatus(h)==0)
return;
int r, n;
static const char resp[] =
@ -1522,10 +1538,13 @@ DeletePinhole(struct upnphttp * h, const char * action)
char iaddr[40], proto[6], lt[12];
unsigned short iport;
if(CheckStatus(h)==0)
return;
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
uid = GetValueFromNameValueList(&data, "UniqueID");
if(!uid)
if(!uid || atoi(uid) < 0 || atoi(uid) > 65535)
{
ClearNameValueList(&data);
SoapError(h, 402, "Invalid Args");
@ -1548,7 +1567,7 @@ DeletePinhole(struct upnphttp * h, const char * action)
r = upnp_delete_inboundpinhole(uid);
if(r <= 0)
if(r < 0)
{
syslog(LOG_INFO, "%s: (inbound) failed to remove pinhole with ID: %s", action, uid);
if(r==-4)
@ -1567,8 +1586,6 @@ DeletePinhole(struct upnphttp * h, const char * action)
static void
CheckPinholeWorking(struct upnphttp * h, const char * action)
{
if(CheckStatus(h)==0)
return;
int r, d;
static const char resp[] =
@ -1585,6 +1602,9 @@ CheckPinholeWorking(struct upnphttp * h, const char * action)
unsigned short eport, iport;
int isWorking = 0;
if(CheckStatus(h)==0)
return;
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
uid = GetValueFromNameValueList(&data, "UniqueID");
@ -1665,8 +1685,6 @@ CheckPinholeWorking(struct upnphttp * h, const char * action)
static void
GetPinholePackets(struct upnphttp * h, const char * action)
{
if(CheckStatus(h)==0)
return;
int r, n;
static const char resp[] =
@ -1683,6 +1701,9 @@ GetPinholePackets(struct upnphttp * h, const char * action)
unsigned short iport;
int pinholePackets = 0;
if(CheckStatus(h)==0)
return;
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
uid = GetValueFromNameValueList(&data, "UniqueID");