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
|
||||
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
|
||||
* MiniUPnP project
|
||||
* 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
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
|
@ -1559,77 +1559,101 @@ static int connecthostport(const char * host, unsigned short port, char * result
|
|||
}
|
||||
#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
|
||||
PinholeVerification(struct upnphttp * h, char * int_ip, unsigned short int_port)
|
||||
{
|
||||
int n;
|
||||
char senderAddr[INET6_ADDRSTRLEN]="";
|
||||
struct addrinfo hints, *ai, *p;
|
||||
char clientaddr_str[INET6_ADDRSTRLEN];
|
||||
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 (inet_pton(AF_INET6, int_ip, &result_ip) <= 0)
|
||||
{
|
||||
n = getaddrinfo(int_ip, NULL, &hints, &ai);
|
||||
if (n == 0)
|
||||
int r;
|
||||
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;
|
||||
for(p = ai; p; p = p->ai_next)
|
||||
{
|
||||
if(p->ai_family == AF_INET6)
|
||||
{
|
||||
inet_ntop(AF_INET6, (struct in6_addr *) p, int_ip, sizeof(struct in6_addr));
|
||||
result_ip = *((struct in6_addr *) p);
|
||||
if (!found)
|
||||
{
|
||||
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;
|
||||
/* 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);
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
syslog(LOG_WARNING, "Failed to convert hostname '%s' to IP address : %s",
|
||||
int_ip, gai_strerror(n));
|
||||
syslog(LOG_WARNING, "%s: Failed to convert hostname '%s' to IP address : %s",
|
||||
"PinholeVerification", int_ip, gai_strerror(r));
|
||||
SoapError(h, 402, "Invalid Args");
|
||||
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");
|
||||
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)
|
||||
{
|
||||
syslog(LOG_INFO, "Client %s tried to access pinhole for internal %s and is not authorized to do it",
|
||||
senderAddr, int_ip);
|
||||
syslog(LOG_INFO, "%s: Client %s tried to access pinhole for internal %s and is not authorized",
|
||||
"PinholeVerification", clientaddr_str, int_ip);
|
||||
SoapError(h, 606, "Action not authorized");
|
||||
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 */
|
||||
if (int_port < 1024)
|
||||
{
|
||||
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");
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue