Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8c0a4e9
Allow connecting to remote IPv6 hosts for TCP or UDP
khorben Jun 14, 2018
f23d9d4
Rework the network listening routine
khorben Jun 15, 2018
fe1704c
Rework the network listening routine some more
khorben Jun 15, 2018
01fd694
Also check for <netinet/ip6.h> and <netinet/icmp6.h>
khorben Jun 14, 2018
4c92ab1
Let IPs resolve to IPv6 addresses
khorben Jun 12, 2018
c49c96b
Add support for receiving SPA messages over IPv6
khorben Jun 15, 2018
d115b43
Interpret incoming addresses according to their family
khorben Jun 26, 2018
f95fcc7
Let access list stanzas be defined in IPv6
khorben Jun 26, 2018
083f812
Allow access control "ANY" with any protocol family
khorben Jul 9, 2018
c3acef5
Rework IPv6 support when comparing addresses
khorben Jul 10, 2018
a9c834b
Use AF_INET instead of PF_INET
khorben Jul 9, 2018
a7ecf43
Use sizeof() instead of re-using hard-coded values
khorben Jul 9, 2018
d1625c7
Use sizeof() instead of re-using hard-coded values
khorben Jul 9, 2018
3b8ff51
Use a constant for AF_INET
khorben Jul 9, 2018
5daa522
Specify the family at run-time for TCP/UDP servers
khorben Jul 10, 2018
3d4b153
Add IPv6 support to the plain UDP and TCP servers
khorben Jul 10, 2018
8d0fb60
Terminate IPs resolved externally as expected
khorben Jul 17, 2018
7a9d02f
Typo
khorben Jun 26, 2018
7dc6ab5
Use the correct offset for inet_ntop()
khorben Jul 18, 2018
a89f206
Constify
khorben Jul 17, 2018
15530a2
Fix some issues with TCP over IPv6
khorben Jul 18, 2018
400ec0f
Add a command-line option to enable IPv6 (TCP/UDP)
khorben Jul 27, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions client/fwknop_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ typedef struct fko_cli_options
int no_save_args;
int use_hmac;
char spa_server_str[MAX_SERVER_STR_LEN]; /* may be a hostname */
char allow_ip_str[MAX_IPV4_STR_LEN];
char spoof_ip_src_str[MAX_IPV4_STR_LEN];
char allow_ip_str[MAX_IPV46_STR_LEN];
char spoof_ip_src_str[MAX_IPV46_STR_LEN];
char spoof_user[MAX_USERNAME_LEN];
int rand_port;
char gpg_recipient_key[MAX_GPG_KEY_ID];
Expand Down
68 changes: 34 additions & 34 deletions client/http_resolve_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,12 @@ struct url
static int
try_url(struct url *url, fko_cli_options_t *options)
{
int sock=-1, sock_success=0, res, error, http_buf_len, i;
int sock=-1, sock_success=0, i, res, error, http_buf_len;
int bytes_read = 0, position = 0;
int o1, o2, o3, o4;
struct addrinfo *result=NULL, *rp, hints;
char http_buf[HTTP_MAX_REQUEST_LEN] = {0};
char http_response[HTTP_MAX_RESPONSE_LEN] = {0};
char *ndx;
char *ndx, c;

#ifdef WIN32
WSADATA wsa_data;
Expand Down Expand Up @@ -197,45 +196,46 @@ try_url(struct url *url, fko_cli_options_t *options)
}
ndx += 4;

/* Walk along the content to try to find the end of the IP address.
* Note: We are expecting the content to be just an IP address
* (possibly followed by whitespace or other not-digit value).
/* Walk along the content to try to find the end of the IP address.
* Note: We are expecting the content to be just an IP address
* (possibly followed by whitespace or other not-digit value).
*/
for(i=0; i<MAX_IPV46_STR_LEN; i++) {
c = *(ndx+i);
if(! isdigit((int)(unsigned char)c) && ! ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) && c != '.' && c != ':')
break;
}

/* Terminate at the first non-digit and non-dot.
*/
for(i=0; i<MAX_IPV4_STR_LEN; i++) {
if(! isdigit((int)(unsigned char)*(ndx+i)) && *(ndx+i) != '.')
break;
}

/* Terminate at the first non-digit and non-dot.
*/
*(ndx+i) = '\0';

/* Now that we have what we think is an IP address string. We make
* sure the format and values are sane.
*/
if((sscanf(ndx, "%u.%u.%u.%u", &o1, &o2, &o3, &o4)) == 4
&& o1 >= 0 && o1 <= 255
&& o2 >= 0 && o2 <= 255
&& o3 >= 0 && o3 <= 255
&& o4 >= 0 && o4 <= 255)
{
strlcpy(options->allow_ip_str, ndx, sizeof(options->allow_ip_str));

log_msg(LOG_VERBOSITY_INFO,
"\n[+] Resolved external IP (via http://%s%s) as: %s",
url->host,
url->path,
options->allow_ip_str);
*(ndx+i) = '\0';

return(1);
}
else
/* Try to parse the content as an IP address. */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_flags = AI_NUMERICHOST | AI_CANONNAME;
error = getaddrinfo(ndx, NULL, &hints, &result);
if (error != 0)
{
log_msg(LOG_VERBOSITY_ERROR,
"[-] From http://%s%s\n Invalid IP (%s) in HTTP response:\n\n%s",
url->host, url->path, ndx, http_response);
return(-1);
}
for (rp = result; rp != NULL; rp = rp->ai_next) {
strlcpy(options->allow_ip_str,
rp->ai_canonname, sizeof(options->allow_ip_str));
break;
}
freeaddrinfo(result);

log_msg(LOG_VERBOSITY_INFO,
"\n[+] Resolved external IP (via http://%s%s) as: %s",
url->host,
url->path,
options->allow_ip_str);

return(1);
}

static int
Expand Down
8 changes: 4 additions & 4 deletions client/spa_comm.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ send_spa_packet_tcp_or_udp(const char *spa_data, const int sd_len,

memset(&hints, 0, sizeof(struct addrinfo));

hints.ai_family = AF_INET; /* Allow IPv4 only */
hints.ai_family = AF_UNSPEC;

if (options->spa_proto == FKO_PROTO_UDP)
{
Expand Down Expand Up @@ -230,7 +230,7 @@ send_spa_packet_tcp_raw(const char *spa_data, const int sd_len,
return res;
}

sock = socket (PF_INET, SOCK_RAW, IPPROTO_RAW);
sock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW);
if (sock < 0)
{
log_msg(LOG_VERBOSITY_ERROR, "send_spa_packet_tcp_raw: create socket: ", strerror(errno));
Expand Down Expand Up @@ -343,7 +343,7 @@ send_spa_packet_udp_raw(const char *spa_data, const int sd_len,
return res;
}

sock = socket (PF_INET, SOCK_RAW, IPPROTO_RAW);
sock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW);
if (sock < 0)
{
log_msg(LOG_VERBOSITY_ERROR, "send_spa_packet_udp_raw: create socket: ", strerror(errno));
Expand Down Expand Up @@ -441,7 +441,7 @@ send_spa_packet_icmp(const char *spa_data, const int sd_len,
return res;
}

sock = socket (PF_INET, SOCK_RAW, IPPROTO_RAW);
sock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW);

if (sock < 0)
{
Expand Down
10 changes: 9 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,15 @@ AC_HEADER_STDC
AC_HEADER_TIME
AC_HEADER_RESOLV

AC_CHECK_HEADERS([arpa/inet.h ctype.h endian.h errno.h locale.h netdb.h net/ethernet.h netinet/in.h stdint.h stdlib.h string.h strings.h sys/byteorder.h sys/endian.h sys/ethernet.h sys/socket.h sys/stat.h sys/time.h sys/wait.h termios.h time.h unistd.h])
AC_CHECK_HEADERS([arpa/inet.h ctype.h endian.h errno.h locale.h netdb.h net/ethernet.h netinet/in.h stdint.h stdlib.h string.h strings.h sys/byteorder.h sys/endian.h sys/ethernet.h sys/socket.h sys/stat.h sys/time.h sys/types.h sys/wait.h termios.h time.h unistd.h])
AC_CHECK_HEADERS([netinet/ip6.h netinet/icmp6.h], [], [],
[#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
])

# Type checks.
#
Expand Down
6 changes: 6 additions & 0 deletions lib/fko_limits.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@
#define MAX_IPV4_STR_LEN 16
#define MIN_IPV4_STR_LEN 7

#define MAX_IPV46_STR_LEN 40
#define MIN_IPV46_STR_LEN 3

#define MAX_IPV6_STR_LEN 40
#define MIN_IPV6_STR_LEN 3

#define MAX_PROTO_STR_LEN 4 /* tcp, udp, icmp for now */
#define MAX_PORT_STR_LEN 5
#define MAX_PORT 65535
Expand Down
73 changes: 56 additions & 17 deletions server/access.c
Original file line number Diff line number Diff line change
Expand Up @@ -373,8 +373,8 @@ add_int_ent(acc_int_list_t **ilist, const char *ip)
*/
if(strcasecmp(ip, "ANY") == 0)
{
new_sle->maddr = 0x0;
new_sle->mask = 0x0;
new_sle->family = AF_UNSPEC;
memset(&new_sle->acc_int, 0, sizeof(new_sle->acc_int));
}
else
{
Expand Down Expand Up @@ -473,17 +473,18 @@ add_int_ent(acc_int_list_t **ilist, const char *ip)

/* Store our mask converted from CIDR to a 32-bit value.
*/
new_sle->family = AF_INET;
if(mask == 32)
new_sle->mask = 0xFFFFFFFF;
new_sle->acc_int.inet.mask = 0xFFFFFFFF;
else if(need_shift && (mask > 0 && mask < 32))
new_sle->mask = (0xFFFFFFFF << (32 - mask));
new_sle->acc_int.inet.mask = (0xFFFFFFFF << (32 - mask));
else
new_sle->mask = mask;
new_sle->acc_int.inet.mask = mask;

/* Store our masked address for comparisons with future incoming
* packets.
*/
new_sle->maddr = ntohl(in.s_addr) & new_sle->mask;
new_sle->acc_int.inet.maddr = ntohl(in.s_addr) & new_sle->acc_int.inet.mask;
}

/* If this is not the first entry, we walk our pointer to the
Expand Down Expand Up @@ -2069,23 +2070,61 @@ int valid_access_stanzas(acc_stanza_t *acc)
return 1;
}

static int
compare_addr_list_ipv4(acc_int_list_t *ip_list, uint32_t ip)
{
for(; ip_list; ip_list = ip_list->next)
{
if(ip_list->family == AF_UNSPEC)
return 1;
if(ip_list->family != AF_INET6)
continue;
if((ip & ip_list->acc_int.inet.mask) == (ip_list->acc_int.inet.maddr & ip_list->acc_int.inet.mask))
return 1;
}
return 0;
}

static int
compare_addr_list_ipv6(acc_int_list_t *ip_list, struct in6_addr *ip6)
{
for(; ip_list; ip_list = ip_list->next)
{
if(ip_list->family == AF_UNSPEC)
return 1;
if(ip_list->family != AF_INET6)
continue;
if(memcmp(&ip_list->acc_int.inet6.maddr, ip6, sizeof(*ip6)) == 0)
return 1;
}
return 0;
}

int
compare_addr_list(acc_int_list_t *ip_list, const uint32_t ip)
compare_addr_list(acc_int_list_t *ip_list, int family, ...)
{
int match = 0;
int res;
va_list ap;
uint32_t ip;
struct in6_addr * ip6;

while(ip_list)
va_start(ap, family);
switch(family)
{
if((ip & ip_list->mask) == (ip_list->maddr & ip_list->mask))
{
match = 1;
case AF_INET:
ip = va_arg(ap, uint32_t);
res = compare_addr_list_ipv4(ip_list, ip);
break;
case AF_INET6:
ip6 = va_arg(ap, struct in6_addr *);
res = compare_addr_list_ipv6(ip_list, ip6);
break;
default:
res = 0;
break;
}

ip_list = ip_list->next;
}

return(match);
va_end(ap);
return res;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion server/access.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ int valid_access_stanzas(acc_stanza_t *acc);
* \return Returns true on a match
*
*/
int compare_addr_list(acc_int_list_t *source_list, const uint32_t ip);
int compare_addr_list(acc_int_list_t *source_list, int family, ...);

/**
* \brief Check for a proto-port string
Expand Down
5 changes: 3 additions & 2 deletions server/cmd_opts.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,9 @@ enum {
/* Our getopt_long options string.
*/
#if USE_LIBNETFILTER_QUEUE
#define GETOPTS_OPTION_STRING "Aa:c:C:d:Dfhi:Kl:nO:p:P:Rr:StUvV"
#define GETOPTS_OPTION_STRING "Aa:c:C:d:Dfhi:6Kl:nO:p:P:Rr:StUvV"
#else
#define GETOPTS_OPTION_STRING "Aa:c:C:d:Dfhi:Kl:O:p:P:Rr:StUvV"
#define GETOPTS_OPTION_STRING "Aa:c:C:d:Dfhi:6Kl:O:p:P:Rr:StUvV"
#endif

/* Our program command-line options...
Expand All @@ -206,6 +206,7 @@ static struct option cmd_opts[] =
{"fault-injection-tag", 1, NULL, FAULT_INJECTION_TAG},
{"help", 0, NULL, 'h'},
{"interface", 1, NULL, 'i'},
{"ipv6", 0, NULL, '6'},
{"key-gen", 0, NULL, 'k'},
{"key-gen-file", 1, NULL, KEY_GEN_FILE },
{"key-len", 1, NULL, KEY_LEN },
Expand Down
4 changes: 4 additions & 0 deletions server/config_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -1372,6 +1372,9 @@ config_init(fko_srv_options_t *opts, int argc, char **argv)
case 'i':
set_config_entry(opts, CONF_PCAP_INTF, optarg);
break;
case '6':
opts->ipv6 = 1;
break;
case FIREWD_DISABLE_CHECK_SUPPORT:
opts->firewd_disable_check_support = 1;
break;
Expand Down Expand Up @@ -1498,6 +1501,7 @@ usage(void)
" a background daemon).\n"
" -i, --interface - Specify interface to listen for incoming SPA\n"
" packets.\n"
" -6, --ipv6 - Start the server in IPv6 mode (TCP/UDP).\n"
" -C, --packet-limit - Limit the number of candidate SPA packets to\n"
" process and exit when this limit is reached.\n"
" -d, --digest-file - Specify an alternate digest.cache file.\n"
Expand Down
4 changes: 2 additions & 2 deletions server/fwknopd.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ main(int argc, char **argv)
if(opts.enable_udp_server ||
strncasecmp(opts.config[CONF_ENABLE_UDP_SERVER], "Y", 1) == 0)
{
if(run_udp_server(&opts) < 0)
if(run_udp_server(&opts, opts.ipv6 ? AF_INET6 : AF_INET) < 0)
{
log_msg(LOG_ERR, "Fatal run_udp_server() error");
clean_exit(&opts, FW_CLEANUP, EXIT_FAILURE);
Expand All @@ -280,7 +280,7 @@ main(int argc, char **argv)
*/
if(strncasecmp(opts.config[CONF_ENABLE_TCP_SERVER], "Y", 1) == 0)
{
if(run_tcp_server(&opts) < 0)
if(run_tcp_server(&opts, opts.ipv6 ? AF_INET6 : AF_INET) < 0)
{
log_msg(LOG_ERR, "Fatal run_tcp_server() error");
clean_exit(&opts, FW_CLEANUP, EXIT_FAILURE);
Expand Down
Loading