Fix PinholeVerification()
see https://miniupnp.tuxfamily.org/forum/viewtopic.php?p=5847
This commit is contained in:
parent
f818ff39fe
commit
99fc9941aa
|
@ -1,4 +1,7 @@
|
||||||
$Id: Changelog.txt,v 1.495 2023/01/19 23:28:24 nanard Exp $
|
$Id: Changelog.txt,v 1.497 2023/02/04 10:36:33 nanard Exp $
|
||||||
|
|
||||||
|
2023/02/04:
|
||||||
|
Fix PinholeVerification()
|
||||||
|
|
||||||
2023/01/28
|
2023/01/28
|
||||||
Fix updating of existing pinhole leasetime by AddPinhole
|
Fix updating of existing pinhole leasetime by AddPinhole
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
/* $Id: upnpsoap.c,v 1.157 2020/05/30 08:28:22 nanard Exp $ */
|
/* $Id: upnpsoap.c,v 1.163 2023/02/04 10:36:34 nanard Exp $ */
|
||||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||||
* MiniUPnP project
|
* MiniUPnP project
|
||||||
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||||
* (c) 2006-2021 Thomas Bernard
|
* (c) 2006-2023 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 */
|
||||||
|
|
||||||
|
@ -1559,77 +1559,101 @@ static int connecthostport(const char * host, unsigned short port, char * result
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Check the security policy right */
|
/* Check the security policy rights
|
||||||
|
* Pinhole InternalClient address must correspond to the action sender
|
||||||
|
* returns 1 if it passes.
|
||||||
|
* call SoapError() and returns 0 if it fails
|
||||||
|
* Side effect : if int_ip is a hostname, convert it to litteral ipv6 */
|
||||||
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;
|
char clientaddr_str[INET6_ADDRSTRLEN];
|
||||||
char senderAddr[INET6_ADDRSTRLEN]="";
|
|
||||||
struct addrinfo hints, *ai, *p;
|
|
||||||
struct in6_addr result_ip;
|
struct in6_addr result_ip;
|
||||||
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
/* 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)
|
if (inet_pton(AF_INET6, int_ip, &result_ip) <= 0)
|
||||||
{
|
{
|
||||||
n = getaddrinfo(int_ip, NULL, &hints, &ai);
|
int r;
|
||||||
if (n == 0)
|
struct addrinfo hints, *ai, *p;
|
||||||
|
|
||||||
|
syslog(LOG_INFO, "%s: InternalClient %s is not an IPv6, assume hostname and convert",
|
||||||
|
"PinholeVerification", int_ip);
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_protocol = 0; /* we may indicate which protocol IPPROTO_UDP / IPPROTO_TCP / IPPROTO_SCTP / IPPROTO_UDPLITE */
|
||||||
|
|
||||||
|
r = getaddrinfo(int_ip, NULL, &hints, &ai);
|
||||||
|
if (r == 0)
|
||||||
{
|
{
|
||||||
int found = 0;
|
int found = 0;
|
||||||
for(p = ai; p; p = p->ai_next)
|
for(p = ai; p; p = p->ai_next)
|
||||||
{
|
{
|
||||||
if(p->ai_family == AF_INET6)
|
if(p->ai_family == AF_INET6)
|
||||||
{
|
{
|
||||||
inet_ntop(AF_INET6, (struct in6_addr *) p, int_ip, sizeof(struct in6_addr));
|
if (!found)
|
||||||
result_ip = *((struct in6_addr *) p);
|
{
|
||||||
|
result_ip = ((struct sockaddr_in6 *)p->ai_addr)->sin6_addr;
|
||||||
|
if (inet_ntop(AF_INET6, &result_ip, int_ip, sizeof(struct in6_addr)) == NULL)
|
||||||
|
syslog(LOG_WARNING, "%s: inet_ntop(): %m", "PinholeVerification");
|
||||||
|
syslog(LOG_INFO, "%s: InternalClient resolved as %s",
|
||||||
|
"PinholeVerification", int_ip);
|
||||||
found = 1;
|
found = 1;
|
||||||
/* TODO : deal with more than one ip per hostname */
|
}
|
||||||
break;
|
else
|
||||||
|
{
|
||||||
|
char tmp[48];
|
||||||
|
sockaddr_to_string(p->ai_addr, tmp, sizeof(tmp));
|
||||||
|
syslog(LOG_INFO, "%s: additionnal IPv6: %s",
|
||||||
|
"PinholeVerification", tmp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
freeaddrinfo(ai);
|
freeaddrinfo(ai);
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "No IPv6 address for hostname '%s'", int_ip);
|
syslog(LOG_NOTICE, "%s: No IPv6 address for hostname '%s'",
|
||||||
|
"PinholeVerification", int_ip);
|
||||||
SoapError(h, 402, "Invalid Args");
|
SoapError(h, 402, "Invalid Args");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
syslog(LOG_WARNING, "Failed to convert hostname '%s' to IP address : %s",
|
syslog(LOG_WARNING, "%s: Failed to convert hostname '%s' to IP address : %s",
|
||||||
int_ip, gai_strerror(n));
|
"PinholeVerification", int_ip, gai_strerror(r));
|
||||||
SoapError(h, 402, "Invalid Args");
|
SoapError(h, 402, "Invalid Args");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(inet_ntop(AF_INET6, &(h->clientaddr_v6), senderAddr, INET6_ADDRSTRLEN) == NULL)
|
if(inet_ntop(AF_INET6, &(h->clientaddr_v6), clientaddr_str, INET6_ADDRSTRLEN) == NULL)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "inet_ntop: %m");
|
syslog(LOG_ERR, "inet_ntop: %m");
|
||||||
|
strncpy(clientaddr_str, "*ERROR*", sizeof(clientaddr_str));
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
|
||||||
printf("\tPinholeVerification:\n\t\tCompare sender @: %s\n\t\t to intClient @: %s\n", senderAddr, int_ip);
|
|
||||||
#endif
|
|
||||||
if(strcmp(senderAddr, int_ip) != 0)
|
|
||||||
if(h->clientaddr_v6.s6_addr != result_ip.s6_addr)
|
if(h->clientaddr_v6.s6_addr != result_ip.s6_addr)
|
||||||
{
|
{
|
||||||
syslog(LOG_INFO, "Client %s tried to access pinhole for internal %s and is not authorized to do it",
|
syslog(LOG_INFO, "%s: Client %s tried to access pinhole for internal %s and is not authorized",
|
||||||
senderAddr, int_ip);
|
"PinholeVerification", clientaddr_str, int_ip);
|
||||||
SoapError(h, 606, "Action not authorized");
|
SoapError(h, 606, "Action not authorized");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
else
|
||||||
|
{
|
||||||
|
syslog(LOG_DEBUG, "%s: sender %s == InternalClient %s",
|
||||||
|
"PinholeVerification", clientaddr_str, int_ip);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* 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);
|
clientaddr_str);
|
||||||
SoapError(h, 606, "Action not authorized");
|
SoapError(h, 606, "Action not authorized");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue