[libfko] implemented shared utility function for ipv4 address checking

This commit implements a single shared utility function for checking the
validaty of an IPv4 address, and both libfko and the fwknopd server use it
now.  The client will be updated as well.
This commit is contained in:
Michael Rash
2013-11-20 17:13:55 -05:00
parent 5f5367cf62
commit 78f696b2f7
7 changed files with 107 additions and 26 deletions
+3 -24
View File
@@ -33,14 +33,6 @@
#include "fko_message.h"
#include "fko.h"
#ifndef WIN32
/* for inet_aton() IP validation
*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
static int
have_allow_ip(const char *msg)
{
@@ -48,9 +40,6 @@ have_allow_ip(const char *msg)
char ip_str[MAX_IPV4_STR_LEN];
int dot_ctr = 0, char_ctr = 0;
int res = FKO_SUCCESS;
#if HAVE_SYS_SOCKET_H
struct in_addr in;
#endif
while(*ndx != ',' && *ndx != '\0')
{
@@ -76,19 +65,9 @@ have_allow_ip(const char *msg)
else
res = FKO_ERROR_INVALID_ALLOW_IP;
if ((res == FKO_SUCCESS) && (char_ctr < MIN_IPV4_STR_LEN))
res = FKO_ERROR_INVALID_ALLOW_IP;
if((res == FKO_SUCCESS) && dot_ctr != 3)
res = FKO_ERROR_INVALID_ALLOW_IP;
#if HAVE_SYS_SOCKET_H
/* Stronger IP validation now that we have a candidate that looks
* close enough
*/
if((res == FKO_SUCCESS) && (inet_aton(ip_str, &in) == 0))
res = FKO_ERROR_INVALID_ALLOW_IP;
#endif
if(res == FKO_SUCCESS)
if (! is_valid_ipv4_addr(ip_str))
res = FKO_ERROR_INVALID_ALLOW_IP;
return(res);
}
+57
View File
@@ -33,6 +33,14 @@
#include <errno.h>
#include <stdarg.h>
#ifndef WIN32
/* for inet_aton() IP validation
*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
/* Check for a FKO error returned by a function an return the error code */
#define RETURN_ON_FKO_ERROR(e, f) do { if (((e)=(f)) != FKO_SUCCESS) { return (e); } } while(0);
@@ -104,6 +112,55 @@ is_valid_encoded_msg_len(const int len)
return(1);
}
/* Validate an IPv4 address
*/
int
is_valid_ipv4_addr(const char * const ip_str)
{
const char *ndx = ip_str;
int dot_ctr = 0, char_ctr = 0;
int res = 1;
#if HAVE_SYS_SOCKET_H
struct in_addr in;
#endif
while(*ndx != '\0')
{
char_ctr++;
if(char_ctr >= MAX_IPV4_STR_LEN)
{
res = 0;
break;
}
if(*ndx == '.')
dot_ctr++;
else if(isdigit(*ndx) == 0)
{
res = 0;
break;
}
ndx++;
}
if(char_ctr >= MAX_IPV4_STR_LEN)
res = 0;
if ((res == 1) && (char_ctr < MIN_IPV4_STR_LEN))
res = 0;
if((res == 1) && dot_ctr != 3)
res = 0;
#if HAVE_SYS_SOCKET_H
/* Stronger IP validation now that we have a candidate that looks
* close enough
*/
if((res == 1) && (inet_aton(ip_str, &in) == 0))
res = 0;
#endif
return(res);
}
/* Convert a digest_type string to its integer value.
*/
short
+1
View File
@@ -38,6 +38,7 @@
int is_valid_encoded_msg_len(const int len);
int is_valid_pt_msg_len(const int len);
int is_valid_digest_len(const int len);
int is_valid_ipv4_addr(const char * const ip_str);
int is_base64(const unsigned char * const buf, const unsigned short int len);
int enc_mode_strtoint(const char *enc_mode_str);
short enc_mode_inttostr(int enc_mode, char* enc_mode_str, size_t enc_mode_size);
+7
View File
@@ -180,6 +180,13 @@ add_acc_force_nat(fko_srv_options_t *opts, acc_stanza_t *curr_acc, const char *v
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
if(! is_valid_ipv4_addr(ip_str))
{
log_msg(LOG_ERR,
"[*] Fatal: invalid FORCE_NAT IP '%s'", ip_str);
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
curr_acc->force_nat = 1;
add_acc_string(&(curr_acc->force_nat_ip), ip_str);
+12
View File
@@ -444,6 +444,18 @@ validate_options(fko_srv_options_t *opts)
set_config_entry(opts, CONF_ENABLE_IPT_SNAT,
DEF_ENABLE_IPT_SNAT);
/* Make sure we have a valid IP if SNAT is enabled
*/
if(strncasecmp(opts->config[CONF_ENABLE_IPT_SNAT], "Y", 1) == 0)
if(opts->config[CONF_SNAT_TRANSLATE_IP] != NULL)
if(! is_valid_ipv4_addr(opts->config[CONF_SNAT_TRANSLATE_IP]))
{
log_msg(LOG_ERR,
"Invalid IPv4 addr for SNAT_TRANSLATE_IP"
);
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
/* Enable IPT OUTPUT.
*/
if(opts->config[CONF_ENABLE_IPT_OUTPUT] == NULL)
+8
View File
@@ -1110,11 +1110,19 @@ process_spa_request(const fko_srv_options_t * const opts,
if(ndx != NULL)
{
strlcpy(nat_ip, spadat->nat_access, (ndx-spadat->nat_access)+1);
if (! is_valid_ipv4_addr(nat_ip))
{
log_msg(LOG_INFO, "Invalid NAT IP in SPA message");
free_acc_port_list(port_list);
return res;
}
nat_port = strtol_wrapper(ndx+1, 0, MAX_PORT, NO_EXIT_UPON_ERR, &is_err);
if(is_err != FKO_SUCCESS)
{
log_msg(LOG_INFO, "Invalid NAT port in SPA message");
free_acc_port_list(port_list);
res = is_err;
return res;
}
}
+19 -2
View File
@@ -643,11 +643,28 @@ incoming_spa(fko_srv_options_t *opts)
continue;
}
if((spa_ip_demark-spadat.spa_message) < MIN_IPV4_STR_LEN-1
|| (spa_ip_demark-spadat.spa_message) > MAX_IPV4_STR_LEN)
{
log_msg(LOG_WARNING, "[%s] (stanza #%d) Invalid source IP in SPA message, ignoring SPA packet",
spadat.pkt_source_ip, stanza_num, fko_errstr(res));
if(ctx != NULL)
{
if(fko_destroy(ctx) == FKO_ERROR_ZERO_OUT_DATA)
log_msg(LOG_WARNING,
"[%s] (stanza #%d) fko_destroy() could not zero out sensitive data buffer.",
spadat.pkt_source_ip, stanza_num, fko_errstr(res)
);
ctx = NULL;
}
break;
}
strlcpy(spadat.spa_message_src_ip,
spadat.spa_message, (spa_ip_demark-spadat.spa_message)+1);
if(strnlen(spadat.spa_message_src_ip,
MIN_IPV4_STR_LEN) < MIN_IPV4_STR_LEN)
if(! is_valid_ipv4_addr(spadat.spa_message_src_ip))
{
log_msg(LOG_WARNING, "[%s] (stanza #%d) Invalid source IP in SPA message, ignoring SPA packet",
spadat.pkt_source_ip, stanza_num, fko_errstr(res));